从静态图像中减去背景

时间:2015-11-24 17:46:07

标签: c++ opencv image-processing

我有像国际象棋一样的棋盘游戏。我从鸟的角度拍摄了2张照片,如:

enter image description here

图像的每个角都有一个标记 1 ,这有助于我扭曲2张图片,这样即使它们可能是从略微不同的视角拍摄的,它们之后看起来大部分相同。

这些图像中的一个将所有棋盘游戏数字放在某个位置,而另一个图像/图片则没有。

现在我在新图像中使用标记作为我的新角落并扭曲两张图片后,我想只得到棋盘游戏的数字(所以基本上在经线之后,我想要有两张图片的区别) 。

我现在的问题是,简单的mat1-mat2cv::substract无法正常工作,因为它是精确的方式,如果这些图片的翘曲不是100%完美的结果根本没有帮助。

我想建立一个阵列,包括棋盘游戏人物的位置,这意味着如果我的想法能够奏效,我可能会更容易找到数字。 实现这一目标的正确方法是什么?在这种情况下,背景减法甚至是正确的做法吗?

(请注意,我不想将我的棋盘游戏数字与标记交换。角落上的标记对我来说已经是妥协。

1 我期待着使用Aruco这个,如果你建议一个替代方案我也可以试试。

2 个答案:

答案 0 :(得分:2)

你应该看看Image Registration

我改编了OpenCV samples

中的以下代码

给出棋盘的两个不同图像(这里我拍摄了原始图像并略微扭曲)

enter image description here enter image description here

您可以注册,将其作为结果图像获取:

enter image description here

这两者之间存在差异:

enter image description here

你可以看到棋盘对齐得很好。注册已经处理了不同的观点。

代码:

#include <opencv2\opencv.hpp>
#include <opencv2\reg\mappergradproj.hpp>
#include <opencv2\reg\mapperpyramid.hpp>
#include <opencv2\reg\mapprojec.hpp>

using namespace cv;
using namespace cv::reg;

int main(int, char**)
{
    Mat img1 = imread("D:\\SO\\temp\\chess.JPG");
    Mat img2 = imread("D:\\SO\\temp\\chess2.png");

    img1.convertTo(img1, CV_64FC3);
    img2.convertTo(img2, CV_64FC3);

    MapperGradProj mapper;
    MapperPyramid mappPyr(mapper);

    Ptr<Map> mapPtr;
    mappPyr.calculate(img1, img2, mapPtr);

    Mat dest;
    MapProjec* mapProj = dynamic_cast<MapProjec*>(mapPtr.get());
    mapProj->normalize();
    mapProj->inverseWarp(img2, dest);

    // Show difference

    Mat image1, image2;
    img1.convertTo(image1, CV_32FC3);
    img2.convertTo(image2, CV_32FC3);

    cvtColor(image1, image1, CV_RGB2GRAY);
    cvtColor(image2, image2, CV_RGB2GRAY);

    Mat imgDiff;
    img1.copyTo(imgDiff);
    imgDiff -= img2;
    imgDiff /= 2.f;
    imgDiff += 128.f;

    Mat imgSh;
    imgDiff.convertTo(imgSh, CV_8UC3);
    imshow("Diff", imgSh);

    dest.convertTo(dest, CV_8UC3);
    imshow("Dest", dest);
    waitKey();

    return 0;
}

答案 1 :(得分:1)

嗯,我不是一个专家,但我建议你使用exacly cv:subtract。这是精确的,但我相信最大的区别在于碎片的位置(最大的斑点)。 要过滤最终的有害噪声,可以在结果上使用一些过滤器(cv :: bilateralFilter等)。或者,您可以尝试查看图像中的差异,例如在10x10窗口中查看结果(窗口大小必须根据图像分辨率而变化)。

这是一个关于smothing图像的链接,可能会帮助您使用cv :: subtract来获得您想要的内容: http://docs.opencv.org/2.4/doc/tutorials/imgproc/gausian_median_blur_bilateral_filter/gausian_median_blur_bilateral_filter.html

此链接可能会帮助您了解有关运动检测的更多信息(基本上就是您想要的,以获得碎片运动,对吧?) https://www.cs.rochester.edu/~nelson/research/motion/motion.html