如何在OpenCV Python中将HoughlinesP坐标合并为一条线?

huangapple go评论64阅读模式
英文:

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&#39;m using cv2.HoughlinesP to find the coordinates for each line in a document image. I&#39;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&#39;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

line_image.png:
如何在OpenCV Python中将HoughlinesP坐标合并为一条线?

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(&#39;page9.png&#39;)
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 &quot;lines&quot; 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(&#39;line_image.png&#39;, line_image)  # Save line_image testing

line_image.png:
如何在OpenCV Python中将HoughlinesP坐标合并为一条线?


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(&#39;page9.png&#39;)
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 &gt;= 100 and h &lt;= 5:
        cv2.drawContours(line_image, [c], 0, (0, 0, 255), cv2.FILLED)
        lines_counter += 1

cv2.imwrite(&#39;line_image.png&#39;, line_image)  # Save line_image testing

huangapple
  • 本文由 发表于 2023年5月22日 18:58:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/76305475.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定