Opencv 用浅色斑点检测斑点

Opencv 用浅色斑点检测斑点,opencv,image-processing,emgucv,opencv3.0,Opencv,Image Processing,Emgucv,Opencv3.0,我在检测一组图像中的特定“斑点”时遇到了一些问题。并非所有的图像都是相同的,但我认为不管怎样,都会使用相同的参数进行检测。 如果你放大,你会看到叶子上有黄色的小蚜虫。我的目标是挑出这些,并计算它们。我真的不需要对图像做太多的处理,只需要获得它们的数量 现在,我有这个: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks

我在检测一组图像中的特定“斑点”时遇到了一些问题。并非所有的图像都是相同的,但我认为不管怎样,都会使用相同的参数进行检测。

如果你放大,你会看到叶子上有黄色的小蚜虫。我的目标是挑出这些,并计算它们。我真的不需要对图像做太多的处理,只需要获得它们的数量

现在,我有这个:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Emgu.CV;
using Emgu.CV.Features2D;
using Emgu.CV.Structure;
using Emgu.CV.Util;

namespace AphidCounter
{
    class Program
    {
        static void Main(string[] args)
        {
            // Read image
            Mat im_in = CvInvoke.Imread("myimage1.jpg", Emgu.CV.CvEnum.LoadImageType.Grayscale);
            //Mat im_in = CvInvoke.Imread("myimage2.png", Emgu.CV.CvEnum.LoadImageType.Color);
            Mat im = im_in;
            CvInvoke.Threshold(im_in, im, 40, 255, Emgu.CV.CvEnum.ThresholdType.BinaryInv);  // 60, 255, 1

            //CvInvoke.NamedWindow("Blob Detector", Emgu.CV.CvEnum.NamedWindowType.AutoSize);

            DetectBlobs(im, 0);

            CvInvoke.WaitKey(0);
        }

        static void DetectBlobs(Mat im, int c)
        {

            int maxT = 50;
            int minA = 125; // Minimum area in pixels
            int maxA = 550; // Maximum area in pixels

            SimpleBlobDetectorParams EMparams = new SimpleBlobDetectorParams();
            SimpleBlobDetector detector;

            EMparams.MinThreshold = 0;
            EMparams.MaxThreshold = 100;

            if (minA < 1) minA = 1;
            EMparams.FilterByArea = true;
            EMparams.MinArea = minA;
            EMparams.MaxArea = maxA;

            if (maxT < 1) maxT = 1;
            EMparams.MinConvexity = (float)maxT / 1000.0F; // 0.67

            EMparams.FilterByInertia = true;
            EMparams.MinInertiaRatio = 0.01F;

            EMparams.FilterByColor = true;
            EMparams.blobColor = 0;

            VectorOfKeyPoint keyPoints = new VectorOfKeyPoint();

            detector = new SimpleBlobDetector(EMparams);
            detector.DetectRaw(im, keyPoints);

            Mat im_with_keypoints = new Mat();
            Bgr color = new Bgr(0, 0, 255);
            Features2DToolbox.DrawKeypoints(im, keyPoints, im_with_keypoints, color, Features2DToolbox.KeypointDrawType.DrawRichKeypoints);

            // Show blobs
            CvInvoke.Imwrite("keypoints1.jpg", im_with_keypoints);
            CvInvoke.Imshow("Blob Detector " + keyPoints.Size, im_with_keypoints);

            System.Console.WriteLine("Number of keypoints: " + keyPoints.Size);

        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
使用Emgu.CV;
使用Emgu.CV.Features2D;
使用Emgu.CV.Structure;
使用Emgu.CV.Util;
名称空间计数器
{
班级计划
{
静态void Main(字符串[]参数)
{
//读取图像
Mat im_in=CvInvoke.Imread(“myimage1.jpg”,Emgu.CV.CvEnum.LoadImageType.Grayscale);
//Mat im_in=CvInvoke.Imread(“myimage2.png”,Emgu.CV.CvEnum.LoadImageType.Color);
Mat im=im_in;
CvInvoke.Threshold(im_in,im,40255,Emgu.CV.CvEnum.ThresholdType.binarynv);/60255,1
//CvInvoke.NamedWindow(“水滴检测器”,Emgu.CV.CvEnum.NamedWindowType.AutoSize);
可检测的LOBS(im,0);
CvInvoke.WaitKey(0);
}
静态空隙检测BLOBS(材料im,内部c)
{
int maxT=50;
int minA=125;//最小面积(像素)
int maxA=550;//以像素为单位的最大面积
SimpleBlobDetectorParams EMparams=新SimpleBlobDetectorParams();
simpleblob检测器;
EMparams.MinThreshold=0;
EMparams.MaxThreshold=100;
如果(minA<1)minA=1;
EMparams.FilterByArea=true;
EMparams.MinArea=minA;
EMparams.MaxArea=maxA;
如果(maxT<1)maxT=1;
EMparams.min凸度=(float)maxT/1000.0F;//0.67
EMparams.FilterByInertia=true;
EMparams.MinInertiaRatio=0.01F;
EMparams.FilterByColor=true;
EMparams.blobColor=0;
VectorOfKeyPoint keyPoints=新VectorOfKeyPoint();
检测器=新的SimpleBlobDetector(EMparams);
检测器。检测器(im,关键点);
Mat im_with_keypoints=新Mat();
Bgr颜色=新的Bgr(0,0,255);
Features2DToolbox.DrawKeypoints(im、keyPoints、im_与_keyPoints、颜色、Features2DToolbox.KeypointDrawType.DrawRichKeypoints);
//显示斑点
CvInvoke.Imwrite(“keypoints1.jpg”,im_与_keypoints);
CvInvoke.Imshow(“水滴探测器”+关键点大小,带有关键点的im);
System.Console.WriteLine(“关键点数量:“+关键点.大小”);
}
}
}
然而,结果是:


我没有得到正确的参数吗?还是我还缺少什么

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

当斑点和背景之间的对比度非常低时,基于灰度的阈值可能无法工作。然而,在本例中,160左右的阈值是可以接受的,但并不准确

我建议使用基于颜色的阈值,因为有一个不错的色差

这里是基于颜色的阈值化的C++实现。使用相同的方法过滤blob

我已将图像从转换为更好的分割

由于提供的图像太大,因此需要更多的时间来处理。因此,我裁剪了图像的一个关键部分,并调整了blob参数。所以我也提供了裁剪后的图像(755x494px)

基于颜色的阈值和斑点过滤:

代码的其余部分保持不变

参数值:

白蚁很难与蚜虫区分,因为我们没有使用颜色信息。因此,必须仔细调整
min_区域
,以排除它们

已处理的图像可在此处找到


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

请提供中间图像,如二进制图像。使用和不使用裁剪图像时,您的处理时间是多少?我的目标是动态地做这类事情(每幅图像20-45秒)。我认为会发生一个可接受的错误水平。我只希望平均水平不超过100张图片的5%-10%。正如你所看到的,蚜虫越多,错过的机会就越多。这可能是一个颜色差异问题吗?我编辑了答案以修改阈值方法。每个高清图像大约需要15-30秒。我的图像处理知识有限,否则我会尝试先进的方法,如模板匹配或前景遮罩等。还可以在阈值设置之前寻找预处理功能来增强图像,以获得更好的结果。太棒了。很抱歉耽搁了很长时间-出现了一些问题。我注意到的一件事是,它会重复计算其中的一些。我已经调整了参数,但还没有找到一个好的“中间地带”来减少它们而不失去准确性。根据大小排除已标记的位置是否可行?因此,如果它检测到一个特定大小的蚜虫,我们保存圆圈的内部区域,并检查以确保后续的命中不在这些区域内?我想知道这会让它慢多少。。。
#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;
}
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