Is it possible to find the edge of a “spotty” region in emgucv?

前端 未结 1 1533
粉色の甜心
粉色の甜心 2021-01-02 06:29

I have an image that looks like this:

\"original\"

and I want to find the edges of the dark part so lik

相关标签:
1条回答
  • 2021-01-02 06:36

    Yes, it's possible, and here is how you could do it:

    • Change the contrast of the image to make the lighter part disappear:

    enter image description here

    • Then, convert it to HSV to perform a threshold operation on the Saturation channel:

    enter image description here

    • And execute erode & dilate operations to get rid of the noises:

    enter image description here

    At this point you'll have the result you were looking for. For testing purposes, at the end I execute the bounding box technique to show how to detect the beggining and the end of the area of interest:

    enter image description here

    I didn't have the time to tweak the parameters and make a perfect detection, but I'm sure you can figure it out. This answer provides a roadmap for achieving that!

    This is the C++ code I came up with, I trust you are capable of converting it to C#:

    #include <cv.h>
    #include <highgui.h>
    
    int main(int argc, char* argv[])
    {
        cv::Mat image = cv::imread(argv[1]);
        cv::Mat new_image = cv::Mat::zeros(image.size(), image.type());
    
        /* Change contrast: new_image(i,j) = alpha*image(i,j) + beta */
    
        double alpha = 1.8;     // [1.0-3.0]
        int beta = 100;         // [0-100]
        for (int y = 0; y < image.rows; y++)
        { 
            for (int x = 0; x < image.cols; x++)
            { 
            for (int c = 0; c < 3; c++)
            {
                new_image.at<cv::Vec3b>(y,x)[c] = 
                cv::saturate_cast<uchar>(alpha * (image.at<cv::Vec3b>(y,x)[c]) + beta);
            }
            }
        }
        cv::imshow("contrast", new_image);
    
        /* Convert RGB Mat into HSV color space */
    
        cv::Mat hsv;
        cv::cvtColor(new_image, hsv, CV_BGR2HSV);
        std::vector<cv::Mat> v;
        cv::split(hsv,v);
    
        // Perform threshold on the S channel of hSv    
        int thres = 15;
        cv::threshold(v[1], v[1], thres, 255, cv::THRESH_BINARY_INV);
        cv::imshow("saturation", v[1]);
    
        /* Erode & Dilate */
    
        int erosion_size = 6;   
        cv::Mat element = cv::getStructuringElement(cv::MORPH_CROSS,
                              cv::Size(2 * erosion_size + 1, 2 * erosion_size + 1), 
                              cv::Point(erosion_size, erosion_size) );
        cv::erode(v[1], v[1], element);
        cv::dilate(v[1], v[1], element);    
        cv::imshow("binary", v[1]);
    
        /* Bounding box */
    
        // Invert colors
        cv::bitwise_not(v[1], v[1]);
    
        // Store the set of points in the image before assembling the bounding box
        std::vector<cv::Point> points;
        cv::Mat_<uchar>::iterator it = v[1].begin<uchar>();
        cv::Mat_<uchar>::iterator end = v[1].end<uchar>();
        for (; it != end; ++it)
        {
            if (*it) points.push_back(it.pos());
        }    
    
        // Compute minimal bounding box
        cv::RotatedRect box = cv::minAreaRect(cv::Mat(points));
    
        // Draw bounding box in the original image (debug purposes)
        cv::Point2f vertices[4];
        box.points(vertices);
        for (int i = 0; i < 4; ++i)
        {
            cv::line(image, vertices[i], vertices[(i + 1) % 4], cv::Scalar(0, 255, 0), 2, CV_AA);
        }
    
        cv::imshow("box", image);    
        cvWaitKey(0);
    
        return 0;
    }
    
    0 讨论(0)
提交回复
热议问题