如何使用OpenCV和Python将视频与参考视频进行比较?

时间:2015-03-09 05:42:37

标签: python opencv video numpy

我需要比较2个视频并检查它们是否相同。此检查实际上是查找视频是否包含任何工件。

我有一个参考视频,必须比较捕获的视频。 视频将在同一时间从2个不同的机顶盒中捕获。一个是运行无伪影的视频,而另一个机顶盒将与稳定的视频相比进行测试。不需要考虑外部条件。

执行此操作的一种方法是将视频分成帧,然后比较每个帧。我不想这样做,因为当我拥有60fps的高分辨率视频时,这将是一个非常漫长的过程。

如何使用中的来完成此操作?

5 个答案:

答案 0 :(得分:2)

您可以查看c ++ Video Input with OpenCV and similarity measurement

的示例

这为您所寻找的内容提供了参考。 我对Python不是很熟悉,但是因为opencv保持了相同的功能,我认为yiu可以从c ++示例中推断出来。

最常用的算法是PSNR(又称峰值信噪比)。

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;
 }
}

但是如果你想要结构相似性,你可以使用下面的OpenCV实现。

 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

 /***********************PRELIMINARY COMPUTING ******************************/

 Mat mu1, mu2;   //
 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;
}

重要的是要注意,由于您要逐帧比较(2张图像),您必须循环浏览视频才能获得相应的对。

答案 1 :(得分:1)

根据PSNR示例您同时运行两个视频并比较两个视频的每个帧(当前时间点)。但是,如果第一个视频内容的1stmin与第二个视频内容的第2或第3分钟匹配,该怎么办? PSNR不适合这种情况。您可以使用&#34;视频帧匹配算法,使用动态编程&#34; http://electronicimaging.spiedigitallibrary.org/article.aspx?articleid=1100207

答案 2 :(得分:0)

如果你的意思是完全相同(即相同的格式,相同的文件类型等),那么最简单的方法是简单的文件比较 - 即只是逐字节地比较每个文件。

它也是唯一可靠的测试 - 例如它们可能几乎完全相同,但是在中途有一些损坏的字节。

这种逐字节比较比尝试解码和解释存在的许多不同视频格式要简单得多。

答案 3 :(得分:0)

打开两个视频。

  • N取决于FPS和视频“速度”(追车视频:N = 1;在绿色景观上缓慢移动:N可能是5甚至10)
  • 在第一个视频中间以“合理”的间隔(例如5秒)获取三帧
  • 对于位置pos处的第二个视频的每N个帧
    • 将该帧的PSNR与帧A,B和C进行比较
    • 如果PSNR小于MinPSNR [A,B或C]。则PSNR
      • MinPSNR [A,B或C] =(PSNR,pos)

如果三个PSNRs.POS中的至少两个间隔约5秒钟,则很可能复制了视频,并且您知道如何进行同步:因此,FirstVideo.pos [A,B或C] = MinPSNR [A,B或C] .pos。

此时,您可以开始逐帧比较已同步的帧,以查找伪像。

答案 4 :(得分:0)

问题仍然有点模糊,但是有很多方法可以尝试比较视频中的伪像。如果它们具有相同的分辨率,fps等,也将大大简化

  1. 如果从另一个视频的frame [N]中减去一个视频的frame [N](您可能需要重新缩放以解决负值),则所有像素的结果帧应接近零。正确的颜色映射将使您能够播放最终的视频,并且“伪像”会很明显,并且带有指示变化幅度的颜色。

  2. 如果计算机可以处理,请在一个轴(x轴)上绘制一个视频的像素值,并在另一轴(y轴)上绘制匹配的像素值。情节越靠近x = y线,视频越相似。在这种情况下,伪像通常会表现为与x = y线的偏差,其幅度大于人们对相似但不完全相同的视频可能期望的“噪声”。然后,您只需要找到偏差的索引,该偏差就超过您定义“人工产物”所设置的阈值

  3. 类似于上面的方法2。像素值可以通过相关性进行比较。如果以更高的维数绘制相关性,则此方法还将给出伪像的位置。

有多种方法可以将视频转换为多维数组,具体取决于您要执行的比较。