使用OpenCV检测在背景图像上绘制的矩形 [英] Detect rectangles drawn on an background image using OpenCV

查看:56
本文介绍了使用OpenCV检测在背景图像上绘制的矩形的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试检测绘制在图像上的一些矩形(白色).(例如使用绘画或其他图像编辑工具).由于我是图像处理的初学者,因此我通过网络和OpenCV示例程序进行搜索以完成这项工作,但无法使其正常运行.我正在使用OpenCV C ++库.

I’m trying to detect some rectangles (white colored) which is drawn on an image. (say using paint or some other image editing tool). As I’m very much beginner to image processing I searched through net and OpenCV sample program to accomplish the job, but could not get it to working perfectly. I’m using OpenCV C++ library.

我尝试过的算法

cv::Mat src = cv::imread(argv[1]);
cv::Mat gray;
cv::cvtColor(src, gray, CV_BGR2GRAY);
meanStdDev(gray, mu, sigma);
cv::Mat bw;
cv::Canny(gray, bw, mu.val[0] - sigma.val[0], mu.val[0] + sigma.val[0]);
std::vector<std::vector<cv::Point> > contours;
cv::findContours(bw.clone(), contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);

std::vector<cv::Point> approx;
for (int i = 0; i < contours.size(); i++){
cv::approxPolyDP(cv::Mat(contours[i]), approx, cv::arcLength(cv::Mat(contours[i]), true)*0.02, true);
if (approx.size() >= 4 && approx.size() <= 6)
Rect boundRect = boundingRect( Mat(approx) );
rectangle( dst, boundRect.tl(), boundRect.br(), Scalar(255,255,255), 1, 8, 0 );}

仅检测到一个矩形.能否请您指导我或提供一些相同的链接.

Only one rectangle is detected. Can you please guide me or some link for the same.

输入图片:

输出图像:

推荐答案

我无法编译您的代码示例,因为在if块中声明了boundRect,但是矩形绘图(尝试访问boundRect)在if块之外,所以我调整了您的代码:

I could not compile your code sample because there boundRect is declared within the if-block but rectangle drawing (trying to access boundRect) is outside of the if-block, so I adjusted your code:

int main(int argc, char* argv[])
{
    cv::Mat src = cv::imread("C:/StackOverflow/Input/rectangles.png");
    cv::Mat dst = src.clone();

    cv::Mat gray;
    cv::cvtColor(src, gray, CV_BGR2GRAY);

    // ADDED: missing declaration of mu and sigma
    cv::Scalar mu, sigma;
    meanStdDev(gray, mu, sigma);
    cv::Mat bw;
    cv::Canny(gray, bw, mu.val[0] - sigma.val[0], mu.val[0] + sigma.val[0]);

    // ADDED: displaying the canny output
    cv::imshow("canny", bw);


    std::vector<std::vector<cv::Point> > contours;
    cv::findContours(bw.clone(), contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);

    std::vector<cv::Point> approx;
    for (int i = 0; i < contours.size(); i++){
        cv::approxPolyDP(cv::Mat(contours[i]), approx, cv::arcLength(cv::Mat(contours[i]), true)*0.02, true);
        if (approx.size() >= 4 && approx.size() <= 6)
        {
            // ADDED: brackets around both lines belonging to the if-block
            cv::Rect boundRect = cv::boundingRect(cv::Mat(approx));
            cv::rectangle(dst, boundRect.tl(), boundRect.br(), cv::Scalar(255, 255, 255), 3, 8, 0);
        }

    }

    // ADDED: displaying input and results
    cv::imshow("input", src);
    cv::imshow("dst", dst);
    cv::imwrite("C:/StackOverflow/Output/rectangles.png", dst);
    cv::waitKey(0);
    return 0;
}

使用您的输入图像,我会得到以下输出:

with your input image I do get this output:

这可能不是您所期望的.看到canny输出图像(查看中间结果以进行视觉调试总是很好!),图像中结构太多,轮廓将覆盖所有这些结构,因此有些近似于多项式具有4到6个元素.

which is probably not what you expected. See the canny output image (it is always good to have a look at intermediate results for visual debugging!), there are just too many structures in the image and contours will cover all of these, so there are some that will be approximated to polynomes with 4 to 6 elements.

相反,您必须变得更加聪明.您可以尝试使用cv :: HoughLinesP提取直线并将其连接起来.或者,您可以尝试通过查找白色区域(如果矩形始终为白色)来对图像进行分割.

Instead you'll have to become a bit smarter. You could try to extract straight lines with cv::HoughLinesP and connect those lines. Or you could try to segment the image first by finding white areas (if your rectangles are always white).

int main(int argc, char* argv[])
{
    cv::Mat src = cv::imread("C:/StackOverflow/Input/rectangles.png");
    cv::Mat dst = src.clone();

    cv::Mat gray;
    cv::cvtColor(src, gray, CV_BGR2GRAY);

    cv::Mat mask;
    // find "white" pixel
    cv::inRange(src, cv::Scalar(230, 230, 230), cv::Scalar(255, 255, 255), mask);
    cv::imshow("mask", mask);

    std::vector<std::vector<cv::Point> > contours;
    cv::findContours(mask, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);

    std::vector<cv::Point> approx;
    for (int i = 0; i < contours.size(); i++){
        cv::approxPolyDP(cv::Mat(contours[i]), approx, cv::arcLength(cv::Mat(contours[i]), true)*0.02, true);
        if (approx.size() >= 4 && approx.size() <= 6)
        {
            cv::Rect boundRect = cv::boundingRect(cv::Mat(approx));
            cv::rectangle(dst, boundRect.tl(), boundRect.br(), cv::Scalar(255, 255, 255), 1, 8, 0);
        }
    }


    cv::imshow("input", src);
    cv::imshow("dst", dst);
    cv::imwrite("C:/StackOverflow/Output/rectangles2.png", dst);
    cv::waitKey(0);
    return 0;
}

给出以下结果:

如您所见,白色附近还有其他明亮的区域.多项式逼近也无济于事.

As you can see, there are other bright regions near white, too. The polynom approximation does not help much, too.

这篇关于使用OpenCV检测在背景图像上绘制的矩形的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆