我正尝试在所附图像中找到所有圆形颗粒。这是我唯一的图像(及其逆图像)。
我已阅读this post,但无法将hsv值用于阈值设置。我尝试使用霍夫变换。
circles = cv2.HoughCircles(img, cv2.HOUGH_GRADIENT, dp=0.01, minDist=0.1, param1=10, param2=5, minRadius=3,maxRadius=6)
并使用以下代码进行绘制
names =[circles]
for nums in names:
color_img = cv2.imread(path)
blue = (211,211,211)
for x, y, r in nums[0]:
cv2.circle(color_img, (x,y), r, blue, 1)
plt.figure(figsize=(15,15))
plt.title("Hough")
plt.imshow(color_img, cmap='gray')
以下代码用于绘制蒙版:
for masks in names:
black = np.zeros(img_gray.shape)
for x, y, r in masks[0]:
cv2.circle(black, (x,y), int(r), 255, -1) # -1 to draw filled circles
plt.imshow(black, gray)
答案 0 :(得分:1)
我的方法是基于一个简单的观察结果,即图像中的大多数粒子的周长大致相同,而“非粒子”的周长大于它们。
首先,看一下RANSAC算法以及如何找到离群值和离群值。它基本上是2D数据,但在这种情况下,我们将不得不将其转换为1D数据。
在您的情况下,我将内部值称为正确的粒子,将外部值称为错误的粒子。
我们必须处理的数据将是这些粒子的周长。要获取周长,请在此图像中找到轮廓,然后获取每个轮廓的周长。 Refer this for information about Contours。
现在,我们有了有关RANSAC算法的数据,知识以及上面提到的简单观察。现在,在这些数据中,我们必须找到最密集,最紧凑的聚类,其中将包含所有的异常值,而其他的则是异常值。
现在让我们假设离群值在40-60范围内,离群值超出60。让我们定义一个阈值T =0。我们说对于数据中的每个点,该点的离群值都在范围内(该点的值-T,该点的值+ T)。
现在,首先遍历数据中的所有点,并为T计算该点的惯性数并存储此信息。找到一个T值可能的最大内线数。现在将T的值增加1,然后再次找到该T的最大内线数。通过将T的值一个一地重复这些步骤。
将存在一个T值范围,其最大内线数相同。这些离群值就是图像中的粒子,而周长大于这些离群值的粒子就是离群值,因此图像中的“非粒子”。
我在与您相似的测试用例中尝试了该算法,并且可以正常工作。我总是能够确定异常值。我希望它也对您有用。
最后一件事,我发现您的粒子边界是不规则且不平滑的,如果此图像不适用于您,请尝试使其平滑并使用此算法。
答案 1 :(得分:1)
一种简单的方法涉及稍微腐蚀图像,以分离触摸的圆形对象,然后进行连接的分量分析并丢弃所有大于某个选定阈值的对象,最后将图像放大回去,以使圆形对象的大小近似于原始大小再次。我们可以对带标签的图像进行这种膨胀,以便保留分离的对象。
我使用DIPlib是因为我最熟悉它(我是作者)。
import diplib as dip
a = dip.ImageRead('6O0Oe.png')
a = a(0) > 127 # the PNG is a color image, but OP's image is binary,
# so we binarize here to simulate OP's condition.
separation = 7 # tweak these two parameters as necessary
size_threshold = 500
b = dip.Erosion(a, dip.SE(separation))
b = dip.Label(b, maxSize=size_threshold)
b = dip.Dilation(b, dip.SE(separation))
请注意,此处使用的图像似乎是放大的屏幕抓图,而不是OP处理的原始图像。如果是这样,则必须使参数变小以识别较小图像中的较小对象。