为什么 opencv houghline 检测到的线与图像中的真实线不平行?
why lines detected by opencv houghline are not parallel with real lines in image?
各位大侠,首先请看下图:
为什么houghline检测和绘制的线与足球场的白线并不平行??
我需要交点在图像上的位置确实准确
然后需要在图像中用白线画直线平行线
谁能帮我解决这个问题
提前致谢
如果您想使用代码,这是原始图像 d.jpg:
这是我的 python 代码:
import numpy as np
import cv2
from collections import defaultdict
import sys
import math
img2 = cv2.imread("e:/d.jpg")
edges2 = cv2.Canny(img2, 40, 55)
def segment_by_angle_kmeans(lines, k=2, **kwargs):
# Define criteria = (type, max_iter, epsilon)
default_criteria_type = cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER
criteria = kwargs.get('criteria', (default_criteria_type, 10, 1.0))
flags = kwargs.get('flags', cv2.KMEANS_RANDOM_CENTERS)
attempts = kwargs.get('attempts', 10)
# Get angles in [0, pi] radians
angles = np.array([line[0][1] for line in lines])
# Multiply the angles by two and find coordinates of that angle on the Unit Circle
pts = np.array([[np.cos(2*angle), np.sin(2*angle)] for angle in angles], dtype=np.float32)
# Run k-means
if sys.version_info[0] == 2:
# python 2.x
ret, labels, centers = cv2.kmeans(pts, k, criteria, attempts, flags)
else:
# python 3.x, syntax has changed.
labels, centers = cv2.kmeans(pts, k, None, criteria, attempts, flags)[1:]
labels = labels.reshape(-1) # Transpose to row vector
# Segment lines based on their label of 0 or 1
segmented = defaultdict(list)
for i, line in zip(range(len(lines)), lines):
segmented[labels[i]].append(line)
segmented = list(segmented.values())
print("Segmented lines into two groups: %d, %d" % (len(segmented[0]), len(segmented[1])))
return segmented
def intersection(line1, line2):
"""
Find the intersection of two lines
specified in Hesse normal form.
Returns closest integer pixel locations.
"""
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]]
def segmented_intersections(lines):
"""
Find the intersection between groups of lines.
"""
intersections = []
for i, group in enumerate(lines[:-1]):
for next_group in lines[i+1:]:
for line1 in group:
for line2 in next_group:
intersections.append(intersection(line1, line2))
return intersections
def drawLines(img, lines, color=(0,0,255)):
"""
Draw lines on an image
"""
for line in lines:
for rho,theta in line:
a = np.cos(theta)
b = np.sin(theta)
x0 = a*rho
y0 = b*rho
x1 = int(x0 + 1000*(-b))
y1 = int(y0 + 1000*(a))
x2 = int(x0 - 1000*(-b))
y2 = int(y0 - 1000*(a))
cv2.line(img, (x1,y1), (x2,y2), color, 2)
# Detect lines
rho = 2.7
theta = np.pi/50
thresh = 410
lines = cv2.HoughLines(edges2, rho, theta, thresh)
print("Found lines: %d" % (len(lines)))
# Draw all Hough lines
img_with_all_lines = np.copy(2)
drawLines(img_with_all_lines, lines)
# Cluster line angles into 2 groups (vertical and horizontal)
segmented = segment_by_angle_kmeans(lines, 2)
# Find the intersections of each vertical line with each horizontal line
intersections = segmented_intersections(segmented)
img_with_segmented_lines = np.copy(img2)
# Draw vertical lines
vertical_lines = segmented[1]
img_with_vertical_lines = np.copy(img2)
drawLines(img_with_segmented_lines, vertical_lines, (255,255,0))
# Draw horizontal lines
horizontal_lines = segmented[0]
img_with_horizontal_lines = np.copy(img2)
drawLines(img_with_segmented_lines, horizontal_lines, (0,255,255))
# Draw intersection points
intersections.pop(5)
intersections.pop(4)
mn = intersections[3]
mk = intersections[2]
intersections = intersections[:2]
intersections.append(mn)
intersections.append(mk)
print(intersections)
for point in intersections:
pt = (point[0][0], point[0][1])
length = 5
cv2.circle(img_with_segmented_lines, pt, 5 , (255, 0, 255), -1)
cv2.imshow("Segmented lines", img_with_segmented_lines)
cv2.waitKey()
Hough 使用具有有限分辨率的累加器,该分辨率决定了精度。您可以降低 theta(以 运行 时间为代价,并且可能会降低可靠性)。
如果我必须这样做,我可能会添加一些 post 处理来更精确地沿着 Hough 线检测线,f.i。使用方向梯度滤波器和稳健的线拟合。
各位大侠,首先请看下图:
为什么houghline检测和绘制的线与足球场的白线并不平行??
我需要交点在图像上的位置确实准确
然后需要在图像中用白线画直线平行线 谁能帮我解决这个问题
提前致谢
如果您想使用代码,这是原始图像 d.jpg:
这是我的 python 代码:
import numpy as np
import cv2
from collections import defaultdict
import sys
import math
img2 = cv2.imread("e:/d.jpg")
edges2 = cv2.Canny(img2, 40, 55)
def segment_by_angle_kmeans(lines, k=2, **kwargs):
# Define criteria = (type, max_iter, epsilon)
default_criteria_type = cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER
criteria = kwargs.get('criteria', (default_criteria_type, 10, 1.0))
flags = kwargs.get('flags', cv2.KMEANS_RANDOM_CENTERS)
attempts = kwargs.get('attempts', 10)
# Get angles in [0, pi] radians
angles = np.array([line[0][1] for line in lines])
# Multiply the angles by two and find coordinates of that angle on the Unit Circle
pts = np.array([[np.cos(2*angle), np.sin(2*angle)] for angle in angles], dtype=np.float32)
# Run k-means
if sys.version_info[0] == 2:
# python 2.x
ret, labels, centers = cv2.kmeans(pts, k, criteria, attempts, flags)
else:
# python 3.x, syntax has changed.
labels, centers = cv2.kmeans(pts, k, None, criteria, attempts, flags)[1:]
labels = labels.reshape(-1) # Transpose to row vector
# Segment lines based on their label of 0 or 1
segmented = defaultdict(list)
for i, line in zip(range(len(lines)), lines):
segmented[labels[i]].append(line)
segmented = list(segmented.values())
print("Segmented lines into two groups: %d, %d" % (len(segmented[0]), len(segmented[1])))
return segmented
def intersection(line1, line2):
"""
Find the intersection of two lines
specified in Hesse normal form.
Returns closest integer pixel locations.
"""
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]]
def segmented_intersections(lines):
"""
Find the intersection between groups of lines.
"""
intersections = []
for i, group in enumerate(lines[:-1]):
for next_group in lines[i+1:]:
for line1 in group:
for line2 in next_group:
intersections.append(intersection(line1, line2))
return intersections
def drawLines(img, lines, color=(0,0,255)):
"""
Draw lines on an image
"""
for line in lines:
for rho,theta in line:
a = np.cos(theta)
b = np.sin(theta)
x0 = a*rho
y0 = b*rho
x1 = int(x0 + 1000*(-b))
y1 = int(y0 + 1000*(a))
x2 = int(x0 - 1000*(-b))
y2 = int(y0 - 1000*(a))
cv2.line(img, (x1,y1), (x2,y2), color, 2)
# Detect lines
rho = 2.7
theta = np.pi/50
thresh = 410
lines = cv2.HoughLines(edges2, rho, theta, thresh)
print("Found lines: %d" % (len(lines)))
# Draw all Hough lines
img_with_all_lines = np.copy(2)
drawLines(img_with_all_lines, lines)
# Cluster line angles into 2 groups (vertical and horizontal)
segmented = segment_by_angle_kmeans(lines, 2)
# Find the intersections of each vertical line with each horizontal line
intersections = segmented_intersections(segmented)
img_with_segmented_lines = np.copy(img2)
# Draw vertical lines
vertical_lines = segmented[1]
img_with_vertical_lines = np.copy(img2)
drawLines(img_with_segmented_lines, vertical_lines, (255,255,0))
# Draw horizontal lines
horizontal_lines = segmented[0]
img_with_horizontal_lines = np.copy(img2)
drawLines(img_with_segmented_lines, horizontal_lines, (0,255,255))
# Draw intersection points
intersections.pop(5)
intersections.pop(4)
mn = intersections[3]
mk = intersections[2]
intersections = intersections[:2]
intersections.append(mn)
intersections.append(mk)
print(intersections)
for point in intersections:
pt = (point[0][0], point[0][1])
length = 5
cv2.circle(img_with_segmented_lines, pt, 5 , (255, 0, 255), -1)
cv2.imshow("Segmented lines", img_with_segmented_lines)
cv2.waitKey()
Hough 使用具有有限分辨率的累加器,该分辨率决定了精度。您可以降低 theta(以 运行 时间为代价,并且可能会降低可靠性)。
如果我必须这样做,我可能会添加一些 post 处理来更精确地沿着 Hough 线检测线,f.i。使用方向梯度滤波器和稳健的线拟合。