使用OpenCV在Blob中创建矩形 [英] Creating rectangle within a blob using OpenCV

查看:89
本文介绍了使用OpenCV在Blob中创建矩形的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

输入图像:

输出图像:

我在图像中有几个彩色的斑点,我正在尝试在每种颜色的最大斑点内创建矩形(或正方形,这似乎要容易得多).我找到了

在这里,我显示了为每个斑点找到的矩形,按颜色划分.然后,您可以只取所需的矩形,每种颜色的最大矩形,或每种颜色的最大blob的矩形.

结果:

代码在这里:

  #include< opencv2/opencv.hpp>#include< algorithm>#include< set>使用命名空间std;使用命名空间cv;//https://stackoverflow.com/a/30418912/5008845矩形findMinRect(const Mat1b& src){Mat1f W(src.rows,src.cols,float(0));Mat1f H(src.rows,src.cols,float(0));矩形maxRect(0,0,0,0);float maxArea = 0.f;对于(int r = 0; r< src.rows; ++ r){对于(int c = 0; c< src.cols; ++ c){如果(src(r,c)== 0){H(r,c)= 1.f +((r> 0)≤H(r-1,c):0); H(r,c)= 1.W(r,c)= 1.f +((c> 0)≤W(r,c-1):0);}浮点数= W(r,c);对于(int h = 0; h< H(r,c); ++ h){minw = min(minw,W(r-h,c));浮动面积=(h +1)* minw;如果(面积> maxArea){maxArea =面积;maxRect = Rect(Point(c-minw + 1,r-h),Point(c +1,r + 1));}}}}返回maxRect;}struct lessVec3b{bool operator()(const Vec3b& lhs,const Vec3b& rhs){返回(lhs [0]!= rhs [0])吗?(lhs [0] <rhs [0]):((lhs [1]!= rhs [1])?(lhs [1] <rhs [1]):(lhs [2] <rhs [2]));}};int main(){//加载图片Mat3b img = imread("path_to_image");//查找独特的颜色设置< Vec3b,lessVec3b>s(img.begin(),img.end());//分割原始图像的平面向量< Mat1b>飞机split(img,飞机);对于(自动彩色:s){//创建仅具有给定颜色的像素的蒙版Mat1b mask(img.rows,img.cols,uchar(255));对于(int i = 0; i< 3; ++ i){遮罩&=;(planes [i] == color [i]);}//查找斑点向量< vector< Point>>轮廓findContours(遮罩,轮廓,RETR_EXTERNAL,CHAIN_APPROX_SIMPLE);for(int i = 0; i< contours.size(); ++ i){//为每个单个Blob创建一个蒙版Mat1b maskSingleContour(img.rows,img.cols,uchar(0));drawContours(maskSingleContour,轮廓,i,标量(255),CV_FILLED);//找到每个斑点的最小矩形矩形框= findMinRect(〜maskSingleContour);//绘制矩形标量rectColor(color [1],color [2],color [0]);矩形(img,box,rectColor,2);}}imshow("Result",img);waitKey();返回0;} 

Input Image:

Output Image:

I have several colored blobs in an image and I'm trying to create rectangles (or squares--which seems to be much easier) inside the largest blob of each color. I've found the answer to how to create a rectangle that bounds a single largest blob, but am unsure as to how to find a square that simply fits inside a blob. It doesn't have to be the largest, it just has to be larger than a certain area otherwise I just won't include it. I've also seen some work done on polygons, but nothing for amorphous shapes.

解决方案

For a single blob, the problem can be formulated as: find the largest rectangle containing only zeros in a matrix.

To find the largest axes-oriented rectangle inside a blob, you can refer to the function findMinRect in my other answer. The code is a porting in C++ of the original in Python from here.


Then the second problem is to find all blobs with the same color. This is a little tricky because your image is jpeg, and compression creates a lot artificial colors near to borders. So I created a png image (shown below), just to show that the algorithm works. It's up to you to provide an image without compression artifacts.

Then you just need to create a mask for each color, find connected components for each blob in this mask, and compute the minimum rectangle for each blob.

Initial image:

Here I show the rects found for each blob, divided by color. You can then take only the rectangles you need, either the maximum rectangle for each color, or the rectangle for the largest blob for each color.

Result:

Here the code:

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

// https://stackoverflow.com/a/30418912/5008845
Rect findMinRect(const Mat1b& src)
{
    Mat1f W(src.rows, src.cols, float(0));
    Mat1f H(src.rows, src.cols, float(0));

    Rect maxRect(0, 0, 0, 0);
    float maxArea = 0.f;

    for (int r = 0; r < src.rows; ++r)
    {
        for (int c = 0; c < src.cols; ++c)
        {
            if (src(r, c) == 0)
            {
                H(r, c) = 1.f + ((r>0) ? H(r - 1, c) : 0);
                W(r, c) = 1.f + ((c>0) ? W(r, c - 1) : 0);
            }

            float minw = W(r, c);
            for (int h = 0; h < H(r, c); ++h)
            {
                minw = min(minw, W(r - h, c));
                float area = (h + 1) * minw;
                if (area > maxArea)
                {
                    maxArea = area;
                    maxRect = Rect(Point(c - minw + 1, r - h), Point(c + 1, r + 1));
                }
            }
        }
    }

    return maxRect;
}


struct lessVec3b
{
    bool operator()(const Vec3b& lhs, const Vec3b& rhs) {
        return (lhs[0] != rhs[0]) ? (lhs[0] < rhs[0]) : ((lhs[1] != rhs[1]) ? (lhs[1] < rhs[1]) : (lhs[2] < rhs[2]));
    }
};

int main()
{
    // Load image
    Mat3b img = imread("path_to_image");

    // Find unique colors
    set<Vec3b, lessVec3b> s(img.begin(), img.end());

    // Divide planes of original image
    vector<Mat1b> planes;
    split(img, planes);
    for (auto color : s)
    {
        // Create a mask with only pixels of the given color
        Mat1b mask(img.rows, img.cols, uchar(255));
        for (int i = 0; i < 3; ++i)
        {
            mask &= (planes[i] == color[i]);
        }

        // Find blobs
        vector<vector<Point>> contours;
        findContours(mask, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

        for (int i = 0; i < contours.size(); ++i)
        {
            // Create a mask for each single blob
            Mat1b maskSingleContour(img.rows, img.cols, uchar(0));
            drawContours(maskSingleContour, contours, i, Scalar(255), CV_FILLED);

            // Find minimum rect for each blob
            Rect box = findMinRect(~maskSingleContour);

            // Draw rect
            Scalar rectColor(color[1], color[2], color[0]);
            rectangle(img, box, rectColor, 2);
        }
    }

    imshow("Result", img);
    waitKey();

    return 0;
}

这篇关于使用OpenCV在Blob中创建矩形的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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