测试文件夹架构
This commit is contained in:
70
新建文件夹/TTLCommunicator.py
Normal file
70
新建文件夹/TTLCommunicator.py
Normal file
@@ -0,0 +1,70 @@
|
||||
import serial
|
||||
import serial.tools.list_ports
|
||||
|
||||
|
||||
class TTLCommunicator:
|
||||
def __init__(self, baudrate=115200, timeout=0.1):
|
||||
"""初始化TTL通信对象"""
|
||||
self.baudrate = baudrate
|
||||
self.timeout = timeout
|
||||
self.ser = None
|
||||
self.connected = False
|
||||
|
||||
@staticmethod # 声明为静态方法
|
||||
def find_usb_ttl_port():
|
||||
"""自动查找USB转TTL设备端口(静态方法,不依赖实例状态)"""
|
||||
ports = list(serial.tools.list_ports.comports())
|
||||
for port in ports:
|
||||
if "USB Serial" in port.description or "CH340" in port.description or "PL2303" in port.description:
|
||||
return port.device
|
||||
return None
|
||||
|
||||
def connect(self, port=None):
|
||||
"""连接到USB转TTL设备"""
|
||||
try:
|
||||
if not port:
|
||||
# 调用静态方法时,可直接通过类名或实例调用(此处保持原有逻辑)
|
||||
port = self.find_usb_ttl_port()
|
||||
if not port:
|
||||
print("未找到USB转TTL设备")
|
||||
return False
|
||||
|
||||
self.ser = serial.Serial(
|
||||
port=port,
|
||||
baudrate=self.baudrate,
|
||||
timeout=self.timeout,
|
||||
parity=serial.PARITY_NONE,
|
||||
stopbits=1,
|
||||
bytesize=serial.EIGHTBITS
|
||||
)
|
||||
|
||||
if self.ser.is_open:
|
||||
self.connected = True
|
||||
print(f"已连接TTL设备:{port}(波特率:{self.baudrate})")
|
||||
return True
|
||||
return False
|
||||
except Exception as e:
|
||||
print(f"连接失败:{str(e)}")
|
||||
return False
|
||||
|
||||
def send_data(self, data_str):
|
||||
"""发送数据到TTL设备"""
|
||||
if not self.connected or not self.ser:
|
||||
print("未连接TTL设备,请先调用connect()")
|
||||
return False
|
||||
|
||||
try:
|
||||
data = (data_str + "\n").encode("utf-8") # 加换行符作为结束标志
|
||||
self.ser.write(data)
|
||||
self.ser.flush()
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"发送失败:{str(e)}")
|
||||
return False
|
||||
|
||||
def close(self):
|
||||
"""关闭串口连接"""
|
||||
if self.ser and self.ser.is_open:
|
||||
self.ser.close()
|
||||
self.connected = False
|
||||
print("TTL连接已关闭")
|
||||
80
新建文件夹/visualizer.py
Normal file
80
新建文件夹/visualizer.py
Normal file
@@ -0,0 +1,80 @@
|
||||
import cv2
|
||||
import numpy as np
|
||||
|
||||
class Visualizer:
|
||||
"""可视化:绘制灯条、装甲板、预测位置等"""
|
||||
def __init__(self):
|
||||
self.colors = {
|
||||
"red": (0, 0, 255),
|
||||
"blue": (255, 0, 0),
|
||||
"light_bar": (0, 255, 255),
|
||||
"armor": (0, 255, 0),
|
||||
"prediction": (0, 165, 255),
|
||||
"text": (255, 255, 255)
|
||||
}
|
||||
|
||||
def draw_light_bars(self, frame, light_bars, target_color):
|
||||
"""绘制灯条(矩形+中心线+标签)"""
|
||||
bar_color = self.colors[target_color]
|
||||
line_color = self.colors["light_bar"]
|
||||
|
||||
for lb in light_bars:
|
||||
cv2.drawContours(frame, [lb["box"]], 0, bar_color, 2)
|
||||
end1 = tuple(map(int, lb["center_line"][0]))
|
||||
end2 = tuple(map(int, lb["center_line"][1]))
|
||||
cv2.line(frame, end1, end2, line_color, 2)
|
||||
center = tuple(map(int, lb["center"]))
|
||||
cv2.putText(
|
||||
frame, target_color, (center[0], center[1] - 8),
|
||||
cv2.FONT_HERSHEY_SIMPLEX, 0.4, bar_color, 1
|
||||
)
|
||||
|
||||
return frame
|
||||
|
||||
def draw_armor_plate(self, frame, armor):
|
||||
"""绘制装甲板(2D框+3D信息)"""
|
||||
corners = armor.get("corners_2d")
|
||||
if corners is not None:
|
||||
# 关键修改:np.int0 替换为 np.int32
|
||||
cv2.polylines(frame, [np.int32(corners)], True, self.colors["armor"], 2)
|
||||
|
||||
center = tuple(map(int, armor["center"]))
|
||||
cv2.circle(frame, center, 3, self.colors["armor"], -1)
|
||||
cv2.putText(
|
||||
frame, "Armor", (center[0] + 5, center[1] - 5),
|
||||
cv2.FONT_HERSHEY_SIMPLEX, 0.5, self.colors["armor"], 2
|
||||
)
|
||||
|
||||
return frame
|
||||
|
||||
def draw_prediction(self, frame, predicted_pos, label="Predicted"):
|
||||
"""绘制预测位置(橙色圆点+标签)"""
|
||||
if predicted_pos is None:
|
||||
return frame
|
||||
|
||||
pos = tuple(map(int, predicted_pos))
|
||||
cv2.circle(frame, pos, 5, self.colors["prediction"], -1)
|
||||
cv2.putText(
|
||||
frame, label, (pos[0] + 10, pos[1] - 10),
|
||||
cv2.FONT_HERSHEY_SIMPLEX, 0.5, self.colors["prediction"], 2
|
||||
)
|
||||
|
||||
return frame
|
||||
|
||||
def draw_offset_text(self, frame, display_center, target_color, is_predicted):
|
||||
"""绘制装甲板相对图像中心的偏移量"""
|
||||
if display_center is None:
|
||||
text = "Armor: unknown | Offset: (0, 0)"
|
||||
else:
|
||||
img_center = (frame.shape[1] // 2, frame.shape[0] // 2)
|
||||
offset_x = int(display_center[0] - img_center[0])
|
||||
offset_y = int(display_center[1] - img_center[1])
|
||||
color_text = f"{target_color} (predicted)" if is_predicted else target_color
|
||||
text = f"Armor: {color_text} | Offset: ({offset_x}, {offset_y})"
|
||||
|
||||
cv2.putText(
|
||||
frame, text, (10, 30),
|
||||
cv2.FONT_HERSHEY_SIMPLEX, 0.8, self.colors["text"], 2
|
||||
)
|
||||
|
||||
return frame
|
||||
Reference in New Issue
Block a user