Group closer white pixels together and draw a rectangle around them in OpenCV

前端 未结 2 562
没有蜡笔的小新
没有蜡笔的小新 2021-01-20 00:57

I want to group these white pixels that are closer to each other and draw a rectangle around them in OpenCV using C++.

Original Image:

相关标签:
2条回答
  • 2021-01-20 01:40

    You can count integral in each row and column. Then search for places where this integral is continuously growing. Here you can also add some moving average to exclude noise etc. Then this places means that here is more white than in other parts. Now you can use rectangle function from openCV to draw rectangle around this area (http://docs.opencv.org/2.4/modules/core/doc/drawing_functions.html#rectangle).

    0 讨论(0)
  • 2021-01-20 01:45

    You can group white pixels according to a given predicate using partition. In this case, your predicate could be: group all white pixels that are within a given euclidean distance.

    You can then compute the bounding boxes for each group, keep the largest box (in RED below), and eventually enlarge it (in GREEN below):

    Code:

    #include <opencv2\opencv.hpp>
    #include <vector>
    #include <algorithm>
    
    using namespace std;
    using namespace cv;
    
    int main()
    {
        // Load the image 
        Mat3b img = imread("path_to_image", IMREAD_COLOR);
    
        // Convert to grayscale
        Mat1b gray;
        cvtColor(img, gray, COLOR_BGR2GRAY);
    
        // Get binary mask (remove jpeg artifacts)
        gray = gray > 200;
    
        // Get all non black points
        vector<Point> pts;
        findNonZero(gray, pts);
    
        // Define the radius tolerance
        int th_distance = 50; // radius tolerance
    
        // Apply partition 
        // All pixels within the radius tolerance distance will belong to the same class (same label)
        vector<int> labels;
    
        // With lambda function (require C++11)
        int th2 = th_distance * th_distance;
        int n_labels = partition(pts, labels, [th2](const Point& lhs, const Point& rhs) {
            return ((lhs.x - rhs.x)*(lhs.x - rhs.x) + (lhs.y - rhs.y)*(lhs.y - rhs.y)) < th2;
        });
    
        // You can save all points in the same class in a vector (one for each class), just like findContours
        vector<vector<Point>> contours(n_labels);
        for (int i = 0; i < pts.size(); ++i)
        {
            contours[labels[i]].push_back(pts[i]);
        }
    
        // Get bounding boxes
        vector<Rect> boxes;
        for (int i = 0; i < contours.size(); ++i)
        {
            Rect box = boundingRect(contours[i]);
            boxes.push_back(box);
        }
    
        // Get largest bounding box
        Rect largest_box = *max_element(boxes.begin(), boxes.end(), [](const Rect& lhs, const Rect& rhs) {
            return lhs.area() < rhs.area();
        });
    
        // Draw largest bounding box in RED
        Mat3b res = img.clone();
        rectangle(res, largest_box, Scalar(0, 0, 255));
    
        // Draw enlarged BOX in GREEN
        Rect enlarged_box = largest_box + Size(20,20);
        enlarged_box -= Point(10,10);
    
        rectangle(res, enlarged_box, Scalar(0, 255, 0));
    
    
        imshow("Result", res);
        waitKey();
    
        return 0;
    }
    
    0 讨论(0)
提交回复
热议问题