mi-task/utils/fisheye.py
2025-08-21 11:25:38 +08:00

98 lines
3.4 KiB
Python
Executable File

import cv2
import numpy as np
import os
def detect_yellow_distance_from_bottom(image_path, visualize=False):
"""
增强可视化版本的鱼眼图像黄色点检测
"""
def show_step(step_name, img, delay=500):
"""显示处理步骤"""
if visualize:
cv2.imshow(step_name, img)
cv2.waitKey(delay)
cv2.imwrite(f"saved_images/step_{step_name}.jpg", img)
# 1. 读取图像
img = cv2.imread(image_path)
if img is None:
raise ValueError("无法读取图像")
show_step("01_original", img)
# 2. 鱼眼矫正(简化版,实际需用真实相机参数)
h, w = img.shape[:2]
K = np.array([[w, 0, w//2], [0, h, h//2], [0, 0, 1]]) # 假设的相机矩阵
D = np.array([-0.3, 0.1, 0, 0]) # 假设的畸变系数
undistorted = cv2.fisheye.undistortImage(img, K, D)
show_step("02_undistorted", undistorted)
# 3. 颜色空间转换
hsv = cv2.cvtColor(undistorted, cv2.COLOR_BGR2HSV)
show_step("03_hsv", cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)) # 转回BGR便于显示
# 4. 颜色阈值处理
lower_yellow = np.array([20, 150, 150]) # 调整后的阈值
upper_yellow = np.array([30, 255, 255])
color_mask = cv2.inRange(hsv, lower_yellow, upper_yellow)
show_step("04_color_mask", color_mask)
# 5. 形态学处理
kernel = np.ones((5,5), np.uint8)
opened = cv2.morphologyEx(color_mask, cv2.MORPH_OPEN, kernel)
closed = cv2.morphologyEx(opened, cv2.MORPH_CLOSE, kernel)
show_step("05_morphology", closed)
# 6. 创建垂直区域掩模
center_x = w // 2
line_width = max(5, int(w * 0.02)) # 2%宽度
vertical_mask = np.zeros((h,w), dtype=np.uint8)
cv2.rectangle(vertical_mask, (center_x-line_width,0), (center_x+line_width,h), 255, -1)
show_step("06_vertical_mask", vertical_mask)
# 7. 组合掩模
final_mask = cv2.bitwise_and(closed, vertical_mask)
show_step("07_final_mask", final_mask)
# 8. 轮廓检测
contours, _ = cv2.findContours(final_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contour_img = cv2.cvtColor(final_mask, cv2.COLOR_GRAY2BGR)
cv2.drawContours(contour_img, contours, -1, (0,255,0), 2)
show_step("08_contours", contour_img)
if not contours:
print("未检测到黄色区域")
return None, None, final_mask
# 9. 寻找最低点
lowest_point = max(
[tuple(cnt[cnt[:,:,1].argmax()][0]) for cnt in contours],
key=lambda p: p[1]
)
distance = h - lowest_point[1]
# 10. 最终可视化
result_img = undistorted.copy()
cv2.line(result_img, (center_x,0), (center_x,h), (0,255,0), 1)
cv2.circle(result_img, lowest_point, 10, (0,0,255), -1)
cv2.line(result_img, lowest_point, (lowest_point[0],h), (0,0,255), 2)
cv2.putText(result_img, f"Distance: {distance}px", (10,30),
cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,255), 2)
show_step("09_final_result", result_img)
return distance, center_x, final_mask
# 使用示例
try:
os.makedirs("saved_images", exist_ok=True)
distance, center_x, _ = detect_yellow_distance_from_bottom(
"/home/mi-task/saved_images/right_eg.jpg",
visualize=True
)
if distance is not None:
print(f"中垂线最低黄点距离底部: {distance}像素 (x={center_x})")
else:
print("未检测到目标")
except Exception as e:
print(f"错误: {str(e)}")