|
|
@ -27,6 +27,7 @@ running = False
|
|
|
|
kf = None
|
|
|
|
kf = None
|
|
|
|
cap = None
|
|
|
|
cap = None
|
|
|
|
root = None
|
|
|
|
root = None
|
|
|
|
|
|
|
|
stop_thread = False
|
|
|
|
def initialize_kalman_filter():
|
|
|
|
def initialize_kalman_filter():
|
|
|
|
"""初始化卡尔曼滤波器"""
|
|
|
|
"""初始化卡尔曼滤波器"""
|
|
|
|
global kf
|
|
|
|
global kf
|
|
|
@ -45,8 +46,8 @@ def initialize_kalman_filter():
|
|
|
|
# 用于初始化卡尔曼滤波器的变量
|
|
|
|
# 用于初始化卡尔曼滤波器的变量
|
|
|
|
initial_measurement = None
|
|
|
|
initial_measurement = None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#初始化摄像头
|
|
|
|
def initialize_camera():
|
|
|
|
def initialize_camera():
|
|
|
|
"""初始化摄像头"""
|
|
|
|
|
|
|
|
global cap
|
|
|
|
global cap
|
|
|
|
cap = cv2.VideoCapture(0)
|
|
|
|
cap = cv2.VideoCapture(0)
|
|
|
|
|
|
|
|
|
|
|
@ -54,19 +55,34 @@ def choose_color():
|
|
|
|
global selected_color
|
|
|
|
global selected_color
|
|
|
|
# 显示颜色选择对话框
|
|
|
|
# 显示颜色选择对话框
|
|
|
|
color_options = list(color_hsv_ranges.keys())
|
|
|
|
color_options = list(color_hsv_ranges.keys())
|
|
|
|
selected_color = simpledialog.askstring("Choose Color", "Enter the color (blue, green, red, custom):",
|
|
|
|
selected_color = simpledialog.askstring("选择颜色", "输入颜色 (blue, green, red, custom):",
|
|
|
|
initialvalue=selected_color, parent=root)
|
|
|
|
initialvalue=selected_color, parent=root)
|
|
|
|
# 检查颜色选择是否有效,更新阈值
|
|
|
|
# 检查颜色选择是否有效,更新阈值
|
|
|
|
if selected_color in color_options:
|
|
|
|
if selected_color in color_options:
|
|
|
|
update_color_threshold(selected_color)
|
|
|
|
update_color_threshold(selected_color)
|
|
|
|
else:
|
|
|
|
else:
|
|
|
|
messagebox.showerror("Error", "Invalid color selection.")
|
|
|
|
messagebox.showerror("错误", "颜色选择无效")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def rgb_to_hsv(rgba):
|
|
|
|
|
|
|
|
"""将RGB颜色转换为HSV颜色"""
|
|
|
|
|
|
|
|
rgb = rgba[:3] # 忽略alpha通道
|
|
|
|
|
|
|
|
hsv = cv2.cvtColor(np.uint8([[rgb]]), cv2.COLOR_RGB2HSV)[0][0]
|
|
|
|
|
|
|
|
return hsv
|
|
|
|
|
|
|
|
|
|
|
|
def choose_custom_color():
|
|
|
|
def choose_custom_color():
|
|
|
|
color_code = colorchooser.askcolor(title="Choose Custom Color")
|
|
|
|
color_code = colorchooser.askcolor(title="选择自定义颜色")
|
|
|
|
if color_code[0] is not None:
|
|
|
|
if color_code[0] is not None:
|
|
|
|
lower = np.array([color_code[0][0] / 2, color_code[0][1] / 2, color_code[0][2] / 2])
|
|
|
|
hsv_color = rgb_to_hsv(color_code[0])
|
|
|
|
upper = np.array([color_code[0][0], color_code[0][1], color_code[0][2]])
|
|
|
|
|
|
|
|
|
|
|
|
# 计算HSV的下限和上限
|
|
|
|
|
|
|
|
lower = np.array([hsv_color[0] - 35, hsv_color[1] * 0.5, hsv_color[2] * 0.65])
|
|
|
|
|
|
|
|
upper = np.array([hsv_color[0] + 10, hsv_color[1] * 1.2, hsv_color[2] * 1.2])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 确保HSV值在有效范围内
|
|
|
|
|
|
|
|
lower = np.clip(lower, 0, 180)
|
|
|
|
|
|
|
|
upper = np.clip(upper, 0, 255)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 更新自定义颜色的HSV阈值
|
|
|
|
update_custom_hsv(lower, upper)
|
|
|
|
update_custom_hsv(lower, upper)
|
|
|
|
|
|
|
|
|
|
|
|
def update_custom_hsv(lower, upper):
|
|
|
|
def update_custom_hsv(lower, upper):
|
|
|
@ -76,17 +92,19 @@ def update_custom_hsv(lower, upper):
|
|
|
|
update_color_threshold('custom')
|
|
|
|
update_color_threshold('custom')
|
|
|
|
|
|
|
|
|
|
|
|
def exit_app():
|
|
|
|
def exit_app():
|
|
|
|
global running, cap
|
|
|
|
global running, cap, stop_thread
|
|
|
|
running = False
|
|
|
|
running = False
|
|
|
|
|
|
|
|
stop_thread = True
|
|
|
|
|
|
|
|
root.quit()
|
|
|
|
cap.release()
|
|
|
|
cap.release()
|
|
|
|
cv2.destroyAllWindows()
|
|
|
|
cv2.destroyAllWindows()
|
|
|
|
root.quit()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def initialize_gui():
|
|
|
|
def initialize_gui():
|
|
|
|
"""初始化GUI界面"""
|
|
|
|
"""初始化GUI界面"""
|
|
|
|
global root
|
|
|
|
global root
|
|
|
|
root = tk.Tk()
|
|
|
|
root = tk.Tk()
|
|
|
|
root.title("Color Tracker")
|
|
|
|
root.title("颜色追踪")
|
|
|
|
# 开始/停止摄像头按钮
|
|
|
|
# 开始/停止摄像头按钮
|
|
|
|
start_button = tk.Button(root, text="开始/停止", command=start_camera)
|
|
|
|
start_button = tk.Button(root, text="开始/停止", command=start_camera)
|
|
|
|
start_button.pack()
|
|
|
|
start_button.pack()
|
|
|
@ -111,37 +129,37 @@ def initialize_gui():
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# 自定义颜色HSV滑块
|
|
|
|
# 自定义颜色HSV滑块
|
|
|
|
lower_h_scale = Scale(root, from_=0, to=180, orient=HORIZONTAL, label="Hue Min",
|
|
|
|
lower_h_scale = Scale(root, from_=0, to=180, orient=HORIZONTAL, label="色调 Min",
|
|
|
|
command=lambda v: set_custom_hsv(v, lower_s_scale.get(), lower_v_scale.get(),
|
|
|
|
command=lambda v: set_custom_hsv(v, lower_s_scale.get(), lower_v_scale.get(),
|
|
|
|
upper_h_scale.get(),
|
|
|
|
upper_h_scale.get(),
|
|
|
|
upper_s_scale.get(), upper_v_scale.get()))
|
|
|
|
upper_s_scale.get(), upper_v_scale.get()))
|
|
|
|
lower_h_scale.pack()
|
|
|
|
lower_h_scale.pack()
|
|
|
|
|
|
|
|
|
|
|
|
lower_s_scale = Scale(root, from_=0, to=255, orient=HORIZONTAL, label="Saturation Min",
|
|
|
|
lower_s_scale = Scale(root, from_=0, to=255, orient=HORIZONTAL, label="饱和度 Min",
|
|
|
|
command=lambda v: set_custom_hsv(lower_h_scale.get(), v, lower_v_scale.get(),
|
|
|
|
command=lambda v: set_custom_hsv(lower_h_scale.get(), v, lower_v_scale.get(),
|
|
|
|
upper_h_scale.get(),
|
|
|
|
upper_h_scale.get(),
|
|
|
|
upper_s_scale.get(), upper_v_scale.get()))
|
|
|
|
upper_s_scale.get(), upper_v_scale.get()))
|
|
|
|
lower_s_scale.pack()
|
|
|
|
lower_s_scale.pack()
|
|
|
|
|
|
|
|
|
|
|
|
lower_v_scale = Scale(root, from_=0, to=255, orient=HORIZONTAL, label="Value Min",
|
|
|
|
lower_v_scale = Scale(root, from_=0, to=255, orient=HORIZONTAL, label="亮度 Min",
|
|
|
|
command=lambda v: set_custom_hsv(lower_h_scale.get(), lower_s_scale.get(), v,
|
|
|
|
command=lambda v: set_custom_hsv(lower_h_scale.get(), lower_s_scale.get(), v,
|
|
|
|
upper_h_scale.get(),
|
|
|
|
upper_h_scale.get(),
|
|
|
|
upper_s_scale.get(), upper_v_scale.get()))
|
|
|
|
upper_s_scale.get(), upper_v_scale.get()))
|
|
|
|
lower_v_scale.pack()
|
|
|
|
lower_v_scale.pack()
|
|
|
|
|
|
|
|
|
|
|
|
upper_h_scale = Scale(root, from_=0, to=180, orient=HORIZONTAL, label="Hue Max",
|
|
|
|
upper_h_scale = Scale(root, from_=0, to=180, orient=HORIZONTAL, label="色调 Max",
|
|
|
|
command=lambda v: set_custom_hsv(lower_h_scale.get(), lower_s_scale.get(),
|
|
|
|
command=lambda v: set_custom_hsv(lower_h_scale.get(), lower_s_scale.get(),
|
|
|
|
lower_v_scale.get(), v,
|
|
|
|
lower_v_scale.get(), v,
|
|
|
|
upper_s_scale.get(), upper_v_scale.get()))
|
|
|
|
upper_s_scale.get(), upper_v_scale.get()))
|
|
|
|
upper_h_scale.pack()
|
|
|
|
upper_h_scale.pack()
|
|
|
|
|
|
|
|
|
|
|
|
upper_s_scale = Scale(root, from_=0, to=255, orient=HORIZONTAL, label="Saturation Max",
|
|
|
|
upper_s_scale = Scale(root, from_=0, to=255, orient=HORIZONTAL, label="饱和度 Max",
|
|
|
|
command=lambda v: set_custom_hsv(lower_h_scale.get(), lower_s_scale.get(),
|
|
|
|
command=lambda v: set_custom_hsv(lower_h_scale.get(), lower_s_scale.get(),
|
|
|
|
lower_v_scale.get(),
|
|
|
|
lower_v_scale.get(),
|
|
|
|
upper_h_scale.get(), v, upper_v_scale.get()))
|
|
|
|
upper_h_scale.get(), v, upper_v_scale.get()))
|
|
|
|
upper_s_scale.pack()
|
|
|
|
upper_s_scale.pack()
|
|
|
|
|
|
|
|
|
|
|
|
upper_v_scale = Scale(root, from_=0, to=255, orient=HORIZONTAL, label="Value Max",
|
|
|
|
upper_v_scale = Scale(root, from_=0, to=255, orient=HORIZONTAL, label="亮度 Max",
|
|
|
|
command=lambda v: set_custom_hsv(lower_h_scale.get(), lower_s_scale.get(),
|
|
|
|
command=lambda v: set_custom_hsv(lower_h_scale.get(), lower_s_scale.get(),
|
|
|
|
lower_v_scale.get(),
|
|
|
|
lower_v_scale.get(),
|
|
|
|
upper_h_scale.get(), upper_s_scale.get(), v))
|
|
|
|
upper_h_scale.get(), upper_s_scale.get(), v))
|
|
|
@ -167,8 +185,8 @@ def start_camera():
|
|
|
|
|
|
|
|
|
|
|
|
def camera_thread():
|
|
|
|
def camera_thread():
|
|
|
|
"""摄像头处理线程函数"""
|
|
|
|
"""摄像头处理线程函数"""
|
|
|
|
global running, initial_measurement, lower_hsv, upper_hsv
|
|
|
|
global running, initial_measurement, lower_hsv, upper_hsv, stop_thread
|
|
|
|
while running:
|
|
|
|
while running and not stop_thread:
|
|
|
|
ret, frame = cap.read()
|
|
|
|
ret, frame = cap.read()
|
|
|
|
if not ret:
|
|
|
|
if not ret:
|
|
|
|
messagebox.showerror("Error", "Failed to read frame from camera.")
|
|
|
|
messagebox.showerror("Error", "Failed to read frame from camera.")
|
|
|
@ -192,7 +210,7 @@ def camera_thread():
|
|
|
|
|
|
|
|
|
|
|
|
# 遍历轮廓,画出边界框
|
|
|
|
# 遍历轮廓,画出边界框
|
|
|
|
for contour in contours:
|
|
|
|
for contour in contours:
|
|
|
|
if cv2.contourArea(contour) > 100:
|
|
|
|
if cv2.contourArea(contour) > 300:
|
|
|
|
x, y, w, h = cv2.boundingRect(contour)
|
|
|
|
x, y, w, h = cv2.boundingRect(contour)
|
|
|
|
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
|
|
|
|
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
|
|
|
|
|
|
|
|
|
|
|
@ -209,6 +227,9 @@ def camera_thread():
|
|
|
|
(int(prediction[0] + w), int(prediction[1] + h)),
|
|
|
|
(int(prediction[0] + w), int(prediction[1] + h)),
|
|
|
|
(255, 0, 0), 2)
|
|
|
|
(255, 0, 0), 2)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
print(lower_hsv, upper_hsv)
|
|
|
|
|
|
|
|
|
|
|
|
cv2.imshow('Frame', frame)
|
|
|
|
cv2.imshow('Frame', frame)
|
|
|
|
cv2.imshow('Mask', mask)
|
|
|
|
cv2.imshow('Mask', mask)
|
|
|
|
|
|
|
|
|
|
|
|