如何通过检测直线来检测主体结构轮廓

3
我正在尝试通过检测直线和边缘来检测许多“楼层平面图”图片的主要结构,参考自这里

enter image description here

上面的例子是我需要处理的一个示例,是否可以通过检测带有 opencv HoughLinesP 的行来获取主要结构?非常感谢您的帮助。
import cv2
import numpy as np

def get_lines(lines_in):
    if cv2.__version__ < '3.0':
        return lines_in[0]
    return [l[0] for l in lines]

img = cv2.imread('./test.jpg', 1)
img_gray = gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

cannied = cv2.Canny(img_gray, threshold1=50, threshold2=200, apertureSize=3)
lines = cv2.HoughLinesP(cannied, rho=1, theta=np.pi / 180, threshold=80, minLineLength=30, maxLineGap=10)

for line in get_lines(lines):
    leftx, boty, rightx, topy = line
    cv2.line(img, (leftx, boty), (rightx,topy), (255, 255, 0), 2)

cv2.imwrite('./lines.png', img)
cv2.imwrite('./canniedHouse.png', cannied)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果:

lines.png

lines.png

canniedHouse.png

canniedHouse.png

其他参考资料:

如何在Python中获取楼层平面图的外轮廓?

楼层平面图边缘检测-图像处理?


你有代码。结果是什么? - fmw42
我更新了结果图像,在其中线条不可见,请检查。 - ah bon
1个回答

6

以下是一种方法

  • 将图像转换为灰度
  • 使用自适应阈值获取二进制图像
  • 执行形态学变换以平滑图像
  • 创建水平卷积核并检测水平线条
  • 创建垂直卷积核并检测垂直线条

将图像转换为灰度后,我们使用自适应阈值法获得二值图像

image = cv2.imread('1.jpg')
original = image.copy()
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

enter image description here

从这里开始,我们对图像进行形态学变换以平滑图像。

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
close = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations=2)

enter image description here

现在我们使用cv2.getStructuringElement()创建一个水平内核,并检测水平线。
# Find horizontal lines
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (35,2))
detect_horizontal = cv2.morphologyEx(close, cv2.MORPH_OPEN, horizontal_kernel, iterations=2)
cnts = cv2.findContours(detect_horizontal, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    cv2.drawContours(original, [c], -1, (36,255,12), -1)

enter image description here

同样地,我们创建一个垂直核并检测垂直线。
# Find vertical lines
vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2,35))
detect_vertical = cv2.morphologyEx(close, cv2.MORPH_OPEN, vertical_kernel, iterations=2)
cnts = cv2.findContours(detect_vertical, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    cv2.drawContours(original, [c], -1, (36,255,12), -1)

enter image description here

这是结果

enter image description here

import cv2
import numpy as np

image = cv2.imread('1.jpg')
original = image.copy()
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
close = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations=2)

# Find horizontal lines
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (35,2))
detect_horizontal = cv2.morphologyEx(close, cv2.MORPH_OPEN, horizontal_kernel, iterations=2)
cnts = cv2.findContours(detect_horizontal, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    cv2.drawContours(original, [c], -1, (36,255,12), -1)

# Find vertical lines
vertical_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2,35))
detect_vertical = cv2.morphologyEx(close, cv2.MORPH_OPEN, vertical_kernel, iterations=2)
cnts = cv2.findContours(detect_vertical, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    cv2.drawContours(original, [c], -1, (36,255,12), -1)

cv2.imshow('thresh', thresh)
cv2.imshow('close', close)
cv2.imshow('original', original)
cv2.waitKey()

如果你只想找到外部轮廓,可以在形态学闭合操作后找到轮廓。
cnts = cv2.findContours(close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    cv2.drawContours(original, [c], -1, (36,255,12), 3)

enter image description here


非常感谢。这样好多了。抱歉,我还有一个问题,您知道如何创建一个遮罩来删除其中的文本吗?例如 01、02、……07、电梯厅 等。 - ah bon
1
我无法想到一个稳健的方法,但可能的方法是找出轮廓并使用轮廓面积进行过滤。 - nathancy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接