OCR 和 OpenCV:高分辨率图像上两帧之间的差异
OCR & OpenCV: Difference between two frames on high resolution images
根据这个post,我现在知道如何用OpenCV找出两幅图像之间的像素差异了。
我想改进此解决方案并将其用于内容丰富的高分辨率图像(来自视频)。上面的示例不适用于大图像,因为处理速度很慢(发现差异太大,"findCountours method" 用 250k 元素填充选项卡,这需要大量时间来处理)。
我的应用程序使用 RLE 解码器来解码视频的压缩帧。解码帧后,我想将当前帧与前一帧进行比较,以便将两个帧之间的差异存储在 "Mat" 选项卡中。
所有这一切的目标是能够对不同的像素进行分析并检查是否有任何拉丁字符。这使我能够减少要分析的像素数量并节省宝贵的时间。
如果有人有其他想法而不是这个想法来执行这样的操作,请随时提出。
感谢您的帮助。
编辑 1:
计算机屏幕的两个高分辨率图像示例。目前,这些是我正在尝试分析的完美示例。正如我们所看到的,两个大图像之间只有一个 window 差异,我想分析任何字符的新 "Challenge" window。
编辑 2:
我正在尝试根据分析的数据调整算法。通常在下面的两张图片上,我只得到绿线作为差异,根本没有文字(这是最有趣的)。我正在努力更好地理解事情是如何运作的。
第一张图片:
第二张图片:
第三张图片:
如您所见,我只有那些绿线而没有文字(在减少计数时我最多只能有一个字母[i].size())
除了你提到的post,你还需要:
- 当您对掩码进行二值化时,使用高于 0 的阈值来消除小差异。
- 移除一些噪音。您可以找到所有连接的组件,并删除较小的组件。
- 求更大连通分量的面积。您可以使用
convexHull
和 fillConvexPoly
来获取屏幕上不同对象的遮罩
- 使用给定的遮罩将第二张图像复制到新图像。
结果将如下所示:
代码:
#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;
}
根据这个post
我想改进此解决方案并将其用于内容丰富的高分辨率图像(来自视频)。上面的示例不适用于大图像,因为处理速度很慢(发现差异太大,"findCountours method" 用 250k 元素填充选项卡,这需要大量时间来处理)。
我的应用程序使用 RLE 解码器来解码视频的压缩帧。解码帧后,我想将当前帧与前一帧进行比较,以便将两个帧之间的差异存储在 "Mat" 选项卡中。
所有这一切的目标是能够对不同的像素进行分析并检查是否有任何拉丁字符。这使我能够减少要分析的像素数量并节省宝贵的时间。
如果有人有其他想法而不是这个想法来执行这样的操作,请随时提出。
感谢您的帮助。
编辑 1: 计算机屏幕的两个高分辨率图像示例。目前,这些是我正在尝试分析的完美示例。正如我们所看到的,两个大图像之间只有一个 window 差异,我想分析任何字符的新 "Challenge" window。
编辑 2: 我正在尝试根据分析的数据调整算法。通常在下面的两张图片上,我只得到绿线作为差异,根本没有文字(这是最有趣的)。我正在努力更好地理解事情是如何运作的。
第一张图片:
第二张图片:
第三张图片:
如您所见,我只有那些绿线而没有文字(在减少计数时我最多只能有一个字母[i].size())
除了你提到的post,你还需要:
- 当您对掩码进行二值化时,使用高于 0 的阈值来消除小差异。
- 移除一些噪音。您可以找到所有连接的组件,并删除较小的组件。
- 求更大连通分量的面积。您可以使用
convexHull
和fillConvexPoly
来获取屏幕上不同对象的遮罩 - 使用给定的遮罩将第二张图像复制到新图像。
结果将如下所示:
代码:
#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;
}