【问题标题】:OCR & OpenCV: Difference between two frames on high resolution imagesOCR 和 OpenCV:高分辨率图像上两帧之间的差异
【发布时间】:2016-03-21 02:50:28
【问题描述】:

根据这篇帖子OCR: Difference between two frames,我现在知道如何使用 OpenCV 查找两个图像之间的像素差异。

我想改进此解决方案并将其与内容丰富的高分辨率图像(来自视频)一起使用。上面的示例不适用于大图像,因为处理速度很慢(发现太多差异,“findCountours 方法”用 250k 元素填充选项卡,这需要大量时间来处理)。

我的应用程序使用 RLE 解码器来解码视频的压缩帧。一旦帧被解码,我想将当前帧与前一帧进行比较,以便将两帧之间的差异存储在“Mat”选项卡中。

所有这些的目标是能够对不同的像素进行分析并检查是否有任何拉丁字符。这让我可以减少要分析的像素数量并节省宝贵的时间。

如果有人有其他想法而不是这个想法来执行此类操作,请随时提出。

感谢您的帮助。

编辑 1: 计算机屏幕的两个高分辨率图像示例。目前,这些是我试图分析的完美例子。正如我们所见,两个大图像之间只有一个窗口,我想分析任何角色的新“挑战”窗口。

编辑 2: 我正在尝试根据分析的数据调整算法。通常在以下两张图片中,我只得到绿线作为差异,根本没有文字(这是最有趣的)。我正在尝试更好地了解事情是如何工作的。

第一张图片

第二张图片

第三张图片

如您所见,我只有那些绿线,而没有文字(在减少 countours[i].size() 时,我最多只能有一个字母)

【问题讨论】:

  • 我不确定这是否能帮助您解决问题,根据我的经验,openCV 无法处理全分辨率的视频(至少在 Windows 中 stackoverflow.com/questions/17993677/…
  • 你能贴两张图片吗?还是指向高分辨率图像的公共链接?
  • @Miki 我刚刚编辑了我的帖子
  • @Engine 我不确定您所说的“无法处理全分辨率视频”是什么意思。我对 OpenCV 很陌生,所以我可能会错过一些东西。我能够对视频的整个帧执行操作,但这对我来说太长了,因为它发现一帧和另一帧之间的差异太大。这里的目标是找到一种只对出现在屏幕上的新窗口而不是整个帧执行操作的方法。

标签: c++ opencv ocr run-length-encoding


【解决方案1】:

除了你提到的帖子,你还需要:

  • 当您对掩码进行二值化时,请使用高于 0 的阈值来消除微小差异。
  • 去除一些噪音。您可以找到所有连接的组件,并删除较小的组件。
  • 找出更大的连通分量的面积。您可以使用convexHullfillConvexPoly 来获取屏幕上不同对象的掩码
  • 使用给定的蒙版将第二张图像复制到新图像中。

结果将如下所示:

代码:

#include <opencv2/opencv.hpp>
#include <vector>
using namespace std;
using namespace cv;

int main()
{
    Mat3b img1 = imread("path_to_image_1");
    Mat3b img2 = imread("path_to_image_2");

    Mat3b diff;
    absdiff(img1, img2, diff);

    // Split each channel
    vector<Mat1b> masks;
    split(diff, masks);

    // Create a black mask
    Mat1b mask(diff.rows, diff.cols, uchar(0));

    // OR with each channel of the N channels mask
    for (int i = 0; i < masks.size(); ++i)
    {
        mask |= masks[i];
    }

    // Binarize mask
    mask = mask > 100;

    // Results images
    vector<Mat3b> difference_images;

    // Remove small blobs
    //Mat kernel = getStructuringElement(MORPH_RECT, Size(5,5));
    //morphologyEx(mask, mask, MORPH_OPEN, kernel);

    // Find connected components
    vector<vector<Point>> contours;
    findContours(mask.clone(), contours, CV_RETR_EXTERNAL, CHAIN_APPROX_NONE);

    for (int i = 0; i < contours.size(); ++i)
    {
        if (contours[i].size() > 1000)
        {
            Mat1b mm(mask.rows, mask.cols, uchar(0));

            vector<Point> hull;
            convexHull(contours[i], hull);


            fillConvexPoly(mm, hull, Scalar(255));

            Mat3b difference_img(img2.rows, img2.cols, Vec3b(0,0,0));
            img2.copyTo(difference_img, mm);

            difference_images.push_back(difference_img.clone());
        }
    }

    return 0;
}

【讨论】:

  • 这很好用,速度非常快,并且完全符合我的要求。谢谢你的帮助三木!
  • 我还有一个问题。为什么你过滤了 contour[i].size() 只保留那些有 1000 个或更多元素的人?这是一种消除帧之间每个“小”差异并只保留大匹配的方法吗? 1000 是平均数字吗?
  • @DylanAlvaro 用于删除小斑点,即周长小于 1000 的斑点。您可以使用任何其他足够大的值,或者根据图像中的一些统计数据计算它。这个 `mask = mask > 100;` 将消除两个图像之间的微小差异(
  • 您添加的图片与最初的图片大不相同,值得提出另一个问题。
猜你喜欢
  • 1970-01-01
  • 2017-08-23
  • 2011-04-07
  • 1970-01-01
  • 2016-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-20
相关资源
最近更新 更多