我想用图像处理来计算图像中金属棒的数量。图像都与此类似:
我想过使用霍夫圆形变换,但是杆不是精确的圆形,并且面上也有缺陷。另一个想法是使用分水岭算法。我采取了以下步骤:
灰度转换
CLAHE增强
金字塔平均移位滤镜可消除纹理和不规则
应用高斯模糊。
Otsu的Thresholding
结果:
上图是4之后,5之后
显然,我无法将此图像用于Watershed。 然后我尝试使用一个简单的阈值处理,它可以提供更好的结果,但仍然不够准确。此外,我希望计数算法独立于所使用的图像,这意味着简单的阈值处理不会。
我在网上搜索了检测圆形物体的算法,但它们似乎都依赖于分割或边缘检测。我不明白如何从这一点开始。我错过了一些基本的东西吗?
编辑:基本的预处理代码:
img = cv2.imread('testc.jpg')
img = cv2.pyrMeanShiftFiltering(img, 21, 51)
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(7,7))
cl1 = clahe.apply(img)
cl1 = cv2.GaussianBlur(cl1, (5,5), 1)
ret3,thresh = cv2.threshold(cl1,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
流域:
D = ndimage.distance_transform_edt(thresh)
localMax = peak_local_max(D, indices=False, min_distance=35,
labels=thresh)
# perform a connected component analysis on the local peaks,
# using 8-connectivity, then appy the Watershed algorithm
markers = ndimage.label(localMax, structure=np.ones((3, 3)))[0]
labels = watershed(-D, markers, mask=thresh)
print("[INFO] {} unique segments found".format(len(np.unique(labels)) - 1))
# loop over the unique labels returned by the Watershed
# algorithm
for label in np.unique(labels):
# if the label is zero, we are examining the 'background'
# so simply ignore it
if label == 0:
continue
# otherwise, allocate memory for the label region and draw
# it on the mask
mask = np.zeros(gray.shape, dtype="uint8")
mask[labels == label] = 255
# detect contours in the mask and grab the largest one
cnts = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)[-2]
c = max(cnts, key=cv2.contourArea)
# draw a circle enclosing the object
((x, y), r) = cv2.minEnclosingCircle(c)
cv2.circle(img, (int(x), int(y)), int(r), (0, 255, 0), 2)
cv2.putText(img, "#{}".format(label), (int(x) - 10, int(y)),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2)
Watershed算法代码我主要来自pyimagesearch我很抱歉没有给出链接,我当前只允许发布两个链接(和No Images)。
这不是我尝试过的唯一一件事,但目前是最好的方法。