项目需求
输入:二维图片
输出:照片中类似下图形式的直线段的起始点(二维坐标)和终止点(二维坐标)
需求:识别并检测类似下图中明显的直线段,从照片中提取出钢筋所在直线段,且对不同场景图(比如以下展示的多张图都具有适应性)。希望实现的效果是:人肉眼可辨的直线,算法也能提取出该直线;而且图中的每条直线只需要一条直线表达,比如断断续续的线段要练成一条直线,然后像钢筋有点粗的情况可能检测到两边边线,需要处理一下,我只要每条直线的中线(1条贯通的长直线)。
具体的场景照片类似如下:







目前做过的一些尝试:

对应代码:
import numpy as np
import cv2
import matplotlib.pyplot as plt
# 关键参数定义
adaptive_thresh_block_size = 11 # 自适应阈值化的块大小,决定计算平均值或加权平均值的区域大小
adaptive_thresh_C = -35 # 自适应阈值化常数,从平均值或加权平均值中减去这个值得到阈值
hough_threshold = 45 # 霍夫变换的阈值,必须超过此值的直线才会被认为是直线
hough_min_line_length = 20 # 检测的直线的最小长度
hough_max_line_gap = 20 # 直线上允许的最大间隙
merge_distance_threshold = 5 # 合并线段时的距离阈值
angle_threshold = np.pi / 180 * 1 # 合并线段时的角度阈值 (1 degree)
# 图像文件路径
image_path = '8.jpg'
img = cv2.imread(image_path)
# 检查图像是否被正确读取
if img is None:
print("错误:无法加载图像。请检查图像路径和文件名。")
else:
# 转换到灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 自适应阈值处理
thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, adaptive_thresh_block_size, adaptive_thresh_C)
# 霍夫线变换
lines = cv2.HoughLinesP(thresh, 1, np.pi / 180, hough_threshold, minLineLength=hough_min_line_length, maxLineGap=hough_max_line_gap)
# 检测到的直线数量
num_lines = 0 if lines is None else len(lines)
print(f"检测到的直线数量: {num_lines}")
# 创建一个图像副本来绘制检测到的线条
line_image = np.copy(img)
# 绘制检测到的线条
if lines is not None:
for line in lines:
for x1, y1, x2, y2 in line:
cv2.line(line_image, (x1, y1), (x2, y2), (0, 255, 0), 2)
# 显示灰度图像、阈值化图像和带有检测到线条的图像
fig, axs = plt.subplots(1, 3, figsize=(20, 10))
axs[0].imshow(gray, cmap='gray')
axs[0].set_title('Gray Image')
axs[0].axis('off')
axs[1].imshow(thresh, cmap='gray')
axs[1].set_title('Adaptive Threshold')
axs[1].axis('off')
axs[2].imshow(cv2.cvtColor(line_image, cv2.COLOR_BGR2RGB))
axs[2].set_title('Detected Lines')
axs[2].axis('off')
plt.show()
以上代码存在的问题:
1、检测到的线太多、太散了(有时候钢筋两边侧线都被检测出来了),而且还存在着断断续续的线段的情况,我只希望每一条钢筋/钢管只有一条贯通的长线表示(或者中线+钢筋所在区域的mask)。
2、适应性不够强,对其他场景图片还需要手动去调参,有的图效果不太好。
3、可选动作(不一定要实现):有没有可能消除掉钢筋影子(阴影)的影响/错误检测。
