gpt4 book ai didi

python - 如何填充空心线opencv

转载 作者:行者123 更新时间:2023-12-05 08:15:16 24 4
gpt4 key购买 nike

我有这样一张图片: enter image description here

在我应用了一些处理之后,例如cv2.Canny(),现在看起来像这样: enter image description here

如您所见,黑线变成了空心的。我试过腐 eclipse 和膨胀,但如果我多次这样做,2个入口将被关闭(意味着成为连接线或闭合轮廓)。

我怎样才能使这些线像下图一样实心,同时不影响 2 个入口?

enter image description here


更新 1

我已经用几张照片测试了以下答案,但代码似乎是定制的,只能处理这一张特定的图片。由于SOF的限制,我不能上传大于2MB的照片,所以我上传到我的Microsoft OneDrive文件夹中,方便大家测试。

https://1drv.ms/u/s!Asflam6BEzhjgbIhgkL4rt1NLSjsZg?e=OXXKBK

更新 2

我选择了@fmw42 的帖子作为答案,因为他的答案是最详细的。它没有回答我的问题,但指出了处理迷宫的正确方法,这是我的最终目标。我喜欢他的回答问题的方式,首先告诉你每一步应该做什么,让你清楚地知道如何完成任务,然后提供从头到尾的完整代码示例。很有帮助。

由于SOF的限制,我只能挑一个答案。如果允许多个答案,我也会选择 Shamshirsaz.Navid 的答案。他的回答不仅指明了解决问题的正确方向,而且可视化的解释对我来说真的很管用~!我想它对所有试图理解为什么需要每一行代码的人都同样有效。他还在评论中跟进了我的问题,这让 SOF 有点互动:)

Ann Zen 的答案中的 Threshold track bar 也是一个非常有用的提示,可以帮助人们快速找出最佳值。

最佳答案

这是一种在 Python/OpenCV 中处理迷宫并纠正它的方法。

  • 阅读输入
  • 转换为灰色
  • 阈值
  • 使用 morphology close 去除最细的(无关的)黑线
  • 反转阈值
  • 获取外部轮廓
  • 保留那些大于输入宽度和高度 1/4 的轮廓
  • 将这些轮廓画成黑色背景上的白线
  • 从白色轮廓线图像中获取凸包
  • 将凸包画成黑底白线
  • 使用 GoodFeaturesToTrack 从白色船体线图像中获取 4 个角
  • 按相对于质心的角度对 4 个角进行排序,以便它们按顺时针顺序排列:左上角、右上角、右下角、左下角
  • 将这些点设置为输入的共轭控制点数组
  • 使用输入维度的 1/2 来定义输出的共轭控制点数组
  • 计算透视变换矩阵
  • 使用透视矩阵扭曲输入图像
  • 保存结果

输入:

enter image description here

import cv2
import numpy as np
import math

# load image
img = cv2.imread('maze.jpg')
hh, ww = img.shape[:2]

# convert to gray
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# threshold
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]

# use morphology to remove the thin lines
kernel = cv2.getStructuringElement(cv2.MORPH_RECT , (5,1))
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)

# invert so that lines are white so that we can get contours for them
thresh_inv = 255 - thresh

# get external contours
contours = cv2.findContours(thresh_inv, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]

# keep contours whose bounding boxes are greater than 1/4 in each dimension
# draw them as white on black background
contour = np.zeros((hh,ww), dtype=np.uint8)
for cntr in contours:
x,y,w,h = cv2.boundingRect(cntr)
if w > ww/4 and h > hh/4:
cv2.drawContours(contour, [cntr], 0, 255, 1)

# get convex hull from contour image white pixels
points = np.column_stack(np.where(contour.transpose() > 0))
hull_pts = cv2.convexHull(points)

# draw hull on copy of input and on black background
hull = img.copy()
cv2.drawContours(hull, [hull_pts], 0, (0,255,0), 2)
hull2 = np.zeros((hh,ww), dtype=np.uint8)
cv2.drawContours(hull2, [hull_pts], 0, 255, 2)

# get 4 corners from white hull points on black background
num = 4
quality = 0.001
mindist = max(ww,hh) // 4
corners = cv2.goodFeaturesToTrack(hull2, num, quality, mindist)
corners = np.int0(corners)
for corner in corners:
px,py = corner.ravel()
cv2.circle(hull, (px,py), 5, (0,0,255), -1)

# get angles to each corner relative to centroid and store with x,y values in list
# angles are clockwise between -180 and +180 with zero along positive X axis (to right)
corner_info = []
center = np.mean(corners, axis=0)
centx = center.ravel()[0]
centy = center.ravel()[1]
for corner in corners:
px,py = corner.ravel()
dx = px - centx
dy = py - centy
angle = (180/math.pi) * math.atan2(dy,dx)
corner_info.append([px,py,angle])

# function to define sort key as element 2 (i.e. angle)
def takeThird(elem):
return elem[2]

# sort corner_info on angle so result will be TL, TR, BR, BL order
corner_info.sort(key=takeThird)

# make conjugate control points
# get input points from corners
corner_list = []
for x, y, angle in corner_info:
corner_list.append([x,y])
print(corner_list)

# define input points from (sorted) corner_list
input = np.float32(corner_list)

# define output points from dimensions of image, say half of input image
width = ww // 2
height = hh // 2
output = np.float32([[0,0], [width-1,0], [width-1,height-1], [0,height-1]])

# compute perspective matrix
matrix = cv2.getPerspectiveTransform(input,output)

# do perspective transformation setting area outside input to black
result = cv2.warpPerspective(img, matrix, (width,height), cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT, borderValue=(0,0,0))

# save output
cv2.imwrite('maze_thresh.jpg', thresh)
cv2.imwrite('maze_contour.jpg', contour)
cv2.imwrite('maze_hull.jpg', hull)
cv2.imwrite('maze_rectified.jpg', result)

# Display various images to see the steps
cv2.imshow('thresh', thresh)
cv2.imshow('contour', contour)
cv2.imshow('hull', hull)
cv2.imshow('result', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

形态学后的阈值图像:

enter image description here

黑色背景上的过滤轮廓:

enter image description here

输入图像上的凸包和 4 个角:

enter image description here

透视变形的结果:

enter image description here

关于python - 如何填充空心线opencv,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67434707/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com