opencv学习历程4

创建一个Trackbar

// 函数定义
int cv::createTrackbar 	( 	const String &  	trackbarname,
		const String &  	winname,
		int *  	value,
		int  	count,
		TrackbarCallback  	onChange = 0,
		void *  	userdata = 0 
// trackbarname trackbar的名字
// winname trackbar所在窗口的名字
// value 滑块的值
// count 滑块最大允许值
// onChange 指向一个函数,每次改变滑块的值,自动调用这个函数,要求函数的原型为 void function_name(int, void *);

// 一个例子, on_trackbar为调用的函数
createTrackbar( "Trackbar", "Linear Blend", &alpha_slider, alpha_slider_max, on_trackbar );
	) 	

Reading Geospatial Raster files with GDAL

dem = cv::imread(argv[2], cv::IMREAD_LOAD_GDAL | cv::IMREAD_ANYDEPTH );

一些简单处理参照Reading Geospatial Raster files with GDAL opencv官方例子

opencv读取视频或调用摄像头

视频流实质也就是连续若干帧的图片,在opencv中读取视频的方法也是如此,先声明一个视频流对象,然后逐帧的取出图片

    VideoCapture source(sourceVideo);
    VideoCapture test;
    test.open(testVideo);// 这两种表达方式含义一致, 都是打开一个视频文件,生成视频流对象
    // VideoCapture本身除了读取视频时候也可以调用摄像头,此时参数应该位设备的ID号
    // 在声明了视频流后可以通过>>操作取出来帧图片
    Mat sourceImage, testImage;
    source >> sourceImage;
    test   >> testImage;
    // 可以通过get函数获取视频相关属性
    // Size为opencv默认数据类型, 构造函数为Size(width, height);
    Size ssource = Size((int) source.get(CAP_PROP_FRAME_WIDTH),
                       (int) source.get(CAP_PROP_FRAME_HEIGHT));
    Size stest   = Size((int) test.get(CAP_PROP_FRAME_WIDTH),
                       (int) test.get(CAP_PROP_FRAME_HEIGHT));
    cout<<"width="<<ssource.width<<"Height="<<ssource.height<<"number="<<source.get(CAP_PROP_FRAME_COUNT);
   

一个输入两个视频文件并计算ssim和psnr的例子

#include//opencv中基础模块
#include//opencv I/O
#include //gaussian blur
#include

#include
#include
#include // 控制输出精度
#include// string to number 转换

using namespace std;
using namespace cv;

double getPSNR(const Mat& I1, const Mat& I2);//计算PSNR值
Scalar getSSIM( const Mat& i1, const Mat& i2);// 计算SSIM值

int main(int agrc, char **argv)
{
    const string sourceVideo = argv[1], testVideo = argv[2];
    int frameNumber = -1; // 视频帧数

    //声明一个视频流的对象
    VideoCapture source(sourceVideo);
    VideoCapture test;
    test.open(testVideo);// 这两种表达方式含义一致
    if(!source.isOpened())
    {
        cout<<"can't open source video"<<endl;
        return -1;
    }
    if(!test.isOpened())
    {
        cout<<"can't open test video"<<endl;
        return -1;
    }
    // 获取视频属性
    // Size为opencv默认数据类型, 构造函数为Size(width, height);
    Size ssource = Size((int) source.get(CAP_PROP_FRAME_WIDTH),
                       (int) source.get(CAP_PROP_FRAME_HEIGHT));
    Size stest   = Size((int) test.get(CAP_PROP_FRAME_WIDTH),
                       (int) test.get(CAP_PROP_FRAME_HEIGHT));
    cout<<"width="<<ssource.width<<"Height="<<ssource.height<<"number="<<source.get(CAP_PROP_FRAME_COUNT);
    if(ssource!=stest)
    {
        cout<<"source video and test video have different size"<<endl;
        return -1;
    }

    const char* WIN_SOURCE  = "source video";
    const char* WIN_TEST = "test video";

    namedWindow(WIN_SOURCE, WINDOW_AUTOSIZE);
    namedWindow(WIN_TEST, WINDOW_AUTOSIZE);
    moveWindow(WIN_SOURCE, 500, 0);
    moveWindow(WIN_TEST, 600+ssource.width, 0);
    

    Mat sourceImage, testImage;
    double psnrV;
    Scalar ssimV;//存储三通道的ssim
    for(;;)
    {
        // 从视频流中获取每一帧图像
        source >> sourceImage;
        test   >> testImage;

        if(sourceImage.empty()||testImage.empty())
        {
            cout<<"over"<<endl;
            break;
        }

        frameNumber++;
        cout<<"frame="<<frameNumber+1<<endl;
        psnrV = getPSNR(sourceImage, sourceImage);
        cout<<setiosflags(ios::fixed)<<setprecision(3)<<psnrV<<endl;

        ssimV = getSSIM(sourceImage, sourceImage);
        cout<<"SSIM"
            <<"R"<<setiosflags(ios::fixed)<<setprecision(3)<<ssimV[2]*100<<"%"
            <<"G"<<setiosflags(ios::fixed)<<setprecision(3)<<ssimV[1]*100<<"%"
            <<"B"<<setiosflags(ios::fixed)<<setprecision(3)<<ssimV[0]*100<<"%"<<endl;
        imshow(WIN_SOURCE, sourceImage);
        imshow(WIN_TEST, testImage);

        char c=(char)waitKey(500);
        if(c==27)
        {
            break;
        }

    }
    return 0;
}

// 对照着具体公式即可很容易理解该部分代码
double getPSNR(const Mat& I1, const Mat& I2)
{
    Mat s1;
    absdiff(I1, I2, s1);       // |I1 - I2|
    s1.convertTo(s1, CV_32F);  // cannot make a square on 8 bits
    s1 = s1.mul(s1);           // |I1 - I2|^2
    Scalar s = sum(s1);        // sum elements per channel
    double sse = s.val[0] + s.val[1] + s.val[2]; // sum channels
    if( sse <= 1e-10) // for small values return zero
        return 0;
    else
    {
        double mse  = sse / (double)(I1.channels() * I1.total());
        double psnr = 10.0 * log10((255 * 255) / mse);
        return psnr;
    }
}
Scalar getSSIM( const Mat& i1, const Mat& i2)
{
    const double C1 = 6.5025, C2 = 58.5225;
    /***************************** INITS **********************************/
    int d = CV_32F;
    Mat I1, I2;
    i1.convertTo(I1, d);            // cannot calculate on one byte large values
    i2.convertTo(I2, d);
    Mat I2_2   = I2.mul(I2);        // I2^2
    Mat I1_2   = I1.mul(I1);        // I1^2
    Mat I1_I2  = I1.mul(I2);        // I1 * I2
    /*************************** END INITS **********************************/
    Mat mu1, mu2;                   // PRELIMINARY COMPUTING
    GaussianBlur(I1, mu1, Size(11, 11), 1.5);
    GaussianBlur(I2, mu2, Size(11, 11), 1.5);
    Mat mu1_2   =   mu1.mul(mu1);
    Mat mu2_2   =   mu2.mul(mu2);
    Mat mu1_mu2 =   mu1.mul(mu2);
    Mat sigma1_2, sigma2_2, sigma12;
    GaussianBlur(I1_2, sigma1_2, Size(11, 11), 1.5);
    sigma1_2 -= mu1_2;
    GaussianBlur(I2_2, sigma2_2, Size(11, 11), 1.5);
    sigma2_2 -= mu2_2;
    GaussianBlur(I1_I2, sigma12, Size(11, 11), 1.5);
    sigma12 -= mu1_mu2;
    Mat t1, t2, t3;
    t1 = 2 * mu1_mu2 + C1;
    t2 = 2 * sigma12 + C2;
    t3 = t1.mul(t2);                 // t3 = ((2*mu1_mu2 + C1).*(2*sigma12 + C2))
    t1 = mu1_2 + mu2_2 + C1;
    t2 = sigma1_2 + sigma2_2 + C2;
    t1 = t1.mul(t2);                 // t1 =((mu1_2 + mu2_2 + C1).*(sigma1_2 + sigma2_2 + C2))
    Mat ssim_map;
    divide(t3, t1, ssim_map);        // ssim_map =  t3./t1;
    Scalar mssim = mean(ssim_map);   // mssim = average of ssim map
    return mssim;
}

opencv进行简单的视频生成

一个视频文件的内容可以从后缀名中得到,主要包括 video feeds, audio feeds or other tracks, video track存储方式是由编码器决定的,opencv主要面对图像处理,因而其中仅支持.avi文件,也仅能生成.avi文件

  1. 要生成视频文件首先要建立一个视频流对象,包括视频名称,编码格式,fps, 视频尺寸等,我们再次以建立一个与输入文件相同格式相同尺寸的视频为例,如果已知要存储的视频编码格式,和fps,尺寸就只需要构造一个VideoWriter对象即可,
// 获取输入视频源
VideoCapture inputVideo(source); 
// CAP_PROP_FOURCC代表编码格式,但get属性获得是double类型8字节,编码器类型4字节,存储在低四字节,故转换为int类型
int ex = static_cast<int>(inputVideo.get(CAP_PROP_FOURCC));     // Get Codec Type- Int form
 // 通过位运算将数字转换为对应的字符串,每1个字节,8位代表一个字符,故通过&运算分别取出每个字节,并在最后加上'\0'
 char EXT[] = {(char)(ex & 0XFF) , (char)((ex & 0XFF00) >> 8),(char)((ex & 0XFF0000) >> 16),(char)((ex & 0XFF000000) >> 24), 0};
 // 获取视频尺寸
 Size S = Size((int) inputVideo.get(CAP_PROP_FRAME_WIDTH),    // Acquire input size
                  (int) inputVideo.get(CAP_PROP_FRAME_HEIGHT));
 VideoWriter outputVideo;
 outputVideo.open(NAME, ex, inputVideo.get(CAP_PROP_FPS), S, true);
  1. 将每一帧图片存储你进行视频源对象中即可
// res即为要存储的帧图片
outputVideo.write(res);  //or
outputVideo << res;

你可能感兴趣的:(opencv)