image_to_pixle_params_yoloSAM/main/point.py

611 lines
23 KiB
Python
Raw Normal View History

2025-07-14 17:36:53 +08:00
import cv2
import numpy as np
import os
# main.py
# ───────────── 导入 utils 内的工具函数 ─────────────
from utils import *
# 之后就可以直接调用,例如:
# tl, tr, br, bl = get_bounding_box(mask_path)
# top_line, right_line, bottom_line, left_line = calculate_lines(tl, tr, br, bl)
def resize_image(image, target_size=(1000, 600)):
"""
将图像缩放到指定尺寸
"""
return cv2.resize(image, target_size, interpolation=cv2.INTER_LINEAR)
def save_eroded(mask_color, out_path, kernel_size=(5, 5), erode_iter=10, dilate_iter=10):
"""
保存腐蚀10次再膨胀10次后的掩膜图像便于可视化
返回处理后的图像
"""
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)
morphed_bgr = cv2.cvtColor(morphed, cv2.COLOR_GRAY2BGR)
cv2.imwrite(out_path, morphed_bgr)
return morphed_bgr
2025-07-28 16:12:59 +08:00
def detect_circles(image_input, bounding_box=None, min_radius=40, max_radius=100, min_dist=20, param1=50, param2=17):
2025-07-14 17:36:53 +08:00
"""
对给定的图像进行霍夫圆检测返回圆心坐标和半径
参数
----
image_input : 图像文件路径或图像数组
2025-07-28 16:12:59 +08:00
bounding_box: 可选(top_left, top_right, bottom_right, bottom_left) 形式的矩形框
2025-07-14 17:36:53 +08:00
"""
# 读取图像并转换为灰度图
if isinstance(image_input, str):
# 如果是文件路径
image = cv2.imread(image_input, cv2.IMREAD_GRAYSCALE)
if image is None:
raise FileNotFoundError(f"图像文件 {image_input} 未找到")
else:
# 如果是图像数组
image = cv2.cvtColor(image_input, cv2.COLOR_BGR2GRAY) if image_input.ndim == 3 else image_input.copy()
2025-07-28 16:12:59 +08:00
# 根据图像宽度动态调整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
2025-07-14 17:36:53 +08:00
# 图像模糊处理,减少噪声
blurred = cv2.GaussianBlur(image, (9, 9), 2)
# 霍夫圆变换检测圆
circles = cv2.HoughCircles(
blurred, cv2.HOUGH_GRADIENT, dp=1.2, minDist=min_dist,
param1=param1, param2=param2, minRadius=min_radius, maxRadius=max_radius
)
# 如果检测到圆
if circles is not None:
circles = np.uint16(np.around(circles))
centers = [(c[0], c[1], c[2]) for c in circles[0]]
2025-07-28 16:12:59 +08:00
# 检查前两个圆心距离
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
2025-07-14 17:36:53 +08:00
return centers # 返回 [(x1, y1, r1), (x2, y2, r2), ...]
else:
print("[Circle] 未检测到圆")
return [] # 返回空列表表示未检测到圆
def draw_line_equation(image, line_info, color=(0, 255, 0), thickness=2):
"""
根据线性表达式绘制线段而非无限直线
"""
if line_info[0] is None:
# 垂直线 x = const
_, x, y1, y2 = line_info
pt1 = (int(x), int(min(y1, y2)))
pt2 = (int(x), int(max(y1, y2)))
elif line_info[0] == 0:
# 水平线 y = const
_, y, x1, x2 = line_info
pt1 = (int(min(x1, x2)), int(y))
pt2 = (int(max(x1, x2)), int(y))
else:
# 斜率线 y = ax + b
a, b, x1, x2 = line_info
x1, x2 = int(x1), int(x2)
pt1 = (x1, int(a * x1 + b))
pt2 = (x2, int(a * x2 + b))
cv2.line(image, pt1, pt2, color, thickness)
def draw_circles(image, circles, color=(0, 0, 255), thickness=2):
"""
根据圆心坐标和半径在图像上绘制圆心和圆并保存图像
"""
for (x, y, r) in circles:
# 画圆边
# cv2.circle(image, (x, y), r, (0, 255, 0), 2)
# 画圆心
cv2.circle(image, (x, y), 3, (0, 0, 255), -1)
# ------------------------- 找 A,B 点 -------------------------
def find_A_B(circles):
"""
circles : [(x, y, r), ...] 来自 detect_circles()
返回 (A, B) 均为 (x, y) None
规则检测到的第 1 个圆心为 A 2 个为 B
"""
if len(circles) == 0:
return None, None
elif len(circles) == 1:
return (circles[0][0], circles[0][1]), None
else:
A = (circles[0][0], circles[0][1])
B = (circles[1][0], circles[1][1])
return A, B
# ------------------------- 找 C 点 -------------------------
def find_C(image, line_info,
thresh_val=250,
do_morph=False,
kernel_size=(5, 5),
iterations=3,
adj = -5):
"""
C 沿给定直线自"下 → 上"遇到的第一个白色像素
"""
# 灰度化
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) if image.ndim == 3 else image.copy()
# 可选形态学
if do_morph:
gray = apply_morphology(gray,
kernel_size=kernel_size,
erode_iter=iterations,
dilate_iter=iterations)
# 垂直线 x = const
if line_info[0] is None:
_, x_const, y1, y2 = line_info
x_const = int(x_const)
for y in range(int(max(y1, y2)), int(min(y1, y2)) - 1, -1): # ⬅️ 下→上
if gray[y, x_const] >= thresh_val:
return x_const, y + adj
# 水平线 y = const极少需要
elif line_info[0] == 0:
_, y_const, x1, x2 = line_info
y_const = int(y_const)
for y in range(gray.shape[0] - 1, -1, -1): # ⬅️ 底→顶
if gray[y, int(x1)] >= thresh_val:
return int(x1), y + adj
# 斜线 y = ax + b
else:
a, b, x1, x2 = line_info
xs = np.linspace(x1, x2, num=abs(int(x2 - x1)) + 1, dtype=int)
ys = (a * xs + b).astype(int)
for x_i, y_i in sorted(zip(xs, ys), key=lambda p: -p[1]): # ⬅️ y 降序
if 0 <= x_i < gray.shape[1] and 0 <= y_i < gray.shape[0]:
if gray[y_i, x_i] >= thresh_val:
return x_i, y_i + adj
return None
# ------------------------- 找 D 点 -------------------------
def find_D(image, line_info,
thresh_val=250,
do_morph=False,
kernel_size=(3, 3),
iterations=9,
adj = - 5):
"""
最右侧直线或给定 line_info与图像区域的第一个白色像素交点
采用"自下而上"扫描策略
参数
----
image : BGR/灰度图
line_info : get_line_equation 返回格式一致
thresh_val : 像素灰度值 thresh_val 判定为白
do_morph : 是否做形态学去噪
kernel_size : 形态学核尺寸
iterations : 腐蚀/膨胀迭代次数
"""
# 1) 灰度化
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) if image.ndim == 3 else image.copy()
# 2) 形态学(可选)
if do_morph:
gray = apply_morphology(gray,
kernel_size=kernel_size,
erode_iter=iterations,
dilate_iter=iterations+1)
# 3) 自下而上扫描
if line_info[0] is None: # 垂直线 x = const
_, x_const, y1, y2 = line_info
x_const = int(x_const)
for y in range(int(max(y1, y2)), int(min(y1, y2)) - 1, -1):
if gray[y, x_const] >= thresh_val:
return x_const, y + adj
elif line_info[0] == 0: # 水平线 y = const少见
_, y_const, x1, x2 = line_info
y_const = int(y_const)
for y in range(gray.shape[0] - 1, -1, -1):
if gray[y, int(x1)] >= thresh_val:
return int(x1), y + adj
else: # 斜率线 y = a x + b
a, b, x1, x2 = line_info
xs = np.linspace(x1, x2, num=abs(int(x2 - x1)) + 1, dtype=int)
ys = (a * xs + b).astype(int)
for x_i, y_i in sorted(zip(xs, ys), key=lambda p: -p[1]): # y 由大到小
if 0 <= x_i < gray.shape[1] and 0 <= y_i < gray.shape[0]:
if gray[y_i, x_i] >= thresh_val:
return x_i, y_i + adj
return None
def find_EFH(A, B, G, bottom_line):
"""
参数
----
A, B, G : 三个已知点坐标 (x, y) None
bottom_line : 外接矩形底边的 line_info来自 calculate_lines
返回
----
(E, F, H) : 三个垂足坐标若对应输入为 None 则返回 None
"""
E = perpendicular_foot(A, bottom_line) if A else None
F = perpendicular_foot(B, bottom_line) if B else None
H = perpendicular_foot(G, bottom_line) if G else None
return E, F, H
# ------------------------- 找 G 点 -------------------------
def find_G(image, line_info,
2025-07-28 16:12:59 +08:00
kernel_size=(3, 3),
erode_iter=3,
dilate_iter=3,
2025-07-14 17:36:53 +08:00
adj=3):
"""
侧视图汽车最高点 G沿直线从左到右或上到下找到遇到的第一个白色像素
"""
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 形态学处理(固定参数版本)
2025-07-28 16:12:59 +08:00
# gray = apply_morphology(gray,
# kernel_size=kernel_size,
# erode_iter=erode_iter,
# dilate_iter=dilate_iter)
# 【调试】保存形态学处理后的图像,检查车顶是否被腐蚀
cv2.imwrite("debug_G_morphed_mask.png", gray)
2025-07-14 17:36:53 +08:00
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))):
2025-07-28 16:12:59 +08:00
if gray[y, int(x)] >= 150:
2025-07-14 17:36:53 +08:00
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))):
2025-07-28 16:12:59 +08:00
if gray[int(y), x] >= 150:
2025-07-14 17:36:53 +08:00
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)
2025-07-28 16:12:59 +08:00
if 0 <= y < gray.shape[0] and gray[y, x] >= 150:
2025-07-14 17:36:53 +08:00
return x, y + adj
return None
def find_bottom_gap_midpoint(mask_color, bottom_line, gap=20, direction='left'):
"""
遍历底边采样点往上找gap距离内的白色点
第一个dy<=gap的点为左端点第一个dy>gap的点的前一个为右端点
L/M点为区间中心
"""
gray = cv2.cvtColor(mask_color, cv2.COLOR_BGR2GRAY)
h, w = gray.shape
# 采样底边线段上的点
if bottom_line[0] is None: # 垂直线
_, x_const, y1, y2 = bottom_line
ys = np.linspace(y1, y2, abs(int(y2 - y1)) + 1, dtype=int)
xs = np.full_like(ys, int(x_const))
elif bottom_line[0] == 0: # 水平线
_, y_const, x1, x2 = bottom_line
xs = np.linspace(x1, x2, abs(int(x2 - x1)) + 1, dtype=int)
ys = np.full_like(xs, int(y_const))
else: # 斜率线
a, b, x1, x2 = bottom_line
xs = np.linspace(x1, x2, abs(int(x2 - x1)) + 1, dtype=int)
ys = (a * xs + b).astype(int)
# 按方向决定遍历顺序
if direction == 'left':
idx_range = range(len(xs))
else:
idx_range = range(len(xs) - 1, -1, -1)
dy_list = [] # 存储(x, y, dy)
for i in idx_range:
x, y = xs[i], ys[i]
dy = None
for d in range(1, gap + 2):
yy = y - d
if 0 <= x < w and 0 <= yy < h and gray[yy, x] >= 200:
dy = d
break
dy_list.append((x, y, dy))
# 找左端点第一个dy<=gap的点
left_idx = None
for i, (x, y, dy) in enumerate(dy_list):
if dy is not None and dy <= gap:
left_idx = i
break
if left_idx is None:
return None
# 找右端点第一个dy>gap的点的前一个
right_idx = None
for i in range(left_idx, len(dy_list)):
dy = dy_list[i][2]
if dy is None or dy > gap:
right_idx = i - 1
break
if right_idx is None:
right_idx = len(dy_list) - 1
# 区间中心
mid_idx = (left_idx + right_idx) // 2
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]))
2025-07-28 16:12:59 +08:00
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)
2025-07-14 17:36:53 +08:00
def process_side(mask_path, rgb_path, out_dir):
"""
处理侧视图检测并标注 A-H
"""
os.makedirs(out_dir, exist_ok=True)
mask_color = cv2.imread(mask_path, cv2.IMREAD_COLOR)
rgb_color = cv2.imread(rgb_path, cv2.IMREAD_COLOR)
if mask_color is None or rgb_color is None:
raise FileNotFoundError("无法读取 mask 或 RGB 图像")
2025-07-28 16:12:59 +08:00
# 先对mask做轻微腐蚀膨胀预处理
mask_color = preprocess_mask(mask_color, kernel_size=(3, 3), erode_iter=2, dilate_iter=2)
2025-07-14 17:36:53 +08:00
2025-07-28 16:12:59 +08:00
# 1. 先获取外接矩形
2025-07-14 17:36:53 +08:00
top_left, top_right, bottom_right, bottom_left = get_bounding_box(mask_color)
2025-07-28 16:12:59 +08:00
# 2. 将矩形框传入霍夫圆检测,只在框内特定区域检测
bounding_box_coords = (top_left, top_right, bottom_right, bottom_left)
circles = detect_circles(mask_color, bounding_box=bounding_box_coords)
# 3. 计算边线
2025-07-14 17:36:53 +08:00
top_line, right_line, bottom_line, left_line = calculate_lines(
top_left, top_right, bottom_right, bottom_left
)
A, B = find_A_B(circles)
C = find_C(mask_color, left_line)
D = find_D(mask_color, right_line)
G = find_G(mask_color, top_line)
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}
2025-07-28 16:12:59 +08:00
# 用原始mask_color和rgb_color做可视化
2025-07-14 17:36:53 +08:00
for canvas in (mask_color, rgb_color):
draw_line_equation(canvas, top_line)
draw_line_equation(canvas, right_line)
draw_line_equation(canvas, bottom_line)
draw_line_equation(canvas, left_line)
for label, pt in points.items():
if pt is not None:
cv2.circle(canvas, pt, 3, (0, 0, 255), -1)
2025-07-28 16:12:59 +08:00
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)
2025-07-14 17:36:53 +08:00
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 )
print(f"[side] 结果已保存到 {out_dir}")
def process_rear(mask_path, rgb_path, out_dir):
"""
处理后视图检测并标注 P, N, O, Q, R
"""
os.makedirs(out_dir, exist_ok=True)
mask_color = cv2.imread(mask_path, cv2.IMREAD_COLOR)
rgb_color = cv2.imread(rgb_path, cv2.IMREAD_COLOR)
if mask_color is None or rgb_color is None:
raise FileNotFoundError("无法读取 mask 或 RGB 图像")
# 先验知识的外接矩形(与正视图一致)
top_left, top_right, bottom_right, bottom_left = get_front_bounding_box_with_prior(mask_color)
top_line, right_line, bottom_line, left_line = calculate_lines(
top_left, top_right, bottom_right, bottom_left
)
# 保存绘制外接矩形的图片
mask_with_rect = mask_color.copy()
draw_line_equation(mask_with_rect, top_line)
draw_line_equation(mask_with_rect, right_line)
draw_line_equation(mask_with_rect, bottom_line)
draw_line_equation(mask_with_rect, left_line)
cv2.imwrite(os.path.join(out_dir, 'rear_with_rect.png'), mask_with_rect)
# P: 上边线段中点
P = ((top_left[0] + top_right[0]) // 2, (top_left[1] + top_right[1]) // 2)
# N: 左边线段的中点
N = ((top_left[0] + bottom_left[0]) // 2, (top_left[1] + bottom_left[1]) // 2)
# O: 右边线段的中点
O = ((top_right[0] + bottom_right[0]) // 2, (top_right[1] + bottom_right[1]) // 2)
R = find_bottom_gap_midpoint(mask_color, bottom_line, gap=8, direction='left')
Q = find_bottom_gap_midpoint(mask_color, bottom_line, gap=8, direction='right')
points = {'P': P, 'N': N, 'O': O, 'Q': Q, 'R': R}
for canvas in (mask_color, rgb_color):
draw_line_equation(canvas, top_line)
draw_line_equation(canvas, right_line)
draw_line_equation(canvas, bottom_line)
draw_line_equation(canvas, left_line)
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)
cv2.imwrite(os.path.join(out_dir, 'rear_output_mask.png'), mask_color)
cv2.imwrite(os.path.join(out_dir, 'rear_output_rgb.png'), rgb_color)
print("P =", P, "N =", N, "O =", O, "Q =", Q, "R =", R)
print(f"[rear] 结果已保存到 {out_dir}")
def get_front_bounding_box_with_prior(mask):
"""
先将mask上1/2区域设为黑色仅用下1/3区域的白色像素计算左右边界上下边界用原始mask
返回 (top_left, top_right, bottom_right, bottom_left)
"""
h, w = mask.shape[:2]
# 1. 生成处理后的mask上2/3黑下1/3保留
mask_proc = mask.copy()
y_cut = h * 1 // 2
mask_proc[:y_cut, :] = 0
# 2. 计算左右边界下1/3区域
# 只考虑白色像素
gray_proc = cv2.cvtColor(mask_proc, cv2.COLOR_BGR2GRAY) if mask_proc.ndim == 3 else mask_proc
coords = cv2.findNonZero((gray_proc > 127).astype(np.uint8))
if coords is None:
raise ValueError("处理后mask没有白色区域无法计算左右边界")
xs = coords[:, 0, 0]
ys = coords[:, 0, 1]
left_x = np.min(xs)
right_x = np.max(xs)
# 3. 计算上下边界原始mask
gray = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY) if mask.ndim == 3 else mask
coords_full = cv2.findNonZero((gray > 127).astype(np.uint8))
if coords_full is None:
raise ValueError("原始mask没有白色区域无法计算上下边界")
top_y = np.min(coords_full[:, 0, 1])
bottom_y = np.max(coords_full[:, 0, 1])
# 4. 返回四个点
top_left = (left_x, top_y)
top_right = (right_x, top_y)
bottom_right = (right_x, bottom_y)
bottom_left = (left_x, bottom_y)
return top_left, top_right, bottom_right, bottom_left
def process_front(mask_path, rgb_path, out_dir):
"""
处理前视图检测并标注 K, I, J, L, M
"""
os.makedirs(out_dir, exist_ok=True)
mask_color = cv2.imread(mask_path, cv2.IMREAD_COLOR)
rgb_color = cv2.imread(rgb_path, cv2.IMREAD_COLOR)
if mask_color is None or rgb_color is None:
raise FileNotFoundError("无法读取 mask 或 RGB 图像")
# 先进行腐蚀膨胀处理
#mask_processed = save_eroded(mask_color, os.path.join(out_dir, 'front_eroded_mask.png'),
# kernel_size=(5, 5), erode_iter=8, dilate_iter=5)
mask_processed = mask_color
# 使用先验知识的外接矩形
top_left, top_right, bottom_right, bottom_left = get_front_bounding_box_with_prior(mask_processed)
top_line, right_line, bottom_line, left_line = calculate_lines(
top_left, top_right, bottom_right, bottom_left
)
# 保存绘制外接矩形的图片
mask_with_rect = mask_processed.copy()
draw_line_equation(mask_with_rect, top_line)
draw_line_equation(mask_with_rect, right_line)
draw_line_equation(mask_with_rect, bottom_line)
draw_line_equation(mask_with_rect, left_line)
cv2.imwrite(os.path.join(out_dir, 'front_with_rect.png'), mask_with_rect)
# K: 上边线段中点
K = ((top_left[0] + top_right[0]) // 2, (top_left[1] + top_right[1]) // 2)
# I: 左边线段的高度一半处
I = (left_line[1], (left_line[2] + left_line[3]) // 2) if left_line[0] is None else None
# J: 右边线段的高度一半处
J = (right_line[1], (right_line[2] + right_line[3]) // 2) if right_line[0] is None else None
M = find_bottom_gap_midpoint(mask_color, bottom_line, gap=8, direction='left')
L = find_bottom_gap_midpoint(mask_color, bottom_line, gap=8, direction='right')
points = {'K': K, 'I': I, 'J': J, 'L': L, 'M': M}
for canvas in (mask_color, rgb_color):
draw_line_equation(canvas, top_line)
draw_line_equation(canvas, right_line)
draw_line_equation(canvas, bottom_line)
draw_line_equation(canvas, left_line)
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)
cv2.imwrite(os.path.join(out_dir, 'front_output_mask.png'), mask_color)
cv2.imwrite(os.path.join(out_dir, 'front_output_rgb.png'), rgb_color)
print("K =", K, "I =", I, "J =", J, "L =", L, "M =", M)
print(f"[front] 结果已保存到 {out_dir}")
if __name__ == '__main__':
2025-07-28 16:12:59 +08:00
side_mask = '../segment-anything-main/output/5_mask.png'
side_rgb = '../ultralytics-main/input/5.jpg'
2025-07-14 17:36:53 +08:00
front_mask = '../segment-anything-main/output/00213_mask.png'
front_rgb = '../ultralytics-main/input/00213.jpg'
rear_mask = '../segment-anything-main/output/3_mask.png'
rear_rgb = '../ultralytics-main/input/3.jpg'
out_dir = './result'
process_side(side_mask, side_rgb, out_dir)
2025-07-28 16:12:59 +08:00
# process_front(front_mask, front_rgb, out_dir)
# process_rear(rear_mask, rear_rgb, out_dir)