【问题标题】:OpenCv subtract same image but from different sourcesOpenCv 减去相同的图像但来自不同的来源
【发布时间】:2015-06-02 06:37:16
【问题描述】:

我需要减去两个图像:

  1. img1是原图作为objectObject Image (img1)
  2. img2 被点击使用相机充当场景Scene Image (img2)
  3. 结果图像:drive.google.com/open?id=0B0IUdCi6RzGcRENDSEdoa3dRN2c&authuser=0 (我不能添加两个以上的链接)

在调用减法之前执行以下步骤:

  1. 对象图像(img1)使用findHomographyperspectiveTransform方法定位到场景图像(img2)中。

  2. 使用getPerspectiveTransformwarpPerspective 方法修复透视图

然后调用subtract 方法,但输出图像包含应该被减去的线条/轮廓。

根据我的观察,这可能是由于一张图像中存在噪点,它看起来不像 img1 那样锐利,我尝试在锐化后调用减法,但它不起作用。

欢迎任何建议/指导

【问题讨论】:

  • 您可以发布示例结果图像吗?并采样具有透视效果的输入图像
  • 输入图像链接在问题中,因为我现在只能添加两个链接,这是结果图像的链接:drive.google.com/…
  • 是照片吗?看起来像模板 imagw 和修改后的模板图像。对不起。
  • 看起来对齐不够好和/或清晰度不够。我的建议:在减去模板图像之前使用二值图像(阈值)扩大模板图像。

标签: image opencv computer-vision subtraction


【解决方案1】:

要消除不清晰的伪影和稍微不完美的对齐问题,您可以尝试仅扩大模板图像。但是你会丢失一些输入信息。

如果您想“做得更好”,我建议您尝试在输入图像中找到模板图像的每个轮廓(例如,具有活动轮廓)。剩下的一切都应该是用户输入。

但这里是带有膨胀的简单版本:

输入:

输入掩码图像:

膨胀后的模板蒙版图像:

差异图片:input - template

请注意,我不使用任何透视校正,这可能会或可能不会改善结果!

int main()
{
    // edited image:
    cv::Mat input = cv::imread("../inputData/earth-science-worksheet-edited.png");
    cv::Mat grayInput;
    cv::cvtColor(input,grayInput,CV_BGR2GRAY);
    cv::Mat maskInput = grayInput < 150; // find everything that isn't "white" on your sheet of paper


    // template image:
    cv::Mat templateImage = cv::imread("../inputData/earth-science-worksheet-printable.png");
    cv::Mat grayTemplate;
    cv::cvtColor(templateImage,grayTemplate,CV_BGR2GRAY);
    cv::Mat maskTemplate = grayTemplate < 150; // find everything that isn't "white" on your sheet of paper

    // dilate the template image to overcome sharpness effects and imperfect alignment
    cv::dilate(maskTemplate, maskTemplate, cv::Mat(), cv::Point(-1,-1),1);

    // compute the difference image
    cv::Mat difference = maskInput - maskTemplate;


    cv::imshow("input", input);

    cv::imshow("mask template", maskTemplate);
    cv::imshow("mask input", maskInput);

    cv::imshow("difference", difference);

    cv::waitKey(0);
    return 0;
}

如果更改为cv::dilate(maskTemplate, maskTemplate, cv::Mat(), cv::Point(-1,-1),2);,您会丢失更多的“输入”,但会移除其他噪声像素。

【讨论】:

  • 非常感谢。我确实在 C++ 中尝试过,它工作得很好,但我将用 Java 编写我的应用程序,我有一个查询:cv::Mat maskTemplate = grayTemplate
  • 不,它会创建一个与grayTemplate 相同大小的新图像,并将在`grayTemplate 中小于150 的每个像素设置为255(所有其他像素为0)。这是一种简单的阈值处理,可以在原始图像中找到您的黑线(轮廓和用户输入)(因为您的背景 = 纸张是白色的)。因此该值不会被复制,而是设置为 0 或 255。
  • 请告诉我“grayTemplate
  • 它是 compare docs.opencv.org/modules/core/doc/… 但我不知道 cmpop 的 int 值,您必须用于 java 调用......这些运算符真的没有在 java 中重载吗API?
  • 如果您选择正确的参数,您可以改用cv::threshold btw。这也可能会给你一些适应性。