英文:
How can I combine HoughlinesP coordinates for a single line in OpenCV Python?
问题
I'll provide the translation of the code-related portion:
我正在使用cv2.HoughlinesP来找到文档图像中每条线的坐标。当我使用HoughlinesP时,即使只有一条线,我会得到2个线坐标。我应该如何合并这两个坐标或将它们视为同一条线,而不是分开处理它们。
问题在于,因为我使用了从houghlinesp获得的坐标,这些线被视为矩形框,即线的顶部端点是分开的,线的底部端点也是分开的。因此,会得到两个独立的线坐标,而不是一条线的坐标。
因此,在这种情况下,当这个表格检测到7条线时,当我使用HoughlinesP来获取这些线坐标时,我得到14个不同的坐标。
接下来是代码部分的翻译:
```python
import cv2
from google.colab.patches import cv2_imshow
import numpy as np
#图像预处理
img= cv2.imread('page9.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#首先,获取灰度图像并进行高斯模糊处理。
kernel_size = 5
blur_gray = cv2.GaussianBlur(gray,(kernel_size, kernel_size),0)
#其次,使用Canny进行边缘检测。
low_threshold = 50
high_threshold = 150
edges = cv2.Canny(blur_gray, low_threshold, high_threshold)
#然后,使用HoughLinesP获取线条。
rho = 1 # Hough网格中的像素距离分辨率
theta = np.pi / 180 # Hough网格中的弧度角分辨率
threshold = 25 # Hough网格单元中的最小投票数(交点数)
min_line_length = 150 # 构成线条所需的最小像素数
max_line_gap = 3 # 连接线段之间的最大像素间隙
line_image = np.copy(img) * 0 # 创建一个空白图像以绘制线条
# 在边缘检测图像上运行Hough变换
# 输出“lines”是一个包含检测到的线段端点的数组
lines = cv2.HoughLinesP(edges, rho, theta, threshold, np.array([]),
min_line_length, max_line_gap)
print(len(lines))
这是我得到的输出,显示线坐标的数量:
13
<details>
<summary>英文:</summary>
I'm using cv2.HoughlinesP to find the coordinates for each line in a document image. I'm getting 2 line coordinates when using HoughlinesP when there is only 1 line. How can I combine these two coordinates or treat them as if they are for the same line instead of treating them as separate lines.
The issue, is that because I'm using coordinates obtained from houghlinesp, the lines are treated as if they are rectangular boxes, as in the top endpoints of the line are separate, and the bottom endpoints of the line are treated separately. Therefore 2 separate line coordinates are given instead of coordinates for 1 line.
So in this case where this form has 7 lines being detected, when I use HoughlinesP to get these line coordinates, I get 14 different coordinates.
[![enter image description here][1]][1]
import cv2
from google.colab.patches import cv2_imshow
import numpy as np
#image preprocessing
img= cv2.imread('page9.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#First, get the gray image and process GaussianBlur.
kernel_size = 5
blur_gray = cv2.GaussianBlur(gray,(kernel_size, kernel_size),0)
#Second, process edge detection use Canny.
low_threshold = 50
high_threshold = 150
edges = cv2.Canny(blur_gray, low_threshold, high_threshold)
#Then, use HoughLinesP to get the lines.
rho = 1 # distance resolution in pixels of the Hough grid
theta = np.pi / 180 # angular resolution in radians of the Hough grid
threshold = 25 # minimum number of votes (intersections in Hough grid cell)
min_line_length = 150 # minimum number of pixels making up a line
max_line_gap = 3 # maximum gap in pixels between connectable line segments
line_image = np.copy(img) * 0 # creating a blank to draw lines on
Run Hough on edge detected image
Output "lines" is an array containing endpoints of detected line segments
lines = cv2.HoughLinesP(edges, rho, theta, threshold, np.array([]),
min_line_length, max_line_gap)
print(len(lines))
and this is the output I get showing the number of line coordinates :
`13`
[1]: https://i.stack.imgur.com/PYOjd.png
</details>
# 答案1
**得分**: 1
A simple solution is reducing the resolution of Hough Grid by increasing the value of `rho`, and decreasing the value of `theta`.
- Increasing `rho` applies less dense grid, so a thick line is not going to be found as two close lines.
- Decreasing `theta` reduces the number of resolution of angles to search, so a thick line is not going to be interpreted as a small angled line (from top left corner to the bottom right corner).
Updated code sample:
```python
import cv2
import numpy as np
# image preprocessing
img = cv2.imread('page9.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# First, get the gray image and process GaussianBlur.
kernel_size = 5
blur_gray = cv2.GaussianBlur(gray, (kernel_size, kernel_size), 0)
# Second, process edge detection using Canny.
low_threshold = 50
high_threshold = 150
edges = cv2.Canny(blur_gray, low_threshold, high_threshold)
# Then, use HoughLinesP to get the lines.
rho = 7
theta = np.pi / 30
threshold = 25
min_line_length = 150
max_line_gap = 3
line_image = np.copy(img) * 0
# Run Hough on edge-detected image
# Output "lines" is an array containing endpoints of detected line segments
lines = cv2.HoughLinesP(edges, rho, theta, threshold, np.array([]), min_line_length, max_line_gap)
print(len(lines)) # 7
# Draw lines with red color for testing
if lines is not None:
for i in range(len(lines)):
l = lines[i][0]
cv2.line(line_image, (l[0], l[1]), (l[2], l[3]), (0, 0, 255), 1, cv2.LINE_AA)
cv2.imwrite('line_image.png', line_image) # Save line_image testing
Note:
In general, using HoughLines is not a robust solution.
Instead of using GaussianBlur
, Canny
, and HoughLinesP
, a more robust solution may be using threshold
, findContours
, and then analyzing the contours' shapes to find horizontal lines.
Example:
import cv2
import numpy as np
img = cv2.imread('page9.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Apply binary thresholding with automatic threshold (with polarity inversion).
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0]
line_image = np.copy(img) * 0 # creating a blank to draw lines on
lines_counter = 0
for c in contours:
x, y, w, h = cv2.boundingRect(c)
if w >= 100 and h <= 5:
cv2.drawContours(line_image, [c], 0, (0, 0, 255), cv2.FILLED)
lines_counter += 1
cv2.imwrite('line_image.png', line_image) # Save line_image testing
英文:
A simple solution is reducing the resolution of Hough Grid by increasing the value of rho
, and decreasing the value of theta
.
- Increasing
rho
applies less dense gird, so a thick line is not going to be found as two close lines. - Decreasing
theta
reduces the number of resolution of angles to search, so a thick line is not going to be interpreted as a small angled line (from top left corner to the bottom right corner).
Updated code sample:
import cv2
#from google.colab.patches import cv2_imshow
import numpy as np
#image preprocessing
img= cv2.imread('page9.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#First, get the gray image and process GaussianBlur.
kernel_size = 5
blur_gray = cv2.GaussianBlur(gray,(kernel_size, kernel_size),0)
#Second, process edge detection use Canny.
low_threshold = 50
high_threshold = 150
edges = cv2.Canny(blur_gray, low_threshold, high_threshold)
#Then, use HoughLinesP to get the lines.
rho = 7 #1 # distance resolution in pixels of the Hough grid
theta = np.pi / 30 # np.pi / 180 # angular resolution in radians of the Hough grid
threshold = 25 # minimum number of votes (intersections in Hough grid cell)
min_line_length = 150 # minimum number of pixels making up a line
max_line_gap = 3 # maximum gap in pixels between connectable line segments
line_image = np.copy(img) * 0 # creating a blank to draw lines on
# Run Hough on edge detected image
# Output "lines" is an array containing endpoints of detected line segments
lines = cv2.HoughLinesP(edges, rho, theta, threshold, np.array([]),
min_line_length, max_line_gap)
print(len(lines)) # 7
# Draw lines with red color for testing
if lines is not None:
for i in range(len(lines)):
l = lines[i][0]
cv2.line(line_image, (l[0], l[1]), (l[2], l[3]), (0, 0, 255), 1, cv2.LINE_AA)
cv2.imwrite('line_image.png', line_image) # Save line_image testing
Note:
In general, using HoughLines is not a robust solution.
Instead of using GaussianBlur
, Canny
and HoughLinesP
, a more robust solution may be using threshold
, findContours
and then analysing the contours shapes for finding horizontal lines.
Example:
import cv2
import numpy as np
img= cv2.imread('page9.png')
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# Apply binary thresholding with automatic threshold (with polarity inversion).
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0]
line_image = np.copy(img) * 0 # creating a blank to draw lines on
lines_counter = 0
for c in contours:
x, y, w, h = cv2.boundingRect(c)
if w >= 100 and h <= 5:
cv2.drawContours(line_image, [c], 0, (0, 0, 255), cv2.FILLED)
lines_counter += 1
cv2.imwrite('line_image.png', line_image) # Save line_image testing
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论