fix: update point.py logic
This commit is contained in:
parent
8d61f7f78c
commit
395dfec375
114
main/point.py
114
main/point.py
|
@ -28,13 +28,14 @@ def save_eroded(mask_color, out_path, kernel_size=(5, 5), erode_iter=10, dilate_
|
|||
cv2.imwrite(out_path, morphed_bgr)
|
||||
return morphed_bgr
|
||||
|
||||
def detect_circles(image_input, min_radius=50, max_radius=60, min_dist=200, param1=50, param2=17):
|
||||
def detect_circles(image_input, bounding_box=None, min_radius=40, max_radius=100, min_dist=20, param1=50, param2=17):
|
||||
"""
|
||||
对给定的图像进行霍夫圆检测,返回圆心坐标和半径
|
||||
|
||||
参数
|
||||
----
|
||||
image_input : 图像文件路径或图像数组
|
||||
bounding_box: 可选,(top_left, top_right, bottom_right, bottom_left) 形式的矩形框
|
||||
"""
|
||||
# 读取图像并转换为灰度图
|
||||
if isinstance(image_input, str):
|
||||
|
@ -46,6 +47,37 @@ def detect_circles(image_input, min_radius=50, max_radius=60, min_dist=200, para
|
|||
# 如果是图像数组
|
||||
image = cv2.cvtColor(image_input, cv2.COLOR_BGR2GRAY) if image_input.ndim == 3 else image_input.copy()
|
||||
|
||||
# 根据图像宽度动态调整max_radius
|
||||
h, w = image.shape[:2]
|
||||
if max(h, w) < 700:
|
||||
max_radius = 60
|
||||
min_radius = 30
|
||||
|
||||
# 如果提供了矩形框,则只在框内(去除左右10%)的区域检测
|
||||
if bounding_box:
|
||||
top_left, top_right, _, _ = bounding_box
|
||||
x_min = top_left[0]
|
||||
x_max = top_right[0]
|
||||
box_width = x_max - x_min
|
||||
|
||||
# 计算要保留的区域
|
||||
start_x = int(x_min + box_width * 0.1)
|
||||
end_x = int(x_max - box_width * 0.1)
|
||||
|
||||
# 创建一个全黑的掩膜
|
||||
mask = np.zeros_like(image)
|
||||
# 将保留区域设为白色
|
||||
mask[:, start_x:end_x] = 255
|
||||
# 将原图与掩膜相乘,只保留目标区域
|
||||
image = cv2.bitwise_and(image, mask)
|
||||
|
||||
else:
|
||||
# 兼容旧逻辑:屏蔽整张图的左右10%
|
||||
w = image.shape[1]
|
||||
image[:, :int(w * 0.05)] = 0
|
||||
image[:, int(w * 0.9):] = 0
|
||||
|
||||
|
||||
# 图像模糊处理,减少噪声
|
||||
blurred = cv2.GaussianBlur(image, (9, 9), 2)
|
||||
|
||||
|
@ -57,9 +89,25 @@ def detect_circles(image_input, min_radius=50, max_radius=60, min_dist=200, para
|
|||
|
||||
# 如果检测到圆
|
||||
if circles is not None:
|
||||
# 将坐标和半径转换为整数并返回
|
||||
circles = np.uint16(np.around(circles))
|
||||
centers = [(c[0], c[1], c[2]) for c in circles[0]]
|
||||
# 检查前两个圆心距离
|
||||
if len(centers) >= 2:
|
||||
x1, y1, _ = centers[0]
|
||||
x2, y2, _ = centers[1]
|
||||
x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2)
|
||||
dist = abs(x1 - x2) + abs(y1 - y2)
|
||||
if dist <= 200:
|
||||
# 增大max_radius并重新检测
|
||||
new_max_radius = max_radius + 20
|
||||
circles2 = cv2.HoughCircles(
|
||||
blurred, cv2.HOUGH_GRADIENT, dp=1.2, minDist=min_dist,
|
||||
param1=param1, param2=param2, minRadius=min_radius, maxRadius=new_max_radius
|
||||
)
|
||||
if circles2 is not None:
|
||||
circles2 = np.uint16(np.around(circles2))
|
||||
centers2 = [(c[0], c[1], c[2]) for c in circles2[0]]
|
||||
return centers2
|
||||
return centers # 返回 [(x1, y1, r1), (x2, y2, r2), ...]
|
||||
else:
|
||||
print("[Circle] 未检测到圆")
|
||||
|
@ -247,9 +295,9 @@ def find_EFH(A, B, G, bottom_line):
|
|||
return E, F, H
|
||||
# ------------------------- 找 G 点 -------------------------
|
||||
def find_G(image, line_info,
|
||||
kernel_size=(7, 7),
|
||||
erode_iter=10,
|
||||
dilate_iter=11,
|
||||
kernel_size=(3, 3),
|
||||
erode_iter=3,
|
||||
dilate_iter=3,
|
||||
adj=3):
|
||||
"""
|
||||
侧视图汽车最高点 G:沿直线从左到右(或上到下)找到遇到的第一个白色像素。
|
||||
|
@ -257,28 +305,32 @@ def find_G(image, line_info,
|
|||
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
|
||||
|
||||
# 形态学处理(固定参数版本)
|
||||
gray = apply_morphology(gray,
|
||||
kernel_size=kernel_size,
|
||||
erode_iter=erode_iter,
|
||||
dilate_iter=dilate_iter)
|
||||
# gray = apply_morphology(gray,
|
||||
# kernel_size=kernel_size,
|
||||
# erode_iter=erode_iter,
|
||||
# dilate_iter=dilate_iter)
|
||||
|
||||
# 【调试】保存形态学处理后的图像,检查车顶是否被腐蚀
|
||||
cv2.imwrite("debug_G_morphed_mask.png", gray)
|
||||
|
||||
|
||||
if line_info[0] is None: # 垂直线 x = const
|
||||
_, x, y1, y2 = line_info
|
||||
for y in range(int(min(y1, y2)), int(max(y1, y2))):
|
||||
if gray[y, int(x)] == 255:
|
||||
if gray[y, int(x)] >= 150:
|
||||
return int(x), y + adj
|
||||
|
||||
elif line_info[0] == 0: # 水平线 y = const
|
||||
_, y, x1, x2 = line_info
|
||||
for x in range(int(min(x1, x2)), int(max(x1, x2))):
|
||||
if gray[int(y), x] == 255:
|
||||
if gray[int(y), x] >= 150:
|
||||
return x, int(y) + adj
|
||||
|
||||
else: # 斜率线 y = ax + b
|
||||
a, b, x1, x2 = line_info
|
||||
for x in range(int(x1), int(x2) + 1):
|
||||
y = int(a * x + b)
|
||||
if 0 <= y < gray.shape[0] and gray[y, x] == 255:
|
||||
if 0 <= y < gray.shape[0] and gray[y, x] >= 150:
|
||||
return x, y + adj
|
||||
return None
|
||||
|
||||
|
@ -345,6 +397,14 @@ def find_bottom_gap_midpoint(mask_color, bottom_line, gap=20, direction='left'):
|
|||
print(f"[find_bottom_gap_midpoint] direction={direction}, 左端点=({dy_list[left_idx][0]}, {dy_list[left_idx][1]}), 右端点=({dy_list[right_idx][0]}, {dy_list[right_idx][1]})")
|
||||
return (int(dy_list[mid_idx][0]), int(dy_list[mid_idx][1]))
|
||||
|
||||
def preprocess_mask(mask_color, kernel_size=(3, 3), erode_iter=2, dilate_iter=2):
|
||||
gray = cv2.cvtColor(mask_color, cv2.COLOR_BGR2GRAY)
|
||||
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, kernel_size)
|
||||
eroded = cv2.erode(gray, kernel, iterations=erode_iter)
|
||||
morphed = cv2.dilate(eroded, kernel, iterations=dilate_iter)
|
||||
return cv2.cvtColor(morphed, cv2.COLOR_GRAY2BGR)
|
||||
|
||||
|
||||
def process_side(mask_path, rgb_path, out_dir):
|
||||
"""
|
||||
处理侧视图,检测并标注 A-H 点
|
||||
|
@ -355,12 +415,17 @@ def process_side(mask_path, rgb_path, out_dir):
|
|||
if mask_color is None or rgb_color is None:
|
||||
raise FileNotFoundError("无法读取 mask 或 RGB 图像")
|
||||
|
||||
# 缩放图像到1000*600
|
||||
# mask_color = resize_image(mask_color, (1000, 600))
|
||||
# rgb_color = resize_image(rgb_color, (1000, 600))
|
||||
# 先对mask做轻微腐蚀膨胀预处理
|
||||
mask_color = preprocess_mask(mask_color, kernel_size=(3, 3), erode_iter=2, dilate_iter=2)
|
||||
|
||||
circles = detect_circles(mask_color)
|
||||
# 1. 先获取外接矩形
|
||||
top_left, top_right, bottom_right, bottom_left = get_bounding_box(mask_color)
|
||||
|
||||
# 2. 将矩形框传入霍夫圆检测,只在框内特定区域检测
|
||||
bounding_box_coords = (top_left, top_right, bottom_right, bottom_left)
|
||||
circles = detect_circles(mask_color, bounding_box=bounding_box_coords)
|
||||
|
||||
# 3. 计算边线
|
||||
top_line, right_line, bottom_line, left_line = calculate_lines(
|
||||
top_left, top_right, bottom_right, bottom_left
|
||||
)
|
||||
|
@ -371,6 +436,7 @@ def process_side(mask_path, rgb_path, out_dir):
|
|||
E, F, H = find_EFH(A, B, G, bottom_line)
|
||||
|
||||
points = {'A': A, 'B': B, 'C': C, 'D': D, 'E': E, 'F': F, 'G': G, 'H': H}
|
||||
# 用原始mask_color和rgb_color做可视化
|
||||
for canvas in (mask_color, rgb_color):
|
||||
draw_line_equation(canvas, top_line)
|
||||
draw_line_equation(canvas, right_line)
|
||||
|
@ -379,8 +445,12 @@ def process_side(mask_path, rgb_path, out_dir):
|
|||
for label, pt in points.items():
|
||||
if pt is not None:
|
||||
cv2.circle(canvas, pt, 3, (0, 0, 255), -1)
|
||||
cv2.putText(canvas, label, (pt[0]+5, pt[1]-5),
|
||||
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 1, cv2.LINE_AA)
|
||||
if label == 'H':
|
||||
cv2.putText(canvas, label, (pt[0]+5, pt[1]+20),
|
||||
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 1, cv2.LINE_AA)
|
||||
else:
|
||||
cv2.putText(canvas, label, (pt[0]+5, pt[1]-5),
|
||||
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 1, cv2.LINE_AA)
|
||||
cv2.imwrite(os.path.join(out_dir, 'side_output_mask.png'), mask_color)
|
||||
cv2.imwrite(os.path.join(out_dir, 'side_output_rgb.png'), rgb_color)
|
||||
print("A =", A, " B =", B,"C =", C, " D =", D," G =", G , "E =", E ,"F =", F ,"H =", H )
|
||||
|
@ -524,8 +594,8 @@ def process_front(mask_path, rgb_path, out_dir):
|
|||
print(f"[front] 结果已保存到 {out_dir}")
|
||||
|
||||
if __name__ == '__main__':
|
||||
side_mask = '../segment-anything-main/output/2_mask.png'
|
||||
side_rgb = '../ultralytics-main/input/2.png'
|
||||
side_mask = '../segment-anything-main/output/5_mask.png'
|
||||
side_rgb = '../ultralytics-main/input/5.jpg'
|
||||
|
||||
front_mask = '../segment-anything-main/output/00213_mask.png'
|
||||
front_rgb = '../ultralytics-main/input/00213.jpg'
|
||||
|
@ -536,5 +606,5 @@ if __name__ == '__main__':
|
|||
out_dir = './result'
|
||||
|
||||
process_side(side_mask, side_rgb, out_dir)
|
||||
process_front(front_mask, front_rgb, out_dir)
|
||||
process_rear(rear_mask, rear_rgb, out_dir)
|
||||
# process_front(front_mask, front_rgb, out_dir)
|
||||
# process_rear(rear_mask, rear_rgb, out_dir)
|
||||
|
|
Loading…
Reference in New Issue