是否有可能找到emgucv中“斑点”区域的边缘?

我有一个像这样的图像:

原版的

我想找到这样的黑暗部分的边缘(红线是我正在寻找的):

需要

我尝试了一些方法,但都没有工作,所以我希望有一个emgu教练愿意帮助我...

方法1

  • 将图像转换为灰度
  • 消除噪音并翻转
  • 删除任何不太亮的东西
  • 获取canny和多边形
  • 代码(我知道我应该正确地处理事情,但我保持代码简短):

    var orig = new Image<Bgr, byte>(inFile);
    
    var contours = orig
        .Convert<Gray, byte>()
        .PyrDown()
        .PyrUp()
        .Not()
        .InRange(new Gray(190), new Gray(255))
        .Canny(new Gray(190), new Gray(255))
        .FindContours(CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE,
                      RETR_TYPE.CV_RETR_TREE);
    
    var output = new Image<Gray, byte>(orig.Size);    
    for (; contours != null; contours = contours.HNext)
    {
        var poly = contours.ApproxPoly(contours.Perimeter*0.05,
                                       contours.Storage);
        output.Draw(poly, new Gray(255), 1);
    }
    output.Save(outFile);
    

    这是结果:

    方法2

  • 将图像转换为灰度
  • 消除噪音并翻转
  • 删除任何不太亮的东西
  • 获取canny然后行
  • 代码为:

    var orig = new Image<Bgr, byte>(inFile);
    
    var linesegs = orig
        .Convert<Gray, byte>()
        .PyrDown()
        .PyrUp()
        .Not()
        .InRange(new Gray(190), new Gray(255))
        .Canny(new Gray(190), new Gray(255))
        .HoughLinesBinary(
            1,
            Math.PI/45.0,
            20,
            30,
            10
        )[0];
    
    var output = new Image<Gray, byte>(orig.Size);    
    foreach (var l in linesegs)
    {
        output.Draw(l, new Gray(255), 1);
    }
    output.Save(outFile);
    

    这是结果:

    笔记

    我尝试调整这两种方法的所有参数并添加平滑,但我无法获得我需要的简单边缘,因为我认为,较暗的区域不是纯色。

    我也尝试过膨胀和腐蚀,但是我必须为这些参数提供的参数非常高,以至于得不到单一的颜色,最终会出现一些灰色的东西,并且会失去准确性。


    是的,这是可能的 ,下面是你如何做到这一点:

  • 改变图像的对比度以使较亮部分消失:
  • 在这里输入图像描述

  • 然后,将其转换为HSV以在饱和通道上执行阈值操作:
  • 并执行侵蚀和扩张操作来摆脱噪音:
  • 在这一点上,你会得到你正在寻找的结果。 出于测试目的,最后我执行边界框技术来展示如何检测开始和感兴趣区域的结束:

    在这里输入图像描述

    我没有时间调整参数并做出完美的检测,但我相信你可以搞清楚。 这个答案提供了实现这一目标的路线图!

    这是我想出的C ++代码,我相信你可以将它转换为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;
    }
    
    链接地址: http://www.djcxy.com/p/79659.html

    上一篇: Is it possible to find the edge of a "spotty" region in emgucv?

    下一篇: anyway to remove algorithmically discolorations from aerial imagery