目录
方法0:
import cv2
import numpy as np
def detect_lines_through_point(image, point_a, theta_step=1, epsilon=1):
# 转换为灰度图像
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 使用Canny边缘检测
edges = cv2.Canny(gray, 50, 150)
# 获取边缘点的坐标
y_coords, x_coords = np.where(edges > 0)
if len(x_coords) == 0 or len(y_coords) == 0:
return []
x0, y0 = point_a # 指定点a的坐标
thetas = np.deg2rad(np.arange(0, 180, theta_step)) # 角度范围及步长
cos_t = np.cos(thetas)
sin_t = np.sin(thetas)
# 计算点a对应的所有rho值
rho_a = x0 * cos_t + y0 * sin_t
# 向量化计算所有边缘点的rho值
x_col = x_coords.reshape(-1, 1)
y_col = y_coords.reshape(-1, 1)
rho_points = x_col * cos_t + y_col * sin_t
# 判断是否满足直线方程(考虑误差epsilon)
matches = np.abs(rho_points - rho_a) <= epsilon
accumulator = np.sum(matches, axis=0)
# 寻找得票最多的theta
best_theta_idx = np.argmax(accumulator)
best_theta = thetas[best_theta_idx]
# 计算直线端点(延长至图像边界)
a = np.cos(best_theta)
b = np.sin(best_theta)
x0, y0 = point_a
height, width = image.shape[:2]
# 计算直线与图像边界的交点
if b != 0:
# 直线斜率存在
x1 = 0
y1 = int((rho_a[best_theta_idx] - x1 * a) / b)
x2 = width
y2 = int((rho_a[best_theta_idx] - x2 * a) / b)
# 确保交点位于图像内
pts = []
if y1 >= 0 and y1 < height:
pts.append((x1, y1))
if y2 >= 0 and y2 < height:
pts.append((x2, y2))
if len(pts) < 2:
y1 = 0
x1 = int((rho_a[best_theta_idx] - y1 * b) / a)
if x1 >= 0 and x1 < width:
pts.append((x1, y1))
y2 = height - 1
x2 = int((rho_a[best_theta_idx] - y2 * b) / a)
if x2 >= 0 and x2 < width:
pts.append((x2, y2))
if len(pts) >= 2:
(x_start, y_start), (x_end, y_end) = pts[:2]
else:
return []
else:
# 垂直线处理
x_start = int(rho_a[best_theta_idx] / a)
y_start = 0
x_end = x_start
y_end = height - 1
return [(x_start, y_start, x_end, y_end)]
# 示例用法
image = cv2.imread('your_image.jpg')
if image is None:
raise FileNotFoundError("Image not found")
point_a = (100, 100) # 替换为你的指定点坐标
detected_lines = detect_lines_through_point(image, point_a, theta_step=1, epsilon=2)
# 绘制检测到的直线
for line in detected_lines:
x_start, y_start, x_end, y_end = line
cv2.line(image, (x_start, y_start), (x_end, y_end), (0, 255, 0), 2)
cv2.imshow('Detected Line', image)
cv2.waitKey(0)
cv2.destroyAllWindows()
方法1
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 给定的点 A(x1, y1)
x1, y1 = 200, 150 # 例如指定的点是(200, 150)
# 读取图像并转为灰度图
image = cv2.imread('your_image.jpg', cv2.IMREAD_GRAYSCALE)
# 应用 Canny 边缘检测
edges = cv2.Canny(image, 50, 150)
# 使用 Hough 变换检测直线
# 这将返回检测到的直线的极坐标表示 (rho, theta)
lines = cv2.HoughLines(edges, 1, np.pi / 180, 150)
# 创建一个副本来显示结果
output_image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)
# 画出检测到的直线
if lines is not None:
for line in lines:
rho, theta = line[0]
# 计算直线的两个端点(极坐标转直角坐标)
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))
# 确保直线通过指定的点 A(x1, y1)
# 计算该点在直线方程中的位置(调整线的截距)
# 如果直线需要调整,重新计算斜率和截距使其通过A(x1, y1)
# 计算斜率 m 和截距 b
if x2 - x1 != 0:
m = (y2 - y1) / (x2 - x1)
b_adjusted = y1 - m * x1
# 通过新的斜率和截距绘制调整后的直线
x_line_start = 0
y_line_start = int(m * x_line_start + b_adjusted)
x_line_end = image.shape[1]
y_line_end = int(m * x_line_end + b_adjusted)
cv2.line(output_image, (x_line_start, y_line_start), (x_line_end, y_line_end), (0, 0, 255), 2)
# 显示最终结果
plt.imshow(cv2.cvtColor(output_image, cv2.COLOR_BGR2RGB))
plt.title('Line Detection with Point A')
plt.show()
方法2
import cv2
import numpy as np
# 给定的点 A(x1, y1)
x1, y1 = 200, 150 # 例如指定的点是(200, 150)
# 读取图像并转为灰度图
image = cv2.imread('your_image.jpg', cv2.IMREAD_GRAYSCALE)
# 检查图像是否正确加载
if image is None:
print("图像加载失败,请检查路径")
exit()
# 应用 Canny 边缘检测
edges = cv2.Canny(image, 50, 150)
# 使用 Hough 变换检测直线(霍夫变换返回的是极坐标表示)
lines = cv2.HoughLines(edges, 1, np.pi / 180, 150)
# 创建一个副本来显示结果
output_image = cv2.cvtColor(image, cv2.COLOR_GRAY2BGR)
# 如果检测到直线,绘制它们
if lines is not None:
for line in lines:
rho, theta = line[0]
# 计算直线的两个端点(极坐标转直角坐标)
a = np.cos(theta)
b = np.sin(theta)
x0 = a * rho
y0 = b * rho
x2 = int(x0 + 1000 * (-b))
y2 = int(y0 + 1000 * (a))
x1_line = int(x0 - 1000 * (-b))
y1_line = int(y0 - 1000 * (a))
# 确保直线通过指定的点 A(x1, y1)
# 计算直线的斜率 m 和截距 b
if x2 - x1_line != 0:
m = (y2 - y1_line) / (x2 - x1_line)
b_adjusted = y1 - m * x1
# 使用新的斜率 m 和截距 b 绘制直线
x_line_start = 0
y_line_start = int(m * x_line_start + b_adjusted)
x_line_end = image.shape[1]
y_line_end = int(m * x_line_end + b_adjusted)
# 绘制调整后的直线(通过指定点 A(x1, y1))
cv2.line(output_image, (x_line_start, y_line_start), (x_line_end, y_line_end), (0, 0, 255), 2)
# 绘制指定点 A
cv2.circle(output_image, (x1, y1), 5, (0, 255, 0), -1)
# 显示结果图像
cv2.imshow('Line Detection through Point A', output_image)
# 等待按键并关闭
cv2.waitKey(0)
cv2.destroyAllWindows()