提取二值图像中的最中心区域

Kat*_*ice 2 python opencv image-processing binary-image

我正在处理二进制图像,之前使用此代码来查找二进制图像中的最大区域:

# Use the hue value to convert to binary
thresh = 20
thresh, thresh_img = cv2.threshold(h, thresh, 255, cv2.THRESH_BINARY)
cv2.imshow('thresh', thresh_img)
cv2.waitKey(0) 
cv2.destroyAllWindows()                        
# Finding Contours
# Use a copy of the image since findContours alters the image

contours, _ = cv2.findContours(thresh_img.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

#Extract the largest area
c = max(contours, key=cv2.contourArea) 
Run Code Online (Sandbox Code Playgroud)

这段代码并没有真正完成我需要它做的事情,现在我认为最好提取二进制图像中最中心的区域。

二值图像 最大图像

这就是代码目前正在提取的内容,但我希望能够获得提取的第一个二进制图像中的中心圆。

Chr*_*itz 5

OpenCV 带有点多边形测试功能(用于轮廓)。如果您需要的话,它甚至可以给出带符号的距离。

我会找到最接近图片中心的轮廓。这可能是实际上与图片中心重叠的轮廓。

计时,在我的 2012 年四核上,相差一毫秒:

  • 查找轮廓:~1 毫秒
  • 所有 pointPolygonTests 和 argmax:~1 毫秒
mask = cv.imread("fkljm.png", cv.IMREAD_GRAYSCALE)
(height, width) = mask.shape
ret, mask = cv.threshold(mask, 128, 255, cv.THRESH_BINARY) # required because the sample picture isn't exactly clean
Run Code Online (Sandbox Code Playgroud)
# get contours
contours, hierarchy = cv.findContours(mask, cv.RETR_LIST | cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
Run Code Online (Sandbox Code Playgroud)
center = (np.array([width, height]) - 1) / 2

# find contour closest to center of picture
distances = [
    cv.pointPolygonTest(contour, center, True) # looking for most positive (inside); negative is outside
    for contour in contours
]
iclosest = np.argmax(distances)
print("closest contour is", iclosest, "with distance", distances[iclosest])

# draw closest contour
canvas = cv.cvtColor(mask, cv.COLOR_GRAY2BGR)
cv.drawContours(image=canvas, contours=[contours[iclosest]], contourIdx=-1, color=(0, 255, 0), thickness=5)
Run Code Online (Sandbox Code Playgroud)
closest contour is 45 with distance 65.19202405202648
Run Code Online (Sandbox Code Playgroud)

帆布


cv.floodFill()中心点上的a也可以快速在该斑点上生成标签......假设那里的掩码为正。否则,就需要进行搜索。

(cx, cy) = center.astype(int)
assert mask[cy,cx], "floodFill not applicable"

# trying cv.floodFill on the image center
mask2 = mask >> 1 # turns everything else gray
cv.floodFill(image=mask2, mask=None, seedPoint=center.astype(int), newVal=255)

# use (mask2 == 255) to identify that blob
Run Code Online (Sandbox Code Playgroud)

这也需要不到一毫秒的时间。

洪水填充


一些实际上更快的方法可能涉及金字塔方案(掩模的低分辨率版本)来快速识别作为精确测试候选者的图片区域(距离/交叉点)。

  • 测试目标像素。击中(正)?完毕。
  • 计算低分辨率掩模。对于每个块,如果任何像素为正,则块为正。
  • 找到积极的区块,按距离排序,仔细检查所有在sqrt(2) * blocksize最佳距离内的区块。