使用浅色斑点进行斑点检测

时间:2016-02-24 02:39:11

标签: opencv image-processing emgucv opencv3.0

我在检测特定" blob"时遇到了一些问题。在一组图像中。并非所有图像都相同,但我认为无论如何都会使用相同的参数进行检测。 Image1

如果你放大,你会在叶子上看到小的黄色蚜虫。我的目标是将这些单独列出并计算它们。我不需要对图像做很多事情,只需要计算它们。

现在,我有这个:

{{1}}

然而,这是结果: Image2

我没有得到正确的参数吗?或者还有其他我想念的东西?

1 个答案:

答案 0 :(得分:3)

这不是因为一些错误的参数。图像分割部分本身有其局限性。

当斑点和背景之间的对比度非常低时,基于灰度的阈值处理可能不起作用。然而,在这个例子中,160左右的阈值是可以容忍的,但不是很准确。

我建议采用基于颜色的阈值处理,因为它有一个不错的色差。

这是基于颜色的阈值处理的C ++实现。 Blob使用相同的SimpleBlobDetector进行过滤。

我已将图片从RGB to ‘Lab’转换为更好的细分。

由于提供的图像太大,需要更多时间来处理。所以我裁剪了图像的关键部分并调整了斑点参数。所以我也提供了裁剪图像(755 x 494像素)。

leaf_cropped

基于颜色的阈值处理和blob过滤:

#include "opencv2\imgproc\imgproc.hpp";
#include "opencv2\highgui\highgui.hpp";
#include "opencv2\features2d\features2d.hpp";

using namespace cv;
using namespace std;

void main()
{
    char image_path[] = "E:/Coding/media/images/leaf_small.jpg";
    Mat img_color, img_lab, img_thresh, img_open, img_close, img_keypoints;

    img_color = imread(image_path, IMREAD_ANYCOLOR);

    //Convert image to CIE Lab colorspace for better colour based segmentation
    cvtColor(img_color, img_lab, CV_BGR2Lab);

    //create window before creating trackbar
    namedWindow("win_thresh", WINDOW_NORMAL);
    namedWindow("win_blob", WINDOW_NORMAL);

    //Using trackbar calculate the range of L,a,b values to seperate blobs
    int low_L = 150, low_A = 0, low_B = 155,
        high_L = 255, high_A = 255, high_B = 255;

    //*Use trackbars to caliberate colour thresholding
    createTrackbar("low_L", "win_thresh", &low_L, 255);
    createTrackbar("low_A", "win_thresh", &low_A, 255);
    createTrackbar("low_B", "win_thresh", &low_B, 255);
    createTrackbar("high_L", "win_thresh", &high_L, 255);
    createTrackbar("high_A", "win_thresh", &high_A, 255);
    createTrackbar("high_B", "win_thresh", &high_B, 255);

    int minArea = 35, maxArea = 172, minCircularity = 58, minConvexity = 87, minInertiaRatio = 21;

    //Use trackbar and set Blob detector parameters
    createTrackbar("minArea", "win_blob", &minArea, 200);
    createTrackbar("maxArea", "win_blob", &maxArea, 200);
    createTrackbar("minCircular", "win_blob", &minCircularity, 99);
    createTrackbar("minConvex", "win_blob", &minConvexity, 99);
    createTrackbar("minInertia", "win_blob", &minInertiaRatio, 99);

    SimpleBlobDetector::Params params;
    vector<KeyPoint> keypoints;

    while (waitKey(1) != 27) //press 'esc' to quit
    {
        //inRange thresholds basedon the Scalar boundaries provided
        inRange(img_lab, Scalar(low_L, low_A, low_B), Scalar(high_L, high_A, high_B), img_thresh);

        //Morphological filling
        Mat strucElement = getStructuringElement(CV_SHAPE_ELLIPSE, Size(5, 5), Point(2, 2));
        morphologyEx(img_thresh, img_close, MORPH_CLOSE, strucElement);

        imshow("win_thresh", img_close);

        //**SimpleBlobDetector works only in inverted binary images
        //i.e.blobs should be in black and background in white.
        bitwise_not(img_close, img_close); // inverts matrix

        //Code crashes if minArea or any miin value is set to zero
        //since trackbar starts from 0, it is adjusted here by adding 1
        params.filterByArea = true;
        params.minArea = minArea + 1;
        params.maxArea = maxArea + 1;

        params.filterByCircularity = true;
        params.filterByConvexity = true;
        params.filterByInertia = true;

        params.minCircularity = (minCircularity + 1) / 100.0;
        params.minConvexity = (minConvexity + 1) / 100.0;
        params.minInertiaRatio = (minInertiaRatio + 1) / 100.0;

        SimpleBlobDetector detector(params);
        detector.detect(img_close, keypoints);
        drawKeypoints(img_color, keypoints, img_keypoints, Scalar(0, 0, 255), DrawMatchesFlags::DEFAULT);

        stringstream displayText;
        displayText = stringstream();
        displayText << "Blob_count: " << keypoints.size();
        putText(img_keypoints, displayText.str(), Point(0, 50), CV_FONT_HERSHEY_PLAIN, 2, Scalar(0, 0, 255), 2);

        imshow("win_blob", img_keypoints);
    }
    return;
}

输出截图

output screenshot

根据实际高清图像调整blob参数。

由于叶子的叶脉几乎与蚜虫的颜色和强度相同,当蚜虫靠近或正好位于静脉顶部时,这种方法也可能完全失败。

这可以是临时修复,但不够健壮。 必须有一种简单而强大的方法来实现结果,使用一些滤波器,变换或边缘检测。如果可用,请分享任何其他最佳解决方案。

编辑:选择以前方法失败的灰度阈值

this_image

的颜色阈值处理方法失败

基于颜色的阈值处理具有非常窄的带宽,如果图像落在带宽内,则精度将非常好,另一方面,颜色偏移完全破坏了准确性。 由于您将处理100个图像,因此颜色阈值可能不合适。

我尝试了正常的灰度阈值处理,并进行了一些形态学侵蚀和填充,并获得了不错的准确度。灰度阈值处理也具有更好的色彩偏移能力。

此外,我们使用OTSU Thresholding自动保留选项,根据图像选择阈值。

代码段:

threshold(img_gray, img_thresh, 0, 255, THRESH_OTSU);

Mat strucElement = getStructuringElement(CV_SHAPE_ELLIPSE, Size(3, 3), Point(1, 1));
morphologyEx(img_thresh, img_open, MORPH_OPEN, strucElement);

其余代码保持不变。

参数值:

minArea = 75, maxArea = 1000, minCircularity = 50, minConvexity = 20, minInertiaRatio = 15

由于我们没有使用颜色信息,白蚂蚁很难与蚜虫区分开来。因此,必须仔细调整min_area以排除它们。

可以在img_1img_2找到已处理的图片。

调整形态学方法和blob参数以获得最佳平均计数。