python - 查找黑色轮廓之间的区域
问题描述
我有一个白色的轮廓,里面和周围都是黑色的。我需要找到最大的圆圈,里面只有白色区域,没有洞,不包含轮廓外部的黑色区域。目前,我找不到这样做的好方法。我在 Python 中使用 openCv 和 Numpy。当然,如果需要任何其他图书馆,我想听听。
##更新##
起初,我尝试使用这段代码,但它给了我最大的圆圈,而不考虑其中的漏洞:
def get_biggest_area_inside_contour(self,image,index):
image_bin=cv2.cvtColor(image,cv2.COLOR_RGB2GRAY)
retval,image_bin=cv2.threshold(image_bin,biggest_circle_thresh,255,cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(image_bin.copy(),cv2.RETR_CCOMP,cv2.CHAIN_APPROX_SIMPLE)
image_with_contour=np.zeros(image.shape, np.uint8)
dist=np.zeros((image.shape[0],image.shape[1]))
for ind_y in range(image.shape[0]):
for ind_x in range(image.shape[1]):
dist[ind_y,ind_x] = cv2.pointPolygonTest(max_contour,(ind_x,ind_y),True)
正如对我的回答,这个问题有一个解决方案。问题是我没有设法将代码从 MATLAB 传递给 python。代码是:
def get_biggest_area_inside_contour(self,image,index):
image_bin=cv2.cvtColor(image,cv2.COLOR_RGB2GRAY)
_,image_bin=cv2.threshold(image_bin,biggest_circle_thresh,255,cv2.THRESH_BINARY)
contours, _ = cv2.findContours(image_bin.copy(),cv2.RETR_CCOMP,cv2.CHAIN_APPROX_SIMPLE)
max_contour=contours[0]
max_area=cv2.contourArea(contours[0])
#Find the biggest white contour, some times can be little white surrond by black area
for _cnt in contours:
_area = cv2.contourArea(_cnt)
if _area>max_area:
max_area=_area
max_contour=_cnt
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
_blurred = cv2.GaussianBlur(gray, (5, 5), 0)
_threshold = cv2.threshold(_blurred, biggest_circle_thresh, 255, cv2.THRESH_BINARY)[1]
result_img=cv2.drawContours(_threshold,max_contour,-1,(255,255,255),1)
contours, _ = cv2.findContours(result_img.copy(),cv2.RETR_CCOMP,cv2.CHAIN_APPROX_SIMPLE)
#cv2.namedWindow('img {}'.format(index), cv2.WINDOW_NORMAL)
#cv2.imshow('img {}'.format(index), result_img)
apdp = cv2.approxPolyDP(max_contour,1,True)
ap = [(a[0][0],a[0][1]) for a in apdp]
vor_ap = Voronoi(ap,incremental=True)
spined = []
for ridge in contours:
x, y, w, h = cv2.boundingRect(ridge)
if cv2.pointPolygonTest(max_contour,(x,y),True) < 0.0 or cv2.pointPolygonTest(max_contour,(x+w,y+h),True) < 0.0:
continue
else:
if tuple((x,y)) not in spined:
spined.append([tuple((x,y))])
if tuple((x+w,y)) not in spined:
spined.append([tuple((x+w,y))])
if tuple((x,y+h)) not in spined:
spined.append([tuple((x,y+h))])
if tuple((x+w,y+h)) not in spined:
spined.append([tuple((x+w,y+h))])
if len(spined)>0:
for index in range(0,len(spined)):
vor_ap.add_points(spined[index])
fig=plt.figure(index)
ax = fig.add_subplot(111)
voronoi_plot_2d(vor_ap, point_size=5, ax=ax)
plt.scatter([s[0][0] for s in spined],[s[0][1] for s in spined])
plt.plot([a[1] for a in ap],[a[0] for a in ap])
if len(spined)>0:
borders_and_holes=ap
for i in range (0,len(spined)):
borders_and_holes.append(spined[i])
points=np.vstack(borders_and_holes)
dt = Delaunay(points)
##cc = compute_triangle_circumcenters(dt.points, dt.simplices) Not sure how to do this
#plt.plot(cc[:, 0], cc[:, 1], ".k")
plt.show()
解决方案
您可以进行距离变换(在 OpenCV 中)。
反转图片,使边缘为白色(真),中心为黑色(假)。您可能需要对图像进行阈值处理,也许要去除中间的污迹。
应用 L2 距离(欧几里得)的距离变换。
找到最高峰 ( minMaxLoc
)。
最高峰是你的圆心,它的值是半径。
推荐阅读
- winapi - 文件系统 WinAPI 与 std::filestystem
- google-cloud-speech - 通过 Google Cloud Speech-to-Text 转换后如何获得一段音频
- ios - 如何为 AppDelegate 中的所有视图控制器独立更改左右栏按钮项文本属性?
- scala - Spark Scala Dataframe 如何使用两个或多个现有列创建新列
- javascript - 加法赋值 += 表达式中的行为
- php - 来自php的firebase云消息传递是否需要https服务器?
- visual-studio-2017 - .targets 文件在哪里,以及 .net 核心是否支持
- x11 - 如何从 xcb_atom_t 中获取字符串?
- node.js - Express Static 找不到以主题标签开头的文件
- android - 我想使用firebase数据库在webview中添加html文件我该如何添加