Krz*_*was 2 python opencv hough-transform
我需要检测给定图像上纸张的角点。它始终是整个图片的裁剪部分,仅包含一个角。我的想法是通过模糊和 Canny 边缘检测来转换图像以获得轮廓,然后应用 Houghlines 来获取角点坐标。
然而,我遇到了一些问题,实际上通过霍夫线一致而精确地检测到任何东西,我已经不知道这可能是什么原因了。
我尝试过使用阈值处理而不是 Canny,但由于适用图像存在许多变化,它不会起作用。我缩小了整个图像,以便更容易看到纸张的边缘,但仍然没有任何改进。增加线条阈值会使纸张内容中的线条消失,但同时边缘线有时会消失
输入
边缘
结果
要重现的代码
import cv2
import numpy as np
img = cv2.imread('inv_0001-01.1_0_corner.jpg')
resized = cv2.resize(img, (250,250), interpolation = cv2.INTER_AREA)
gray = cv2.cvtColor(resized, cv2.COLOR_BGR2GRAY)
kernel_size = 5
blur_gray = cv2.GaussianBlur(gray,(kernel_size, kernel_size),0)
edges = cv2.Canny(blur_gray,50,150,apertureSize = 3)
cv2.imshow('edges', edges)
cv2.waitKey()
min_line_length = 50
max_line_gap = 20
lines = cv2.HoughLinesP(edges, 1, np.pi / 180, 5, np.array([]), min_line_length, max_line_gap)
for line in lines:
for x1,y1,x2,y2 in line:
cv2.line(resized,(x1,y1),(x2,y2),(255,0,0),5)
cv2.imshow('hough', resized)
cv2.waitKey()
Run Code Online (Sandbox Code Playgroud)
我的首选结果是给定图像中纸角的坐标,但在这篇文章中,我宁愿寻求一些帮助来理解如何使用 Houglines 来完成此类任务
这个答案解释了如何找到角点。找到角点需要两部分的解决方案。首先,图像需要分割为两个区域:纸张和背景。其次,您可以在分割图像中寻找角点。
找到边缘后,对图像进行填充以将纸张与背景分开(这是填充图像):
mask = np.zeros((h+2, w+2), np.uint8)
# Floodfill from point (0, 0)
cv2.floodFill(edges, mask, (0,0), 123);
Run Code Online (Sandbox Code Playgroud)
现在您已经分割了图像,使用蒙版去除纸上的文本(这是标题为“蒙版”的图像):
bg = np.zeros_like(edges)
bg[edges == 123] = 255
Run Code Online (Sandbox Code Playgroud)
获得蒙版后,再次应用 canny 边缘过滤器来获取纸张的轮廓线(HoughLines 需要轮廓而不是蒙版...这是“蒙版后的边缘”图像):
bg = cv2.blur(bg, (3,3))
edges = cv2.Canny(bg,50,150,apertureSize = 3)
Run Code Online (Sandbox Code Playgroud)
现在您可以在更干净的图像上运行 HoughLines 算法。我使用了与你不同的 HoughLines 算法,但你的也应该可以工作。这是我使用的完整代码:
import cv2
import numpy as np
import matplotlib.pyplot as plt
# Create a multi plot
f, axarr = plt.subplots(2,3, sharex=True)
img = cv2.imread('/home/stephen/Desktop/IRcCAWL.png')
resized = cv2.resize(img, (250,250), interpolation = cv2.INTER_AREA)
# Show source image
axarr[0,0].imshow(resized)
gray = cv2.cvtColor(resized, cv2.COLOR_BGR2GRAY)
kernel_size = 5
blur_gray = cv2.GaussianBlur(gray,(kernel_size, kernel_size),0)
edges = cv2.Canny(blur_gray,50,150,apertureSize = 3)
# Show first edges image
axarr[0,1].imshow(edges)
h, w = edges.shape[:2]
mask = np.zeros((h+2, w+2), np.uint8)
# Floodfill from point (0, 0)
cv2.floodFill(edges, mask, (0,0), 123);
# Show the flood fill image
axarr[0,2].imshow(edges)
floodfill = edges.copy()
bg = np.zeros_like(edges)
bg[edges == 123] = 255
# Show the masked image
axarr[1,0].imshow(bg)
bg = cv2.blur(bg, (3,3))
edges = cv2.Canny(bg,50,150,apertureSize = 3)
# Show the edges after masking
axarr[1,1].imshow(edges)
min_line_length = 50
max_line_gap = 20
def intersection(line1, line2):
"""Finds the intersection of two lines given in Hesse normal form.
Returns closest integer pixel locations.
See /sf/answers/26846921/
"""
rho1, theta1 = line1[0]
rho2, theta2 = line2[0]
A = np.array([
[np.cos(theta1), np.sin(theta1)],
[np.cos(theta2), np.sin(theta2)]
])
b = np.array([[rho1], [rho2]])
x0, y0 = np.linalg.solve(A, b)
x0, y0 = int(np.round(x0)), int(np.round(y0))
return [[x0, y0]]
import math
lines = cv2.HoughLines(edges, 1, np.pi / 180, 100, None, 0, 0)
# Draw the lines
if lines is not None:
for i in range(0, len(lines)):
rho = lines[i][0][0]
theta = lines[i][0][1]
a = math.cos(theta)
b = math.sin(theta)
x0 = a * rho
y0 = b * rho
pt1 = (int(x0 + 1000*(-b)), int(y0 + 1000*(a)))
pt2 = (int(x0 - 1000*(-b)), int(y0 - 1000*(a)))
cv2.line(resized, pt1, pt2, (123,234,123), 2, cv2.LINE_AA)
xy = tuple(intersection(lines[0], lines[1])[0])
resized = cv2.circle(resized, xy, 5, 255, 2)
# Show the image with the corner
axarr[1,2].imshow(resized)
# Add titles
axarr[0,0].set_title('Source Image')
axarr[0,1].set_title('Edges')
axarr[0,2].set_title('Floodfill')
axarr[1,0].set_title('Masking')
axarr[1,1].set_title('Edges after masking')
axarr[1,2].set_title('Hough Lines')
# Clean up
axarr[0,0].axis('off')
axarr[0,1].axis('off')
axarr[1,0].axis('off')
axarr[1,1].axis('off')
axarr[1,2].axis('off')
axarr[0,2].axis('off')
plt.show()
Run Code Online (Sandbox Code Playgroud)