zhoutao 6 months ago
parent a17d594247
commit 54a0afa4f4

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

@ -1,7 +1,23 @@
import cv2 import cv2
import numpy as np import numpy as np
kf = cv2.KalmanFilter(4, 2)
kf.measurementMatrix = np.array([[1, 0, 0, 0],
[0, 1, 0, 0]], np.float32)
kf.transitionMatrix = np.array([[1, 0, 1, 0],
[0, 1, 0, 1],
[0, 0, 1, 0],
[0, 0, 0, 1]], np.float32)
kf.processNoiseCov = np.array([[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]], np.float32) * 0.03
# 用于初始化卡尔曼滤波器的变量
initial_measurement = None
def main(): def main():
global initial_measurement, kf
# 初始化摄像头 # 初始化摄像头
cap = cv2.VideoCapture(0) cap = cv2.VideoCapture(0)
@ -31,8 +47,6 @@ def main():
color_mean = np.mean(roi_hsv, axis=(0, 1)) color_mean = np.mean(roi_hsv, axis=(0, 1))
color_mean = np.uint8(color_mean) color_mean = np.uint8(color_mean)
# 创建颜色范围
# color_range = 10
color_lower = np.array( color_lower = np.array(
[max(color_mean[0] - 30, 0), max(color_mean[1] - 60, 0), max(color_mean[2] - 55, 0)]) [max(color_mean[0] - 30, 0), max(color_mean[1] - 60, 0), max(color_mean[2] - 55, 0)])
color_upper = np.array( color_upper = np.array(
@ -65,7 +79,19 @@ def main():
if cv2.contourArea(contour) > 300: 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)
print(color_lower, color_upper)
# 初始化卡尔曼滤波器的测量值
if initial_measurement is None:
initial_measurement = np.array([[x], [y]], np.float32)
kf.statePost = initial_measurement
else:
# 更新卡尔曼滤波器
measurement = np.array([[x], [y]], np.float32)
kf.correct(measurement)
prediction = kf.predict()
cv2.rectangle(frame, (int(prediction[0]), int(prediction[1])),
(int(prediction[0] + w), int(prediction[1] + h)),
(255, 0, 0), 2)
# 显示原图和结果图像 # 显示原图和结果图像
cv2.imshow('Original', frame) cv2.imshow('Original', frame)
@ -80,5 +106,4 @@ def main():
cv2.destroyAllWindows() cv2.destroyAllWindows()
if __name__ == '__main__': if __name__ == '__main__':
main() main()

@ -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)

@ -26,9 +26,11 @@ button2.move(50, 100)
button2.clicked.connect(Area_tracking.main) button2.clicked.connect(Area_tracking.main)
quit_button = QPushButton('退出', widget) quit_button = QPushButton('退出', widget)
quit_button.move(150, 50) quit_button.move(200, 50)
quit_button.clicked.connect(quit_app) quit_button.clicked.connect(quit_app)
widget.show() widget.show()
sys.exit(app.exec()) sys.exit(app.exec())

Loading…
Cancel
Save