首页 > 代码库 > OpenCV Tutorials —— Video Input with OpenCV and similarity measurement

OpenCV Tutorials —— Video Input with OpenCV and similarity measurement

OpenCV 的视频操作都与 VideoCapture 相关

If this argument is an integer then you will bind the class to a camera, a device. The number passed here is the ID of the device, assigned by the operating system.

If you have a single camera attached to your system its ID will probably be zero and further ones increasing from there.

If the parameter passed to these is a string it will refer to a video file, and the string points to the location and name of the file.

 

1,通过构造函数或者 open 来打开视频流

2,通过 isOpen  判断是否打开成功

3,通过 >> 将frame信息读入Mat 中

4,empty 来检测是否完结

5,获取视频其他信息,用get

Size refS = Size((int) captRefrnc.get(CV_CAP_PROP_FRAME_WIDTH),                 (int) captRefrnc.get(CV_CAP_PROP_FRAME_HEIGHT)),cout << "Reference frame resolution: Width=" << refS.width << "  Height=" << refS.height     << " of nr#: " << captRefrnc.get(CV_CAP_PROP_FRAME_COUNT) << endl;

set 设置信息:

captRefrnc.set(CV_CAP_PROP_POS_MSEC, 1.2);  // go to the 1.2 second in the videocaptRefrnc.set(CV_CAP_PROP_POS_FRAMES, 10); // go to the 10th frame of the video

 

 

Image similarity - PSNR and SSIM

PSNR (aka Peak signal-to-noise ratio). The simplest definition of this starts out from the mean squad error. Let there be two images: I1 and I2; with a two dimensional size i and j, composed of c number of channels.

MSE = \frac{1}{c*i*j} \sum{(I_1-I_2)^2}

Then the PSNR is expressed as:

PSNR = 10 \cdot \log_{10} \left( \frac{MAX_I^2}{MSE} \right)

Here the MAX_I^2 is the maximum valid value for a pixel.

 

其中两像素相减会发生除数为零的情况,需要在程序中区分对待

 

程序的目的是比较原始视频和压缩视频每帧图像的相似度(信息损失度)

 

Code

#include "stdafx.h"#include <iostream>	// for standard I/O#include <string>   // for strings#include <iomanip>  // for controlling float print precision#include <sstream>  // string to number conversion#include <opencv2/imgproc/imgproc.hpp>  // Gaussian Blur#include <opencv2/core/core.hpp>        // Basic OpenCV structures (cv::Mat, Scalar)#include <opencv2/highgui/highgui.hpp>  // OpenCV window I/Ousing namespace std;using namespace cv;double getPSNR ( const Mat& I1, const Mat& I2);Scalar getMSSIM( const Mat& I1, const Mat& I2);void help(){	cout		<< "\n--------------------------------------------------------------------------" << endl		<< "This program shows how to read a video file with OpenCV. In addition, it tests the"		<< " similarity of two input videos first with PSNR, and for the frames below a PSNR "  << endl		<< "trigger value, also with MSSIM."<< endl		<< "Usage:"                                                                       << endl		<< "./video-source referenceVideo useCaseTestVideo PSNR_Trigger_Value Wait_Between_Frames " << endl		<< "--------------------------------------------------------------------------"   << endl		<< endl;}int main(int argc, char *argv[], char *window_name){	help();	/*	if (argc != 5)	{		cout << "Not enough parameters" << endl;		return -1;	}*/	stringstream conv;	const string sourceReference = "video/Megamind.avi",sourceCompareWith = "video/Megamind_bug.avi";	int psnrTriggerValue, delay;	conv << "35" << endl << "10";		  // put in the strings	conv >> psnrTriggerValue >> delay;// take out the numbers	char c;	int frameNum = -1;			// Frame counter	VideoCapture captRefrnc(sourceReference),	// 通过构造函数打开视频流		captUndTst(sourceCompareWith);	if ( !captRefrnc.isOpened())	{		cout  << "Could not open reference " << sourceReference << endl;		return -1;	}	if( !captUndTst.isOpened())	{		cout  << "Could not open case test " << sourceCompareWith << endl;		return -1;	}	Size refS = Size((int) captRefrnc.get(CV_CAP_PROP_FRAME_WIDTH),		(int) captRefrnc.get(CV_CAP_PROP_FRAME_HEIGHT)),		uTSi = Size((int) captUndTst.get(CV_CAP_PROP_FRAME_WIDTH),		(int) captUndTst.get(CV_CAP_PROP_FRAME_HEIGHT));	if (refS != uTSi)	{		cout << "Inputs have different size!!! Closing." << endl;		return -1;	}	const char* WIN_UT = "Under Test";	const char* WIN_RF = "Reference";	// Windows	namedWindow(WIN_RF, CV_WINDOW_AUTOSIZE );	namedWindow(WIN_UT, CV_WINDOW_AUTOSIZE );	cvMoveWindow(WIN_RF, 400       ,            0);		 //750,  2 (bernat =0)	cvMoveWindow(WIN_UT, refS.width,            0);		 //1500, 2	cout << "Reference frame resolution: Width=" << refS.width << "  Height=" << refS.height		<< " of nr#: " << captRefrnc.get(CV_CAP_PROP_FRAME_COUNT) << endl;	cout << "PSNR trigger value " <<		setiosflags(ios::fixed) << setprecision(3) << psnrTriggerValue << endl;	Mat frameReference, frameUnderTest;	double psnrV;	Scalar mssimV;	while( true) //Show the image captured in the window and repeat	{		captRefrnc >> frameReference;		captUndTst >> frameUnderTest;		if( frameReference.empty()  || frameUnderTest.empty())		{			cout << " < < <  Game over!  > > > ";			break;		}		++frameNum;		cout <<"Frame:" << frameNum <<"# ";		///////////////////////////////// PSNR ////////////////////////////////////////////////////		psnrV = getPSNR(frameReference,frameUnderTest);					//get PSNR		cout << setiosflags(ios::fixed) << setprecision(3) << psnrV << "dB";		//////////////////////////////////// MSSIM /////////////////////////////////////////////////		if (psnrV < psnrTriggerValue && psnrV)		{			mssimV = getMSSIM(frameReference,frameUnderTest);			cout << " MSSIM: "				<< " R " << setiosflags(ios::fixed) << setprecision(2) << mssimV.val[2] * 100 << "%"				<< " G " << setiosflags(ios::fixed) << setprecision(2) << mssimV.val[1] * 100 << "%"				<< " B " << setiosflags(ios::fixed) << setprecision(2) << mssimV.val[0] * 100 << "%";		}		cout << endl;		////////////////////////////////// Show Image /////////////////////////////////////////////		imshow( WIN_RF, frameReference);		imshow( WIN_UT, frameUnderTest);		c = cvWaitKey(delay);		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 getMSSIM( 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;	///////////////////////////////// FORMULA ////////////////////////////////	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 Tutorials —— Video Input with OpenCV and similarity measurement