更好的轮廓检测和质心形成的方法

问题描述 投票:0回答:1

我的任务是找到该图像中这些密集物体的轮廓。到目前为止我有这个代码:

import cv2
import numpy as np
from google.colab.patches import cv2_imshow
import imutils


first  =    cv2.imread('/content/test.png')
img = cv2.resize(first,(800,800))
mask =  np.zeros(img.shape[:2],np.uint8)


bgdModel =  np.zeros((1,65),np.float64)*255
fgdModel =  np.zeros((1,65),np.float64)*255

rect =  (134,150,660,730)
cv2.grabCut(img,mask,rect,bgdModel,fgdModel,5,
            cv2.GC_INIT_WITH_RECT)


mask2  =  np.where((mask==2)|(mask==0),0,1).astype('uint8')
img  =  img*mask2[:,:,np.newaxis]

#cv2_imshow(img) result

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#Otsu for Threshold possibly?
blur = cv2.GaussianBlur(gray, (5,5), 0) #What would be the optimal argument for the Blur?
thresh = cv2.adaptiveThreshold(blur,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY,23,1) 


# Find contours and filter using contour area
cnts, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

for contour in cnts:
  cv2.drawContours(img, [contour], 0, (0, 255, 0), 2)
  x, y, w, h = cv2.boundingRect(contour)
  cx, cy = x + w//2, y + h//2

  img = cv2.circle(img, (cx, cy), 4, (255, 255, 255), -1)

cv2_imshow(img)

此代码使用 OpenCV 的抓取算法来区分颗粒和噪声背景,然后将其传递以创建可在其中找到轮廓的自适应阈值。使用这些轮廓,找到边界矩形,然后使用它来找到每个轮廓的质心。本文中还附加的图像显示了检测和质心计算的结果(圆圈对应于图像上覆盖的质心:。但是,轮廓并不能完美地正确捕获所有这些颗粒,质心也没有正确捕获)捕获计算出的每个颗粒或轮廓的中心。

为了解决这个问题,我尝试过一些方法,即修改高斯核,但并没有带来太大的改善。我原以为质心完全位于轮廓的中间,但对于其中一些颗粒,它们位于这些颗粒的右侧或左侧,有时甚至没有出现在某些轮廓上。有些轮廓的格式也不正确,因为有些轮廓没有捕获整个颗粒,但这个问题并不是什么大问题。我可以实施哪些方法来解决此检测问题?理想情况下,我希望更准确地捕获轮廓,但我的主要目标只是更好地捕获质心,更准确的轮廓检测只是我想要追求的额外好处。

python opencv object-detection contour
1个回答
0
投票

要回答有关正确找到质心的问题,您需要使用矩,而不是边界矩形的中心。这是我在您的代码中修改的内容以及结果:

for contour in cnts:
    if 10<cv2.contourArea(contour)<10000: # filter according to area, adjust as needed
        cv2.drawContours(img, [contour], 0, (0, 255, 0), 2) # draw contour as green
        M = cv2.moments(contour) # get moments
        if M["m00"] != 0: # if it does not 0
            cX = int(M["m10"] / M["m00"]) # get x coord of centroid
            cY = int(M["m01"] / M["m00"]) # get y coord of centroid
            img = cv2.circle(img, (cX, cY), 5, (0, 0, 255), -1) # draw circle

这是根据 10 到 10000 像素的区域过滤轮廓的结果:

如您所见,质心现在更有意义了。对于那些没有意义的,它们就在原处,因为斑点没有彼此分离。需要做更多的工作来识别单个颗粒。

这里有一个问题要问你,你想要的输出是什么样的?清晰可见的闪光颗粒的轮廓和质心?还是只能从径向表面看到的?

© www.soinside.com 2019 - 2024. All rights reserved.