Files
innovate_project/OpenCV/detect_weld.py
2025-10-01 10:43:55 +08:00

112 lines
4.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import cv2
import numpy as np
import math
import os
def find_and_mask_weld_seam_v3(image_path):
"""
加载图像,使用更激进的预处理方法检测低对比度直线。
:param image_path: 输入图像的完整路径。
:return: None
"""
# --- 步骤 1: 加载图像 ---
image = cv2.imread(image_path)
if image is None:
print(f"错误: 无法加载图像 '{image_path}'")
return
visualization_image = image.copy()
height, width, _ = image.shape
image_center_x = width / 2
# --- 步骤 2: 图像预处理 (超强版) ---
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 2.1 高斯模糊以去除噪声
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
# 2.2 自适应阈值二值化 (关键步骤!)
# 这个操作对于光照不均、对比度低的区域效果非常好,能强制分离出边缘
# blocksize: 邻域大小,必须是奇数
# C: 从均值或加权均值中减去的常数,用于微调
binary_image = cv2.adaptiveThreshold(
blurred, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY_INV, 21, 5
)
# 使用THRESH_BINARY_INV是因为我们感兴趣的边缘是暗色背景下的亮色线条
# 2.3 形态学操作来清理和连接线条
# 创建一个垂直的结构元素,因为我们的目标是垂直线
kernel = np.ones((15, 1), np.uint8) # 强调垂直方向
# 使用“闭运算”来填充断开的线段中的小洞
closed = cv2.morphologyEx(binary_image, cv2.MORPH_CLOSE, kernel)
# --- 步骤 3: 霍夫直线变换 (直接在处理后的二值图上进行) ---
# Canny不再是必需的因为二值化已经完成了边缘提取
lines = cv2.HoughLinesP(
closed, # 在闭运算结果上检测
rho=1,
theta=np.pi / 180,
threshold=100, # 需要较高的阈值,因为线现在更连续了
minLineLength=int(height * 0.5), # 线至少要有一半图像高度那么长
maxLineGap=50 # 允许较大的间隙
)
# --- 步骤 4: 筛选最佳直线 (逻辑与之前类似) ---
best_line = None
max_length = 0
if lines is not None:
for line in lines:
x1, y1, x2, y2 = line[0]
# 角度过滤,寻找近乎垂直的线
angle = abs(math.degrees(math.atan2(y2 - y1, x2 - x1)))
if abs(angle - 90) < 5: # 检查角度是否在90度左右垂直
length = math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2)
if length > max_length:
max_length = length
best_line = line[0]
# --- 步骤 5: 处理和显示结果 ---
if best_line is not None:
bx1, by1, bx2, by2 = best_line
print(f"成功找到直线!起点:({bx1}, {by1}), 终点:({bx2}, {by2})")
cv2.line(visualization_image, (bx1, by1), (bx2, by2), (0, 0, 255), 3)
# 显示中间处理结果以供调试
cv2.imshow('1. Original Image', image)
cv2.imshow('2. Adaptive Threshold', binary_image)
cv2.imshow('3. Morphological Closing', closed) # 检查闭运算效果
cv2.imshow('4. Final Detection', visualization_image)
else:
print("未能在图像中找到符合条件的直线。")
cv2.imshow('1. Original Image', image)
cv2.imshow('2. Adaptive Threshold', binary_image)
cv2.imshow('3. Morphological Closing', closed)
cv2.waitKey(0)
cv2.destroyAllWindows()
# --- 主程序入口 ---
if __name__ == '__main__':
try:
script_dir = os.path.dirname(os.path.abspath(__file__))
except NameError:
script_dir = os.getcwd()
# 请确保你的图片路径正确
image_filename = 'data/test3/l2.jpeg'
image_path = os.path.join(script_dir, image_filename)
if not os.path.exists(image_path):
# 如果找不到,尝试直接使用文件名(假设图片和脚本在同一目录)
image_path = '13-l.bmp'
if not os.path.exists(image_path):
print(f"错误: 输入文件 '{image_path}' 不存在。")
else:
find_and_mask_weld_seam_v3(image_path)
else:
find_and_mask_weld_seam_v3(image_path)