我发现霍夫变换有更多的线条,但有些东西与我的最终目标非常相似。
例如
在这张图片中我有 5 行,但我实际上只需要 2 行。
如何删除不必要的线条?
我的代码是
image = cv.Canny(image, 200);
lines = cv.HoughLinesP(image,'Threshold',80,'MinLineLength',100,'MaxLineGap',50);
一种简单的方法是线相交,但在某些情况下线可以平行且非常接近。
有什么想法吗?
我的粗略方法是
我用它来检测卡片的边缘,所以我选取了四条最佳线。
这是我解决问题的方法。首先,我根据 rho 和 theta 值的阈值对类似的线进行分组。一旦线被分组,我就会对每组内相似的线参数进行平均,以创建一条代表线。
import cv2
import numpy as np
def unify_lines(lines, rho_threshold=10, theta_threshold=np.pi/180*10):
# Group lines that are similar based on thresholds
unified_lines = []
for line in lines:
for rho, theta in line:
if not unified_lines:
unified_lines.append((rho, theta))
else:
matched = False
for u_rho, u_theta in unified_lines:
if abs(u_rho - rho) < rho_threshold and abs(u_theta - theta) < theta_threshold:
average_rho = (u_rho + rho) / 2
average_theta = (u_theta + theta) / 2
unified_lines[unified_lines.index((u_rho, u_theta))] = (average_rho, average_theta)
matched = True
break
if not matched:
unified_lines.append((rho, theta))
return np.array([[line] for line in unified_lines], dtype=np.float32)
image = cv2.imread('image.png', 0)
edges = cv2.Canny(image, 50, 150)
lines = cv2.HoughLines(edges, 1, np.pi / 180, 100)
# Unify similar lines
unified_lines = unify_lines(lines)
# Draw the unified lines
for line in unified_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(image, (x1, y1), (x2, y2), (0, 0, 255), 2)
cv2.imshow('Unified Lines', image)
cv2.waitKey(0)
cv2.destroyAllWindows()
您可以根据您的特定用例调整这些阈值(
rho_threshold
和 theta_threshold
)以获得所需的线条统一。
[更新]基于多米尼克的评论:
新方法首先对所有相似的线进行分组,然后计算平均值,并根据线的长度为线分配权重。这样,较长的线通常是预期线方向和位置的更可靠的指标,对最终平均线的影响更大。
import cv2
import numpy as np
def calculate_length(line):
rho, theta = line
return abs(rho) # Length could be represented by the absolute value of rho
def unify_lines(lines, rho_threshold=10, theta_threshold=np.pi/180*10):
grouped_lines = []
# Step 1: Group similar lines
for line in lines:
for rho, theta in line:
matched_group = None
for group in grouped_lines:
for u_rho, u_theta in group:
if (abs(u_rho - rho) < rho_threshold and abs(u_theta - theta) < theta_threshold) or \
(abs(u_rho + rho) < rho_threshold and abs(u_theta - (theta + np.pi)) % (2 * np.pi) < theta_threshold):
matched_group = group
break
if matched_group:
break
if matched_group:
matched_group.append((rho, theta))
else:
grouped_lines.append([(rho, theta)])
# Step 2: Compute weighted average for each group
unified_lines = []
for group in grouped_lines:
total_weight = sum(calculate_length(line) for line in group)
average_rho = sum(rho * calculate_length((rho, theta)) for rho, theta in group) / total_weight
average_theta = sum(theta * calculate_length((rho, theta)) for rho, theta in group) / total_weight
unified_lines.append((average_rho, average_theta))
return np.array([[line] for line in unified_lines], dtype=np.float32)
我会计算直线的斜率和截距,并比较它们,看看它们是否都在您定义的某个容差范围内。截距应在同一坐标系上描述,例如原点位于像素 r,c = (0,0) 处。然后可以合并相同的线。我能想到的唯一失败情况是,如果您有具有相同斜率和截距的非连续线段 - 这些线段将与此方法合并。但在你的形象中,你似乎没有这个问题。