寻找图像中的最大斑点

时间:2016-08-19 17:40:02

标签: opencv image-processing emgucv

我在使用EmguCV从图像中提取blob时遇到了一些问题。我在网上看到的所有内容都使用Contours对象,但我想这是从EmguCV3.0中删除的?每次我尝试使用它时都会出现异常。我没有找到许多未过时的最新/相关SO主题。

基本上,我有一张叶子的照片。背景可能是白色,绿色,黑色等。我想基本上删除背景,以便我可以在叶子上执行操作而不会干扰背景。我只是不确定我在哪里出错:

enter image description here

        Image<Bgr, Byte> Original = Core.CurrentLeaf.GetImageBGR;
        Image<Gray, Byte> imgBinary = Original.Convert<Gray, Byte>();
        imgBinary.PyrDown().PyrUp(); // Smoothen a little bit
        imgBinary = imgBinary.ThresholdBinaryInv(new Gray(100), new Gray(255)); // Apply inverse suppression

        // Now, copy pixels from original image that are black in the mask, to a new Mat.  Then scan?
        Image<Gray, Byte> imgMask;
        imgMask = imgBinary.Copy(imgBinary);
        CvInvoke.cvCopy(Original, imgMask, imgBinary);

        VectorOfVectorOfPoint contoursDetected = new VectorOfVectorOfPoint();
        CvInvoke.FindContours(imgBinary, contoursDetected, null, Emgu.CV.CvEnum.RetrType.List, Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxSimple);

        var contoursArray = new List<VectorOfPoint>();
        int count = contoursDetected.Size;
        for (int i = 0; i < count; i++)
        {
            using (VectorOfPoint currContour = contoursDetected[i])
            {
                contoursArray.Add(currContour);
            }
        }

有了这个,我得到一个带有一点白线的黑色图像。我来回绞尽脑汁,无法想出一些东西。任何指针都会非常感激!

2 个答案:

答案 0 :(得分:1)

  1. 我认为您需要在每个轮廓上找到使用ContourArea的最大区域。
  2. 找到最大的轮廓后,你需要填充它(因为轮廓只是blob的底线而不是其中的所有像素)使用FillPoly并创建一个掩码,作为叶子像素值为1和一切别的用0。
  3. 最后使用蒙版从原始图像中提取叶子像素
  4. 我对c#的熟练程度不是很高,所以我用opencv在python中附加一个代码来给你一些帮助。

    结果图片: enter image description here

    希望这会有用。

    import cv2
    import numpy as np
    
    # Read image
    
    Irgb = cv2.imread('leaf.jpg')
    R,G,B = cv2.split(Irgb)
    
    # Do some denosiong on the red chnnale (The red channel gave better result than the gray because it is has more contrast
    Rfilter = cv2.bilateralFilter(R,25,25,10)
    
    # Threshold image
    ret, Ithres = cv2.threshold(Rfilter,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
    
    # Find the largest contour and extract it
    im, contours, hierarchy = cv2.findContours(Ithres,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE )
    
    maxContour = 0
    for contour in contours:
        contourSize = cv2.contourArea(contour)
        if contourSize > maxContour:
            maxContour = contourSize
            maxContourData = contour
    
    # Create a mask from the largest contour
    mask = np.zeros_like(Ithres)
    cv2.fillPoly(mask,[maxContourData],1)
    
    # Use mask to crop data from original image
    finalImage = np.zeros_like(Irgb)
    finalImage[:,:,0] = np.multiply(R,mask)
    finalImage[:,:,1] = np.multiply(G,mask)
    finalImage[:,:,2] = np.multiply(B,mask)
    cv2.imshow('final',finalImage)
    

答案 1 :(得分:-1)

我建议你看看Otsu阈值。它为您提供了一个阈值,您可以使用该阈值将图像分为两类(背景和前景)。使用OpenCV的阈值方法,您可以在必要时创建一个掩码。