1、在main函数中调用d455深度相机,拍摄RGB图片和深度图片,打开窗口,窗框里面有3个小窗口,依次显示RGB图片、深度图片、对深度图处理后的深度图像,当用户点击空格则保存图片,点击q键则关闭程序;
2、在强光照环境下,为深度相机添加红外滤光片
3、对窗框线段进行聚类和延长处理,形成完整框架
4、使用RANSAC算法拟合更精确的直线方程
请按照上面要求修改下面程序代码,并提供一份完整的程序代码
import cv2
import numpy as np
import matplotlib.pyplot as plt
import os
import sys
def safe_imread(file_path, flags=cv2.IMREAD_COLOR):
"""
安全读取图像文件,解决文件路径错误和中文路径问题
参数:
file_path: 图像文件路径
flags: OpenCV读取标志 (cv2.IMREAD_COLOR, cv2.IMREAD_GRAYSCALE, cv2.IMREAD_UNCHANGED)
返回:
图像数据 (numpy数组) 或 None
"""
# 检查文件是否存在
if not os.path.exists(file_path):
print(f"[错误] 文件不存在: {file_path}")
return None
# 检查文件是否可读
if not os.access(file_path, os.R_OK):
print(f"[错误] 文件不可读: {file_path}")
return None
# 使用cv2.imdecode解决中文路径问题 [^1]
try:
with open(file_path, 'rb') as f:
img_bytes = np.frombuffer(f.read(), dtype=np.uint8)
img = cv2.imdecode(img_bytes, flags)
if img is None:
print(f"[错误] 无法解码图像: {file_path}")
return img
except Exception as e:
print(f"[异常] 读取图像时出错: {str(e)}")
return None
def validate_image(img, name):
"""
验证图像是否有效
参数:
img: 图像数据
name: 图像名称 (用于错误信息)
返回:
bool: 图像是否有效
"""
if img is None:
print(f"[错误] {name} 图像为空")
return False
if img.size == 0:
print(f"[错误] {name} 图像尺寸为0")
return False
if len(img.shape) < 2:
print(f"[错误] {name} 图像维度不足")
return False
return True
def safe_cvtColor(img, conversion_code):
"""
安全的颜色空间转换函数
参数:
img: 输入图像
conversion_code: OpenCV颜色转换代码
返回:
转换后的图像
"""
# 验证输入图像
if not validate_image(img, "颜色转换输入"):
return None
# 处理特殊情况:灰度图转RGB
if conversion_code in [cv2.COLOR_BGR2GRAY, cv2.COLOR_RGB2GRAY]:
if len(img.shape) == 2: # 已经是灰度图
return img.copy()
elif img.shape[2] == 1: # 单通道彩色图
return img[:, :, 0].copy()
# 处理特殊情况:RGB转灰度
if conversion_code in [cv2.COLOR_GRAY2BGR, cv2.COLOR_GRAY2RGB]:
if len(img.shape) == 3: # 已经是彩色图
return img.copy()
elif len(img.shape) == 2: # 灰度图
return cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
# 尝试标准转换
try:
return cv2.cvtColor(img, conversion_code)
except cv2.error as e:
print(f"[错误] 颜色转换失败: {str(e)}")
return None
def detect_glass_and_frame(rgb_img, depth_map):
"""
检测玻璃及窗框的核心函数(包含错误处理)
参数:
rgb_img: RGB彩色图像
depth_map: 深度图
返回:
glass_mask: 玻璃区域掩膜
frame_lines: 检测到的窗框线段
result_img: 可视化结果图像
"""
# 验证输入图像
if not validate_image(rgb_img, "RGB图像"):
return None, None, None
if not validate_image(depth_map, "深度图"):
return None, None, None
# 确保深度图是单通道
if len(depth_map.shape) > 2:
depth_map = depth_map[:, :, 0]
# 1. 深度图预处理
try:
# 创建玻璃候选区域掩膜(深度值为0的区域)
glass_mask = np.where(depth_map == 0, 255, 0).astype(np.uint8)
# 形态学操作优化掩膜
kernel = np.ones((5, 5), np.uint8)
glass_mask = cv2.morphologyEx(glass_mask, cv2.MORPH_CLOSE, kernel)
glass_mask = cv2.dilate(glass_mask, kernel, iterations=2)
glass_mask = cv2.medianBlur(glass_mask, 5)
except Exception as e:
print(f"[错误] 深度图预处理失败: {str(e)}")
return None, None, None
# 2. 玻璃区域分割
try:
# 查找轮廓并过滤小区域
contours, _ = cv2.findContours(glass_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
min_area = 1000
glass_roi = np.zeros_like(glass_mask)
for cnt in contours:
area = cv2.contourArea(cnt)
if area > min_area:
cv2.drawContours(glass_roi, [cnt], -1, 255, -1)
except Exception as e:
print(f"[错误] 玻璃区域分割失败: {str(e)}")
return None, None, None
# 3. 窗框检测
try:
# RGB图像预处理 - 使用安全转换
gray = safe_cvtColor(rgb_img, cv2.COLOR_BGR2GRAY)
if gray is None:
print("[警告] 使用备选灰度转换方法")
gray = cv2.cvtColor(rgb_img, cv2.COLOR_BGR2GRAY) if len(rgb_img.shape) == 3 else rgb_img
# 增强对比度
clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8, 8))
enhanced = clahe.apply(gray)
# 边缘检测
edges = cv2.Canny(enhanced, 50, 150)
# 霍夫变换检测直线
lines = cv2.HoughLinesP(edges, rho=1, theta=np.pi/180, threshold=50,
minLineLength=100, maxLineGap=10)
# 几何约束筛选窗框线
frame_lines = []
if lines is not None:
for line in lines:
x1, y1, x2, y2 = line[0]
if abs(x1 - x2) < 10 or abs(y1 - y2) < 10: # 水平/垂直线
frame_lines.append(line[0])
except Exception as e:
print(f"[错误] 窗框检测失败: {str(e)}")
frame_lines = []
# 4. 结果可视化
try:
result_img = rgb_img.copy()
# 确保结果图像是三通道
if len(result_img.shape) == 2:
result_img = cv2.cvtColor(result_img, cv2.COLOR_GRAY2BGR)
# 绘制玻璃区域(半透明红色)
glass_color = np.zeros_like(result_img)
glass_color[glass_roi == 255] = [0, 0, 255] # 红色
cv2.addWeighted(glass_color, 0.3, result_img, 1, 0, result_img)
# 绘制窗框线
for line in frame_lines:
x1, y1, x2, y2 = line
cv2.line(result_img, (x1, y1), (x2, y2), (0, 255, 0), 2)
except Exception as e:
print(f"[错误] 结果可视化失败: {str(e)}")
result_img = rgb_img.copy() # 返回原始图像作为备选
return glass_roi, frame_lines, result_img
def main():
"""主函数,包含完整的错误处理"""
print("玻璃窗检测程序启动")
# 获取当前脚本所在目录
script_dir = os.path.dirname(os.path.abspath(__file__)) if '__file__' in globals() else os.getcwd()
print(f"脚本目录: {script_dir}")
# 构建图像路径
rgb_path = os.path.join(script_dir, 'window_scene.jpg')
depth_path = os.path.join(script_dir, 'depth_map.png')
print(f"RGB图像路径: {rgb_path}")
print(f"深度图路径: {depth_path}")
# 安全读取图像
rgb_img = safe_imread(rgb_path, cv2.IMREAD_COLOR)
depth_map = safe_imread(depth_path, cv2.IMREAD_ANYDEPTH)
# 检查图像读取结果
if not validate_image(rgb_img, "RGB图像") or not validate_image(depth_map, "深度图"):
print("程序因图像读取失败而终止")
return
# 执行检测
try:
glass_mask, frame_lines, result_img = detect_glass_and_frame(rgb_img, depth_map)
except Exception as e:
print(f"[严重错误] 检测过程中发生异常: {str(e)}")
return
# 显示结果
plt.figure(figsize=(15, 10))
# RGB图像
plt.subplot(221)
plt.title("RGB Image")
if len(rgb_img.shape) == 2:
plt.imshow(rgb_img, cmap='gray')
else:
plt.imshow(cv2.cvtColor(rgb_img, cv2.COLOR_BGR2RGB))
# 深度图
plt.subplot(222)
plt.title("Depth Map")
plt.imshow(depth_map, cmap='jet')
plt.colorbar()
# 玻璃检测结果
plt.subplot(223)
plt.title("Glass Detection")
if glass_mask is not None:
plt.imshow(glass_mask, cmap='gray')
else:
plt.text(0.5, 0.5, "玻璃检测失败", ha='center', va='center')
plt.axis('off')
# 最终结果
plt.subplot(224)
plt.title("Detection Result")
if result_img is not None:
if len(result_img.shape) == 2:
plt.imshow(result_img, cmap='gray')
else:
plt.imshow(cv2.cvtColor(result_img, cv2.COLOR_BGR2RGB))
else:
plt.text(0.5, 0.5, "结果可视化失败", ha='center', va='center')
plt.axis('off')
plt.tight_layout()
plt.savefig('detection_results.png')
print("结果已保存为 detection_results.png")
plt.show()
if __name__ == "__main__":
main()
print("程序执行完成")