【问题标题】:How to compare a video with a reference video using OpenCV and Python?如何使用 OpenCV 和 Python 将视频与参考视频进行比较?
【发布时间】:2015-05-10 05:54:08
【问题描述】:

我需要比较 2 个视频并检查它们是否相同。此检查是为了实际查找视频是否包含任何伪影。

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

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

如何在 中使用 执行此操作?

【问题讨论】:

  • 请展示您到目前为止所做的尝试。究竟是什么意思“检查它们是否相同”?一样什么?确切地?还是差不多?是否允许强度变化?不同的压缩方式?
  • 我将有一个以相同分辨率和压缩率拍摄的参考视频。我基本上是在尝试比较 2 个视频以查看视频伪影,由于没有好的方法,我正在考虑比较视频并得出结论,如果它们不一样,那么存在一些伪影
  • 这是同一视频只处理了两次还是涉及两次不同的捕获?你正在拍摄的房间有什么变化?光照条件?我仍然不清楚这两个视频是什么。您是否需要查明视频文件中是否存在伪像或确切位置(时间和/或空间)?
  • 请编辑您的问题以添加更多信息。不是每个人都会通读评论,如果您的问题包含所有需要的信息,您更有可能得到答案。

标签: opencv numpy matplotlib python python opencv video numpy


【解决方案1】:

您可以查看 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 张图像),因此您必须循环播放视频以获取对应的对。

【讨论】:

  • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接的答案可能会失效。
【解决方案2】:

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

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

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

【讨论】:

  • 没有真正理解“逐字节”比较的意思
  • @MridulaMadhusudan - 从两个文件中读取第一个字节;检查它们是否相同;读取下一个字节等。在循环中执行,一旦发现差异就中断。
【解决方案3】:

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

【讨论】:

    【解决方案4】:

    打开两个视频。

    • 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)

    如果三个 PSNR.POS 中至少有两个相隔约 5 秒,则视频很可能会重复,并且您知道如何同步它们:因此 FirstVideo.pos[A, B 或 C] = MinPSNR[A, B or C].pos.

    此时您可以开始一一比较同步的帧,寻找伪影。

    【讨论】:

      【解决方案5】:

      这个问题仍然有点模糊,但有很多方法可以尝试比较视频中的伪像。如果它们具有相同的分辨率、fps 等,也容易得多。

      1. 如果您从另一个视频的帧 [N] 中减去一个视频的帧 [N],(您可能需要重新缩放以考虑负值)结果帧的所有像素应接近零。适当的颜色映射将允许您播放生成的视频,并且“伪影”会很明显,颜色表明变化的幅度。

      2. 如果您的计算机可以处理,请在一个轴(x 轴)上绘制一个视频的像素值,并在另一个轴(y 轴)上绘制匹配的像素值。图越靠近 x=y 线,视频越相似。在这种情况下,伪影通常会显示为与 x=y 线的偏差,其幅度大于人们可能从相似但不完全相同的视频中预期的“噪音”。然后你只需要找到高于你设置的阈值的偏差的索引来定义'artifacts'

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

      根据您想要执行的比较,有多种方法可以将您的视频转换为多维数组。

      【讨论】:

        猜你喜欢
        • 2014-04-01
        • 2016-02-09
        • 1970-01-01
        • 2017-08-11
        • 1970-01-01
        • 2018-02-07
        • 2011-08-03
        • 2011-03-26
        • 1970-01-01
        相关资源
        最近更新 更多