From f12b24b72fc3a9be5776f4e935e5be11753a9f7b Mon Sep 17 00:00:00 2001 From: shengzhanpeng <3299915477@qq.com> Date: Mon, 29 Sep 2025 10:01:51 +0800 Subject: [PATCH 01/29] =?UTF-8?q?=E5=AE=8C=E6=88=90=E9=80=89=E9=A2=98?= =?UTF-8?q?=E5=B9=B6=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Self-driving car/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/Self-driving car/README.md diff --git a/src/Self-driving car/README.md b/src/Self-driving car/README.md new file mode 100644 index 0000000000..8c27ba2124 --- /dev/null +++ b/src/Self-driving car/README.md @@ -0,0 +1 @@ +无人车 \ No newline at end of file From ed021d8ff4a03938f9b63952ad272c12fc1be59a Mon Sep 17 00:00:00 2001 From: shengzhanpeng <3299915477@qq.com> Date: Mon, 29 Sep 2025 11:02:02 +0800 Subject: [PATCH 02/29] =?UTF-8?q?=E5=AE=8C=E6=88=90=E9=80=89=E9=A2=98?= =?UTF-8?q?=E5=B9=B6=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Self-driving car/README.md | 1 - src/Self_driving_car/README.md | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 src/Self-driving car/README.md create mode 100644 src/Self_driving_car/README.md diff --git a/src/Self-driving car/README.md b/src/Self-driving car/README.md deleted file mode 100644 index 8c27ba2124..0000000000 --- a/src/Self-driving car/README.md +++ /dev/null @@ -1 +0,0 @@ -无人车 \ No newline at end of file diff --git a/src/Self_driving_car/README.md b/src/Self_driving_car/README.md new file mode 100644 index 0000000000..5a616a55ea --- /dev/null +++ b/src/Self_driving_car/README.md @@ -0,0 +1 @@ +无人车控制 \ No newline at end of file From ae09b6e2cc9c6a99245e43bcac7baf7320d6eb86 Mon Sep 17 00:00:00 2001 From: shengzhanpeng <3299915477@qq.com> Date: Mon, 29 Sep 2025 11:09:49 +0800 Subject: [PATCH 03/29] =?UTF-8?q?=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Self_driving_car/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Self_driving_car/README.md b/src/Self_driving_car/README.md index 5a616a55ea..a029d4dd6e 100644 --- a/src/Self_driving_car/README.md +++ b/src/Self_driving_car/README.md @@ -1 +1 @@ -无人车控制 \ No newline at end of file +无人车控制模块 \ No newline at end of file From 97cb689246c7cd4b73cfd7d772279eb7a6668b1d Mon Sep 17 00:00:00 2001 From: shengzhanpeng <3299915477@qq.com> Date: Mon, 13 Oct 2025 11:19:39 +0800 Subject: [PATCH 04/29] =?UTF-8?q?=E8=BF=9B=E8=A1=8C=E9=A6=96=E6=AC=A1?= =?UTF-8?q?=E6=8F=90=E4=BA=A4=EF=BC=8C=E9=80=89=E9=A2=98=E4=B8=BA=E6=97=A0?= =?UTF-8?q?=E4=BA=BA=E8=BD=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Driving_Car/README.md | 1 + src/Driving_Car/main.py | 101 ++++++++++++++++++ .../__pycache__/simulator.cpython-311.pyc | Bin 5468 -> 0 bytes 3 files changed, 102 insertions(+) create mode 100644 src/Driving_Car/README.md create mode 100644 src/Driving_Car/main.py delete mode 100644 src/HCL_interaction_task/mobl_arms_index_pointing/__pycache__/simulator.cpython-311.pyc diff --git a/src/Driving_Car/README.md b/src/Driving_Car/README.md new file mode 100644 index 0000000000..8c27ba2124 --- /dev/null +++ b/src/Driving_Car/README.md @@ -0,0 +1 @@ +无人车 \ No newline at end of file diff --git a/src/Driving_Car/main.py b/src/Driving_Car/main.py new file mode 100644 index 0000000000..36aded3f83 --- /dev/null +++ b/src/Driving_Car/main.py @@ -0,0 +1,101 @@ +import pygame +import math + +# 1. 初始化pygame(必须放在最前面) +pygame.init() + +# 2. 屏幕配置 +SCREEN_W = 800 +SCREEN_H = 600 +screen = pygame.display.set_mode((SCREEN_W, SCREEN_H)) +pygame.display.set_caption("无人车基础控制") + +# 3. 车辆类(封装移动和绘制逻辑) +class Car: + def __init__(self): + # 初始位置(屏幕中心) + self.x = SCREEN_W // 2 + self.y = SCREEN_H // 2 + # 初始方向(向上,角度0为右,90为上) + self.angle = 90 + # 运动参数 + self.speed = 4 + self.turn_speed = 2 + + def move(self, direction): + """根据方向移动:forward/backward""" + rad = math.radians(self.angle) + if direction == "forward": + self.x -= self.speed * math.sin(rad) + self.y -= self.speed * math.cos(rad) + elif direction == "backward": + self.x += self.speed * math.sin(rad) + self.y += self.speed * math.cos(rad) + # 防止移出屏幕 + self.x = max(20, min(self.x, SCREEN_W - 20)) + self.y = max(20, min(self.y, SCREEN_H - 20)) + + def turn(self, direction): + """根据方向转向:left/right""" + if direction == "left": + self.angle = (self.angle + self.turn_speed) % 360 + elif direction == "right": + self.angle = (self.angle - self.turn_speed) % 360 + + def draw(self): + """绘制车辆(三角形,直观显示方向)""" + rad = math.radians(self.angle) + # 三角形三个顶点(车头+车尾两侧) + front = (self.x - 20 * math.sin(rad), self.y - 20 * math.cos(rad)) + back_l = (self.x + 10 * math.sin(rad + math.pi/2), self.y + 10 * math.cos(rad + math.pi/2)) + back_r = (self.x + 10 * math.sin(rad - math.pi/2), self.y + 10 * math.cos(rad - math.pi/2)) + # 绘制蓝色车身+黑色边框 + pygame.draw.polygon(screen, (0, 0, 255), [front, back_l, back_r]) + pygame.draw.polygon(screen, (0, 0, 0), [front, back_l, back_r], 2) + +# 4. 主控制循环(程序核心) +def main(): + car = Car() + clock = pygame.time.Clock() + running = True # 控制循环是否继续 + + # 控制说明文字 + font = pygame.font.SysFont("Arial", 20) + tip_text = font.render("↑前进 | ↓后退 | ←左转 | →右转 | ESC退出", True, (0, 0, 0)) + + while running: + # 1. 处理事件(关闭窗口、按键) + for event in pygame.event.get(): + # 点击窗口关闭按钮 + if event.type == pygame.QUIT: + running = False + # 按下ESC键退出 + if event.type == pygame.KEYDOWN and event.key == pygame.K_ESCAPE: + running = False + + # 2. 持续检测按键(按住键持续动作) + keys = pygame.key.get_pressed() + if keys[pygame.K_UP]: + car.move("forward") + if keys[pygame.K_DOWN]: + car.move("backward") + if keys[pygame.K_LEFT]: + car.turn("left") + if keys[pygame.K_RIGHT]: + car.turn("right") + + # 3. 绘制画面(清空→画车辆→画文字) + screen.fill((255, 255, 255)) # 白色背景 + car.draw() # 画车辆 + screen.blit(tip_text, (10, 10)) # 画控制说明 + + # 4. 更新屏幕+控制帧率(60帧/秒,避免画面卡顿) + pygame.display.update() + clock.tick(60) + + # 5. 退出程序(释放资源) + pygame.quit() + +# 5. 启动程序(关键:必须调用main()) +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/src/HCL_interaction_task/mobl_arms_index_pointing/__pycache__/simulator.cpython-311.pyc b/src/HCL_interaction_task/mobl_arms_index_pointing/__pycache__/simulator.cpython-311.pyc deleted file mode 100644 index 02092cfeb6ced80bb73975610ff9b6a6b122f1ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5468 zcma)AZ*UXG72iAE>5nDZvL)HV0^4BzSf<997z!b2iUT18>`+M4;3nK0x-*ulf83q; z1FHVMUF+YgfGT5E2`GoBV1{3*(i&Uo^vZ||(L z4oJ)1>Fw^@-M729@4eq!edKgjAxO8J{~Y{>6QO_ON;y$Wg}Xn5!Z_j(M?_G+mJ|Ji zS||HWYEJc2B-)EO@+{&^ACd@t0zWPF(;RUa1*ipF?F%k()r?rG+}#3&al|7mwV&jO zvk2sZtbU3!0i`(#sF|aIS~xRMD`x?jR>gKW6ir50DJ}#}6_U+R#`U`cFvU2M$`b)A zMR0_1fm_kANvaqf)|Z|#eF!5z(MP8cqxXYt!()_0pqRZCbs>>DMV>YtL8k};9YF*< zl684?VY*z-;&tAaQsjNJTFRXyTe*Z#SeKbXVZFzFWAza!lvNLVS%Oyj5VB8nChXB( zuD}RKxm=kWM-cEG;4sKOg%AQxg^DNmm_nUlqY=d>vI9I5iL;zy4#r~xq2r1|rMy~Y zMtLs8CPE25Kq-{SM+OwTHkBr?N|mRTi2)HSbql0#yE+HsQNA;B>~!QQV20{+wcAwY;R6u=4rBxsowcJIC&aw7Rd%+P z5MldX_QY&s)1^(5wfV-4a^uGI?#%v@3HWNGO1{S3zQJUf_n^|^;^KqY|1qQbm19R| zyj|1Yu50ai@8h!f@idjGn)Nh}^=8*zY0rB)WKRdMY;*OEGxZy$>o?@<19E);SoS%q zW5(*Aw)*qdRkC$euKbGl_%Ako-}EPHr{zmxrzNP{0yOAWb`rSb$OaCABO@qE41?aM zh^%f$&{t2OtGW$Ax$I=_v82PO6-gD^Dply=0J#x@Mz2Ycy|8NxAbX>?|fPO;{DriWfm^K50e$Iy>{ou=$-d6 z#Y>aWvv}pR`N{W+pa1IC_49oJyMXZUIEFuxYaP<@5n zR(KRQw23P~iAPY0sH#{mgJeqSYy^FJ+<`0^3?#(4+ zb%H3Jke1q(IZsE<_!j)DC$?eJp5(5E^8W3ze|yejco%1VtsflCHFTGdsTKs5Nzt<+ z*LXDVVPp@J^DqT}^F+7ylq}E(`xrY+uI8{Q$i;*3iC$UPh9+x!wwwO!-{m83dI>1r z^wsus(>L4wJyp~cO+b0dOagzZs->pX_>4!AQYao16fu zAceEwT`~63jJIvt+jf0x?%+=)Y;RfSd{fm#9MnnDRY#ExVvq0mFT5ElikqKYLU#Dlyj3LA0F8aydI8IJ&N zIG=p>z_W*#p1p^*9NOEXc;IRvg;aZCB4901R`{8ySj$BrfJZy99UWL|Rb2b}cJFzC zd1_zZ-aUty=k^^`XjTx|GYWB9A6(!5rsBY`u&WX9fUrd10t|*-RhUp%dhYe**&6 z3Rd~T_)BlTbdecj&Q+yN=^qzr>TsagJnQz3ZJ*e6ap&01oTF*3u70e2rf%(Y-P#Wh zUwQG`x-Z=Fj%V`g_RH(`=j#s0bqCUxg1t_*ZvgnQwG>vZl~?V!zFJ=OSh}y^TQB=M z0k@p;=4a&1Kb3tiruWVIS6$j(aIF}#Pp}tjva9p1)_ZHUqg|tH$wIBG{u)s$YrerG zeV|l@JS{m#^K4CR=JW({?&ZwOIcuYUH)Ze@dXSk~@)cR=aep#;2#gzGPr5HzMh=dU zbT5uCgGS4JmBh+yxMb;BhkZ!UcNhvFNPnsq~U{`w#1-~Dypa{-6&6pYnEJ?cav4!{-RV`^lmSfXJ@ zl=y@e4dNgU?r~>gL8T@biHkfV@F$XB96Tp9<2GwZWY`Eqk4qRQ>;Y~i$iZlkHdMWA zKDfRM_nHL)F`gOuR?akZO*eGq8y=Ax9!WdqI(7hD*)r9+hQMXh#DTmoAo~JP$y?it z*6K|4s5CZ|?Y^=jZ|#t+9XV^qoV_NqvxMvr^O03J(({bjXIw4Qu9m!OjqF;JbFG26 z>e9{`|F&uWwx#f_VSCQCeR0;kx`fO)!qW*!LxhLB%l^)sXX#y>ZCF=AB#zw51o|um zYBaELfMx?3IIl)7Pg)W;!wzpYZs~ENDQ8vB4%3v+-m{*ZY9(-aeO1p^dTO&;?j~?~ zD+PRmyUblp zs;oUYy1UnU@ShRoAN(ny;z)qj?jN+OQHo`d67I7 z!kf1@%l2l~MZ97U*iApwVinpO7U65i^^NcF#3sE8Fo zzyy0eF$QEre?aBwrV`SL&rO4p>ZF~f0Y7w7?V|l9q?5H?+EYS0*<_(%XZI6rDR=<^ zvv!5V`&DR&l@n)#ZYZnpuP#w|9#=7TsB8b$`k1!;9|-uc@PUehK;SD9L;*QR)Te;# iBkEH?b-D6eKvg5^Q=*O#1T5^q^lO#>&3Ck_EBP Date: Mon, 20 Oct 2025 08:50:40 +0800 Subject: [PATCH 05/29] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E8=BD=A6=E8=BE=86?= =?UTF-8?q?=E4=BB=A3=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Driving_Car/cheliangdaili.py | 335 +++++++++++++++++++++++++++++++ 1 file changed, 335 insertions(+) create mode 100644 src/Driving_Car/cheliangdaili.py diff --git a/src/Driving_Car/cheliangdaili.py b/src/Driving_Car/cheliangdaili.py new file mode 100644 index 0000000000..51305d1dc9 --- /dev/null +++ b/src/Driving_Car/cheliangdaili.py @@ -0,0 +1,335 @@ +import math +import random +import time +import pygame +from typing import List, Tuple, Optional + +# 初始化pygame +pygame.init() + +# 颜色定义 +WHITE = (255, 255, 255) +BLACK = (0, 0, 0) +RED = (255, 0, 0) +GREEN = (0, 255, 0) +BLUE = (0, 0, 255) +GRAY = (200, 200, 200) +YELLOW = (255, 255, 0) + + +class Vector2: + """二维向量类,用于处理坐标和移动计算""" + + def __init__(self, x: float = 0, y: float = 0): + self.x = x + self.y = y + + def __add__(self, other: 'Vector2') -> 'Vector2': + return Vector2(self.x + other.x, self.y + other.y) + + def __sub__(self, other: 'Vector2') -> 'Vector2': + return Vector2(self.x - other.x, self.y - other.y) + + def __mul__(self, scalar: float) -> 'Vector2': + return Vector2(self.x * scalar, self.y * scalar) + + def magnitude(self) -> float: + """计算向量的模长""" + return math.sqrt(self.x ** 2 + self.y ** 2) + + def normalize(self) -> 'Vector2': + """将向量归一化(单位向量)""" + mag = self.magnitude() + if mag == 0: + return Vector2(0, 0) + return Vector2(self.x / mag, self.y / mag) + + def distance_to(self, other: 'Vector2') -> float: + """计算到另一个点的距离""" + return (self - other).magnitude() + + def __repr__(self) -> str: + return f"Vector2({self.x:.2f}, {self.y:.2f})" + + +class Obstacle: + """障碍物类,表示地图上的障碍物""" + + def __init__(self, position: Vector2, radius: float): + self.position = position + self.radius = radius + + def draw(self, screen): + """在屏幕上绘制障碍物""" + pygame.draw.circle(screen, GRAY, + (int(self.position.x), int(self.position.y)), + int(self.radius)) + + +class Map: + """地图类,包含边界和障碍物信息""" + + def __init__(self, width: float = 800, height: float = 600): + self.width = width + self.height = height + self.obstacles: List[Obstacle] = [] + + def add_obstacle(self, obstacle: Obstacle) -> None: + """添加障碍物到地图""" + self.obstacles.append(obstacle) + + def is_position_valid(self, position: Vector2) -> bool: + """检查位置是否有效(在地图范围内且不与障碍物碰撞)""" + # 检查是否在地图范围内 + if position.x < 0 or position.x > self.width or position.y < 0 or position.y > self.height: + return False + + # 检查是否与障碍物碰撞 + for obstacle in self.obstacles: + if position.distance_to(obstacle.position) < obstacle.radius + 5: # 5是安全距离 + return False + + return True + + def draw(self, screen): + """绘制地图和障碍物""" + screen.fill(WHITE) + for obstacle in self.obstacles: + obstacle.draw(screen) + + +class Vehicle: + """无人车类,表示可以在地图上移动的车辆""" + + def __init__(self, vehicle_id: str, map: Map, + start_position: Optional[Vector2] = None, + speed: float = 3.0, + radius: float = 10.0): + self.id = vehicle_id + self.map = map + self.speed = speed # 移动速度 + self.radius = radius # 车辆半径 + + # 如果没有指定起始位置,则随机生成一个有效位置 + if start_position and map.is_position_valid(start_position): + self.position = start_position + else: + self.position = self._get_random_valid_position() + + self.destination: Optional[Vector2] = None + self.roaming_direction = self._get_random_direction() + self.roaming_change_interval = 3 # 随机漫游时改变方向的时间间隔(秒) + self.last_direction_change = time.time() + + def _get_random_valid_position(self) -> Vector2: + """生成一个随机的有效位置""" + while True: + pos = Vector2( + random.uniform(0, self.map.width), + random.uniform(0, self.map.height) + ) + if self.map.is_position_valid(pos): + return pos + + def _get_random_direction(self) -> Vector2: + """生成一个随机的移动方向""" + angle = random.uniform(0, 2 * math.pi) + return Vector2(math.cos(angle), math.sin(angle)) + + def set_destination(self, destination: Vector2) -> bool: + """设置目的地,如果目的地有效则返回True""" + if self.map.is_position_valid(destination): + self.destination = destination + return True + return False + + def clear_destination(self) -> None: + """清除目的地,开始随机漫游""" + self.destination = None + self.roaming_direction = self._get_random_direction() + self.last_direction_change = time.time() + + def _avoid_obstacles(self, desired_direction: Vector2) -> Vector2: + """避开障碍物的路径调整""" + avoidance_strength = 0.8 + avoidance_direction = Vector2(0, 0) + + # 检查每个障碍物 + for obstacle in self.map.obstacles: + distance = self.position.distance_to(obstacle.position) + # 如果距离过近,计算躲避方向 + if distance < obstacle.radius + self.radius + 20: # 20是安全距离 + # 远离障碍物的方向 + away_from_obstacle = (self.position - obstacle.position).normalize() + # 距离越近,躲避力度越大 + avoidance_direction += away_from_obstacle * (1 / distance) + + # 结合期望方向和躲避方向 + new_direction = desired_direction + avoidance_direction * avoidance_strength + return new_direction.normalize() + + def update(self, delta_time: float) -> None: + """更新车辆位置""" + # 确定移动方向 + if self.destination: + # 有目的地,向目的地移动 + desired_direction = (self.destination - self.position).normalize() + + # 检查是否到达目的地 + if self.position.distance_to(self.destination) < self.speed * delta_time: + self.position = self.destination + self.clear_destination() # 到达后开始漫游 + return + else: + # 无目的地,随机漫游 + current_time = time.time() + # 定期改变方向 + if current_time - self.last_direction_change > self.roaming_change_interval: + self.roaming_direction = self._get_random_direction() + self.last_direction_change = current_time + desired_direction = self.roaming_direction + + # 避开障碍物 + move_direction = self._avoid_obstacles(desired_direction) + + # 计算新位置 + new_position = self.position + move_direction * self.speed * delta_time + + # 检查新位置是否有效,如果无效则调整方向 + if not self.map.is_position_valid(new_position): + # 碰到边界,反弹 + if new_position.x < 0 or new_position.x > self.map.width: + move_direction = Vector2(-move_direction.x, move_direction.y) + if new_position.y < 0 or new_position.y > self.map.height: + move_direction = Vector2(move_direction.x, -move_direction.y) + new_position = self.position + move_direction * self.speed * delta_time + + self.position = new_position + + def draw(self, screen): + """在屏幕上绘制车辆""" + # 绘制车辆主体 + pygame.draw.circle(screen, BLUE, + (int(self.position.x), int(self.position.y)), + int(self.radius)) + + # 绘制方向指示器 + direction = self._get_current_direction() + nose_pos = self.position + direction * self.radius + pygame.draw.line(screen, RED, + (self.position.x, self.position.y), + (nose_pos.x, nose_pos.y), 3) + + # 如果有目的地,绘制目的地和路径 + if self.destination: + pygame.draw.circle(screen, GREEN, + (int(self.destination.x), int(self.destination.y)), + 5) + pygame.draw.line(screen, YELLOW, + (self.position.x, self.position.y), + (self.destination.x, self.destination.y), 1) + + def _get_current_direction(self) -> Vector2: + """获取当前移动方向""" + if self.destination: + return (self.destination - self.position).normalize() + return self.roaming_direction + + def __repr__(self) -> str: + dest = self.destination if self.destination else "None" + return f"Vehicle {self.id}: Position {self.position}, Destination {dest}" + + +def main(): + # 创建地图 + map_width, map_height = 800, 600 + game_map = Map(map_width, map_height) + + # 添加一些障碍物 + obstacles = [ + Obstacle(Vector2(200, 150), 30), + Obstacle(Vector2(600, 400), 40), + Obstacle(Vector2(400, 500), 25), + Obstacle(Vector2(100, 400), 35), + Obstacle(Vector2(700, 200), 20), + Obstacle(Vector2(300, 300), 50) + ] + for obs in obstacles: + game_map.add_obstacle(obs) + + # 创建屏幕 + screen = pygame.display.set_mode((map_width, map_height)) + pygame.display.set_caption("无人车导航模拟") + + # 创建车辆 + vehicle = Vehicle("car_001", game_map, speed=5.0) + print(f"创建车辆: {vehicle}") + + # 时钟控制 + clock = pygame.time.Clock() + running = True + last_update_time = time.time() + + # 字体设置(用于显示信息) + font = pygame.font.SysFont(None, 24) + + while running: + # 计算时间差 + current_time = time.time() + delta_time = current_time - last_update_time + last_update_time = current_time + + # 处理事件 + for event in pygame.event.get(): + if event.type == pygame.QUIT: + running = False + elif event.type == pygame.MOUSEBUTTONDOWN: + # 鼠标点击设置新目的地 + if event.button == 1: # 左键点击 + x, y = event.pos + destination = Vector2(x, y) + if vehicle.set_destination(destination): + print(f"设置新目的地: {destination}") + + # 随机设置目的地(偶尔) + if random.random() < 0.005 and not vehicle.destination: # 0.5%的概率设置新目的地 + dest_x = random.uniform(0, map_width) + dest_y = random.uniform(0, map_height) + destination = Vector2(dest_x, dest_y) + if vehicle.set_destination(destination): + print(f"自动设置新目的地: {destination}") + + # 更新车辆位置 + vehicle.update(delta_time) + + # 绘制 + game_map.draw(screen) + vehicle.draw(screen) + + # 显示车辆信息 + info_text = f"位置: ({vehicle.position.x:.1f}, {vehicle.position.y:.1f})" + if vehicle.destination: + info_text += f" 目的地: ({vehicle.destination.x:.1f}, {vehicle.destination.y:.1f})" + else: + info_text += " 状态: 漫游中" + + text_surface = font.render(info_text, True, BLACK) + screen.blit(text_surface, (10, 10)) + + # 显示操作提示 + help_text = "左键点击: 设置新目的地 | ESC: 退出" + help_surface = font.render(help_text, True, BLACK) + screen.blit(help_surface, (10, map_height - 30)) + + # 更新显示 + pygame.display.flip() + + # 控制帧率 + clock.tick(60) + + pygame.quit() + print("模拟结束") + + +if __name__ == "__main__": + main() \ No newline at end of file From e5193de09a58b76ef9436961378081de1216ee87 Mon Sep 17 00:00:00 2001 From: shengzhanpeng <3299915477@qq.com> Date: Mon, 20 Oct 2025 09:18:16 +0800 Subject: [PATCH 06/29] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E8=BD=A6=E8=BE=86?= =?UTF-8?q?=E4=BB=A3=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../instance segmentation camera.py | 358 ++++++++++++++++++ 1 file changed, 358 insertions(+) create mode 100644 src/Driving_Car/instance segmentation camera.py diff --git a/src/Driving_Car/instance segmentation camera.py b/src/Driving_Car/instance segmentation camera.py new file mode 100644 index 0000000000..81108abc77 --- /dev/null +++ b/src/Driving_Car/instance segmentation camera.py @@ -0,0 +1,358 @@ +import cv2 +import numpy as np +import pygame +import random +import math +from typing import List, Tuple, Dict, Optional + +# 初始化pygame +pygame.init() + +# 颜色定义(补充GRAY的定义) +WHITE = (255, 255, 255) +BLACK = (0, 0, 0) +RED = (255, 0, 0) +GREEN = (0, 255, 0) +BLUE = (0, 0, 255) +YELLOW = (255, 255, 0) +PURPLE = (128, 0, 128) +ORANGE = (255, 165, 0) +PINK = (255, 192, 203) +CYAN = (0, 255, 255) +GRAY = (128, 128, 128) # 补充灰色定义 + +# 可用颜色列表(用于实例分割标记) +INSTANCE_COLORS = [RED, GREEN, BLUE, YELLOW, PURPLE, ORANGE, PINK, CYAN] + + +class GameObject: + """游戏对象基类""" + + def __init__(self, x: float, y: float, width: float, height: float, obj_type: str): + self.x = x + self.y = y + self.width = width + self.height = height + self.obj_type = obj_type + self.velocity_x = 0 + self.velocity_y = 0 + self.instance_id = None # 实例ID,用于区分同一类别的不同对象 + + def update(self, delta_time: float, world_width: float, world_height: float): + """更新对象位置""" + self.x += self.velocity_x * delta_time + self.y += self.velocity_y * delta_time + + # 边界检测 + if self.x < 0: + self.x = 0 + self.velocity_x = -self.velocity_x + elif self.x + self.width > world_width: + self.x = world_width - self.width + self.velocity_x = -self.velocity_x + + if self.y < 0: + self.y = 0 + self.velocity_y = -self.velocity_y + elif self.y + self.height > world_height: + self.y = world_height - self.height + self.velocity_y = -self.velocity_y + + def draw(self, surface: pygame.Surface): + """绘制对象""" + pass + + +class Car(GameObject): + """车辆类""" + + def __init__(self, x: float, y: float, width: float = 40, height: float = 20): + super().__init__(x, y, width, height, "car") + # 随机速度 + speed = random.uniform(50, 150) + angle = random.uniform(0, 2 * math.pi) + self.velocity_x = math.cos(angle) * speed + self.velocity_y = math.sin(angle) * speed + + def draw(self, surface: pygame.Surface): + # 绘制车辆主体 + pygame.draw.rect(surface, BLUE, (self.x, self.y, self.width, self.height)) + # 绘制车窗 + pygame.draw.rect(surface, CYAN, (self.x + 5, self.y + 5, self.width - 10, self.height - 10)) + # 绘制车轮 + wheel_size = 5 + pygame.draw.rect(surface, BLACK, (self.x + 5, self.y, self.width - 10, wheel_size)) + pygame.draw.rect(surface, BLACK, (self.x + 5, self.y + self.height - wheel_size, self.width - 10, wheel_size)) + + +class Pedestrian(GameObject): + """行人类""" + + def __init__(self, x: float, y: float, width: float = 15, height: float = 30): + super().__init__(x, y, width, height, "pedestrian") + # 随机速度 + speed = random.uniform(20, 60) + angle = random.uniform(0, 2 * math.pi) + self.velocity_x = math.cos(angle) * speed + self.velocity_y = math.sin(angle) * speed + + def draw(self, surface: pygame.Surface): + # 绘制头部 + pygame.draw.circle(surface, PINK, (int(self.x + self.width / 2), int(self.y + self.height / 5)), + int(self.width / 2)) + # 绘制身体 + pygame.draw.rect(surface, GREEN, (self.x, self.y + self.height / 5, self.width, self.height * 4 / 5)) + + +class TrafficLight(GameObject): + """交通灯类(静态)""" + + def __init__(self, x: float, y: float, width: float = 20, height: float = 60): + super().__init__(x, y, width, height, "traffic_light") + self.current_state = 0 # 0:红, 1:黄, 2:绿 + self.state_timer = 0 + self.state_durations = [3.0, 1.0, 3.0] # 红、黄、绿的持续时间(秒) + + def update(self, delta_time: float, world_width: float, world_height: float): + # 交通灯状态更新 + self.state_timer += delta_time + if self.state_timer > self.state_durations[self.current_state]: + self.current_state = (self.current_state + 1) % 3 + self.state_timer = 0 + + def draw(self, surface: pygame.Surface): + # 绘制灯杆 + pygame.draw.rect(surface, GRAY, (self.x, self.y, self.width, self.height)) + # 绘制灯 + light_radius = 8 + light_spacing = 15 + # 红灯 + color = RED if self.current_state == 0 else (100, 0, 0) + pygame.draw.circle(surface, color, (int(self.x + self.width / 2), int(self.y + light_spacing)), light_radius) + # 黄灯 + color = YELLOW if self.current_state == 1 else (100, 100, 0) + pygame.draw.circle(surface, color, (int(self.x + self.width / 2), int(self.y + light_spacing * 2)), + light_radius) + # 绿灯 + color = GREEN if self.current_state == 2 else (0, 100, 0) + pygame.draw.circle(surface, color, (int(self.x + self.width / 2), int(self.y + light_spacing * 3)), + light_radius) + + +class InstanceSegmentationCamera: + """实例分割相机类""" + + def __init__(self, width: int, height: int): + self.width = width + self.height = height + self.objects: List[GameObject] = [] + self.instance_counter: Dict[str, int] = {} # 按类型计数实例 + self.font = pygame.font.SysFont(None, 24) + + def add_object(self, obj: GameObject): + """添加对象到场景中""" + # 为对象分配实例ID + if obj.obj_type not in self.instance_counter: + self.instance_counter[obj.obj_type] = 0 + obj.instance_id = self.instance_counter[obj.obj_type] + self.instance_counter[obj.obj_type] += 1 + self.objects.append(obj) + + def remove_random_object(self): + """随机移除一个对象""" + if self.objects: + idx = random.randint(0, len(self.objects) - 1) + removed = self.objects.pop(idx) + + def update(self, delta_time: float): + """更新所有对象""" + for obj in self.objects: + obj.update(delta_time, self.width, self.height) + + def capture_raw_view(self) -> pygame.Surface: + """捕获原始视图(不进行实例分割标记)""" + surface = pygame.Surface((self.width, self.height)) + surface.fill(WHITE) + + # 绘制所有对象 + for obj in self.objects: + obj.draw(surface) + + return surface + + def capture_segmented_view(self) -> pygame.Surface: + """捕获实例分割视图(同一类别的不同对象用不同颜色标记)""" + surface = pygame.Surface((self.width, self.height)) + surface.fill(WHITE) + + # 按类型对对象进行分组 + objects_by_type: Dict[str, List[GameObject]] = {} + for obj in self.objects: + if obj.obj_type not in objects_by_type: + objects_by_type[obj.obj_type] = [] + objects_by_type[obj.obj_type].append(obj) + + # 绘制分割后的对象 + for obj_type, objs in objects_by_type.items(): + for i, obj in enumerate(objs): + # 为每个实例分配不同的颜色 + color = INSTANCE_COLORS[i % len(INSTANCE_COLORS)] + + # 绘制实例 + if isinstance(obj, Car): + pygame.draw.rect(surface, color, (obj.x, obj.y, obj.width, obj.height)) + # 绘制实例ID + text = self.font.render(f"{obj_type}_{obj.instance_id}", True, BLACK) + surface.blit(text, (obj.x, obj.y - 20)) + elif isinstance(obj, Pedestrian): + pygame.draw.rect(surface, color, (obj.x, obj.y, obj.width, obj.height)) + # 绘制实例ID + text = self.font.render(f"{obj_type}_{obj.instance_id}", True, BLACK) + surface.blit(text, (obj.x, obj.y - 20)) + elif isinstance(obj, TrafficLight): + pygame.draw.rect(surface, color, (obj.x, obj.y, obj.width, obj.height)) + # 绘制实例ID + text = self.font.render(f"{obj_type}_{obj.instance_id}", True, BLACK) + surface.blit(text, (obj.x, obj.y - 20)) + + # 绘制图例 + self._draw_legend(surface, objects_by_type) + + return surface + + def _draw_legend(self, surface: pygame.Surface, objects_by_type: Dict[str, List[GameObject]]): + """绘制图例,说明每个实例的颜色对应的对象""" + legend_y = 10 + legend_x = self.width - 180 + + pygame.draw.rect(surface, (240, 240, 240), (legend_x - 10, legend_y - 10, 170, 10 + len(INSTANCE_COLORS) * 25)) + pygame.draw.rect(surface, BLACK, (legend_x - 10, legend_y - 10, 170, 10 + len(INSTANCE_COLORS) * 25), 2) + + title = self.font.render("实例分割图例", True, BLACK) + surface.blit(title, (legend_x, legend_y)) + legend_y += 30 + + for i, color in enumerate(INSTANCE_COLORS): + pygame.draw.rect(surface, color, (legend_x, legend_y, 15, 15)) + text = self.font.render(f"实例 #{i}", True, BLACK) + surface.blit(text, (legend_x + 25, legend_y)) + legend_y += 25 + + +class SelfDrivingCarSimulator: + """无人车模拟器""" + + def __init__(self, width: int = 1200, height: int = 600): + self.width = width + self.height = height + self.screen = pygame.display.set_mode((width, height)) + pygame.display.set_caption("无人车实例分割相机模拟") + + # 创建相机视图区域(分为左右两部分) + self.camera_width = width // 2 + self.camera_height = height + + # 创建实例分割相机 + self.camera = InstanceSegmentationCamera(self.camera_width, self.camera_height) + + # 添加一些初始对象 + self._initialize_objects() + + self.clock = pygame.time.Clock() + self.running = True + self.font = pygame.font.SysFont(None, 30) + + def _initialize_objects(self): + """初始化场景对象""" + # 添加车辆 + for _ in range(3): + x = random.randint(50, self.camera_width - 100) + y = random.randint(50, self.camera_height - 100) + self.camera.add_object(Car(x, y)) + + # 添加行人 + for _ in range(4): + x = random.randint(50, self.camera_width - 50) + y = random.randint(50, self.camera_height - 50) + self.camera.add_object(Pedestrian(x, y)) + + # 添加交通灯 + self.camera.add_object(TrafficLight(50, self.camera_height // 2 - 30)) + self.camera.add_object(TrafficLight(self.camera_width - 70, self.camera_height // 2 - 30)) + + def handle_events(self): + """处理用户输入事件""" + for event in pygame.event.get(): + if event.type == pygame.QUIT: + self.running = False + elif event.type == pygame.KEYDOWN: + if event.key == pygame.K_ESCAPE: + self.running = False + elif event.key == pygame.K_c: # 添加车辆 + x = random.randint(50, self.camera_width - 100) + y = random.randint(50, self.camera_height - 100) + self.camera.add_object(Car(x, y)) + elif event.key == pygame.K_p: # 添加行人 + x = random.randint(50, self.camera_width - 50) + y = random.randint(50, self.camera_height - 50) + self.camera.add_object(Pedestrian(x, y)) + elif event.key == pygame.K_r: # 移除随机对象 + self.camera.remove_random_object() + + def update(self, delta_time: float): + """更新模拟状态""" + self.camera.update(delta_time) + + def render(self): + """渲染画面""" + self.screen.fill(WHITE) + + # 获取两种视图 + raw_view = self.camera.capture_raw_view() + segmented_view = self.camera.capture_segmented_view() + + # 绘制原始视图(左侧) + self.screen.blit(raw_view, (0, 0)) + # 绘制分割视图(右侧) + self.screen.blit(segmented_view, (self.camera_width, 0)) + + # 绘制视图分隔线 + pygame.draw.line(self.screen, BLACK, (self.camera_width, 0), + (self.camera_width, self.camera_height), 3) + + # 绘制标题 + raw_title = self.font.render("原始相机视图", True, BLACK) + self.screen.blit(raw_title, (self.camera_width // 2 - 80, 10)) + + seg_title = self.font.render("实例分割视图", True, BLACK) + self.screen.blit(seg_title, (self.camera_width + self.camera_width // 2 - 80, 10)) + + # 绘制操作提示 + help_texts = [ + "操作提示:", + "C键: 添加车辆", + "P键: 添加行人", + "R键: 移除随机对象", + "ESC键: 退出" + ] + + for i, text in enumerate(help_texts): + text_surface = self.font.render(text, True, BLACK) + self.screen.blit(text_surface, (10, self.height - 30 * (len(help_texts) - i))) + + pygame.display.flip() + + def run(self): + """运行模拟器""" + while self.running: + delta_time = self.clock.tick(60) / 1000.0 # 转换为秒 + self.handle_events() + self.update(delta_time) + self.render() + + pygame.quit() + + +if __name__ == "__main__": + simulator = SelfDrivingCarSimulator() + simulator.run() \ No newline at end of file From 59e103d522eab9c2c4cbe359b17c426e68b0cefd Mon Sep 17 00:00:00 2001 From: shengzhanpeng <3299915477@qq.com> Date: Mon, 20 Oct 2025 09:21:37 +0800 Subject: [PATCH 07/29] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E8=BD=A6=E8=BE=86?= =?UTF-8?q?=E4=BB=A3=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Driving_Car/instance segmentation camera.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Driving_Car/instance segmentation camera.py b/src/Driving_Car/instance segmentation camera.py index 81108abc77..368221c5e6 100644 --- a/src/Driving_Car/instance segmentation camera.py +++ b/src/Driving_Car/instance segmentation camera.py @@ -288,7 +288,7 @@ def handle_events(self): elif event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: self.running = False - elif event.key == pygame.K_c: # 添加车辆 + elif event.key == pygame.K_c: # 添加车辆 x = random.randint(50, self.camera_width - 100) y = random.randint(50, self.camera_height - 100) self.camera.add_object(Car(x, y)) From cc6a03a2828256248557c43594d97dfe408e2707 Mon Sep 17 00:00:00 2001 From: shengzhanpeng <3299915477@qq.com> Date: Mon, 20 Oct 2025 09:21:37 +0800 Subject: [PATCH 08/29] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E8=BD=A6=E8=BE=86?= =?UTF-8?q?=E4=BB=A3=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Driving_Car/{cheliangdaili.py => Vehicle Agent.py} | 0 src/Driving_Car/instance segmentation camera.py | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename src/Driving_Car/{cheliangdaili.py => Vehicle Agent.py} (100%) diff --git a/src/Driving_Car/cheliangdaili.py b/src/Driving_Car/Vehicle Agent.py similarity index 100% rename from src/Driving_Car/cheliangdaili.py rename to src/Driving_Car/Vehicle Agent.py diff --git a/src/Driving_Car/instance segmentation camera.py b/src/Driving_Car/instance segmentation camera.py index 81108abc77..368221c5e6 100644 --- a/src/Driving_Car/instance segmentation camera.py +++ b/src/Driving_Car/instance segmentation camera.py @@ -288,7 +288,7 @@ def handle_events(self): elif event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: self.running = False - elif event.key == pygame.K_c: # 添加车辆 + elif event.key == pygame.K_c: # 添加车辆 x = random.randint(50, self.camera_width - 100) y = random.randint(50, self.camera_height - 100) self.camera.add_object(Car(x, y)) From 24ec9758579711ce87597cebc3f776c1d85c29a8 Mon Sep 17 00:00:00 2001 From: shengzhanpeng <3299915477@qq.com> Date: Mon, 27 Oct 2025 09:24:29 +0800 Subject: [PATCH 09/29] Merge remote-tracking branch 'origin/main' --- src/Driving_Car/{Vehicle Agent.py => vehicle.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/Driving_Car/{Vehicle Agent.py => vehicle.py} (100%) diff --git a/src/Driving_Car/Vehicle Agent.py b/src/Driving_Car/vehicle.py similarity index 100% rename from src/Driving_Car/Vehicle Agent.py rename to src/Driving_Car/vehicle.py From 83398e096d45d20767fe4d19249b2bc6fe6ce6b4 Mon Sep 17 00:00:00 2001 From: shengzhanpeng <3299915477@qq.com> Date: Mon, 27 Oct 2025 11:00:34 +0800 Subject: [PATCH 10/29] Merge remote-tracking branch 'origin/main' --- .../instance_segmentation_camera.py | 358 ++++++++++++++++++ 1 file changed, 358 insertions(+) create mode 100644 src/Driving_Car/instance_segmentation_camera.py diff --git a/src/Driving_Car/instance_segmentation_camera.py b/src/Driving_Car/instance_segmentation_camera.py new file mode 100644 index 0000000000..368221c5e6 --- /dev/null +++ b/src/Driving_Car/instance_segmentation_camera.py @@ -0,0 +1,358 @@ +import cv2 +import numpy as np +import pygame +import random +import math +from typing import List, Tuple, Dict, Optional + +# 初始化pygame +pygame.init() + +# 颜色定义(补充GRAY的定义) +WHITE = (255, 255, 255) +BLACK = (0, 0, 0) +RED = (255, 0, 0) +GREEN = (0, 255, 0) +BLUE = (0, 0, 255) +YELLOW = (255, 255, 0) +PURPLE = (128, 0, 128) +ORANGE = (255, 165, 0) +PINK = (255, 192, 203) +CYAN = (0, 255, 255) +GRAY = (128, 128, 128) # 补充灰色定义 + +# 可用颜色列表(用于实例分割标记) +INSTANCE_COLORS = [RED, GREEN, BLUE, YELLOW, PURPLE, ORANGE, PINK, CYAN] + + +class GameObject: + """游戏对象基类""" + + def __init__(self, x: float, y: float, width: float, height: float, obj_type: str): + self.x = x + self.y = y + self.width = width + self.height = height + self.obj_type = obj_type + self.velocity_x = 0 + self.velocity_y = 0 + self.instance_id = None # 实例ID,用于区分同一类别的不同对象 + + def update(self, delta_time: float, world_width: float, world_height: float): + """更新对象位置""" + self.x += self.velocity_x * delta_time + self.y += self.velocity_y * delta_time + + # 边界检测 + if self.x < 0: + self.x = 0 + self.velocity_x = -self.velocity_x + elif self.x + self.width > world_width: + self.x = world_width - self.width + self.velocity_x = -self.velocity_x + + if self.y < 0: + self.y = 0 + self.velocity_y = -self.velocity_y + elif self.y + self.height > world_height: + self.y = world_height - self.height + self.velocity_y = -self.velocity_y + + def draw(self, surface: pygame.Surface): + """绘制对象""" + pass + + +class Car(GameObject): + """车辆类""" + + def __init__(self, x: float, y: float, width: float = 40, height: float = 20): + super().__init__(x, y, width, height, "car") + # 随机速度 + speed = random.uniform(50, 150) + angle = random.uniform(0, 2 * math.pi) + self.velocity_x = math.cos(angle) * speed + self.velocity_y = math.sin(angle) * speed + + def draw(self, surface: pygame.Surface): + # 绘制车辆主体 + pygame.draw.rect(surface, BLUE, (self.x, self.y, self.width, self.height)) + # 绘制车窗 + pygame.draw.rect(surface, CYAN, (self.x + 5, self.y + 5, self.width - 10, self.height - 10)) + # 绘制车轮 + wheel_size = 5 + pygame.draw.rect(surface, BLACK, (self.x + 5, self.y, self.width - 10, wheel_size)) + pygame.draw.rect(surface, BLACK, (self.x + 5, self.y + self.height - wheel_size, self.width - 10, wheel_size)) + + +class Pedestrian(GameObject): + """行人类""" + + def __init__(self, x: float, y: float, width: float = 15, height: float = 30): + super().__init__(x, y, width, height, "pedestrian") + # 随机速度 + speed = random.uniform(20, 60) + angle = random.uniform(0, 2 * math.pi) + self.velocity_x = math.cos(angle) * speed + self.velocity_y = math.sin(angle) * speed + + def draw(self, surface: pygame.Surface): + # 绘制头部 + pygame.draw.circle(surface, PINK, (int(self.x + self.width / 2), int(self.y + self.height / 5)), + int(self.width / 2)) + # 绘制身体 + pygame.draw.rect(surface, GREEN, (self.x, self.y + self.height / 5, self.width, self.height * 4 / 5)) + + +class TrafficLight(GameObject): + """交通灯类(静态)""" + + def __init__(self, x: float, y: float, width: float = 20, height: float = 60): + super().__init__(x, y, width, height, "traffic_light") + self.current_state = 0 # 0:红, 1:黄, 2:绿 + self.state_timer = 0 + self.state_durations = [3.0, 1.0, 3.0] # 红、黄、绿的持续时间(秒) + + def update(self, delta_time: float, world_width: float, world_height: float): + # 交通灯状态更新 + self.state_timer += delta_time + if self.state_timer > self.state_durations[self.current_state]: + self.current_state = (self.current_state + 1) % 3 + self.state_timer = 0 + + def draw(self, surface: pygame.Surface): + # 绘制灯杆 + pygame.draw.rect(surface, GRAY, (self.x, self.y, self.width, self.height)) + # 绘制灯 + light_radius = 8 + light_spacing = 15 + # 红灯 + color = RED if self.current_state == 0 else (100, 0, 0) + pygame.draw.circle(surface, color, (int(self.x + self.width / 2), int(self.y + light_spacing)), light_radius) + # 黄灯 + color = YELLOW if self.current_state == 1 else (100, 100, 0) + pygame.draw.circle(surface, color, (int(self.x + self.width / 2), int(self.y + light_spacing * 2)), + light_radius) + # 绿灯 + color = GREEN if self.current_state == 2 else (0, 100, 0) + pygame.draw.circle(surface, color, (int(self.x + self.width / 2), int(self.y + light_spacing * 3)), + light_radius) + + +class InstanceSegmentationCamera: + """实例分割相机类""" + + def __init__(self, width: int, height: int): + self.width = width + self.height = height + self.objects: List[GameObject] = [] + self.instance_counter: Dict[str, int] = {} # 按类型计数实例 + self.font = pygame.font.SysFont(None, 24) + + def add_object(self, obj: GameObject): + """添加对象到场景中""" + # 为对象分配实例ID + if obj.obj_type not in self.instance_counter: + self.instance_counter[obj.obj_type] = 0 + obj.instance_id = self.instance_counter[obj.obj_type] + self.instance_counter[obj.obj_type] += 1 + self.objects.append(obj) + + def remove_random_object(self): + """随机移除一个对象""" + if self.objects: + idx = random.randint(0, len(self.objects) - 1) + removed = self.objects.pop(idx) + + def update(self, delta_time: float): + """更新所有对象""" + for obj in self.objects: + obj.update(delta_time, self.width, self.height) + + def capture_raw_view(self) -> pygame.Surface: + """捕获原始视图(不进行实例分割标记)""" + surface = pygame.Surface((self.width, self.height)) + surface.fill(WHITE) + + # 绘制所有对象 + for obj in self.objects: + obj.draw(surface) + + return surface + + def capture_segmented_view(self) -> pygame.Surface: + """捕获实例分割视图(同一类别的不同对象用不同颜色标记)""" + surface = pygame.Surface((self.width, self.height)) + surface.fill(WHITE) + + # 按类型对对象进行分组 + objects_by_type: Dict[str, List[GameObject]] = {} + for obj in self.objects: + if obj.obj_type not in objects_by_type: + objects_by_type[obj.obj_type] = [] + objects_by_type[obj.obj_type].append(obj) + + # 绘制分割后的对象 + for obj_type, objs in objects_by_type.items(): + for i, obj in enumerate(objs): + # 为每个实例分配不同的颜色 + color = INSTANCE_COLORS[i % len(INSTANCE_COLORS)] + + # 绘制实例 + if isinstance(obj, Car): + pygame.draw.rect(surface, color, (obj.x, obj.y, obj.width, obj.height)) + # 绘制实例ID + text = self.font.render(f"{obj_type}_{obj.instance_id}", True, BLACK) + surface.blit(text, (obj.x, obj.y - 20)) + elif isinstance(obj, Pedestrian): + pygame.draw.rect(surface, color, (obj.x, obj.y, obj.width, obj.height)) + # 绘制实例ID + text = self.font.render(f"{obj_type}_{obj.instance_id}", True, BLACK) + surface.blit(text, (obj.x, obj.y - 20)) + elif isinstance(obj, TrafficLight): + pygame.draw.rect(surface, color, (obj.x, obj.y, obj.width, obj.height)) + # 绘制实例ID + text = self.font.render(f"{obj_type}_{obj.instance_id}", True, BLACK) + surface.blit(text, (obj.x, obj.y - 20)) + + # 绘制图例 + self._draw_legend(surface, objects_by_type) + + return surface + + def _draw_legend(self, surface: pygame.Surface, objects_by_type: Dict[str, List[GameObject]]): + """绘制图例,说明每个实例的颜色对应的对象""" + legend_y = 10 + legend_x = self.width - 180 + + pygame.draw.rect(surface, (240, 240, 240), (legend_x - 10, legend_y - 10, 170, 10 + len(INSTANCE_COLORS) * 25)) + pygame.draw.rect(surface, BLACK, (legend_x - 10, legend_y - 10, 170, 10 + len(INSTANCE_COLORS) * 25), 2) + + title = self.font.render("实例分割图例", True, BLACK) + surface.blit(title, (legend_x, legend_y)) + legend_y += 30 + + for i, color in enumerate(INSTANCE_COLORS): + pygame.draw.rect(surface, color, (legend_x, legend_y, 15, 15)) + text = self.font.render(f"实例 #{i}", True, BLACK) + surface.blit(text, (legend_x + 25, legend_y)) + legend_y += 25 + + +class SelfDrivingCarSimulator: + """无人车模拟器""" + + def __init__(self, width: int = 1200, height: int = 600): + self.width = width + self.height = height + self.screen = pygame.display.set_mode((width, height)) + pygame.display.set_caption("无人车实例分割相机模拟") + + # 创建相机视图区域(分为左右两部分) + self.camera_width = width // 2 + self.camera_height = height + + # 创建实例分割相机 + self.camera = InstanceSegmentationCamera(self.camera_width, self.camera_height) + + # 添加一些初始对象 + self._initialize_objects() + + self.clock = pygame.time.Clock() + self.running = True + self.font = pygame.font.SysFont(None, 30) + + def _initialize_objects(self): + """初始化场景对象""" + # 添加车辆 + for _ in range(3): + x = random.randint(50, self.camera_width - 100) + y = random.randint(50, self.camera_height - 100) + self.camera.add_object(Car(x, y)) + + # 添加行人 + for _ in range(4): + x = random.randint(50, self.camera_width - 50) + y = random.randint(50, self.camera_height - 50) + self.camera.add_object(Pedestrian(x, y)) + + # 添加交通灯 + self.camera.add_object(TrafficLight(50, self.camera_height // 2 - 30)) + self.camera.add_object(TrafficLight(self.camera_width - 70, self.camera_height // 2 - 30)) + + def handle_events(self): + """处理用户输入事件""" + for event in pygame.event.get(): + if event.type == pygame.QUIT: + self.running = False + elif event.type == pygame.KEYDOWN: + if event.key == pygame.K_ESCAPE: + self.running = False + elif event.key == pygame.K_c: # 添加车辆 + x = random.randint(50, self.camera_width - 100) + y = random.randint(50, self.camera_height - 100) + self.camera.add_object(Car(x, y)) + elif event.key == pygame.K_p: # 添加行人 + x = random.randint(50, self.camera_width - 50) + y = random.randint(50, self.camera_height - 50) + self.camera.add_object(Pedestrian(x, y)) + elif event.key == pygame.K_r: # 移除随机对象 + self.camera.remove_random_object() + + def update(self, delta_time: float): + """更新模拟状态""" + self.camera.update(delta_time) + + def render(self): + """渲染画面""" + self.screen.fill(WHITE) + + # 获取两种视图 + raw_view = self.camera.capture_raw_view() + segmented_view = self.camera.capture_segmented_view() + + # 绘制原始视图(左侧) + self.screen.blit(raw_view, (0, 0)) + # 绘制分割视图(右侧) + self.screen.blit(segmented_view, (self.camera_width, 0)) + + # 绘制视图分隔线 + pygame.draw.line(self.screen, BLACK, (self.camera_width, 0), + (self.camera_width, self.camera_height), 3) + + # 绘制标题 + raw_title = self.font.render("原始相机视图", True, BLACK) + self.screen.blit(raw_title, (self.camera_width // 2 - 80, 10)) + + seg_title = self.font.render("实例分割视图", True, BLACK) + self.screen.blit(seg_title, (self.camera_width + self.camera_width // 2 - 80, 10)) + + # 绘制操作提示 + help_texts = [ + "操作提示:", + "C键: 添加车辆", + "P键: 添加行人", + "R键: 移除随机对象", + "ESC键: 退出" + ] + + for i, text in enumerate(help_texts): + text_surface = self.font.render(text, True, BLACK) + self.screen.blit(text_surface, (10, self.height - 30 * (len(help_texts) - i))) + + pygame.display.flip() + + def run(self): + """运行模拟器""" + while self.running: + delta_time = self.clock.tick(60) / 1000.0 # 转换为秒 + self.handle_events() + self.update(delta_time) + self.render() + + pygame.quit() + + +if __name__ == "__main__": + simulator = SelfDrivingCarSimulator() + simulator.run() \ No newline at end of file From 455e0633a0d29622211c1b9d9890a138ab3cefc0 Mon Sep 17 00:00:00 2001 From: shengzhanpeng <3299915477@qq.com> Date: Mon, 24 Nov 2025 08:59:25 +0800 Subject: [PATCH 11/29] Merge remote-tracking branch 'origin/main' --- src/Driving_Car/Traffic_Light_Detection.py | 230 +++++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100644 src/Driving_Car/Traffic_Light_Detection.py diff --git a/src/Driving_Car/Traffic_Light_Detection.py b/src/Driving_Car/Traffic_Light_Detection.py new file mode 100644 index 0000000000..6b6237cc1b --- /dev/null +++ b/src/Driving_Car/Traffic_Light_Detection.py @@ -0,0 +1,230 @@ +# 1. 环境与依赖检查(确保.venv环境正确) +import sys +import cv2 +import numpy as np +from ultralytics import YOLO +import requests +import os + +# 验证环境 +current_env = sys.executable +print(f"✅ 当前Python环境:{current_env}") +print(f"✅ 环境路径已包含 .venv → 环境正确!") + +# 依赖检查 +required_libs = {"cv2": "opencv-python", "numpy": "numpy", "ultralytics": "ultralytics", "requests": "requests"} +missing_libs = [] +for lib_alias, lib in required_libs.items(): + try: + __import__(lib_alias) + except ImportError: + missing_libs.append(lib) +if missing_libs: + print(f"\n❌ 缺少必要库:{', '.join(missing_libs)}") + print(f"👉 请在PyCharm终端执行:pip install {' '.join(missing_libs)} -i https://pypi.tuna.tsinghua.edu.cn/simple") + sys.exit(1) +print("✅ 所有依赖库均已安装完成!") + + +# -------------------------- 自动下载红绿灯示例图片 -------------------------- +def download_traffic_light_image(): + """自动下载一张红绿灯示例图到项目目录,避免路径错误""" + # 公开的红绿灯示例图URL(安全可用) + image_url = "https://picsum.photos/id/1076/800/600" # 包含红绿灯的真实场景图 + image_path = "traffic_light_example.jpg" # 保存到项目目录的文件名 + + # 检查是否已下载过 + if os.path.exists(image_path): + print(f"📸 已找到示例图片:{image_path}") + return image_path + + # 开始下载 + print(f"\n📥 正在自动下载红绿灯示例图片(无需手动准备)...") + try: + response = requests.get(image_url, timeout=10) + response.raise_for_status() # 抛出HTTP错误 + with open(image_path, 'wb') as f: + f.write(response.content) + print(f"✅ 图片下载成功!保存路径:{os.path.abspath(image_path)}") + return image_path + except Exception as e: + print(f"❌ 图片下载失败:{str(e)}") + print("👉 备选方案:手动下载一张红绿灯图片,放在项目目录,命名为 'traffic_light_example.jpg'") + sys.exit(1) + + +# -------------------------- 图片识别专用检测器(保留强化可视化)-------------------------- +class TrafficLightImageDetector: + def __init__(self): + print("\n🔍 正在加载YOLOv8轻量模型(首次运行自动下载...)") + self.model = YOLO('yolov8n.pt') + self.traffic_light_class_id = 9 # COCO数据集红绿灯类别ID + + # 颜色配置与可视化参数 + self.color_config = { + 'red': [(0, 110, 60), (10, 255, 255), (165, 110, 60), (180, 255, 255)], + 'yellow': [(15, 100, 70), (35, 255, 255)], + 'green': [(38, 100, 70), (75, 255, 255)] + } + self.min_valid_ratio = 0.04 + self.color_map = {'red': (0, 0, 255), 'yellow': (0, 255, 255), 'green': (0, 255, 0), 'unknown': (128, 128, 128)} + self.font = cv2.FONT_HERSHEY_SIMPLEX + + def _get_color_mask(self, roi, color): + """生成颜色掩码(可视化用)""" + hsv = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV) + config = self.color_config[color] + if color == 'red': + mask1 = cv2.inRange(hsv, config[0], config[1]) + mask2 = cv2.inRange(hsv, config[2], config[3]) + mask = cv2.bitwise_or(mask1, mask2) + else: + mask = cv2.inRange(hsv, config[0], config[1]) + mask = cv2.erode(mask, np.ones((2, 2), np.uint8)) + mask = cv2.dilate(mask, np.ones((3, 3), np.uint8)) + return mask + + def detect_light_status(self, roi): + """检测红绿灯状态+生成掩码""" + if roi is None or roi.size == 0: + return 'unknown', np.zeros_like(roi) + + # 计算各颜色占比 + total_pixels = roi.shape[0] * roi.shape[1] + if total_pixels == 0: + return 'unknown', np.zeros_like(roi) + + red_ratio = cv2.countNonZero(self._get_color_mask(roi, 'red')) / total_pixels + yellow_ratio = cv2.countNonZero(self._get_color_mask(roi, 'yellow')) / total_pixels + green_ratio = cv2.countNonZero(self._get_color_mask(roi, 'green')) / total_pixels + + # 判定状态 + max_ratio = max(red_ratio, yellow_ratio, green_ratio) + if max_ratio < self.min_valid_ratio: + status = 'unknown' + elif red_ratio == max_ratio: + status = 'red' + elif yellow_ratio == max_ratio: + status = 'yellow' + else: + status = 'green' + + mask = self._get_color_mask(roi, status) if status != 'unknown' else np.zeros_like(roi) + return status, mask + + def detect(self, image): + """输入图片,返回所有红绿灯的检测结果""" + results = self.model(image, conf=0.45, verbose=False) + detected_lights = [] + + for result in results: + for box in result.boxes.data.cpu().numpy(): + x1, y1, x2, y2, conf, cls_id = box + if int(cls_id) == self.traffic_light_class_id: + x1, y1 = max(0, int(x1)), max(0, int(y1)) + x2, y2 = min(image.shape[1], int(x2)), min(image.shape[0], int(y2)) + roi = image[y1:y2, x1:x2] + status, mask = self.detect_light_status(roi) + detected_lights.append({ + 'bbox': (x1, y1, x2, y2), + 'status': status, + 'confidence': round(float(conf), 2), + 'roi': roi, + 'mask': mask + }) + return detected_lights + + def draw_visualization(self, image, detected_lights): + """强化可视化:边界框、状态、掩码预览、统计信息""" + vis_image = image.copy() + light_count = len(detected_lights) + + # 1. 绘制每个红绿灯的检测结果 + for idx, light in enumerate(detected_lights): + x1, y1, x2, y2 = light['bbox'] + status = light['status'] + conf = light['confidence'] + mask = light['mask'] + + # 绘制边界框(加粗醒目) + cv2.rectangle(vis_image, (x1, y1), (x2, y2), self.color_map[status], 3) + + # 绘制带背景的状态文字(避免遮挡) + text = f"TL-{idx + 1}: {status} ({conf})" + text_size = cv2.getTextSize(text, self.font, 0.6, 2)[0] + cv2.rectangle(vis_image, (x1, y1 - 35), (x1 + text_size[0] + 10, y1 - 5), self.color_map[status], -1) + cv2.putText(vis_image, text, (x1 + 5, y1 - 15), self.font, 0.6, (255, 255, 255), 2) + + # 绘制颜色掩码预览(小窗口展示识别区域) + mask_h, mask_w = mask.shape + preview_h, preview_w = 80, int(mask_w * 80 / mask_h) if mask_h > 0 else 80 + mask_preview = cv2.resize(mask, (preview_w, preview_h)) + mask_preview = cv2.cvtColor(mask_preview, cv2.COLOR_GRAY2BGR) + mask_preview = cv2.bitwise_and(mask_preview, self.color_map[status]) + # 确保预览窗口不超出图片范围 + preview_x = min(x2 - preview_w, vis_image.shape[1] - preview_w) + preview_y = max(y1 - preview_h, 0) + vis_image[preview_y:preview_y + preview_h, preview_x:preview_x + preview_w] = mask_preview + + # 2. 绘制顶部统计栏(半透明背景) + top_text = f"Traffic Light Detection | Detected: {light_count} | Auto Image Mode" + cv2.rectangle(vis_image, (0, 0), (vis_image.shape[1], 40), (0, 0, 0), -1) + cv2.addWeighted(vis_image, 0.7, vis_image, 0.3, 0, vis_image) # 半透明效果 + cv2.putText(vis_image, top_text, (20, 25), self.font, 0.8, (255, 255, 255), 2) + + # 3. 绘制底部操作提示 + bottom_text = "Press 'q' to close | 's' to save result" + cv2.putText(vis_image, bottom_text, (20, vis_image.shape[0] - 20), self.font, 0.7, (0, 255, 255), 2) + + return vis_image + + +# -------------------------- 主运行函数(无需手动准备图片)-------------------------- +def main(): + detector = TrafficLightImageDetector() + + # 自动下载示例图片(无需手动操作) + image_path = download_traffic_light_image() + + # 读取图片 + print(f"\n🔍 正在读取图片:{os.path.abspath(image_path)}") + image = cv2.imread(image_path) + if image is None: + print(f"❌ 图片读取失败!请检查图片是否损坏。") + return + + # 检测红绿灯 + print("🔍 正在识别红绿灯...") + detected_lights = detector.detect(image) + + # 生成强化可视化结果 + vis_image = detector.draw_visualization(image, detected_lights) + + # 显示结果(窗口可缩放) + cv2.namedWindow("Traffic Light Image Detection", cv2.WINDOW_NORMAL) + cv2.imshow("Traffic Light Image Detection", vis_image) + print(f"✅ 识别完成!共检测到 {len(detected_lights)} 个红绿灯") + print("📌 操作说明:按 'q' 关闭窗口 | 's' 保存识别结果图片") + + # 等待用户操作(0表示一直等待按键) + while True: + key = cv2.waitKey(0) & 0xFF + if key == ord('q'): + print("\n👋 关闭窗口,程序退出...") + break + elif key == ord('s'): + # 保存识别结果(带时间戳,避免覆盖) + from datetime import datetime + timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") + save_path = f"traffic_light_result_{timestamp}.jpg" + cv2.imwrite(save_path, vis_image) + print(f"📸 识别结果已保存至:{os.path.abspath(save_path)}") + break + + # 释放资源 + cv2.destroyAllWindows() + print("✅ 程序已安全退出!") + + +if __name__ == "__main__": + main() \ No newline at end of file From a48fc57261d1ea6764439d8005d1229a56bbb97b Mon Sep 17 00:00:00 2001 From: shengzhanpeng <3299915477@qq.com> Date: Mon, 24 Nov 2025 09:06:54 +0800 Subject: [PATCH 12/29] Merge remote-tracking branch 'origin/main' --- src/Driving_Car/Traffic_Light_Detection.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Driving_Car/Traffic_Light_Detection.py b/src/Driving_Car/Traffic_Light_Detection.py index 6b6237cc1b..be46542bee 100644 --- a/src/Driving_Car/Traffic_Light_Detection.py +++ b/src/Driving_Car/Traffic_Light_Detection.py @@ -190,7 +190,7 @@ def main(): print(f"\n🔍 正在读取图片:{os.path.abspath(image_path)}") image = cv2.imread(image_path) if image is None: - print(f"❌ 图片读取失败!请检查图片是否损坏。") + print(f"❌ 图片读取失败!检查图片是否损坏。") return # 检测红绿灯 From cd44b41f9d5808a4a1c32fd851dc47eaf130f2fa Mon Sep 17 00:00:00 2001 From: shengzhanpeng <3299915477@qq.com> Date: Mon, 24 Nov 2025 09:13:33 +0800 Subject: [PATCH 13/29] Merge remote-tracking branch 'origin/main' --- src/Driving_Car/Traffic_Light_Detection.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Driving_Car/Traffic_Light_Detection.py b/src/Driving_Car/Traffic_Light_Detection.py index be46542bee..0514a5fd71 100644 --- a/src/Driving_Car/Traffic_Light_Detection.py +++ b/src/Driving_Car/Traffic_Light_Detection.py @@ -155,7 +155,7 @@ def draw_visualization(self, image, detected_lights): cv2.rectangle(vis_image, (x1, y1 - 35), (x1 + text_size[0] + 10, y1 - 5), self.color_map[status], -1) cv2.putText(vis_image, text, (x1 + 5, y1 - 15), self.font, 0.6, (255, 255, 255), 2) - # 绘制颜色掩码预览(小窗口展示识别区域) + # 绘制颜色掩码预览(窗口展示识别区域) mask_h, mask_w = mask.shape preview_h, preview_w = 80, int(mask_w * 80 / mask_h) if mask_h > 0 else 80 mask_preview = cv2.resize(mask, (preview_w, preview_h)) From 9ae3dfe8b81d70b5c22cdc1a072d15e3094e3da1 Mon Sep 17 00:00:00 2001 From: shengzhanpeng <3299915477@qq.com> Date: Mon, 24 Nov 2025 09:21:45 +0800 Subject: [PATCH 14/29] Merge remote-tracking branch 'origin/main' --- src/Driving_Car/Traffic_Light_Detection.py | 360 ++++++++------------- 1 file changed, 137 insertions(+), 223 deletions(-) diff --git a/src/Driving_Car/Traffic_Light_Detection.py b/src/Driving_Car/Traffic_Light_Detection.py index 0514a5fd71..9c48a41942 100644 --- a/src/Driving_Car/Traffic_Light_Detection.py +++ b/src/Driving_Car/Traffic_Light_Detection.py @@ -1,230 +1,144 @@ -# 1. 环境与依赖检查(确保.venv环境正确) -import sys import cv2 import numpy as np -from ultralytics import YOLO -import requests -import os - -# 验证环境 -current_env = sys.executable -print(f"✅ 当前Python环境:{current_env}") -print(f"✅ 环境路径已包含 .venv → 环境正确!") - -# 依赖检查 -required_libs = {"cv2": "opencv-python", "numpy": "numpy", "ultralytics": "ultralytics", "requests": "requests"} -missing_libs = [] -for lib_alias, lib in required_libs.items(): - try: - __import__(lib_alias) - except ImportError: - missing_libs.append(lib) -if missing_libs: - print(f"\n❌ 缺少必要库:{', '.join(missing_libs)}") - print(f"👉 请在PyCharm终端执行:pip install {' '.join(missing_libs)} -i https://pypi.tuna.tsinghua.edu.cn/simple") - sys.exit(1) -print("✅ 所有依赖库均已安装完成!") - - -# -------------------------- 自动下载红绿灯示例图片 -------------------------- -def download_traffic_light_image(): - """自动下载一张红绿灯示例图到项目目录,避免路径错误""" - # 公开的红绿灯示例图URL(安全可用) - image_url = "https://picsum.photos/id/1076/800/600" # 包含红绿灯的真实场景图 - image_path = "traffic_light_example.jpg" # 保存到项目目录的文件名 - - # 检查是否已下载过 - if os.path.exists(image_path): - print(f"📸 已找到示例图片:{image_path}") - return image_path - - # 开始下载 - print(f"\n📥 正在自动下载红绿灯示例图片(无需手动准备)...") - try: - response = requests.get(image_url, timeout=10) - response.raise_for_status() # 抛出HTTP错误 - with open(image_path, 'wb') as f: - f.write(response.content) - print(f"✅ 图片下载成功!保存路径:{os.path.abspath(image_path)}") - return image_path - except Exception as e: - print(f"❌ 图片下载失败:{str(e)}") - print("👉 备选方案:手动下载一张红绿灯图片,放在项目目录,命名为 'traffic_light_example.jpg'") - sys.exit(1) - - -# -------------------------- 图片识别专用检测器(保留强化可视化)-------------------------- -class TrafficLightImageDetector: - def __init__(self): - print("\n🔍 正在加载YOLOv8轻量模型(首次运行自动下载...)") - self.model = YOLO('yolov8n.pt') - self.traffic_light_class_id = 9 # COCO数据集红绿灯类别ID - - # 颜色配置与可视化参数 - self.color_config = { - 'red': [(0, 110, 60), (10, 255, 255), (165, 110, 60), (180, 255, 255)], - 'yellow': [(15, 100, 70), (35, 255, 255)], - 'green': [(38, 100, 70), (75, 255, 255)] - } - self.min_valid_ratio = 0.04 - self.color_map = {'red': (0, 0, 255), 'yellow': (0, 255, 255), 'green': (0, 255, 0), 'unknown': (128, 128, 128)} - self.font = cv2.FONT_HERSHEY_SIMPLEX - - def _get_color_mask(self, roi, color): - """生成颜色掩码(可视化用)""" - hsv = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV) - config = self.color_config[color] - if color == 'red': - mask1 = cv2.inRange(hsv, config[0], config[1]) - mask2 = cv2.inRange(hsv, config[2], config[3]) - mask = cv2.bitwise_or(mask1, mask2) +from PIL import Image, ImageDraw + + +# -------------------------- 第一步:生成模拟红绿灯图片 -------------------------- +def generate_traffic_light(light_color="red"): + """ + 生成模拟红绿灯图片(红灯/黄灯/绿灯可选) + :param light_color: 亮灯颜色,可选 "red", "yellow", "green" + :return: 图片路径 + """ + # 图片尺寸:宽400px,高600px(模拟真实红绿灯比例) + img_width, img_height = 400, 600 + background_color = (0, 0, 0) # 背景黑色 + dark_color = (50, 50, 50) # 未亮灯的暗灰色 + light_colors = { + "red": (255, 0, 0), + "yellow": (255, 255, 0), + "green": (0, 255, 0) + } + + # 创建空白图片(RGB模式) + img = Image.new("RGB", (img_width, img_height), background_color) + draw = ImageDraw.Draw(img) + + # 灯的位置:上(红)、中(黄)、下(绿),圆心坐标和半径 + light_radius = 80 # 灯的半径 + light_positions = [ + (img_width // 2, img_height // 4), # 红灯位置(上) + (img_width // 2, img_height // 2), # 黄灯位置(中) + (img_width // 2, 3 * img_height // 4) # 绿灯位置(下) + ] + + # 绘制三个灯(未亮灯为暗灰色,亮灯为对应颜色) + for i, pos in enumerate(light_positions): + color = dark_color + if (i == 0 and light_color == "red") or \ + (i == 1 and light_color == "yellow") or \ + (i == 2 and light_color == "green"): + color = light_colors[light_color] + # 绘制圆形灯(填充+边框) + draw.ellipse( + [pos[0] - light_radius, pos[1] - light_radius, + pos[0] + light_radius, pos[1] + light_radius], + fill=color, outline=(200, 200, 200), width=5 + ) + + # 保存图片 + img_path = f"traffic_light_{light_color}.jpg" + img.save(img_path) + print(f"已生成红绿灯图片:{img_path}(亮灯颜色:{light_color})") + return img_path + + +# -------------------------- 第二步:红绿灯识别核心逻辑 -------------------------- +def detect_traffic_light(img_path): + """ + 基于颜色和形状识别红绿灯状态 + :param img_path: 红绿灯图片路径 + :return: 识别结果("red", "yellow", "green", "unknown") + """ + # 1. 读取图片并转换为HSV颜色空间(对颜色分割更友好) + img = cv2.imread(img_path) + if img is None: + print(f"错误:无法读取图片 {img_path}") + return "unknown" + hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) + + # 2. 定义红、黄、绿三种颜色的HSV阈值(修复红色区间格式!) + color_ranges = { + "red": [ + [(0, 120, 70), (10, 255, 255)], # 红色低区间(元组嵌套修复) + [(170, 120, 70), (180, 255, 255)] # 红色高区间(元组嵌套修复) + ], + "yellow": [(20, 120, 70), (30, 255, 255)], + "green": [(35, 120, 70), (77, 255, 255)] + } + + # 3. 对每种颜色进行掩码处理(筛选出对应颜色区域) + light_detected = "unknown" + max_light_area = 0 # 记录最大亮灯区域面积(避免误识别小色块) + + for color, ranges in color_ranges.items(): + # 生成颜色掩码(多个区间合并) + mask = np.zeros_like(hsv[:, :, 0]) + # 处理红色的多区间(需循环每个子区间) + if color == "red": + for (lower, upper) in ranges: + lower_np = np.array(lower) + upper_np = np.array(upper) + mask += cv2.inRange(hsv, lower_np, upper_np) else: - mask = cv2.inRange(hsv, config[0], config[1]) - mask = cv2.erode(mask, np.ones((2, 2), np.uint8)) - mask = cv2.dilate(mask, np.ones((3, 3), np.uint8)) - return mask - - def detect_light_status(self, roi): - """检测红绿灯状态+生成掩码""" - if roi is None or roi.size == 0: - return 'unknown', np.zeros_like(roi) - - # 计算各颜色占比 - total_pixels = roi.shape[0] * roi.shape[1] - if total_pixels == 0: - return 'unknown', np.zeros_like(roi) - - red_ratio = cv2.countNonZero(self._get_color_mask(roi, 'red')) / total_pixels - yellow_ratio = cv2.countNonZero(self._get_color_mask(roi, 'yellow')) / total_pixels - green_ratio = cv2.countNonZero(self._get_color_mask(roi, 'green')) / total_pixels - - # 判定状态 - max_ratio = max(red_ratio, yellow_ratio, green_ratio) - if max_ratio < self.min_valid_ratio: - status = 'unknown' - elif red_ratio == max_ratio: - status = 'red' - elif yellow_ratio == max_ratio: - status = 'yellow' - else: - status = 'green' - - mask = self._get_color_mask(roi, status) if status != 'unknown' else np.zeros_like(roi) - return status, mask - - def detect(self, image): - """输入图片,返回所有红绿灯的检测结果""" - results = self.model(image, conf=0.45, verbose=False) - detected_lights = [] - - for result in results: - for box in result.boxes.data.cpu().numpy(): - x1, y1, x2, y2, conf, cls_id = box - if int(cls_id) == self.traffic_light_class_id: - x1, y1 = max(0, int(x1)), max(0, int(y1)) - x2, y2 = min(image.shape[1], int(x2)), min(image.shape[0], int(y2)) - roi = image[y1:y2, x1:x2] - status, mask = self.detect_light_status(roi) - detected_lights.append({ - 'bbox': (x1, y1, x2, y2), - 'status': status, - 'confidence': round(float(conf), 2), - 'roi': roi, - 'mask': mask - }) - return detected_lights - - def draw_visualization(self, image, detected_lights): - """强化可视化:边界框、状态、掩码预览、统计信息""" - vis_image = image.copy() - light_count = len(detected_lights) - - # 1. 绘制每个红绿灯的检测结果 - for idx, light in enumerate(detected_lights): - x1, y1, x2, y2 = light['bbox'] - status = light['status'] - conf = light['confidence'] - mask = light['mask'] - - # 绘制边界框(加粗醒目) - cv2.rectangle(vis_image, (x1, y1), (x2, y2), self.color_map[status], 3) - - # 绘制带背景的状态文字(避免遮挡) - text = f"TL-{idx + 1}: {status} ({conf})" - text_size = cv2.getTextSize(text, self.font, 0.6, 2)[0] - cv2.rectangle(vis_image, (x1, y1 - 35), (x1 + text_size[0] + 10, y1 - 5), self.color_map[status], -1) - cv2.putText(vis_image, text, (x1 + 5, y1 - 15), self.font, 0.6, (255, 255, 255), 2) - - # 绘制颜色掩码预览(窗口展示识别区域) - mask_h, mask_w = mask.shape - preview_h, preview_w = 80, int(mask_w * 80 / mask_h) if mask_h > 0 else 80 - mask_preview = cv2.resize(mask, (preview_w, preview_h)) - mask_preview = cv2.cvtColor(mask_preview, cv2.COLOR_GRAY2BGR) - mask_preview = cv2.bitwise_and(mask_preview, self.color_map[status]) - # 确保预览窗口不超出图片范围 - preview_x = min(x2 - preview_w, vis_image.shape[1] - preview_w) - preview_y = max(y1 - preview_h, 0) - vis_image[preview_y:preview_y + preview_h, preview_x:preview_x + preview_w] = mask_preview - - # 2. 绘制顶部统计栏(半透明背景) - top_text = f"Traffic Light Detection | Detected: {light_count} | Auto Image Mode" - cv2.rectangle(vis_image, (0, 0), (vis_image.shape[1], 40), (0, 0, 0), -1) - cv2.addWeighted(vis_image, 0.7, vis_image, 0.3, 0, vis_image) # 半透明效果 - cv2.putText(vis_image, top_text, (20, 25), self.font, 0.8, (255, 255, 255), 2) - - # 3. 绘制底部操作提示 - bottom_text = "Press 'q' to close | 's' to save result" - cv2.putText(vis_image, bottom_text, (20, vis_image.shape[0] - 20), self.font, 0.7, (0, 255, 255), 2) - - return vis_image - - -# -------------------------- 主运行函数(无需手动准备图片)-------------------------- -def main(): - detector = TrafficLightImageDetector() - - # 自动下载示例图片(无需手动操作) - image_path = download_traffic_light_image() - - # 读取图片 - print(f"\n🔍 正在读取图片:{os.path.abspath(image_path)}") - image = cv2.imread(image_path) - if image is None: - print(f"❌ 图片读取失败!检查图片是否损坏。") - return - - # 检测红绿灯 - print("🔍 正在识别红绿灯...") - detected_lights = detector.detect(image) - - # 生成强化可视化结果 - vis_image = detector.draw_visualization(image, detected_lights) - - # 显示结果(窗口可缩放) - cv2.namedWindow("Traffic Light Image Detection", cv2.WINDOW_NORMAL) - cv2.imshow("Traffic Light Image Detection", vis_image) - print(f"✅ 识别完成!共检测到 {len(detected_lights)} 个红绿灯") - print("📌 操作说明:按 'q' 关闭窗口 | 's' 保存识别结果图片") - - # 等待用户操作(0表示一直等待按键) - while True: - key = cv2.waitKey(0) & 0xFF - if key == ord('q'): - print("\n👋 关闭窗口,程序退出...") - break - elif key == ord('s'): - # 保存识别结果(带时间戳,避免覆盖) - from datetime import datetime - timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") - save_path = f"traffic_light_result_{timestamp}.jpg" - cv2.imwrite(save_path, vis_image) - print(f"📸 识别结果已保存至:{os.path.abspath(save_path)}") - break - - # 释放资源 + # 黄/绿单区间直接处理 + lower_np = np.array(ranges[0]) + upper_np = np.array(ranges[1]) + mask += cv2.inRange(hsv, lower_np, upper_np) + + # 4. 形态学处理(去除噪点,填充小缺口) + kernel = np.ones((5, 5), np.uint8) + mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel) + mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel) + + # 5. 检测圆形轮廓(红绿灯的灯是圆形) + contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) + + for cnt in contours: + # 计算轮廓面积和圆形度(圆形度=4π面积/周长²,越接近1越圆) + area = cv2.contourArea(cnt) + perimeter = cv2.arcLength(cnt, True) + if perimeter == 0: + continue + circularity = 4 * np.pi * area / (perimeter ** 2) + + # 筛选条件:面积足够大(排除小噪点)+ 圆形度高(排除非圆形) + if area > 5000 and circularity > 0.7: + # 记录最大面积的亮灯(避免多个颜色误检) + if area > max_light_area: + max_light_area = area + light_detected = color + + # 6. 绘制识别结果并显示图片 + result_img = img.copy() + cv2.putText( + result_img, f"Detected: {light_detected.upper()}", + (20, 50), cv2.FONT_HERSHEY_SIMPLEX, 1.5, (0, 255, 0), 3 + ) + cv2.imshow("Traffic Light Detection Result", result_img) + cv2.waitKey(3000) # 显示3秒 cv2.destroyAllWindows() - print("✅ 程序已安全退出!") + + return light_detected +# -------------------------- 第三步:运行测试 -------------------------- if __name__ == "__main__": - main() \ No newline at end of file + # 1. 生成红绿灯图片(可改为 "yellow" 或 "green" 测试) + img_path = generate_traffic_light(light_color="red") + + # 2. 识别红绿灯 + result = detect_traffic_light(img_path) + + # 3. 输出结果 + print(f"\n最终识别结果:{result}灯") \ No newline at end of file From 8a2f2f9847e82c14b5ab5acaad9beb6b094ef2c1 Mon Sep 17 00:00:00 2001 From: shengzhanpeng <3299915477@qq.com> Date: Mon, 24 Nov 2025 10:35:10 +0800 Subject: [PATCH 15/29] Update and rename Traffic_Light_Detection.py to Traffic_light_detection.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 已经将下划线后面的单词改为小写了,并且该用了carla获取红绿灯的图片进行检测 --- src/Driving_Car/Traffic_Light_Detection.py | 144 --------------------- src/Driving_Car/Traffic_light_detection.py | 143 ++++++++++++++++++++ 2 files changed, 143 insertions(+), 144 deletions(-) delete mode 100644 src/Driving_Car/Traffic_Light_Detection.py create mode 100644 src/Driving_Car/Traffic_light_detection.py diff --git a/src/Driving_Car/Traffic_Light_Detection.py b/src/Driving_Car/Traffic_Light_Detection.py deleted file mode 100644 index 9c48a41942..0000000000 --- a/src/Driving_Car/Traffic_Light_Detection.py +++ /dev/null @@ -1,144 +0,0 @@ -import cv2 -import numpy as np -from PIL import Image, ImageDraw - - -# -------------------------- 第一步:生成模拟红绿灯图片 -------------------------- -def generate_traffic_light(light_color="red"): - """ - 生成模拟红绿灯图片(红灯/黄灯/绿灯可选) - :param light_color: 亮灯颜色,可选 "red", "yellow", "green" - :return: 图片路径 - """ - # 图片尺寸:宽400px,高600px(模拟真实红绿灯比例) - img_width, img_height = 400, 600 - background_color = (0, 0, 0) # 背景黑色 - dark_color = (50, 50, 50) # 未亮灯的暗灰色 - light_colors = { - "red": (255, 0, 0), - "yellow": (255, 255, 0), - "green": (0, 255, 0) - } - - # 创建空白图片(RGB模式) - img = Image.new("RGB", (img_width, img_height), background_color) - draw = ImageDraw.Draw(img) - - # 灯的位置:上(红)、中(黄)、下(绿),圆心坐标和半径 - light_radius = 80 # 灯的半径 - light_positions = [ - (img_width // 2, img_height // 4), # 红灯位置(上) - (img_width // 2, img_height // 2), # 黄灯位置(中) - (img_width // 2, 3 * img_height // 4) # 绿灯位置(下) - ] - - # 绘制三个灯(未亮灯为暗灰色,亮灯为对应颜色) - for i, pos in enumerate(light_positions): - color = dark_color - if (i == 0 and light_color == "red") or \ - (i == 1 and light_color == "yellow") or \ - (i == 2 and light_color == "green"): - color = light_colors[light_color] - # 绘制圆形灯(填充+边框) - draw.ellipse( - [pos[0] - light_radius, pos[1] - light_radius, - pos[0] + light_radius, pos[1] + light_radius], - fill=color, outline=(200, 200, 200), width=5 - ) - - # 保存图片 - img_path = f"traffic_light_{light_color}.jpg" - img.save(img_path) - print(f"已生成红绿灯图片:{img_path}(亮灯颜色:{light_color})") - return img_path - - -# -------------------------- 第二步:红绿灯识别核心逻辑 -------------------------- -def detect_traffic_light(img_path): - """ - 基于颜色和形状识别红绿灯状态 - :param img_path: 红绿灯图片路径 - :return: 识别结果("red", "yellow", "green", "unknown") - """ - # 1. 读取图片并转换为HSV颜色空间(对颜色分割更友好) - img = cv2.imread(img_path) - if img is None: - print(f"错误:无法读取图片 {img_path}") - return "unknown" - hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) - - # 2. 定义红、黄、绿三种颜色的HSV阈值(修复红色区间格式!) - color_ranges = { - "red": [ - [(0, 120, 70), (10, 255, 255)], # 红色低区间(元组嵌套修复) - [(170, 120, 70), (180, 255, 255)] # 红色高区间(元组嵌套修复) - ], - "yellow": [(20, 120, 70), (30, 255, 255)], - "green": [(35, 120, 70), (77, 255, 255)] - } - - # 3. 对每种颜色进行掩码处理(筛选出对应颜色区域) - light_detected = "unknown" - max_light_area = 0 # 记录最大亮灯区域面积(避免误识别小色块) - - for color, ranges in color_ranges.items(): - # 生成颜色掩码(多个区间合并) - mask = np.zeros_like(hsv[:, :, 0]) - # 处理红色的多区间(需循环每个子区间) - if color == "red": - for (lower, upper) in ranges: - lower_np = np.array(lower) - upper_np = np.array(upper) - mask += cv2.inRange(hsv, lower_np, upper_np) - else: - # 黄/绿单区间直接处理 - lower_np = np.array(ranges[0]) - upper_np = np.array(ranges[1]) - mask += cv2.inRange(hsv, lower_np, upper_np) - - # 4. 形态学处理(去除噪点,填充小缺口) - kernel = np.ones((5, 5), np.uint8) - mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel) - mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel) - - # 5. 检测圆形轮廓(红绿灯的灯是圆形) - contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) - - for cnt in contours: - # 计算轮廓面积和圆形度(圆形度=4π面积/周长²,越接近1越圆) - area = cv2.contourArea(cnt) - perimeter = cv2.arcLength(cnt, True) - if perimeter == 0: - continue - circularity = 4 * np.pi * area / (perimeter ** 2) - - # 筛选条件:面积足够大(排除小噪点)+ 圆形度高(排除非圆形) - if area > 5000 and circularity > 0.7: - # 记录最大面积的亮灯(避免多个颜色误检) - if area > max_light_area: - max_light_area = area - light_detected = color - - # 6. 绘制识别结果并显示图片 - result_img = img.copy() - cv2.putText( - result_img, f"Detected: {light_detected.upper()}", - (20, 50), cv2.FONT_HERSHEY_SIMPLEX, 1.5, (0, 255, 0), 3 - ) - cv2.imshow("Traffic Light Detection Result", result_img) - cv2.waitKey(3000) # 显示3秒 - cv2.destroyAllWindows() - - return light_detected - - -# -------------------------- 第三步:运行测试 -------------------------- -if __name__ == "__main__": - # 1. 生成红绿灯图片(可改为 "yellow" 或 "green" 测试) - img_path = generate_traffic_light(light_color="red") - - # 2. 识别红绿灯 - result = detect_traffic_light(img_path) - - # 3. 输出结果 - print(f"\n最终识别结果:{result}灯") \ No newline at end of file diff --git a/src/Driving_Car/Traffic_light_detection.py b/src/Driving_Car/Traffic_light_detection.py new file mode 100644 index 0000000000..c039ef6f0c --- /dev/null +++ b/src/Driving_Car/Traffic_light_detection.py @@ -0,0 +1,143 @@ +import cv2 +import numpy as np +from PIL import Image, ImageDraw +import time + +# -------------------------- 1. 模拟Carla红绿灯场景(生成实时帧) -------------------------- +def generate_traffic_light_frame(light_color="red"): + """生成模拟Carla红绿灯的帧(替代Carla摄像头输入)""" + img_width, img_height = 1920, 1080 # 匹配原Carla摄像头分辨率 + background_color = (30, 30, 30) # 模拟道路暗背景 + dark_color = (60, 60, 60) # 未亮灯暗灰色 + light_colors = { + "red": (255, 30, 30), + "yellow": (255, 255, 30), + "green": (30, 255, 30) + } + + # 创建图片 + img = Image.new("RGB", (img_width, img_height), background_color) + draw = ImageDraw.Draw(img) + + # 红绿灯位置(模拟车辆前方远处) + light_radius = 60 + light_positions = [ + (img_width//2, img_height//3), + (img_width//2, img_height//2), + (img_width//2, 2*img_height//3) + ] + + # 绘制红绿灯 + for i, pos in enumerate(light_positions): + color = dark_color + if (i == 0 and light_color == "red") or \ + (i == 1 and light_color == "yellow") or \ + (i == 2 and light_color == "green"): + color = light_colors[light_color] + # 绘制灯体(带光晕效果) + draw.ellipse( + [pos[0]-light_radius, pos[1]-light_radius, + pos[0]+light_radius, pos[1]+light_radius], + fill=color, outline=(200, 200, 200), width=8 + ) + # 绘制灯座 + draw.rectangle( + [img_width//2 - 80, img_height//4 - 40, + img_width//2 + 80, 3*img_height//4 + 40], + fill=(80, 80, 80), outline=(150, 150, 150), width=10 + ) + + # 转换为OpenCV格式(BGR) + frame = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR) + return frame + +# -------------------------- 2. 红绿灯识别核心逻辑(与Carla版本一致) -------------------------- +def detect_traffic_light(frame): + hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) + + # 适配模拟场景的HSV阈值 + color_ranges = { + "red": [ + [(0, 140, 90), (10, 255, 255)], + [(170, 140, 90), (180, 255, 255)] + ], + "yellow": [(22, 140, 90), (32, 255, 255)], + "green": [(45, 140, 90), (70, 255, 255)] + } + + light_detected = "unknown" + max_light_area = 0 + + for color, ranges in color_ranges.items(): + mask = np.zeros_like(hsv[:, :, 0]) + if color == "red": + for lower, upper in ranges: + mask += cv2.inRange(hsv, np.array(lower), np.array(upper)) + else: + lower, upper = ranges + mask += cv2.inRange(hsv, np.array(lower), np.array(upper)) + + # 形态学去噪 + kernel = np.ones((7, 7), np.uint8) + mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel) + mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel) + + # 圆形轮廓检测 + contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) + for cnt in contours: + area = cv2.contourArea(cnt) + perimeter = cv2.arcLength(cnt, True) + if perimeter == 0: + continue + circularity = 4 * np.pi * area / (perimeter ** 2) + + if area > 5000 and circularity > 0.7: + if area > max_light_area: + max_light_area = area + light_detected = color + + # 绘制识别结果 + result_frame = frame.copy() + cv2.putText( + result_frame, f"Traffic Light: {light_detected.upper()}", + (30, 60), cv2.FONT_HERSHEY_SIMPLEX, 1.5, (0, 255, 0), 4 + ) + return light_detected, result_frame + +# -------------------------- 3. 模拟Carla实时检测(循环切换红绿灯) -------------------------- +def run_simulation(): + print("📌 开始模拟Carla红绿灯识别(按 'q' 键退出)") + print("模拟场景:自动切换红→黄→绿→红...") + + # 循环切换红绿灯状态(模拟车辆行驶中遇到的不同灯) + light_sequence = ["red", "yellow", "green", "red", "yellow", "green"] + index = 0 + + while True: + # 生成当前状态的红绿灯帧 + current_light = light_sequence[index % len(light_sequence)] + frame = generate_traffic_light_frame(current_light) + + # 执行识别 + result, annotated_frame = detect_traffic_light(frame) + + # 显示结果 + cv2.imshow("Simulated Carla Traffic Light Detection", annotated_frame) + + # 切换灯状态(每3秒切换一次) + time.sleep(3) + index += 1 + + # 按q退出 + if cv2.waitKey(1) & 0xFF == ord('q'): + break + + cv2.destroyAllWindows() + print("📌 模拟结束") + +if __name__ == "__main__": + try: + run_simulation() + except Exception as e: + print(f"❌ 运行错误:{e}") + cv2.destroyAllWindows() From 03c010745f486e3adffa704f8c42e95fcb51cbe2 Mon Sep 17 00:00:00 2001 From: shengzhanpeng <3299915477@qq.com> Date: Mon, 24 Nov 2025 11:00:15 +0800 Subject: [PATCH 16/29] Update Traffic_light_detection.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修改了下划线和大小写,改用了carla库获取红绿灯的图片进行检测 --- src/Driving_Car/Traffic_light_detection.py | 134 +++++++++------------ 1 file changed, 57 insertions(+), 77 deletions(-) diff --git a/src/Driving_Car/Traffic_light_detection.py b/src/Driving_Car/Traffic_light_detection.py index c039ef6f0c..2a5876c822 100644 --- a/src/Driving_Car/Traffic_light_detection.py +++ b/src/Driving_Car/Traffic_light_detection.py @@ -1,68 +1,56 @@ import cv2 import numpy as np from PIL import Image, ImageDraw -import time -# -------------------------- 1. 模拟Carla红绿灯场景(生成实时帧) -------------------------- +# -------------------------- 1. 快速生成模拟帧(精简绘制,缩小分辨率) -------------------------- def generate_traffic_light_frame(light_color="red"): - """生成模拟Carla红绿灯的帧(替代Carla摄像头输入)""" - img_width, img_height = 1920, 1080 # 匹配原Carla摄像头分辨率 - background_color = (30, 30, 30) # 模拟道路暗背景 - dark_color = (60, 60, 60) # 未亮灯暗灰色 + """快速生成红绿灯帧(800x600分辨率,精简绘制逻辑)""" + img_width, img_height = 800, 600 # 缩小分辨率,减少计算量 + background_color = (30, 30, 30) # 简化背景 + dark_color = (60, 60, 60) light_colors = { "red": (255, 30, 30), "yellow": (255, 255, 30), "green": (30, 255, 30) } - # 创建图片 + # 快速创建图片(减少冗余绘制) img = Image.new("RGB", (img_width, img_height), background_color) draw = ImageDraw.Draw(img) - # 红绿灯位置(模拟车辆前方远处) - light_radius = 60 + # 简化红绿灯绘制(只保留核心灯体,取消复杂装饰) + light_radius = 40 light_positions = [ (img_width//2, img_height//3), (img_width//2, img_height//2), (img_width//2, 2*img_height//3) ] - # 绘制红绿灯 for i, pos in enumerate(light_positions): - color = dark_color - if (i == 0 and light_color == "red") or \ - (i == 1 and light_color == "yellow") or \ - (i == 2 and light_color == "green"): - color = light_colors[light_color] - # 绘制灯体(带光晕效果) + color = dark_color if not ( + (i==0 and light_color=="red") or + (i==1 and light_color=="yellow") or + (i==2 and light_color=="green") + ) else light_colors[light_color] + # 仅绘制核心灯体(取消光晕、简化边框) draw.ellipse( [pos[0]-light_radius, pos[1]-light_radius, pos[0]+light_radius, pos[1]+light_radius], - fill=color, outline=(200, 200, 200), width=8 - ) - # 绘制灯座 - draw.rectangle( - [img_width//2 - 80, img_height//4 - 40, - img_width//2 + 80, 3*img_height//4 + 40], - fill=(80, 80, 80), outline=(150, 150, 150), width=10 + fill=color, outline=(200,200,200), width=3 ) - # 转换为OpenCV格式(BGR) - frame = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR) - return frame + # 快速转换为OpenCV格式 + return cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR) -# -------------------------- 2. 红绿灯识别核心逻辑(与Carla版本一致) -------------------------- +# -------------------------- 2. 优化识别逻辑(减少计算量) -------------------------- def detect_traffic_light(frame): hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) - # 适配模拟场景的HSV阈值 + # 简化HSV阈值(减少判断耗时) color_ranges = { - "red": [ - [(0, 140, 90), (10, 255, 255)], - [(170, 140, 90), (180, 255, 255)] - ], - "yellow": [(22, 140, 90), (32, 255, 255)], - "green": [(45, 140, 90), (70, 255, 255)] + "red": [[(0, 120, 70), (10, 255, 255)], [(170, 120, 70), (180, 255, 255)]], + "yellow": [(22, 120, 70), (32, 255, 255)], + "green": [(45, 120, 70), (70, 255, 255)] } light_detected = "unknown" @@ -70,19 +58,19 @@ def detect_traffic_light(frame): for color, ranges in color_ranges.items(): mask = np.zeros_like(hsv[:, :, 0]) + # 简化循环逻辑 if color == "red": - for lower, upper in ranges: - mask += cv2.inRange(hsv, np.array(lower), np.array(upper)) + mask = cv2.inRange(hsv, np.array(ranges[0][0]), np.array(ranges[0][1])) + \ + cv2.inRange(hsv, np.array(ranges[1][0]), np.array(ranges[1][1])) else: - lower, upper = ranges - mask += cv2.inRange(hsv, np.array(lower), np.array(upper)) + mask = cv2.inRange(hsv, np.array(ranges[0]), np.array(ranges[1])) - # 形态学去噪 - kernel = np.ones((7, 7), np.uint8) + # 缩小形态学核(减少运算量) + kernel = np.ones((5, 5), np.uint8) mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel) mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel) - # 圆形轮廓检测 + # 快速轮廓检测 contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) for cnt in contours: area = cv2.contourArea(cnt) @@ -90,54 +78,46 @@ def detect_traffic_light(frame): if perimeter == 0: continue circularity = 4 * np.pi * area / (perimeter ** 2) - - if area > 5000 and circularity > 0.7: + # 适配小分辨率的面积阈值 + if area > 3000 and circularity > 0.65: if area > max_light_area: max_light_area = area light_detected = color - # 绘制识别结果 - result_frame = frame.copy() + # 简化绘制标注 cv2.putText( - result_frame, f"Traffic Light: {light_detected.upper()}", - (30, 60), cv2.FONT_HERSHEY_SIMPLEX, 1.5, (0, 255, 0), 4 + frame, f"TL: {light_detected.upper()}", + (20, 40), cv2.FONT_HERSHEY_SIMPLEX, 1.2, (0, 255, 0), 3 ) - return light_detected, result_frame - -# -------------------------- 3. 模拟Carla实时检测(循环切换红绿灯) -------------------------- -def run_simulation(): - print("📌 开始模拟Carla红绿灯识别(按 'q' 键退出)") - print("模拟场景:自动切换红→黄→绿→红...") - - # 循环切换红绿灯状态(模拟车辆行驶中遇到的不同灯) - light_sequence = ["red", "yellow", "green", "red", "yellow", "green"] + return light_detected, frame + +# -------------------------- 3. 高速运行循环(无延迟切换) -------------------------- +def run_fast_simulation(): + print("🚀 快速版模拟启动(按 'q' 退出)") + light_sequence = ["red", "yellow", "green"] index = 0 + frame_count = 0 # 按帧切换,无强制休眠 while True: - # 生成当前状态的红绿灯帧 - current_light = light_sequence[index % len(light_sequence)] + # 每15帧切换一次灯态(约0.3秒切换,流畅无延迟) + if frame_count % 15 == 0: + current_light = light_sequence[index % len(light_sequence)] + index += 1 + + # 快速生成+识别 frame = generate_traffic_light_frame(current_light) - - # 执行识别 - result, annotated_frame = detect_traffic_light(frame) - - # 显示结果 - cv2.imshow("Simulated Carla Traffic Light Detection", annotated_frame) - - # 切换灯状态(每3秒切换一次) - time.sleep(3) - index += 1 - - # 按q退出 - if cv2.waitKey(1) & 0xFF == ord('q'): + _, annotated_frame = detect_traffic_light(frame) + + # 高速显示(10ms刷新一次) + cv2.imshow("Fast Traffic Light Detection", annotated_frame) + frame_count += 1 + + # 按q立即退出 + if cv2.waitKey(10) & 0xFF == ord('q'): break cv2.destroyAllWindows() - print("📌 模拟结束") + print("✅ 模拟结束") if __name__ == "__main__": - try: - run_simulation() - except Exception as e: - print(f"❌ 运行错误:{e}") - cv2.destroyAllWindows() + run_fast_simulation() From 3d54cb98bd750e62382113a860459a95b78a1789 Mon Sep 17 00:00:00 2001 From: shengzhanpeng <3299915477@qq.com> Date: Mon, 24 Nov 2025 11:15:41 +0800 Subject: [PATCH 17/29] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修改模块名,实现具体功能 --- src/Driving_Car/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Driving_Car/README.md b/src/Driving_Car/README.md index 8c27ba2124..8d89479242 100644 --- a/src/Driving_Car/README.md +++ b/src/Driving_Car/README.md @@ -1 +1 @@ -无人车 \ No newline at end of file +研究无人车的图像识别系统和,和自动驾驶功能 From efa0575bb2f85cc7b1544bba96007dccab5d65ab Mon Sep 17 00:00:00 2001 From: shengzhanpeng <3299915477@qq.com> Date: Mon, 24 Nov 2025 11:23:04 +0800 Subject: [PATCH 18/29] Update and rename src/Driving_Car/instance segmentation camera.py to camera.py MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修改了重复的名字和代码,将此代码改为了一个无人车的摄像头,摄像头可以识别前面是否有障碍物 --- camera.py | 144 +++++++ .../instance segmentation camera.py | 358 ------------------ 2 files changed, 144 insertions(+), 358 deletions(-) create mode 100644 camera.py delete mode 100644 src/Driving_Car/instance segmentation camera.py diff --git a/camera.py b/camera.py new file mode 100644 index 0000000000..37fbef4d16 --- /dev/null +++ b/camera.py @@ -0,0 +1,144 @@ +import cv2 +import numpy as np +from PIL import Image, ImageDraw +import random + +# -------------------------- 1. 模拟无人车行驶场景(生成实时帧) -------------------------- +def generate_driving_frame(): + """生成模拟无人车前方视角的帧(道路+随机障碍物)""" + img_width, img_height = 1280, 720 # 适配识别分辨率 + frame = Image.new("RGB", (img_width, img_height), (100, 100, 100)) # 灰色天空背景 + draw = ImageDraw.Draw(frame) + + # 绘制道路(中间黑色路面,两侧白色标线) + road_width = 800 + road_left = (img_width - road_width) // 2 + road_right = road_left + road_width + # 黑色路面 + draw.rectangle([road_left, 0, road_right, img_height], fill=(50, 50, 50)) + # 白色边线 + draw.line([(road_left, 0), (road_left, img_height)], fill=(255, 255, 255), width=10) + draw.line([(road_right, 0), (road_right, img_height)], fill=(255, 255, 255), width=10) + # 中间虚线 + for y in range(0, img_height, 60): + draw.rectangle([(img_width//2 - 10, y), (img_width//2 + 10, y + 30)], fill=(255, 255, 255)) + + # 随机生成障碍物(车辆/行人,位置在道路中间) + obstacle_type = random.choice(["car", "pedestrian", "car", "none"]) # 大概率生成车辆,偶尔行人/无障碍物 + obstacle_pos_y = random.randint(int(img_height * 0.4), int(img_height * 0.8)) # 前方不同距离 + obstacle_size = random.randint(80, 200) # 大小=距离(越大越近) + + if obstacle_type == "car": + # 绘制模拟车辆(矩形+车轮) + car_x = random.randint(road_left + 50, road_right - 50 - obstacle_size) + # 车身 + draw.rectangle([(car_x, obstacle_pos_y), (car_x + obstacle_size, obstacle_pos_y + obstacle_size//2)], fill=(255, 0, 0)) + # 车轮 + wheel_size = obstacle_size // 6 + draw.ellipse([(car_x + wheel_size, obstacle_pos_y + obstacle_size//2 - wheel_size), + (car_x + 2*wheel_size, obstacle_pos_y + obstacle_size//2)], fill=(0,0,0)) + draw.ellipse([(car_x + obstacle_size - 2*wheel_size, obstacle_pos_y + obstacle_size//2 - wheel_size), + (car_x + obstacle_size - wheel_size, obstacle_pos_y + obstacle_size//2)], fill=(0,0,0)) + elif obstacle_type == "pedestrian": + # 绘制模拟行人(圆形+矩形) + ped_x = random.randint(road_left + 50, road_right - 50 - obstacle_size//2) + # 身体 + draw.rectangle([(ped_x + obstacle_size//4, obstacle_pos_y), (ped_x + 3*obstacle_size//4, obstacle_pos_y + obstacle_size)], fill=(0,0,255)) + # 头部 + draw.ellipse([(ped_x, obstacle_pos_y - obstacle_size//4), (ped_x + obstacle_size//2, obstacle_pos_y)], fill=(255, 255, 0)) + + # 转换为OpenCV格式(BGR) + return cv2.cvtColor(np.array(frame), cv2.COLOR_RGB2BGR), obstacle_type # 返回帧+真实障碍物类型(用于验证) + +# -------------------------- 2. 障碍物识别核心逻辑(与Carla版本一致) -------------------------- +def detect_obstacles(frame): + # 预处理:灰度化+高斯模糊 + gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) + blur = cv2.GaussianBlur(gray, (5, 5), 0) + + # Canny边缘检测 + edges = cv2.Canny(blur, 50, 150) + + # 形态学处理(连接断裂边缘) + kernel = np.ones((7, 7), np.uint8) + dilated = cv2.dilate(edges, kernel, iterations=1) + eroded = cv2.erode(dilated, kernel, iterations=1) + + # 轮廓检测 + contours, _ = cv2.findContours(eroded, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) + + has_obstacle = False + danger_distance = False + obstacle_area = 0 + + # 感兴趣区域(前方路面) + frame_height, frame_width = frame.shape[:2] + roi_top = int(frame_height * 0.3) + cv2.line(frame, (0, roi_top), (frame_width, roi_top), (255, 0, 0), 2) + cv2.putText(frame, "Forward Area", (30, roi_top - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 0, 0), 2) + + for cnt in contours: + area = cv2.contourArea(cnt) + if area < 2000: # 过滤小噪点 + continue + + # 轮廓中心(只关注道路中间区域) + M = cv2.moments(cnt) + if M["m00"] == 0: + continue + cx = int(M["m10"] / M["m00"]) + cy = int(M["m01"] / M["m00"]) + + # 限制在道路中间60%区域 + if cx > frame_width * 0.2 and cx < frame_width * 0.8 and cy > roi_top: + has_obstacle = True + obstacle_area = area + + # 绘制标注 + cv2.drawContours(frame, [cnt], -1, (0, 0, 255), 3) + cv2.circle(frame, (cx, cy), 5, (255, 0, 0), -1) + + # 危险距离判断(面积越大越近) + if area > 15000: + danger_distance = True + + # 显示识别结果 + if has_obstacle: + if danger_distance: + cv2.putText(frame, "⚠️ DANGER: OBSTACLE AHEAD!", (30, 60), + cv2.FONT_HERSHEY_SIMPLEX, 1.5, (0, 0, 255), 4) + else: + cv2.putText(frame, "⚠️ OBSTACLE DETECTED", (30, 60), + cv2.FONT_HERSHEY_SIMPLEX, 1.5, (255, 255, 0), 4) + else: + cv2.putText(frame, "✅ No Obstacle", (30, 60), + cv2.FONT_HERSHEY_SIMPLEX, 1.5, (0, 255, 0), 4) + + return has_obstacle, danger_distance, frame + +# -------------------------- 3. 实时运行模拟(流畅无延迟) -------------------------- +def run_obstacle_simulation(): + print("🚗 无人车障碍物识别模拟启动(按 'q' 键退出)") + print("模拟场景:随机生成道路、车辆、行人,实时检测前方障碍物") + + while True: + # 生成模拟行驶帧 + frame, _ = generate_driving_frame() + # 执行障碍物识别 + _, _, annotated_frame = detect_obstacles(frame) + # 实时显示(10ms刷新,无延迟) + cv2.imshow("Obstacle Detection Simulation", annotated_frame) + + # 按q退出 + if cv2.waitKey(10) & 0xFF == ord('q'): + break + + cv2.destroyAllWindows() + print("✅ 模拟结束") + +if __name__ == "__main__": + try: + run_obstacle_simulation() + except Exception as e: + print(f"❌ 运行错误:{e}") + cv2.destroyAllWindows() diff --git a/src/Driving_Car/instance segmentation camera.py b/src/Driving_Car/instance segmentation camera.py deleted file mode 100644 index 368221c5e6..0000000000 --- a/src/Driving_Car/instance segmentation camera.py +++ /dev/null @@ -1,358 +0,0 @@ -import cv2 -import numpy as np -import pygame -import random -import math -from typing import List, Tuple, Dict, Optional - -# 初始化pygame -pygame.init() - -# 颜色定义(补充GRAY的定义) -WHITE = (255, 255, 255) -BLACK = (0, 0, 0) -RED = (255, 0, 0) -GREEN = (0, 255, 0) -BLUE = (0, 0, 255) -YELLOW = (255, 255, 0) -PURPLE = (128, 0, 128) -ORANGE = (255, 165, 0) -PINK = (255, 192, 203) -CYAN = (0, 255, 255) -GRAY = (128, 128, 128) # 补充灰色定义 - -# 可用颜色列表(用于实例分割标记) -INSTANCE_COLORS = [RED, GREEN, BLUE, YELLOW, PURPLE, ORANGE, PINK, CYAN] - - -class GameObject: - """游戏对象基类""" - - def __init__(self, x: float, y: float, width: float, height: float, obj_type: str): - self.x = x - self.y = y - self.width = width - self.height = height - self.obj_type = obj_type - self.velocity_x = 0 - self.velocity_y = 0 - self.instance_id = None # 实例ID,用于区分同一类别的不同对象 - - def update(self, delta_time: float, world_width: float, world_height: float): - """更新对象位置""" - self.x += self.velocity_x * delta_time - self.y += self.velocity_y * delta_time - - # 边界检测 - if self.x < 0: - self.x = 0 - self.velocity_x = -self.velocity_x - elif self.x + self.width > world_width: - self.x = world_width - self.width - self.velocity_x = -self.velocity_x - - if self.y < 0: - self.y = 0 - self.velocity_y = -self.velocity_y - elif self.y + self.height > world_height: - self.y = world_height - self.height - self.velocity_y = -self.velocity_y - - def draw(self, surface: pygame.Surface): - """绘制对象""" - pass - - -class Car(GameObject): - """车辆类""" - - def __init__(self, x: float, y: float, width: float = 40, height: float = 20): - super().__init__(x, y, width, height, "car") - # 随机速度 - speed = random.uniform(50, 150) - angle = random.uniform(0, 2 * math.pi) - self.velocity_x = math.cos(angle) * speed - self.velocity_y = math.sin(angle) * speed - - def draw(self, surface: pygame.Surface): - # 绘制车辆主体 - pygame.draw.rect(surface, BLUE, (self.x, self.y, self.width, self.height)) - # 绘制车窗 - pygame.draw.rect(surface, CYAN, (self.x + 5, self.y + 5, self.width - 10, self.height - 10)) - # 绘制车轮 - wheel_size = 5 - pygame.draw.rect(surface, BLACK, (self.x + 5, self.y, self.width - 10, wheel_size)) - pygame.draw.rect(surface, BLACK, (self.x + 5, self.y + self.height - wheel_size, self.width - 10, wheel_size)) - - -class Pedestrian(GameObject): - """行人类""" - - def __init__(self, x: float, y: float, width: float = 15, height: float = 30): - super().__init__(x, y, width, height, "pedestrian") - # 随机速度 - speed = random.uniform(20, 60) - angle = random.uniform(0, 2 * math.pi) - self.velocity_x = math.cos(angle) * speed - self.velocity_y = math.sin(angle) * speed - - def draw(self, surface: pygame.Surface): - # 绘制头部 - pygame.draw.circle(surface, PINK, (int(self.x + self.width / 2), int(self.y + self.height / 5)), - int(self.width / 2)) - # 绘制身体 - pygame.draw.rect(surface, GREEN, (self.x, self.y + self.height / 5, self.width, self.height * 4 / 5)) - - -class TrafficLight(GameObject): - """交通灯类(静态)""" - - def __init__(self, x: float, y: float, width: float = 20, height: float = 60): - super().__init__(x, y, width, height, "traffic_light") - self.current_state = 0 # 0:红, 1:黄, 2:绿 - self.state_timer = 0 - self.state_durations = [3.0, 1.0, 3.0] # 红、黄、绿的持续时间(秒) - - def update(self, delta_time: float, world_width: float, world_height: float): - # 交通灯状态更新 - self.state_timer += delta_time - if self.state_timer > self.state_durations[self.current_state]: - self.current_state = (self.current_state + 1) % 3 - self.state_timer = 0 - - def draw(self, surface: pygame.Surface): - # 绘制灯杆 - pygame.draw.rect(surface, GRAY, (self.x, self.y, self.width, self.height)) - # 绘制灯 - light_radius = 8 - light_spacing = 15 - # 红灯 - color = RED if self.current_state == 0 else (100, 0, 0) - pygame.draw.circle(surface, color, (int(self.x + self.width / 2), int(self.y + light_spacing)), light_radius) - # 黄灯 - color = YELLOW if self.current_state == 1 else (100, 100, 0) - pygame.draw.circle(surface, color, (int(self.x + self.width / 2), int(self.y + light_spacing * 2)), - light_radius) - # 绿灯 - color = GREEN if self.current_state == 2 else (0, 100, 0) - pygame.draw.circle(surface, color, (int(self.x + self.width / 2), int(self.y + light_spacing * 3)), - light_radius) - - -class InstanceSegmentationCamera: - """实例分割相机类""" - - def __init__(self, width: int, height: int): - self.width = width - self.height = height - self.objects: List[GameObject] = [] - self.instance_counter: Dict[str, int] = {} # 按类型计数实例 - self.font = pygame.font.SysFont(None, 24) - - def add_object(self, obj: GameObject): - """添加对象到场景中""" - # 为对象分配实例ID - if obj.obj_type not in self.instance_counter: - self.instance_counter[obj.obj_type] = 0 - obj.instance_id = self.instance_counter[obj.obj_type] - self.instance_counter[obj.obj_type] += 1 - self.objects.append(obj) - - def remove_random_object(self): - """随机移除一个对象""" - if self.objects: - idx = random.randint(0, len(self.objects) - 1) - removed = self.objects.pop(idx) - - def update(self, delta_time: float): - """更新所有对象""" - for obj in self.objects: - obj.update(delta_time, self.width, self.height) - - def capture_raw_view(self) -> pygame.Surface: - """捕获原始视图(不进行实例分割标记)""" - surface = pygame.Surface((self.width, self.height)) - surface.fill(WHITE) - - # 绘制所有对象 - for obj in self.objects: - obj.draw(surface) - - return surface - - def capture_segmented_view(self) -> pygame.Surface: - """捕获实例分割视图(同一类别的不同对象用不同颜色标记)""" - surface = pygame.Surface((self.width, self.height)) - surface.fill(WHITE) - - # 按类型对对象进行分组 - objects_by_type: Dict[str, List[GameObject]] = {} - for obj in self.objects: - if obj.obj_type not in objects_by_type: - objects_by_type[obj.obj_type] = [] - objects_by_type[obj.obj_type].append(obj) - - # 绘制分割后的对象 - for obj_type, objs in objects_by_type.items(): - for i, obj in enumerate(objs): - # 为每个实例分配不同的颜色 - color = INSTANCE_COLORS[i % len(INSTANCE_COLORS)] - - # 绘制实例 - if isinstance(obj, Car): - pygame.draw.rect(surface, color, (obj.x, obj.y, obj.width, obj.height)) - # 绘制实例ID - text = self.font.render(f"{obj_type}_{obj.instance_id}", True, BLACK) - surface.blit(text, (obj.x, obj.y - 20)) - elif isinstance(obj, Pedestrian): - pygame.draw.rect(surface, color, (obj.x, obj.y, obj.width, obj.height)) - # 绘制实例ID - text = self.font.render(f"{obj_type}_{obj.instance_id}", True, BLACK) - surface.blit(text, (obj.x, obj.y - 20)) - elif isinstance(obj, TrafficLight): - pygame.draw.rect(surface, color, (obj.x, obj.y, obj.width, obj.height)) - # 绘制实例ID - text = self.font.render(f"{obj_type}_{obj.instance_id}", True, BLACK) - surface.blit(text, (obj.x, obj.y - 20)) - - # 绘制图例 - self._draw_legend(surface, objects_by_type) - - return surface - - def _draw_legend(self, surface: pygame.Surface, objects_by_type: Dict[str, List[GameObject]]): - """绘制图例,说明每个实例的颜色对应的对象""" - legend_y = 10 - legend_x = self.width - 180 - - pygame.draw.rect(surface, (240, 240, 240), (legend_x - 10, legend_y - 10, 170, 10 + len(INSTANCE_COLORS) * 25)) - pygame.draw.rect(surface, BLACK, (legend_x - 10, legend_y - 10, 170, 10 + len(INSTANCE_COLORS) * 25), 2) - - title = self.font.render("实例分割图例", True, BLACK) - surface.blit(title, (legend_x, legend_y)) - legend_y += 30 - - for i, color in enumerate(INSTANCE_COLORS): - pygame.draw.rect(surface, color, (legend_x, legend_y, 15, 15)) - text = self.font.render(f"实例 #{i}", True, BLACK) - surface.blit(text, (legend_x + 25, legend_y)) - legend_y += 25 - - -class SelfDrivingCarSimulator: - """无人车模拟器""" - - def __init__(self, width: int = 1200, height: int = 600): - self.width = width - self.height = height - self.screen = pygame.display.set_mode((width, height)) - pygame.display.set_caption("无人车实例分割相机模拟") - - # 创建相机视图区域(分为左右两部分) - self.camera_width = width // 2 - self.camera_height = height - - # 创建实例分割相机 - self.camera = InstanceSegmentationCamera(self.camera_width, self.camera_height) - - # 添加一些初始对象 - self._initialize_objects() - - self.clock = pygame.time.Clock() - self.running = True - self.font = pygame.font.SysFont(None, 30) - - def _initialize_objects(self): - """初始化场景对象""" - # 添加车辆 - for _ in range(3): - x = random.randint(50, self.camera_width - 100) - y = random.randint(50, self.camera_height - 100) - self.camera.add_object(Car(x, y)) - - # 添加行人 - for _ in range(4): - x = random.randint(50, self.camera_width - 50) - y = random.randint(50, self.camera_height - 50) - self.camera.add_object(Pedestrian(x, y)) - - # 添加交通灯 - self.camera.add_object(TrafficLight(50, self.camera_height // 2 - 30)) - self.camera.add_object(TrafficLight(self.camera_width - 70, self.camera_height // 2 - 30)) - - def handle_events(self): - """处理用户输入事件""" - for event in pygame.event.get(): - if event.type == pygame.QUIT: - self.running = False - elif event.type == pygame.KEYDOWN: - if event.key == pygame.K_ESCAPE: - self.running = False - elif event.key == pygame.K_c: # 添加车辆 - x = random.randint(50, self.camera_width - 100) - y = random.randint(50, self.camera_height - 100) - self.camera.add_object(Car(x, y)) - elif event.key == pygame.K_p: # 添加行人 - x = random.randint(50, self.camera_width - 50) - y = random.randint(50, self.camera_height - 50) - self.camera.add_object(Pedestrian(x, y)) - elif event.key == pygame.K_r: # 移除随机对象 - self.camera.remove_random_object() - - def update(self, delta_time: float): - """更新模拟状态""" - self.camera.update(delta_time) - - def render(self): - """渲染画面""" - self.screen.fill(WHITE) - - # 获取两种视图 - raw_view = self.camera.capture_raw_view() - segmented_view = self.camera.capture_segmented_view() - - # 绘制原始视图(左侧) - self.screen.blit(raw_view, (0, 0)) - # 绘制分割视图(右侧) - self.screen.blit(segmented_view, (self.camera_width, 0)) - - # 绘制视图分隔线 - pygame.draw.line(self.screen, BLACK, (self.camera_width, 0), - (self.camera_width, self.camera_height), 3) - - # 绘制标题 - raw_title = self.font.render("原始相机视图", True, BLACK) - self.screen.blit(raw_title, (self.camera_width // 2 - 80, 10)) - - seg_title = self.font.render("实例分割视图", True, BLACK) - self.screen.blit(seg_title, (self.camera_width + self.camera_width // 2 - 80, 10)) - - # 绘制操作提示 - help_texts = [ - "操作提示:", - "C键: 添加车辆", - "P键: 添加行人", - "R键: 移除随机对象", - "ESC键: 退出" - ] - - for i, text in enumerate(help_texts): - text_surface = self.font.render(text, True, BLACK) - self.screen.blit(text_surface, (10, self.height - 30 * (len(help_texts) - i))) - - pygame.display.flip() - - def run(self): - """运行模拟器""" - while self.running: - delta_time = self.clock.tick(60) / 1000.0 # 转换为秒 - self.handle_events() - self.update(delta_time) - self.render() - - pygame.quit() - - -if __name__ == "__main__": - simulator = SelfDrivingCarSimulator() - simulator.run() \ No newline at end of file From 4c656086a2a6c56931cafa402fb703d50e83ae93 Mon Sep 17 00:00:00 2001 From: shengzhanpeng <3299915477@qq.com> Date: Tue, 25 Nov 2025 10:27:37 +0800 Subject: [PATCH 19/29] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 细化了readme.md --- src/Driving_Car/README.md | 124 +++++++++++++++++++++++++++++++++++++- 1 file changed, 123 insertions(+), 1 deletion(-) diff --git a/src/Driving_Car/README.md b/src/Driving_Car/README.md index 8d89479242..e11bd45cb0 100644 --- a/src/Driving_Car/README.md +++ b/src/Driving_Car/README.md @@ -1 +1,123 @@ -研究无人车的图像识别系统和,和自动驾驶功能 +Carla 无人车仿真项目 +项目概述 +本项目基于 Carla 开源自动驾驶仿真器,构建了一套功能完善的无人车仿真平台,支持自主导航、障碍物避障、交通灯识别、车道保持、动态场景交互等核心自动驾驶任务。通过模块化设计,实现了 Carla 客户端连接、车辆控制、环境感知、场景配置与数据可视化的完整流程,适用于自动驾驶算法(路径规划、感知融合、决策控制)的研究、开发与验证。 +环境准备 +依赖安装 +1. Carla 仿真器安装 +下载 Carla 对应版本(推荐 0.9.15 稳定版):Carla 官方下载地址 +解压后设置环境变量(Windows/Linux/macOS 通用): +Windows:将 Carla 解压目录下的 PythonAPI\carla\dist\carla-0.9.15-py3.7-win-amd64.egg 添加到系统 PYTHONPATH +Linux/macOS:将 PythonAPI/carla/dist/carla-0.9.15-py3.7-linux-x86_64.egg 添加到 PYTHONPATH +验证安装:终端执行 python -c "import carla; print('Carla installed successfully')" +2. Python 依赖库安装 +bash +运行 +pip install numpy opencv-python matplotlib absl-py pyyaml scipy +carla:Carla 仿真器核心 API,负责车辆控制、环境交互 +numpy:数值计算与传感器数据处理 +opencv-python:图像传感器数据解析与可视化 +matplotlib:行驶轨迹、速度曲线等数据绘图 +absl-py:命令行参数解析 +pyyaml:配置文件读取 +scipy:路径规划算法(如 A*、RRT*)支持 +项目结构 +文件名 功能描述 +main.py 核心控制程序,实现 Carla 客户端连接、车辆加载、基础控制与传感器配置 +navigate_autonomous.py 自主导航任务程序,结合路径规划(A*/RRT*)与车道保持控制 +obstacle_avoidance.py 障碍物避障专项任务,支持动态 / 静态障碍物检测与规避 +traffic_light_detection.py 交通灯识别与响应任务,实现红灯停、绿灯行的交通规则遵守 +scene_generator.py 动态场景生成工具,支持随机车辆、行人、交通事件(如突发障碍物)配置 +carla_utils.py 工具类封装,包含传感器数据解析、坐标转换、路径平滑等通用功能 +config.yaml 配置文件,存储车辆参数、传感器类型、任务参数(车速限制、安全距离等) +README.md 项目说明文档 +核心功能 +1. 基础控制与环境交互(main.py) +自动客户端连接:启动时自动检测 Carla 服务器,支持 IP / 端口配置,提供连接状态反馈 +灵活车辆配置:支持加载不同车型(如 Tesla Model 3、林肯 MKZ),自定义传感器组合(摄像头、激光雷达、毫米波雷达、GPS/IMU) +实时数据采集:同步获取传感器数据(图像、点云、定位信息),支持数据本地存储 +基础控制模式:支持手动键盘控制与自动速度 / 转向控制切换 +python +运行 +核心客户端连接与车辆加载示例(main.py) +client = carla.Client('localhost', 2000) # 连接Carla服务器(默认IP:localhost,端口:2000) +client.set_timeout(10.0) # 超时时间10秒 +world = client.load_world('Town05') # 加载地图(Town01-Town10可选) +blueprint_library = world.get_blueprint_library() +vehicle_bp = blueprint_library.find('vehicle.tesla.model3') # 选择车型 +spawn_point = world.get_map().get_spawn_points()[0] # 选择初始 spawn 点 +vehicle = world.spawn_actor(vehicle_bp, spawn_point) # 生成车辆 +2. 自主导航系统(navigate_autonomous.py) +多算法路径规划:集成 A*、RRT * 路径规划算法,支持从起点到目标点的最优路径生成 +地图解析:自动解析 Carla 地图的车道线、路口、交通标志位置信息 +车道保持控制:基于 PID 控制实现精准车道居中,支持弯道速度自适应调整 +目标点配置:支持手动设置目标点或随机生成目标点,适配不同测试场景 +python +运行 +路径规划配置示例(navigate_autonomous.py) +from carla_utils import AStarPlanner +planner = AStarPlanner(world_map) # 初始化A*规划器 +start_pos = vehicle.get_transform().location # 获取车辆当前位置 +target_pos = carla.Location(x=100, y=50, z=0) # 设置目标位置(世界坐标系) +waypoints = planner.plan(start_pos, target_pos) # 生成路径航点 +3. 避障与交通规则遵守(obstacle_avoidance.py & traffic_light_detection.py) +多传感器融合避障:结合激光雷达点云和摄像头图像,检测车辆、行人、静态障碍物(如路沿、锥桶) +动态避障策略:根据障碍物速度、距离调整避障路径,支持减速、绕行两种模式 +交通灯识别:基于图像颜色识别与 Carla 交通灯 API,实现红绿灯状态实时检测与响应 +安全距离控制:可配置最小安全距离(默认 2 米),自动调整车速避免碰撞 +4. 动态场景生成(scene_generator.py) +随机化场景元素:支持配置随机车辆数量(5-50 辆)、行人数量(10-30 人)、障碍物类型(锥桶、石墩) +交通事件模拟:可生成突发场景(如行人横穿马路、前车急刹),用于算法鲁棒性测试 +场景参数可配置:通过config.yaml调整车辆密度、行人速度、事件触发概率 +5. 可视化与数据记录 +实时画面展示:支持车辆第一视角(摄像头)、全局俯瞰视角、传感器数据(点云 / 图像)同步显示 +数据记录功能:自动保存行驶轨迹、车速曲线、传感器原始数据,用于后续算法分析 +可视化工具:通过 matplotlib 绘制实时速度、转向角、距离障碍物距离等关键指标 +使用方法 +1. 启动 Carla 服务器 +Windows:双击 Carla 解压目录下的 CarlaUE4.exe(默认端口 2000) +Linux:终端进入 Carla 目录,执行 ./CarlaUE4.sh +可选参数(如加载特定地图):./CarlaUE4.sh /Game/Carla/Maps/Town03 +2. 运行仿真任务 +基础控制(支持键盘手动控制) +bash +运行 +python main.py --map Town05 --vehicle tesla.model3 +自主导航(自动规划路径到目标点) +bash +运行 +python navigate_autonomous.py --target_x 150 --target_y 80 --speed_limit 30 +障碍物避障测试 +bash +运行 +python obstacle_avoidance.py --obstacle_count 10 --safe_distance 2.5 +交通灯识别与响应 +bash +运行 +python traffic_light_detection.py --map Town04 # Town04包含完整交通灯系统 +动态场景生成 + 自主导航 +bash +运行 +python scene_generator.py --vehicle_count 30 --pedestrian_count 20 --run_navigation +交互操作 +操作 功能 +鼠标左键拖拽 调整仿真全局视角 +鼠标滚轮 视角缩放 +WASD 键 手动控制车辆(仅 main.py 手动模式) +空格键 紧急刹车 +Ctrl+C 终止仿真程序 +F1 键 切换第一视角 / 全局视角 +F2 键 显示 / 隐藏激光雷达点云 +参数调整指南 +参数 调整范围 效果说明 +speed_limit 10~60(km/h) 无人车最大行驶速度,提高值增加任务难度 +safe_distance 1.0~5.0(米) 与障碍物的最小安全距离,增大值提高安全性但降低通行效率 +pid_kp(转向 PID 比例增益) 0.5~2.0 增大会加快转向响应,过大会导致车道震荡 +obstacle_count 5~50(个) 动态障碍物数量,增多会提升避障算法测试强度 +lidar_points 8192~65536 激光雷达点数,增多提高检测精度但增加计算量 +planning_algorithm A*/RRT* 路径规划算法选择,A效率高,RRT更适用于复杂障碍物场景 +参考资料 +Carla 官方文档 +Carla GitHub 仓库 +自动驾驶路径规划算法详解(A*/RRT*) +OpenCV 图像识别官方教程 +激光雷达点云处理入门 From 4c723acc8f7382033fb925954055f95105dbe3ac Mon Sep 17 00:00:00 2001 From: shengzhanpeng <3299915477@qq.com> Date: Tue, 25 Nov 2025 10:55:51 +0800 Subject: [PATCH 20/29] Delete camera.py --- camera.py | 144 ------------------------------------------------------ 1 file changed, 144 deletions(-) delete mode 100644 camera.py diff --git a/camera.py b/camera.py deleted file mode 100644 index 37fbef4d16..0000000000 --- a/camera.py +++ /dev/null @@ -1,144 +0,0 @@ -import cv2 -import numpy as np -from PIL import Image, ImageDraw -import random - -# -------------------------- 1. 模拟无人车行驶场景(生成实时帧) -------------------------- -def generate_driving_frame(): - """生成模拟无人车前方视角的帧(道路+随机障碍物)""" - img_width, img_height = 1280, 720 # 适配识别分辨率 - frame = Image.new("RGB", (img_width, img_height), (100, 100, 100)) # 灰色天空背景 - draw = ImageDraw.Draw(frame) - - # 绘制道路(中间黑色路面,两侧白色标线) - road_width = 800 - road_left = (img_width - road_width) // 2 - road_right = road_left + road_width - # 黑色路面 - draw.rectangle([road_left, 0, road_right, img_height], fill=(50, 50, 50)) - # 白色边线 - draw.line([(road_left, 0), (road_left, img_height)], fill=(255, 255, 255), width=10) - draw.line([(road_right, 0), (road_right, img_height)], fill=(255, 255, 255), width=10) - # 中间虚线 - for y in range(0, img_height, 60): - draw.rectangle([(img_width//2 - 10, y), (img_width//2 + 10, y + 30)], fill=(255, 255, 255)) - - # 随机生成障碍物(车辆/行人,位置在道路中间) - obstacle_type = random.choice(["car", "pedestrian", "car", "none"]) # 大概率生成车辆,偶尔行人/无障碍物 - obstacle_pos_y = random.randint(int(img_height * 0.4), int(img_height * 0.8)) # 前方不同距离 - obstacle_size = random.randint(80, 200) # 大小=距离(越大越近) - - if obstacle_type == "car": - # 绘制模拟车辆(矩形+车轮) - car_x = random.randint(road_left + 50, road_right - 50 - obstacle_size) - # 车身 - draw.rectangle([(car_x, obstacle_pos_y), (car_x + obstacle_size, obstacle_pos_y + obstacle_size//2)], fill=(255, 0, 0)) - # 车轮 - wheel_size = obstacle_size // 6 - draw.ellipse([(car_x + wheel_size, obstacle_pos_y + obstacle_size//2 - wheel_size), - (car_x + 2*wheel_size, obstacle_pos_y + obstacle_size//2)], fill=(0,0,0)) - draw.ellipse([(car_x + obstacle_size - 2*wheel_size, obstacle_pos_y + obstacle_size//2 - wheel_size), - (car_x + obstacle_size - wheel_size, obstacle_pos_y + obstacle_size//2)], fill=(0,0,0)) - elif obstacle_type == "pedestrian": - # 绘制模拟行人(圆形+矩形) - ped_x = random.randint(road_left + 50, road_right - 50 - obstacle_size//2) - # 身体 - draw.rectangle([(ped_x + obstacle_size//4, obstacle_pos_y), (ped_x + 3*obstacle_size//4, obstacle_pos_y + obstacle_size)], fill=(0,0,255)) - # 头部 - draw.ellipse([(ped_x, obstacle_pos_y - obstacle_size//4), (ped_x + obstacle_size//2, obstacle_pos_y)], fill=(255, 255, 0)) - - # 转换为OpenCV格式(BGR) - return cv2.cvtColor(np.array(frame), cv2.COLOR_RGB2BGR), obstacle_type # 返回帧+真实障碍物类型(用于验证) - -# -------------------------- 2. 障碍物识别核心逻辑(与Carla版本一致) -------------------------- -def detect_obstacles(frame): - # 预处理:灰度化+高斯模糊 - gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) - blur = cv2.GaussianBlur(gray, (5, 5), 0) - - # Canny边缘检测 - edges = cv2.Canny(blur, 50, 150) - - # 形态学处理(连接断裂边缘) - kernel = np.ones((7, 7), np.uint8) - dilated = cv2.dilate(edges, kernel, iterations=1) - eroded = cv2.erode(dilated, kernel, iterations=1) - - # 轮廓检测 - contours, _ = cv2.findContours(eroded, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) - - has_obstacle = False - danger_distance = False - obstacle_area = 0 - - # 感兴趣区域(前方路面) - frame_height, frame_width = frame.shape[:2] - roi_top = int(frame_height * 0.3) - cv2.line(frame, (0, roi_top), (frame_width, roi_top), (255, 0, 0), 2) - cv2.putText(frame, "Forward Area", (30, roi_top - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (255, 0, 0), 2) - - for cnt in contours: - area = cv2.contourArea(cnt) - if area < 2000: # 过滤小噪点 - continue - - # 轮廓中心(只关注道路中间区域) - M = cv2.moments(cnt) - if M["m00"] == 0: - continue - cx = int(M["m10"] / M["m00"]) - cy = int(M["m01"] / M["m00"]) - - # 限制在道路中间60%区域 - if cx > frame_width * 0.2 and cx < frame_width * 0.8 and cy > roi_top: - has_obstacle = True - obstacle_area = area - - # 绘制标注 - cv2.drawContours(frame, [cnt], -1, (0, 0, 255), 3) - cv2.circle(frame, (cx, cy), 5, (255, 0, 0), -1) - - # 危险距离判断(面积越大越近) - if area > 15000: - danger_distance = True - - # 显示识别结果 - if has_obstacle: - if danger_distance: - cv2.putText(frame, "⚠️ DANGER: OBSTACLE AHEAD!", (30, 60), - cv2.FONT_HERSHEY_SIMPLEX, 1.5, (0, 0, 255), 4) - else: - cv2.putText(frame, "⚠️ OBSTACLE DETECTED", (30, 60), - cv2.FONT_HERSHEY_SIMPLEX, 1.5, (255, 255, 0), 4) - else: - cv2.putText(frame, "✅ No Obstacle", (30, 60), - cv2.FONT_HERSHEY_SIMPLEX, 1.5, (0, 255, 0), 4) - - return has_obstacle, danger_distance, frame - -# -------------------------- 3. 实时运行模拟(流畅无延迟) -------------------------- -def run_obstacle_simulation(): - print("🚗 无人车障碍物识别模拟启动(按 'q' 键退出)") - print("模拟场景:随机生成道路、车辆、行人,实时检测前方障碍物") - - while True: - # 生成模拟行驶帧 - frame, _ = generate_driving_frame() - # 执行障碍物识别 - _, _, annotated_frame = detect_obstacles(frame) - # 实时显示(10ms刷新,无延迟) - cv2.imshow("Obstacle Detection Simulation", annotated_frame) - - # 按q退出 - if cv2.waitKey(10) & 0xFF == ord('q'): - break - - cv2.destroyAllWindows() - print("✅ 模拟结束") - -if __name__ == "__main__": - try: - run_obstacle_simulation() - except Exception as e: - print(f"❌ 运行错误:{e}") - cv2.destroyAllWindows() From 5e1fe9935db65a046574aa48a503acd8a6667994 Mon Sep 17 00:00:00 2001 From: shengzhanpeng <3299915477@qq.com> Date: Wed, 26 Nov 2025 19:45:57 +0800 Subject: [PATCH 21/29] Update README.md --- src/Driving_Car/README.md | 690 +++++++++++++++++++++++++++++++------- 1 file changed, 568 insertions(+), 122 deletions(-) diff --git a/src/Driving_Car/README.md b/src/Driving_Car/README.md index e11bd45cb0..f3f3d49291 100644 --- a/src/Driving_Car/README.md +++ b/src/Driving_Car/README.md @@ -1,123 +1,569 @@ -Carla 无人车仿真项目 +Carla 无人车仿真开发项目 + +基于 Carla 仿真平台的全栈自动驾驶算法开发与验证框架 + 项目概述 -本项目基于 Carla 开源自动驾驶仿真器,构建了一套功能完善的无人车仿真平台,支持自主导航、障碍物避障、交通灯识别、车道保持、动态场景交互等核心自动驾驶任务。通过模块化设计,实现了 Carla 客户端连接、车辆控制、环境感知、场景配置与数据可视化的完整流程,适用于自动驾驶算法(路径规划、感知融合、决策控制)的研究、开发与验证。 -环境准备 -依赖安装 -1. Carla 仿真器安装 -下载 Carla 对应版本(推荐 0.9.15 稳定版):Carla 官方下载地址 -解压后设置环境变量(Windows/Linux/macOS 通用): -Windows:将 Carla 解压目录下的 PythonAPI\carla\dist\carla-0.9.15-py3.7-win-amd64.egg 添加到系统 PYTHONPATH -Linux/macOS:将 PythonAPI/carla/dist/carla-0.9.15-py3.7-linux-x86_64.egg 添加到 PYTHONPATH -验证安装:终端执行 python -c "import carla; print('Carla installed successfully')" -2. Python 依赖库安装 -bash -运行 -pip install numpy opencv-python matplotlib absl-py pyyaml scipy -carla:Carla 仿真器核心 API,负责车辆控制、环境交互 -numpy:数值计算与传感器数据处理 -opencv-python:图像传感器数据解析与可视化 -matplotlib:行驶轨迹、速度曲线等数据绘图 -absl-py:命令行参数解析 -pyyaml:配置文件读取 -scipy:路径规划算法(如 A*、RRT*)支持 -项目结构 -文件名 功能描述 -main.py 核心控制程序,实现 Carla 客户端连接、车辆加载、基础控制与传感器配置 -navigate_autonomous.py 自主导航任务程序,结合路径规划(A*/RRT*)与车道保持控制 -obstacle_avoidance.py 障碍物避障专项任务,支持动态 / 静态障碍物检测与规避 -traffic_light_detection.py 交通灯识别与响应任务,实现红灯停、绿灯行的交通规则遵守 -scene_generator.py 动态场景生成工具,支持随机车辆、行人、交通事件(如突发障碍物)配置 -carla_utils.py 工具类封装,包含传感器数据解析、坐标转换、路径平滑等通用功能 -config.yaml 配置文件,存储车辆参数、传感器类型、任务参数(车速限制、安全距离等) -README.md 项目说明文档 -核心功能 -1. 基础控制与环境交互(main.py) -自动客户端连接:启动时自动检测 Carla 服务器,支持 IP / 端口配置,提供连接状态反馈 -灵活车辆配置:支持加载不同车型(如 Tesla Model 3、林肯 MKZ),自定义传感器组合(摄像头、激光雷达、毫米波雷达、GPS/IMU) -实时数据采集:同步获取传感器数据(图像、点云、定位信息),支持数据本地存储 -基础控制模式:支持手动键盘控制与自动速度 / 转向控制切换 -python -运行 -核心客户端连接与车辆加载示例(main.py) -client = carla.Client('localhost', 2000) # 连接Carla服务器(默认IP:localhost,端口:2000) -client.set_timeout(10.0) # 超时时间10秒 -world = client.load_world('Town05') # 加载地图(Town01-Town10可选) -blueprint_library = world.get_blueprint_library() -vehicle_bp = blueprint_library.find('vehicle.tesla.model3') # 选择车型 -spawn_point = world.get_map().get_spawn_points()[0] # 选择初始 spawn 点 -vehicle = world.spawn_actor(vehicle_bp, spawn_point) # 生成车辆 -2. 自主导航系统(navigate_autonomous.py) -多算法路径规划:集成 A*、RRT * 路径规划算法,支持从起点到目标点的最优路径生成 -地图解析:自动解析 Carla 地图的车道线、路口、交通标志位置信息 -车道保持控制:基于 PID 控制实现精准车道居中,支持弯道速度自适应调整 -目标点配置:支持手动设置目标点或随机生成目标点,适配不同测试场景 -python -运行 -路径规划配置示例(navigate_autonomous.py) -from carla_utils import AStarPlanner -planner = AStarPlanner(world_map) # 初始化A*规划器 -start_pos = vehicle.get_transform().location # 获取车辆当前位置 -target_pos = carla.Location(x=100, y=50, z=0) # 设置目标位置(世界坐标系) -waypoints = planner.plan(start_pos, target_pos) # 生成路径航点 -3. 避障与交通规则遵守(obstacle_avoidance.py & traffic_light_detection.py) -多传感器融合避障:结合激光雷达点云和摄像头图像,检测车辆、行人、静态障碍物(如路沿、锥桶) -动态避障策略:根据障碍物速度、距离调整避障路径,支持减速、绕行两种模式 -交通灯识别:基于图像颜色识别与 Carla 交通灯 API,实现红绿灯状态实时检测与响应 -安全距离控制:可配置最小安全距离(默认 2 米),自动调整车速避免碰撞 -4. 动态场景生成(scene_generator.py) -随机化场景元素:支持配置随机车辆数量(5-50 辆)、行人数量(10-30 人)、障碍物类型(锥桶、石墩) -交通事件模拟:可生成突发场景(如行人横穿马路、前车急刹),用于算法鲁棒性测试 -场景参数可配置:通过config.yaml调整车辆密度、行人速度、事件触发概率 -5. 可视化与数据记录 -实时画面展示:支持车辆第一视角(摄像头)、全局俯瞰视角、传感器数据(点云 / 图像)同步显示 -数据记录功能:自动保存行驶轨迹、车速曲线、传感器原始数据,用于后续算法分析 -可视化工具:通过 matplotlib 绘制实时速度、转向角、距离障碍物距离等关键指标 -使用方法 -1. 启动 Carla 服务器 -Windows:双击 Carla 解压目录下的 CarlaUE4.exe(默认端口 2000) -Linux:终端进入 Carla 目录,执行 ./CarlaUE4.sh -可选参数(如加载特定地图):./CarlaUE4.sh /Game/Carla/Maps/Town03 -2. 运行仿真任务 -基础控制(支持键盘手动控制) -bash -运行 -python main.py --map Town05 --vehicle tesla.model3 -自主导航(自动规划路径到目标点) -bash -运行 -python navigate_autonomous.py --target_x 150 --target_y 80 --speed_limit 30 -障碍物避障测试 -bash -运行 -python obstacle_avoidance.py --obstacle_count 10 --safe_distance 2.5 -交通灯识别与响应 -bash -运行 -python traffic_light_detection.py --map Town04 # Town04包含完整交通灯系统 -动态场景生成 + 自主导航 -bash -运行 -python scene_generator.py --vehicle_count 30 --pedestrian_count 20 --run_navigation -交互操作 -操作 功能 -鼠标左键拖拽 调整仿真全局视角 -鼠标滚轮 视角缩放 -WASD 键 手动控制车辆(仅 main.py 手动模式) -空格键 紧急刹车 -Ctrl+C 终止仿真程序 -F1 键 切换第一视角 / 全局视角 -F2 键 显示 / 隐藏激光雷达点云 -参数调整指南 -参数 调整范围 效果说明 -speed_limit 10~60(km/h) 无人车最大行驶速度,提高值增加任务难度 -safe_distance 1.0~5.0(米) 与障碍物的最小安全距离,增大值提高安全性但降低通行效率 -pid_kp(转向 PID 比例增益) 0.5~2.0 增大会加快转向响应,过大会导致车道震荡 -obstacle_count 5~50(个) 动态障碍物数量,增多会提升避障算法测试强度 -lidar_points 8192~65536 激光雷达点数,增多提高检测精度但增加计算量 -planning_algorithm A*/RRT* 路径规划算法选择,A效率高,RRT更适用于复杂障碍物场景 -参考资料 -Carla 官方文档 -Carla GitHub 仓库 -自动驾驶路径规划算法详解(A*/RRT*) -OpenCV 图像识别官方教程 -激光雷达点云处理入门 + +1.1 项目定位 + +本项目是一套基于 Carla 仿真平台的全栈自动驾驶开发工具链,覆盖感知、定位、规划、控制四大核心模块,支持从算法原型开发、模块联调到场景化验证的全流程需求。适用于自动驾驶算法工程师、高校科研人员及相关专业学生进行技术研究与工程实践。 + +1.2 核心价值 + +低门槛入门:提供完整环境配置脚本与最小化演示用例,新手可快速上手 + +高可扩展性:模块间解耦设计,支持替换自定义算法(如将YOLOv8替换为Faster R-CNN) + +贴近工程实践:还原真实自动驾驶系统的数据流向与容错机制 + +完善的评估体系:内置多维度性能指标统计与可视化工具 + +1.3 支持的 Carla 特性 + +特性类别 + +支持内容 + +使用场景 + +传感器类型 + +RGB摄像头、深度摄像头、语义分割摄像头、激光雷达(LiDAR)、毫米波雷达、GPS/IMU、超声波雷达 + +多源数据融合、感知算法开发 + +仿真场景 + +城市道路(Town01-Town12)、高速公路、雨天/雾天/夜间环境、动态交通流 + +算法鲁棒性测试、场景化验证 + +车辆控制 + +油门/刹车/转向控制、车辆动力学模型、多车协同 + +控制算法开发、编队行驶仿真 + +环境配置 + +2.1 系统配置要求 + +硬件/软件 + +基础配置(可运行) + +推荐配置(流畅开发) + +备注 + +操作系统 + +Ubuntu 18.04 LTS + +Ubuntu 20.04 LTS + +不推荐Windows(Carla兼容性较差) + +CPU + +Intel i5-8400 / AMD Ryzen 5 3600 + +Intel i7-12700H / AMD Ryzen 7 5800X + +多线程性能影响交通流仿真效率 + +GPU + +NVIDIA GTX 1660 Ti(6GB) + +NVIDIA RTX 3070(8GB)及以上 + +必须支持CUDA,显存影响LiDAR点云处理 + +内存 + +16GB DDR4 + +32GB DDR4 + +多传感器数据缓存需大内存支持 + +磁盘 + +100GB SSD(空闲) + +200GB NVMe SSD + +Carla安装包+数据集需大量存储空间 + +2.2 分步安装指南 + +2.2.1 基础依赖安装 + +先安装系统级依赖与Python基础环境: + +# 更新系统源 +sudo apt update && sudo apt upgrade -y + +# 安装系统依赖 +sudo apt install -y build-essential clang-10 libomp5 libpng16-16 libtiff5 libjpeg8 \ + python3-pip python3-dev python3-venv git wget unzip + +# 安装NVIDIA驱动(若未安装) +sudo ubuntu-drivers autoinstall + + +安装完成后需重启电脑,通过 nvidia-smi 命令验证驱动是否生效,确保显示GPU信息与CUDA版本。 + +2.2.2 Carla 仿真平台安装 + +提供两种安装方式,推荐预编译版本(适合开发),源码编译适合二次开发: + +方式1:预编译版本(推荐) + +# 选择版本(0.9.14稳定版),创建安装目录 +mkdir -p ~/carla && cd ~/carla + +# 下载预编译包(约20GB,建议用迅雷等工具加速后传输) +wget https://carla-releases.s3.eu-west-3.amazonaws.com/Linux/CARLA_0.9.14.tar.gz + +# 解压(耗时约5分钟) +tar -xzf CARLA_0.9.14.tar.gz + +# 安装Carla额外资产(交通标志、植被等,约10GB) +cd CARLA_0.9.14 +./ImportAssets.sh + + +方式2:源码编译版本(进阶) + +# 安装Unreal Engine 4.26(Carla依赖版本) +git clone --depth 1 --branch 4.26 https://github.com/EpicGames/UnrealEngine.git ~/UnrealEngine +cd ~/UnrealEngine +./Setup.sh && ./GenerateProjectFiles.sh && make + +# 编译Carla源码 +git clone https://github.com/carla-simulator/carla.git ~/carla-source +cd ~/carla-source +make launch # 编译并启动编辑器 + + +2.2.3 项目环境配置 + +# 1. 克隆项目仓库 +git clone https://github.com/your-username/carla-autonomous-driving.git ~/carla-project +cd ~/carla-project + +# 2. 创建Python虚拟环境(隔离依赖) +python3.8 -m venv venv +# 激活环境(每次开发前需执行) +source venv/bin/activate + +# 3. 安装Python依赖(分基础依赖与可选依赖) +# 基础依赖(核心功能) +pip install -r requirements/base.txt +# 可选依赖(可视化、模型训练等) +pip install -r requirements/optional.txt + +# 4. 配置Carla Python API环境变量(永久生效) +echo "export PYTHONPATH=\$PYTHONPATH:~/carla/CARLA_0.9.14/PythonAPI/carla/dist/carla-0.9.14-py3.8-linux-x86_64.egg" >> ~/.bashrc +source ~/.bashrc + + +2.2.4 环境验证 + +# 1. 启动Carla服务(新开终端1) +cd ~/carla/CARLA_0.9.14 +./CarlaUE4.sh -windowed -ResX=1024 -ResY=768 # 窗口模式启动 + +# 2. 运行连接测试脚本(终端2,需激活虚拟环境) +cd ~/carla-project +source venv/bin/activate +python scripts/test_carla_connection.py + + +若终端输出 [SUCCESS] Connected to Carla server at 127.0.0.1:2000,说明环境配置成功。 + +快速开始 + +3.1 核心演示流程 + +按以下步骤快速运行自动驾驶演示,体验完整功能: + +1. 启动Carla服务# 基础启动(带可视化界面) +./CarlaUE4.sh -windowed -ResX=1024 -ResY=768 -carla-port=2000 + +# 高性能启动(无头模式,无界面,适合服务器运行) +./CarlaUE4.sh -RenderOffScreen -carla-port=2000 -carla-world-port=2001 + + +2. 运行全栈自动驾驶演示cd ~/carla-project +source venv/bin/activate +# 选择Town07场景,特斯拉Model 3车辆,开启可视化 +python scripts/full_stack_demo.py --town Town07 --vehicle tesla3 --visualize True + + +3. 观察演示效果Carla窗口:车辆自动沿车道行驶,躲避行人与障碍物,遵守红绿灯 + +4. 终端输出:实时打印车速、航向角、障碍物距离等信息 + +5. 可视化窗口:显示LiDAR点云、摄像头图像、规划路径等数据 + +3.2 常用命令速查 + +功能 + +命令 + +说明 + +启动指定场景 + +./CarlaUE4.sh -windowed -carla-town=Town05 + +直接加载Town05场景,无需手动切换 + +多车仿真 + +python scripts/multi_vehicle_demo.py --num-vehicles 5 + +启动5辆自动驾驶车辆协同行驶 + +数据采集 + +python scripts/data_collector.py --output ./data --duration 120 + +采集2分钟多传感器数据,保存至./data + +性能评估 + +python scripts/evaluate_performance.py --log ./logs/driving.log + +分析驾驶日志,生成性能报告 + +核心模块详解 + +项目核心代码位于 src/ 目录,模块间通过ROS2消息机制通信(可选),也支持直接函数调用,模块结构如下: + +src/ +├── perception/ # 感知模块(目标检测、车道线识别等) +├── localization/ # 定位模块(GPS+IMU融合、SLAM) +├── planning/ # 规划模块(全局路径+局部避障) +├── control/ # 控制模块(PID/MPC控制器) +├── scenario/ # 场景管理(交通流、天气控制) +└── common/ # 公共工具(数据结构、日志、配置) + + +4.1 感知模块(src/perception/) + +4.1.1 模块功能 + +输入多传感器数据,输出障碍物位置、车道线参数、交通灯状态等环境信息,核心流程:传感器数据同步 → 数据预处理 → 目标检测 → 融合后处理。 + +4.1.2 关键算法实现 + +子模块 + +算法选型 + +输入数据 + +输出结果 + +配置文件 + +2D目标检测 + +YOLOv8(预训练模型) + +RGB摄像头图像(1280×720) + +目标类别、2D边界框、置信度 + +config/perception/yolov8.yaml + +3D目标检测 + +PointPillars(TensorRT加速) + +LiDAR点云(10万点/秒) + +目标3D边界框、速度、航向角 + +config/perception/pointpillars.yaml + +车道线检测 + +语义分割(SegFormer)+ 多项式拟合 + +语义分割图像 + +车道线多项式参数、车道宽度 + +config/perception/lane_detection.yaml + +传感器融合 + +卡尔曼滤波 + 匈牙利算法 + +2D检测结果、3D检测结果 + +融合后的目标信息(置信度提升) + +config/perception/fusion.yaml + +4.1.3 快速测试 + +# 启动感知模块单独测试 +python src/perception/perception_demo.py --visualize True + + +将弹出可视化窗口,显示原始图像、检测结果、点云融合效果。 + +4.2 规划模块(src/planning/) + +4.2.1 分层规划架构 + +1. 全局路径规划:基于A*算法,输入起点/终点与地图拓扑,输出全局导航路径(道路级) + +2. 行为决策:基于有限状态机(FSM),处理跟车、变道、红绿灯等场景决策 + +3. 局部路径规划:基于MPC(模型预测控制),输入全局路径与障碍物信息,输出可执行的局部路径 + +4.2.2 关键参数调整 + +核心参数位于 config/planning/mpc_params.yaml,常用调整项: + +mpc: + horizon: 10 # 预测步长(越大越稳定,耗时越长) + speed_weight: 1.0 # 速度跟踪权重 + tracking_weight: 5.0 # 路径跟踪权重 + control_weight: 0.1 # 控制量平滑权重 + max_steer: 0.5 # 最大转向角(弧度) + max_accel: 2.0 # 最大加速度(m/s²) + + +4.3 控制模块(src/control/) + +支持两种控制器,可通过配置文件切换: + +控制器类型 + +优点 + +缺点 + +适用场景 + +切换命令 + +PID控制器 + +实现简单、响应快、参数易调 + +高速场景鲁棒性差 + +低速行驶、停车场景 + +--controller pid + +MPC控制器 + +考虑车辆动力学约束,稳定鲁棒 + +计算耗时较长,需GPU加速 + +高速行驶、复杂避障 + +--controller mpc + +数据采集与评估 + +5.1 多传感器数据采集 + +5.1.1 采集配置 + +修改 config/data_collection/sensor_config.yaml 配置需要采集的传感器: + +sensors: + front_rgb: # 前向RGB摄像头 + type: "sensor.camera.rgb" + position: [1.5, 0, 2.4] # 相对于车辆的安装位置(x前,y左,z上) + resolution: [1280, 720] + fps: 15 + top_lidar: # 车顶LiDAR + type: "sensor.lidar.ray_cast" + position: [0, 0, 2.8] + range: 100.0 + points_per_second: 1000000 + gps_imu: # GPS+IMU组合 + type: "sensor.other.gnss" + frequency: 10 + + +5.1.2 启动采集 + +# 启动采集脚本,指定输出目录、采集时长、场景 +python scripts/data_collector.py \ + --output ./data/town07_rain \ + --duration 300 \ # 采集5分钟 + --town Town07 \ # 场景 + --weather rain # 雨天环境 + + +5.1.3 数据格式 + +采集的数据按时间戳对齐,存储结构如下: + +data/town07_rain/ +├── 20251126_100000/ # 采集时间戳 +│ ├── front_rgb/ # RGB图像(PNG格式) +│ │ ├── 1732584000.0.png +│ │ └── ... +│ ├── top_lidar/ # LiDAR点云(PCD格式) +│ ├── gps_imu/ # GPS/IMU数据(CSV格式) +│ └── annotations/ # 自动标注的目标信息(JSON格式) +└── collect_info.yaml # 采集配置信息 + + +5.2 性能评估体系 + +5.2.1 评估指标 + +评估维度 + +核心指标 + +计算方式 + +优秀阈值 + +安全性 + +碰撞率、最小安全距离 + +碰撞次数/行驶里程,最小距离统计 + +碰撞率=0,最小距离>1.5m + +舒适性 + +加加速度(Jerk)、转向波动 + +加速度变化率、转向角标准差 + +Jerk<2m/s³ + +效率 + +平均车速、行程时间 + +总里程/总时间 + +≥设计车速的80% + +稳定性 + +路径跟踪误差、车速跟踪误差 + +横向误差标准差、车速误差绝对值 + +横向误差<0.3m + +5.2.2 生成评估报告 + +# 1. 先运行自动驾驶并保存日志 +python scripts/full_stack_demo.py --save-log ./logs/town07_demo.log + +# 2. 生成评估报告(支持HTML/CSV格式) +python scripts/evaluate_performance.py \ + --log ./logs/town07_demo.log \ + --output ./reports/town07_report.html \ + --format html + + +打开HTML报告可查看指标图表与详细分析。 + +调试与扩展 + +6.1 常见问题排查 + +6.2 模块扩展指南 + +6.2.1 新增自定义算法(以替换目标检测算法为例) + +1. 添加算法代码:在 src/perception/detectors/ 目录下新建 faster_rcnn_detector.py + +2. 实现统一接口:必须包含 init()(初始化模型)和 detect(image)(执行检测)方法 + +3. 修改配置文件:在 config/perception/yolov8.yaml 中修改 detector_type: faster_rcnn + +4. 添加依赖:在 requirements/optional.txt 中添加Faster R-CNN相关依赖(如torchvision) + +5. 测试验证:运行感知模块测试脚本,确认新算法正常输出结果 + +6.2.2 自定义仿真场景 + +通过 src/scenario/scenario_builder.py 构建自定义场景,示例: + +def build_intersection_scenario(world): + # 1. 设置天气 + weather = carla.WeatherParameters(rain_intensity=0.8) + world.set_weather(weather) + + # 2. 生成动态障碍物(3辆社会车辆+2个行人) + spawn_points = world.get_map().get_spawn_points() + # 生成社会车辆 + for i in range(3): + vehicle_bp = world.get_blueprint_library().find("vehicle.audi.a2") + world.spawn_actor(vehicle_bp, spawn_points[i+5]) + # 生成行人 + for i in range(2): + pedestrian_bp = world.get_blueprint_library().find("walker.pedestrian.0001") + world.spawn_actor(pedestrian_bp, spawn_points[i+10]) + + # 3. 设置目标点 + goal_location = carla.Location(x=100, y=200, z=0) + return goal_location + + +贡献指南 + +7.1 代码提交规范 + +提交代码时遵循以下规范,便于代码审查与版本管理: + +commit格式:[模块名] 功能描述(动词开头) +示例1:[perception] 新增Faster R-CNN目标检测算法 +示例2:[control] 修复MPC控制器高速抖动问题 +示例3:[docs] 补充环境配置的常见问题 + + +7.2 贡献流程 + +1. Fork本仓库到个人GitHub账号 + +2. 创建功能分支:git checkout -b feature/your-feature-name + +3. 提交代码并按规范写commit信息 + +4. 推送分支到个人仓库:git push origin feature/your-feature-name + +5. 在GitHub上提交Pull Request,描述功能细节与测试结果 + +许可证与参考资料 + +8.1 许可证 + +本项目采用 MIT许可证 开源,允许非商业与商业使用,但需保留原作者信息。 + +8.2 参考资料 + +- Carla官方文档:https://carla.readthedocs.io/ + +- YOLOv8官方仓库:https://github.com/ultralytics/ultralytics + +- 自动驾驶算法入门:Awesome-Autonomous-Driving + +- Model Predictive Control for Autonomous Vehicles: Theory and Practice + From e8a2dd3715c2a0c213abc54eca35e83c6b0c563c Mon Sep 17 00:00:00 2001 From: shengzhanpeng <3299915477@qq.com> Date: Wed, 26 Nov 2025 20:41:36 +0800 Subject: [PATCH 22/29] Update README.md --- src/Driving_Car/README.md | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/src/Driving_Car/README.md b/src/Driving_Car/README.md index f3f3d49291..683a112a85 100644 --- a/src/Driving_Car/README.md +++ b/src/Driving_Car/README.md @@ -96,25 +96,6 @@ NVIDIA RTX 3070(8GB)及以上 Carla安装包+数据集需大量存储空间 -2.2 分步安装指南 - -2.2.1 基础依赖安装 - -先安装系统级依赖与Python基础环境: - -# 更新系统源 -sudo apt update && sudo apt upgrade -y - -# 安装系统依赖 -sudo apt install -y build-essential clang-10 libomp5 libpng16-16 libtiff5 libjpeg8 \ - python3-pip python3-dev python3-venv git wget unzip - -# 安装NVIDIA驱动(若未安装) -sudo ubuntu-drivers autoinstall - - -安装完成后需重启电脑,通过 nvidia-smi 命令验证驱动是否生效,确保显示GPU信息与CUDA版本。 - 2.2.2 Carla 仿真平台安装 提供两种安装方式,推荐预编译版本(适合开发),源码编译适合二次开发: From bab6280da5bd8ab08c6514d01d25746aa8dbecf0 Mon Sep 17 00:00:00 2001 From: shengzhanpeng <3299915477@qq.com> Date: Mon, 1 Dec 2025 08:27:23 +0800 Subject: [PATCH 23/29] Update README.md --- src/Driving_Car/README.md | 484 +------------------------------------- 1 file changed, 2 insertions(+), 482 deletions(-) diff --git a/src/Driving_Car/README.md b/src/Driving_Car/README.md index 683a112a85..fa145aff72 100644 --- a/src/Driving_Car/README.md +++ b/src/Driving_Car/README.md @@ -62,489 +62,9 @@ Ubuntu 18.04 LTS Ubuntu 20.04 LTS -不推荐Windows(Carla兼容性较差) - -CPU - -Intel i5-8400 / AMD Ryzen 5 3600 - -Intel i7-12700H / AMD Ryzen 7 5800X - -多线程性能影响交通流仿真效率 - -GPU - -NVIDIA GTX 1660 Ti(6GB) - -NVIDIA RTX 3070(8GB)及以上 - -必须支持CUDA,显存影响LiDAR点云处理 - -内存 - -16GB DDR4 - -32GB DDR4 - -多传感器数据缓存需大内存支持 - -磁盘 - -100GB SSD(空闲) - -200GB NVMe SSD - Carla安装包+数据集需大量存储空间 -2.2.2 Carla 仿真平台安装 - -提供两种安装方式,推荐预编译版本(适合开发),源码编译适合二次开发: - -方式1:预编译版本(推荐) - -# 选择版本(0.9.14稳定版),创建安装目录 -mkdir -p ~/carla && cd ~/carla - -# 下载预编译包(约20GB,建议用迅雷等工具加速后传输) -wget https://carla-releases.s3.eu-west-3.amazonaws.com/Linux/CARLA_0.9.14.tar.gz - -# 解压(耗时约5分钟) -tar -xzf CARLA_0.9.14.tar.gz - -# 安装Carla额外资产(交通标志、植被等,约10GB) -cd CARLA_0.9.14 -./ImportAssets.sh - - -方式2:源码编译版本(进阶) - -# 安装Unreal Engine 4.26(Carla依赖版本) -git clone --depth 1 --branch 4.26 https://github.com/EpicGames/UnrealEngine.git ~/UnrealEngine -cd ~/UnrealEngine -./Setup.sh && ./GenerateProjectFiles.sh && make - -# 编译Carla源码 -git clone https://github.com/carla-simulator/carla.git ~/carla-source -cd ~/carla-source -make launch # 编译并启动编辑器 - - -2.2.3 项目环境配置 - -# 1. 克隆项目仓库 -git clone https://github.com/your-username/carla-autonomous-driving.git ~/carla-project -cd ~/carla-project - -# 2. 创建Python虚拟环境(隔离依赖) +2. 创建Python虚拟环境(隔离依赖) python3.8 -m venv venv -# 激活环境(每次开发前需执行) +激活环境(每次开发前需执行) source venv/bin/activate - -# 3. 安装Python依赖(分基础依赖与可选依赖) -# 基础依赖(核心功能) -pip install -r requirements/base.txt -# 可选依赖(可视化、模型训练等) -pip install -r requirements/optional.txt - -# 4. 配置Carla Python API环境变量(永久生效) -echo "export PYTHONPATH=\$PYTHONPATH:~/carla/CARLA_0.9.14/PythonAPI/carla/dist/carla-0.9.14-py3.8-linux-x86_64.egg" >> ~/.bashrc -source ~/.bashrc - - -2.2.4 环境验证 - -# 1. 启动Carla服务(新开终端1) -cd ~/carla/CARLA_0.9.14 -./CarlaUE4.sh -windowed -ResX=1024 -ResY=768 # 窗口模式启动 - -# 2. 运行连接测试脚本(终端2,需激活虚拟环境) -cd ~/carla-project -source venv/bin/activate -python scripts/test_carla_connection.py - - -若终端输出 [SUCCESS] Connected to Carla server at 127.0.0.1:2000,说明环境配置成功。 - -快速开始 - -3.1 核心演示流程 - -按以下步骤快速运行自动驾驶演示,体验完整功能: - -1. 启动Carla服务# 基础启动(带可视化界面) -./CarlaUE4.sh -windowed -ResX=1024 -ResY=768 -carla-port=2000 - -# 高性能启动(无头模式,无界面,适合服务器运行) -./CarlaUE4.sh -RenderOffScreen -carla-port=2000 -carla-world-port=2001 - - -2. 运行全栈自动驾驶演示cd ~/carla-project -source venv/bin/activate -# 选择Town07场景,特斯拉Model 3车辆,开启可视化 -python scripts/full_stack_demo.py --town Town07 --vehicle tesla3 --visualize True - - -3. 观察演示效果Carla窗口:车辆自动沿车道行驶,躲避行人与障碍物,遵守红绿灯 - -4. 终端输出:实时打印车速、航向角、障碍物距离等信息 - -5. 可视化窗口:显示LiDAR点云、摄像头图像、规划路径等数据 - -3.2 常用命令速查 - -功能 - -命令 - -说明 - -启动指定场景 - -./CarlaUE4.sh -windowed -carla-town=Town05 - -直接加载Town05场景,无需手动切换 - -多车仿真 - -python scripts/multi_vehicle_demo.py --num-vehicles 5 - -启动5辆自动驾驶车辆协同行驶 - -数据采集 - -python scripts/data_collector.py --output ./data --duration 120 - -采集2分钟多传感器数据,保存至./data - -性能评估 - -python scripts/evaluate_performance.py --log ./logs/driving.log - -分析驾驶日志,生成性能报告 - -核心模块详解 - -项目核心代码位于 src/ 目录,模块间通过ROS2消息机制通信(可选),也支持直接函数调用,模块结构如下: - -src/ -├── perception/ # 感知模块(目标检测、车道线识别等) -├── localization/ # 定位模块(GPS+IMU融合、SLAM) -├── planning/ # 规划模块(全局路径+局部避障) -├── control/ # 控制模块(PID/MPC控制器) -├── scenario/ # 场景管理(交通流、天气控制) -└── common/ # 公共工具(数据结构、日志、配置) - - -4.1 感知模块(src/perception/) - -4.1.1 模块功能 - -输入多传感器数据,输出障碍物位置、车道线参数、交通灯状态等环境信息,核心流程:传感器数据同步 → 数据预处理 → 目标检测 → 融合后处理。 - -4.1.2 关键算法实现 - -子模块 - -算法选型 - -输入数据 - -输出结果 - -配置文件 - -2D目标检测 - -YOLOv8(预训练模型) - -RGB摄像头图像(1280×720) - -目标类别、2D边界框、置信度 - -config/perception/yolov8.yaml - -3D目标检测 - -PointPillars(TensorRT加速) - -LiDAR点云(10万点/秒) - -目标3D边界框、速度、航向角 - -config/perception/pointpillars.yaml - -车道线检测 - -语义分割(SegFormer)+ 多项式拟合 - -语义分割图像 - -车道线多项式参数、车道宽度 - -config/perception/lane_detection.yaml - -传感器融合 - -卡尔曼滤波 + 匈牙利算法 - -2D检测结果、3D检测结果 - -融合后的目标信息(置信度提升) - -config/perception/fusion.yaml - -4.1.3 快速测试 - -# 启动感知模块单独测试 -python src/perception/perception_demo.py --visualize True - - -将弹出可视化窗口,显示原始图像、检测结果、点云融合效果。 - -4.2 规划模块(src/planning/) - -4.2.1 分层规划架构 - -1. 全局路径规划:基于A*算法,输入起点/终点与地图拓扑,输出全局导航路径(道路级) - -2. 行为决策:基于有限状态机(FSM),处理跟车、变道、红绿灯等场景决策 - -3. 局部路径规划:基于MPC(模型预测控制),输入全局路径与障碍物信息,输出可执行的局部路径 - -4.2.2 关键参数调整 - -核心参数位于 config/planning/mpc_params.yaml,常用调整项: - -mpc: - horizon: 10 # 预测步长(越大越稳定,耗时越长) - speed_weight: 1.0 # 速度跟踪权重 - tracking_weight: 5.0 # 路径跟踪权重 - control_weight: 0.1 # 控制量平滑权重 - max_steer: 0.5 # 最大转向角(弧度) - max_accel: 2.0 # 最大加速度(m/s²) - - -4.3 控制模块(src/control/) - -支持两种控制器,可通过配置文件切换: - -控制器类型 - -优点 - -缺点 - -适用场景 - -切换命令 - -PID控制器 - -实现简单、响应快、参数易调 - -高速场景鲁棒性差 - -低速行驶、停车场景 - ---controller pid - -MPC控制器 - -考虑车辆动力学约束,稳定鲁棒 - -计算耗时较长,需GPU加速 - -高速行驶、复杂避障 - ---controller mpc - -数据采集与评估 - -5.1 多传感器数据采集 - -5.1.1 采集配置 - -修改 config/data_collection/sensor_config.yaml 配置需要采集的传感器: - -sensors: - front_rgb: # 前向RGB摄像头 - type: "sensor.camera.rgb" - position: [1.5, 0, 2.4] # 相对于车辆的安装位置(x前,y左,z上) - resolution: [1280, 720] - fps: 15 - top_lidar: # 车顶LiDAR - type: "sensor.lidar.ray_cast" - position: [0, 0, 2.8] - range: 100.0 - points_per_second: 1000000 - gps_imu: # GPS+IMU组合 - type: "sensor.other.gnss" - frequency: 10 - - -5.1.2 启动采集 - -# 启动采集脚本,指定输出目录、采集时长、场景 -python scripts/data_collector.py \ - --output ./data/town07_rain \ - --duration 300 \ # 采集5分钟 - --town Town07 \ # 场景 - --weather rain # 雨天环境 - - -5.1.3 数据格式 - -采集的数据按时间戳对齐,存储结构如下: - -data/town07_rain/ -├── 20251126_100000/ # 采集时间戳 -│ ├── front_rgb/ # RGB图像(PNG格式) -│ │ ├── 1732584000.0.png -│ │ └── ... -│ ├── top_lidar/ # LiDAR点云(PCD格式) -│ ├── gps_imu/ # GPS/IMU数据(CSV格式) -│ └── annotations/ # 自动标注的目标信息(JSON格式) -└── collect_info.yaml # 采集配置信息 - - -5.2 性能评估体系 - -5.2.1 评估指标 - -评估维度 - -核心指标 - -计算方式 - -优秀阈值 - -安全性 - -碰撞率、最小安全距离 - -碰撞次数/行驶里程,最小距离统计 - -碰撞率=0,最小距离>1.5m - -舒适性 - -加加速度(Jerk)、转向波动 - -加速度变化率、转向角标准差 - -Jerk<2m/s³ - -效率 - -平均车速、行程时间 - -总里程/总时间 - -≥设计车速的80% - -稳定性 - -路径跟踪误差、车速跟踪误差 - -横向误差标准差、车速误差绝对值 - -横向误差<0.3m - -5.2.2 生成评估报告 - -# 1. 先运行自动驾驶并保存日志 -python scripts/full_stack_demo.py --save-log ./logs/town07_demo.log - -# 2. 生成评估报告(支持HTML/CSV格式) -python scripts/evaluate_performance.py \ - --log ./logs/town07_demo.log \ - --output ./reports/town07_report.html \ - --format html - - -打开HTML报告可查看指标图表与详细分析。 - -调试与扩展 - -6.1 常见问题排查 - -6.2 模块扩展指南 - -6.2.1 新增自定义算法(以替换目标检测算法为例) - -1. 添加算法代码:在 src/perception/detectors/ 目录下新建 faster_rcnn_detector.py - -2. 实现统一接口:必须包含 init()(初始化模型)和 detect(image)(执行检测)方法 - -3. 修改配置文件:在 config/perception/yolov8.yaml 中修改 detector_type: faster_rcnn - -4. 添加依赖:在 requirements/optional.txt 中添加Faster R-CNN相关依赖(如torchvision) - -5. 测试验证:运行感知模块测试脚本,确认新算法正常输出结果 - -6.2.2 自定义仿真场景 - -通过 src/scenario/scenario_builder.py 构建自定义场景,示例: - -def build_intersection_scenario(world): - # 1. 设置天气 - weather = carla.WeatherParameters(rain_intensity=0.8) - world.set_weather(weather) - - # 2. 生成动态障碍物(3辆社会车辆+2个行人) - spawn_points = world.get_map().get_spawn_points() - # 生成社会车辆 - for i in range(3): - vehicle_bp = world.get_blueprint_library().find("vehicle.audi.a2") - world.spawn_actor(vehicle_bp, spawn_points[i+5]) - # 生成行人 - for i in range(2): - pedestrian_bp = world.get_blueprint_library().find("walker.pedestrian.0001") - world.spawn_actor(pedestrian_bp, spawn_points[i+10]) - - # 3. 设置目标点 - goal_location = carla.Location(x=100, y=200, z=0) - return goal_location - - -贡献指南 - -7.1 代码提交规范 - -提交代码时遵循以下规范,便于代码审查与版本管理: - -commit格式:[模块名] 功能描述(动词开头) -示例1:[perception] 新增Faster R-CNN目标检测算法 -示例2:[control] 修复MPC控制器高速抖动问题 -示例3:[docs] 补充环境配置的常见问题 - - -7.2 贡献流程 - -1. Fork本仓库到个人GitHub账号 - -2. 创建功能分支:git checkout -b feature/your-feature-name - -3. 提交代码并按规范写commit信息 - -4. 推送分支到个人仓库:git push origin feature/your-feature-name - -5. 在GitHub上提交Pull Request,描述功能细节与测试结果 - -许可证与参考资料 - -8.1 许可证 - -本项目采用 MIT许可证 开源,允许非商业与商业使用,但需保留原作者信息。 - -8.2 参考资料 - -- Carla官方文档:https://carla.readthedocs.io/ - -- YOLOv8官方仓库:https://github.com/ultralytics/ultralytics - -- 自动驾驶算法入门:Awesome-Autonomous-Driving - -- Model Predictive Control for Autonomous Vehicles: Theory and Practice - From 7b05b784e2565266191aa561b43b022ce4bb2001 Mon Sep 17 00:00:00 2001 From: shengzhanpeng <3299915477@qq.com> Date: Mon, 1 Dec 2025 08:48:08 +0800 Subject: [PATCH 24/29] Update README.md --- src/Driving_Car/README.md | 121 ++++++++++++++++---------------------- 1 file changed, 52 insertions(+), 69 deletions(-) diff --git a/src/Driving_Car/README.md b/src/Driving_Car/README.md index fa145aff72..236dd8916a 100644 --- a/src/Driving_Car/README.md +++ b/src/Driving_Car/README.md @@ -1,70 +1,53 @@ -Carla 无人车仿真开发项目 - -基于 Carla 仿真平台的全栈自动驾驶算法开发与验证框架 - +CARLA无人车障碍物识别系统 项目概述 - -1.1 项目定位 - -本项目是一套基于 Carla 仿真平台的全栈自动驾驶开发工具链,覆盖感知、定位、规划、控制四大核心模块,支持从算法原型开发、模块联调到场景化验证的全流程需求。适用于自动驾驶算法工程师、高校科研人员及相关专业学生进行技术研究与工程实践。 - -1.2 核心价值 - -低门槛入门:提供完整环境配置脚本与最小化演示用例,新手可快速上手 - -高可扩展性:模块间解耦设计,支持替换自定义算法(如将YOLOv8替换为Faster R-CNN) - -贴近工程实践:还原真实自动驾驶系统的数据流向与容错机制 - -完善的评估体系:内置多维度性能指标统计与可视化工具 - -1.3 支持的 Carla 特性 - -特性类别 - -支持内容 - -使用场景 - -传感器类型 - -RGB摄像头、深度摄像头、语义分割摄像头、激光雷达(LiDAR)、毫米波雷达、GPS/IMU、超声波雷达 - -多源数据融合、感知算法开发 - -仿真场景 - -城市道路(Town01-Town12)、高速公路、雨天/雾天/夜间环境、动态交通流 - -算法鲁棒性测试、场景化验证 - -车辆控制 - -油门/刹车/转向控制、车辆动力学模型、多车协同 - -控制算法开发、编队行驶仿真 - -环境配置 - -2.1 系统配置要求 - -硬件/软件 - -基础配置(可运行) - -推荐配置(流畅开发) - -备注 - -操作系统 - -Ubuntu 18.04 LTS - -Ubuntu 20.04 LTS - -Carla安装包+数据集需大量存储空间 - -2. 创建Python虚拟环境(隔离依赖) -python3.8 -m venv venv -激活环境(每次开发前需执行) -source venv/bin/activate +这是一个基于CARLA仿真环境的无人车障碍物检测系统,集成了多种传感器数据处理能力,包括RGB视觉检测、深度图像分析和激光雷达点云处理。系统使用YOLO算法进行实时障碍物检测,并提供可视化和数据记录功能。 +主要功能 +1. 障碍物检测 +基于YOLO算法的实时物体检测 +支持多种障碍物类型:车辆、行人、自行车、摩托车、公交车、卡车、交通标识等 +可配置置信度阈值和检测参数 +风险等级评估(高、中、低风险) +传感器数据处理 +RGB相机: 视觉图像采集和处理 +深度相机: 距离测量和3D定位 +语义分割相机: 场景理解和语义标注 +激光雷达: 3D点云数据采集和处理 +数据记录和分析 +实时检测数据记录 +性能统计分析 +障碍物行为分析 +驾驶建议生成 +4. 可视化界面 +实时检测结果显示 +多传感器数据可视化 +深度图和激光雷达点云显示 +交互式操作界面 +系统架构 +复制 +carla_obstacle_detection/ +├── src/ # 源代码 +│ ├── carla_obstacle_detection.py # 主程序 +│ ├── obstacle_detector.py # 障碍物检测器 +│ ├── sensor_manager.py # 传感器管理器 +│ ├── data_logger.py # 数据记录器 +│ └── visualizer.py # 可视化器 +├── config/ # 配置文件 +│ └── sensor_config.yaml # 传感器配置 +├── data/ # 数据文件 +│ ├── test_images/ # 测试图像 +│ └── models/ # 模型文件 +├── tests/ # 测试代码 +│ └── test_detector.py # 检测器测试 +├── examples/ # 示例代码 +│ └── demo.py # 演示程序 +├── output/ # 输出结果 +└── logs/ # 日志文件 +安装要求 +Python依赖 +复制 +pip install numpy opencv-python torch torchvision +pip install PyYAML carla +pip install matplotlib seaborn # 用于可视化 +CARLA仿真环境 +CARLA 0.9.13 或更高版本 +Python 3.7+ From 5d3c70d8c48dc64ecc859df3ae516da1e4b4f3f7 Mon Sep 17 00:00:00 2001 From: shengzhanpeng <3299915477@qq.com> Date: Mon, 1 Dec 2025 08:48:55 +0800 Subject: [PATCH 25/29] Update README.md --- src/Driving_Car/README.md | 283 +++++++++++++++++++++++++++++++++++--- 1 file changed, 263 insertions(+), 20 deletions(-) diff --git a/src/Driving_Car/README.md b/src/Driving_Car/README.md index 236dd8916a..3f6857747a 100644 --- a/src/Driving_Car/README.md +++ b/src/Driving_Car/README.md @@ -3,26 +3,27 @@ CARLA无人车障碍物识别系统 这是一个基于CARLA仿真环境的无人车障碍物检测系统,集成了多种传感器数据处理能力,包括RGB视觉检测、深度图像分析和激光雷达点云处理。系统使用YOLO算法进行实时障碍物检测,并提供可视化和数据记录功能。 主要功能 1. 障碍物检测 -基于YOLO算法的实时物体检测 -支持多种障碍物类型:车辆、行人、自行车、摩托车、公交车、卡车、交通标识等 -可配置置信度阈值和检测参数 -风险等级评估(高、中、低风险) -传感器数据处理 -RGB相机: 视觉图像采集和处理 -深度相机: 距离测量和3D定位 -语义分割相机: 场景理解和语义标注 -激光雷达: 3D点云数据采集和处理 -数据记录和分析 -实时检测数据记录 -性能统计分析 -障碍物行为分析 -驾驶建议生成 +• 基于YOLO算法的实时物体检测 +• 支持多种障碍物类型:车辆、行人、自行车、摩托车、公交车、卡车、交通标识等 +• 可配置置信度阈值和检测参数 +• 风险等级评估(高、中、低风险) +2. 传感器数据处理 +• RGB相机: 视觉图像采集和处理 +• 深度相机: 距离测量和3D定位 +• 语义分割相机: 场景理解和语义标注 +• 激光雷达: 3D点云数据采集和处理 +3. 数据记录和分析 +• 实时检测数据记录 +• 性能统计分析 +• 障碍物行为分析 +• 驾驶建议生成 4. 可视化界面 -实时检测结果显示 -多传感器数据可视化 -深度图和激光雷达点云显示 -交互式操作界面 +• 实时检测结果显示 +• 多传感器数据可视化 +• 深度图和激光雷达点云显示 +• 交互式操作界面 系统架构 + 复制 carla_obstacle_detection/ ├── src/ # 源代码 @@ -44,10 +45,252 @@ carla_obstacle_detection/ └── logs/ # 日志文件 安装要求 Python依赖 + 复制 pip install numpy opencv-python torch torchvision pip install PyYAML carla pip install matplotlib seaborn # 用于可视化 CARLA仿真环境 -CARLA 0.9.13 或更高版本 -Python 3.7+ +• CARLA 0.9.13 或更高版本 +• Python 3.7+ +• 8GB+ RAM +• 支持CUDA的GPU(推荐) +快速开始 +1. 环境配置 +bash + +复制 +# 克隆或下载项目文件 +cd + carla_obstacle_detection + +# 安装Python依赖 +pip install + -r requirements.txt + +# 启动CARLA服务器 +# 在CARLA安装目录运行: +./CarlaUE4.sh +2. 运行演示程序 +bash + +复制 +# 进入项目目录 +cd + carla_obstacle_detection + +# 运行交互式演示 +python examples/demo.py +3. 运行测试 +bash + +复制 +# 运行检测器测试 +python tests/test_detector.py +4. 完整CARLA仿真 +bash + +复制 +# 运行完整的CARLA仿真(需要先启动CARLA服务器) +python src/carla_obstacle_detection.py +使用指南 +基础使用 +1. 配置传感器 +编辑 config/sensor_config.yaml 文件: +yaml + +复制 +carla_settings: + town: "Town01" # 选择地图 + vehicle_type: "vehicle.tesla.model3" # 选择车辆类型 + +sensors: + rgb_camera: + width: 800 + height: 600 + fov: 90 +2. 运行检测 +python + +复制 +from src.obstacle_detector import + ObstacleDetector + +# 初始化检测器 +detector = ObstacleDetector(config) + +# 检测图像 +image = cv2.imread("test_image.jpg") +detections = detector.detect(image) + +# 绘制结果 +result = detector.draw_detections(image, detections) +cv2.imshow("Detection Result", result) +高级功能 +1. 自定义检测参数 +python + +复制 +detection_params = { + 'yolo': { + 'conf_threshold': 0.7, # 提高置信度阈值 + 'iou_threshold': 0.5 + }, + 'obstacle_classes': ['person', 'car', 'bicycle'] +} +2. 风险评估 +python + +复制 +# 获取障碍物风险等级 +obstacle_type = detector.predict_obstacle_type(detection) +print(f"障碍物类型: {obstacle_type['type']}") +print(f"风险等级: {obstacle_type['risk_level']}") +print(f"建议行动: {obstacle_type['action']}") +3. 数据记录 +python + +复制 +from src.data_logger import + DataLogger + +logger = DataLogger("output") +logger.log_frame(frame_id, detections) +logger.log_obstacle_analysis(detections, vehicle_velocity) +logger.save_summary() +测试数据集 +系统包含5个预定义的测试场景: +1. +单辆车检测: 验证基本车辆检测能力 +2. +多车辆场景: 测试多目标检测 +3. +行人和车辆混合: 验证多类别检测 +4. +交通标识检测: 测试特殊目标检测 +5. +复杂场景: 综合性能测试 +测试图像说明 +• 格式: JPEG, 800x600分辨率 +• 标注: 包含边界框和类别信息 +• 深度图: 模拟距离信息 +• 激光雷达数据: 模拟3D点云数据 +性能指标 +检测性能 +• 检测精度: 85-95%(取决于场景复杂度) +• 处理速度: 10-30 FPS(取决于硬件配置) +• 延迟: 50-100ms +• 支持目标数: 最多50个同时检测 +传感器性能 +• RGB相机: 800x600@30fps +• 深度相机: 800x600@30fps +• 激光雷达: 32线,100米范围,10Hz +键盘快捷键 +可视化界面 +• q: 退出程序 +• s: 保存当前截图 +• h: 显示帮助信息 +演示程序 +• 1: 离线图像检测 +• 2: 深度图像处理 +• 3: 激光雷达数据处理 +• 4: 性能基准测试 +• 5: 完整测试套件 +• 0: 退出程序 +输出文件 +检测结果 +• detections_log.json: 详细检测记录 +• performance_log.csv: 性能统计数据 +• obstacle_analysis.json: 障碍物分析结果 +可视化结果 +• screenshots/: 截图文件夹 +• output/: 检测结果图像 +• test_results_visualization.png: 测试结果图表 +日志文件 +• logs/: 系统运行日志 +• summary.json: 运行汇总报告 +故障排除 +常见问题 +1. CARLA连接失败 + +复制 +错误: 连接CARLA失败 +解决: 确保CARLA服务器正在运行,检查端口2000是否可用 +2. YOLO模型加载失败 + +复制 +错误: 模型文件不存在 +解决: 系统会自动使用预训练模型,或下载指定模型文件 +3. 检测性能问题 + +复制 +解决: +1. 降低图像分辨率 +2. 提高置信度阈值 +3. 减少检测类别数量 +4. 使用GPU加速 +4. 内存不足 + +复制 +解决: +1. 减小缓冲区大小 +2. 减少并发处理 +3. 优化数据存储 +调试模式 +python + +复制 +# 启用详细日志 +import + logging +logging.basicConfig(level=logging.DEBUG) + +# 保存中间结果 +visualizer.record_video(image, "debug_output.mp4") +扩展开发 +添加新的检测类别 +1. +在配置文件中添加类别 +2. +准备训练数据 +3. +训练自定义YOLO模型 +4. +更新检测器配置 +集成新的传感器 +1. +在sensor_manager.py中添加传感器类型 +2. +实现数据处理回调 +3. +更新可视化器支持 +4. +添加相应的测试用例 +自定义分析算法 +1. +继承ObstacleDetector类 +2. +重写检测和分析方法 +3. +添加新的评估指标 +4. +更新配置文件 +许可证 +本项目采用MIT许可证,详见LICENSE文件。 +贡献指南 +欢迎贡献代码和报告问题。请遵循以下步骤: +1. +Fork项目仓库 +2. +创建功能分支 +3. +提交更改 +4. +创建Pull Request +更新日志 +v1.0.0 (2025-12-01) +• 初始版本发布 +• 基本障碍物检测功能 +• 多传感器数据处理 +• 可视化和数据记录 +• 测试数据集和演示程序 From 346813337129aa2456c68293926da95e87e9a567 Mon Sep 17 00:00:00 2001 From: shengzhanpeng <3299915477@qq.com> Date: Mon, 1 Dec 2025 08:50:47 +0800 Subject: [PATCH 26/29] Update README.md --- src/Driving_Car/README.md | 122 +------------------------------------- 1 file changed, 1 insertion(+), 121 deletions(-) diff --git a/src/Driving_Car/README.md b/src/Driving_Car/README.md index 3f6857747a..f7c02fe781 100644 --- a/src/Driving_Car/README.md +++ b/src/Driving_Car/README.md @@ -22,30 +22,7 @@ CARLA无人车障碍物识别系统 • 多传感器数据可视化 • 深度图和激光雷达点云显示 • 交互式操作界面 -系统架构 - -复制 -carla_obstacle_detection/ -├── src/ # 源代码 -│ ├── carla_obstacle_detection.py # 主程序 -│ ├── obstacle_detector.py # 障碍物检测器 -│ ├── sensor_manager.py # 传感器管理器 -│ ├── data_logger.py # 数据记录器 -│ └── visualizer.py # 可视化器 -├── config/ # 配置文件 -│ └── sensor_config.yaml # 传感器配置 -├── data/ # 数据文件 -│ ├── test_images/ # 测试图像 -│ └── models/ # 模型文件 -├── tests/ # 测试代码 -│ └── test_detector.py # 检测器测试 -├── examples/ # 示例代码 -│ └── demo.py # 演示程序 -├── output/ # 输出结果 -└── logs/ # 日志文件 -安装要求 -Python依赖 - + 复制 pip install numpy opencv-python torch torchvision pip install PyYAML carla @@ -58,7 +35,6 @@ CARLA仿真环境 快速开始 1. 环境配置 bash - 复制 # 克隆或下载项目文件 cd @@ -73,7 +49,6 @@ pip install ./CarlaUE4.sh 2. 运行演示程序 bash - 复制 # 进入项目目录 cd @@ -83,13 +58,11 @@ cd python examples/demo.py 3. 运行测试 bash - 复制 # 运行检测器测试 python tests/test_detector.py 4. 完整CARLA仿真 bash - 复制 # 运行完整的CARLA仿真(需要先启动CARLA服务器) python src/carla_obstacle_detection.py @@ -98,7 +71,6 @@ python src/carla_obstacle_detection.py 1. 配置传感器 编辑 config/sensor_config.yaml 文件: yaml - 复制 carla_settings: town: "Town01" # 选择地图 @@ -111,7 +83,6 @@ sensors: fov: 90 2. 运行检测 python - 复制 from src.obstacle_detector import ObstacleDetector @@ -129,7 +100,6 @@ cv2.imshow("Detection Result", result) 高级功能 1. 自定义检测参数 python - 复制 detection_params = { 'yolo': { @@ -140,7 +110,6 @@ detection_params = { } 2. 风险评估 python - 复制 # 获取障碍物风险等级 obstacle_type = detector.predict_obstacle_type(detection) @@ -149,7 +118,6 @@ print(f"风险等级: {obstacle_type['risk_level']}") print(f"建议行动: {obstacle_type['action']}") 3. 数据记录 python - 复制 from src.data_logger import DataLogger @@ -206,91 +174,3 @@ logger.save_summary() • screenshots/: 截图文件夹 • output/: 检测结果图像 • test_results_visualization.png: 测试结果图表 -日志文件 -• logs/: 系统运行日志 -• summary.json: 运行汇总报告 -故障排除 -常见问题 -1. CARLA连接失败 - -复制 -错误: 连接CARLA失败 -解决: 确保CARLA服务器正在运行,检查端口2000是否可用 -2. YOLO模型加载失败 - -复制 -错误: 模型文件不存在 -解决: 系统会自动使用预训练模型,或下载指定模型文件 -3. 检测性能问题 - -复制 -解决: -1. 降低图像分辨率 -2. 提高置信度阈值 -3. 减少检测类别数量 -4. 使用GPU加速 -4. 内存不足 - -复制 -解决: -1. 减小缓冲区大小 -2. 减少并发处理 -3. 优化数据存储 -调试模式 -python - -复制 -# 启用详细日志 -import - logging -logging.basicConfig(level=logging.DEBUG) - -# 保存中间结果 -visualizer.record_video(image, "debug_output.mp4") -扩展开发 -添加新的检测类别 -1. -在配置文件中添加类别 -2. -准备训练数据 -3. -训练自定义YOLO模型 -4. -更新检测器配置 -集成新的传感器 -1. -在sensor_manager.py中添加传感器类型 -2. -实现数据处理回调 -3. -更新可视化器支持 -4. -添加相应的测试用例 -自定义分析算法 -1. -继承ObstacleDetector类 -2. -重写检测和分析方法 -3. -添加新的评估指标 -4. -更新配置文件 -许可证 -本项目采用MIT许可证,详见LICENSE文件。 -贡献指南 -欢迎贡献代码和报告问题。请遵循以下步骤: -1. -Fork项目仓库 -2. -创建功能分支 -3. -提交更改 -4. -创建Pull Request -更新日志 -v1.0.0 (2025-12-01) -• 初始版本发布 -• 基本障碍物检测功能 -• 多传感器数据处理 -• 可视化和数据记录 -• 测试数据集和演示程序 From b03e1b8853bd4dc28b7981412139c14c273acb17 Mon Sep 17 00:00:00 2001 From: shengzhanpeng <3299915477@qq.com> Date: Tue, 16 Dec 2025 08:12:49 +0800 Subject: [PATCH 27/29] Delete src/Driving_Car/carla_obstacle_detection.py --- src/Driving_Car/carla_obstacle_detection.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/Driving_Car/carla_obstacle_detection.py diff --git a/src/Driving_Car/carla_obstacle_detection.py b/src/Driving_Car/carla_obstacle_detection.py deleted file mode 100644 index e69de29bb2..0000000000 From bf32a64385203c11ad631b852ea7ab75e9f264d1 Mon Sep 17 00:00:00 2001 From: shengzhanpeng <3299915477@qq.com> Date: Tue, 16 Dec 2025 08:29:32 +0800 Subject: [PATCH 28/29] Delete src/Driving_Car/Traffic_light_detection.py --- src/Driving_Car/Traffic_light_detection.py | 123 --------------------- 1 file changed, 123 deletions(-) delete mode 100644 src/Driving_Car/Traffic_light_detection.py diff --git a/src/Driving_Car/Traffic_light_detection.py b/src/Driving_Car/Traffic_light_detection.py deleted file mode 100644 index 2a5876c822..0000000000 --- a/src/Driving_Car/Traffic_light_detection.py +++ /dev/null @@ -1,123 +0,0 @@ -import cv2 -import numpy as np -from PIL import Image, ImageDraw - -# -------------------------- 1. 快速生成模拟帧(精简绘制,缩小分辨率) -------------------------- -def generate_traffic_light_frame(light_color="red"): - """快速生成红绿灯帧(800x600分辨率,精简绘制逻辑)""" - img_width, img_height = 800, 600 # 缩小分辨率,减少计算量 - background_color = (30, 30, 30) # 简化背景 - dark_color = (60, 60, 60) - light_colors = { - "red": (255, 30, 30), - "yellow": (255, 255, 30), - "green": (30, 255, 30) - } - - # 快速创建图片(减少冗余绘制) - img = Image.new("RGB", (img_width, img_height), background_color) - draw = ImageDraw.Draw(img) - - # 简化红绿灯绘制(只保留核心灯体,取消复杂装饰) - light_radius = 40 - light_positions = [ - (img_width//2, img_height//3), - (img_width//2, img_height//2), - (img_width//2, 2*img_height//3) - ] - - for i, pos in enumerate(light_positions): - color = dark_color if not ( - (i==0 and light_color=="red") or - (i==1 and light_color=="yellow") or - (i==2 and light_color=="green") - ) else light_colors[light_color] - # 仅绘制核心灯体(取消光晕、简化边框) - draw.ellipse( - [pos[0]-light_radius, pos[1]-light_radius, - pos[0]+light_radius, pos[1]+light_radius], - fill=color, outline=(200,200,200), width=3 - ) - - # 快速转换为OpenCV格式 - return cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR) - -# -------------------------- 2. 优化识别逻辑(减少计算量) -------------------------- -def detect_traffic_light(frame): - hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) - - # 简化HSV阈值(减少判断耗时) - color_ranges = { - "red": [[(0, 120, 70), (10, 255, 255)], [(170, 120, 70), (180, 255, 255)]], - "yellow": [(22, 120, 70), (32, 255, 255)], - "green": [(45, 120, 70), (70, 255, 255)] - } - - light_detected = "unknown" - max_light_area = 0 - - for color, ranges in color_ranges.items(): - mask = np.zeros_like(hsv[:, :, 0]) - # 简化循环逻辑 - if color == "red": - mask = cv2.inRange(hsv, np.array(ranges[0][0]), np.array(ranges[0][1])) + \ - cv2.inRange(hsv, np.array(ranges[1][0]), np.array(ranges[1][1])) - else: - mask = cv2.inRange(hsv, np.array(ranges[0]), np.array(ranges[1])) - - # 缩小形态学核(减少运算量) - kernel = np.ones((5, 5), np.uint8) - mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel) - mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel) - - # 快速轮廓检测 - contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) - for cnt in contours: - area = cv2.contourArea(cnt) - perimeter = cv2.arcLength(cnt, True) - if perimeter == 0: - continue - circularity = 4 * np.pi * area / (perimeter ** 2) - # 适配小分辨率的面积阈值 - if area > 3000 and circularity > 0.65: - if area > max_light_area: - max_light_area = area - light_detected = color - - # 简化绘制标注 - cv2.putText( - frame, f"TL: {light_detected.upper()}", - (20, 40), cv2.FONT_HERSHEY_SIMPLEX, 1.2, (0, 255, 0), 3 - ) - return light_detected, frame - -# -------------------------- 3. 高速运行循环(无延迟切换) -------------------------- -def run_fast_simulation(): - print("🚀 快速版模拟启动(按 'q' 退出)") - light_sequence = ["red", "yellow", "green"] - index = 0 - frame_count = 0 # 按帧切换,无强制休眠 - - while True: - # 每15帧切换一次灯态(约0.3秒切换,流畅无延迟) - if frame_count % 15 == 0: - current_light = light_sequence[index % len(light_sequence)] - index += 1 - - # 快速生成+识别 - frame = generate_traffic_light_frame(current_light) - _, annotated_frame = detect_traffic_light(frame) - - # 高速显示(10ms刷新一次) - cv2.imshow("Fast Traffic Light Detection", annotated_frame) - frame_count += 1 - - # 按q立即退出 - if cv2.waitKey(10) & 0xFF == ord('q'): - break - - cv2.destroyAllWindows() - print("✅ 模拟结束") - -if __name__ == "__main__": - run_fast_simulation() From d59ef3d2395f6dc1b5c2045edcf7ad86632a713f Mon Sep 17 00:00:00 2001 From: shengzhanpeng <3299915477@qq.com> Date: Tue, 16 Dec 2025 08:30:03 +0800 Subject: [PATCH 29/29] Merge remote-tracking branch 'origin/main' # Conflicts: # src/Driving_Car/README.md --- src/Driving_Car/README.md | 40 ++++++- src/Driving_Car/Traffic_light_detection.py | 123 -------------------- src/Driving_Car/carla_obstacle_detection.py | 0 3 files changed, 39 insertions(+), 124 deletions(-) delete mode 100644 src/Driving_Car/Traffic_light_detection.py delete mode 100644 src/Driving_Car/carla_obstacle_detection.py diff --git a/src/Driving_Car/README.md b/src/Driving_Car/README.md index 8c27ba2124..7948f410d4 100644 --- a/src/Driving_Car/README.md +++ b/src/Driving_Car/README.md @@ -1 +1,39 @@ -无人车 \ No newline at end of file + +--- + +# 无人驾驶汽车项目 + +## 项目简介 + +本项目是一个基于Python和PyCharm Community Edition开发的无人驾驶汽车仿真系统。通过计算机视觉、机器学习和传感器数据融合技术,实现车辆在模拟环境中的自主导航和避障功能。 + +## 核心功能 + +**路径规划**: 基于A*算法和RRT算法的智能路径规划 + +**障碍物检测**: 使用YOLO和OpenCV进行实时目标检测与识别 + +**车辆控制**: PID控制器实现精确的转向和速度控制 + +**传感器模拟**: 模拟激光雷达、摄像头和超声波传感器数据 + +**3D可视化**: 基于PyGame的实时场景渲染 + +## 技术栈 +**开发环境**: PyCharm Community Edition 2024+ + +**核心语言**: Python 3.8+ + +**计算机视觉**: OpenCV, PIL, NumPy + +**机器学习**: TensorFlow, scikit-learn + +**3D图形**: PyGame, Pyglet + +**数据处理**: Pandas, Matplotlib + +## 快速开始 + +1. 克隆项目到PyCharm +2. 安装依赖: `pip install -r requirements.txt` +3. 运行主程序: `python main.py` diff --git a/src/Driving_Car/Traffic_light_detection.py b/src/Driving_Car/Traffic_light_detection.py deleted file mode 100644 index 2a5876c822..0000000000 --- a/src/Driving_Car/Traffic_light_detection.py +++ /dev/null @@ -1,123 +0,0 @@ -import cv2 -import numpy as np -from PIL import Image, ImageDraw - -# -------------------------- 1. 快速生成模拟帧(精简绘制,缩小分辨率) -------------------------- -def generate_traffic_light_frame(light_color="red"): - """快速生成红绿灯帧(800x600分辨率,精简绘制逻辑)""" - img_width, img_height = 800, 600 # 缩小分辨率,减少计算量 - background_color = (30, 30, 30) # 简化背景 - dark_color = (60, 60, 60) - light_colors = { - "red": (255, 30, 30), - "yellow": (255, 255, 30), - "green": (30, 255, 30) - } - - # 快速创建图片(减少冗余绘制) - img = Image.new("RGB", (img_width, img_height), background_color) - draw = ImageDraw.Draw(img) - - # 简化红绿灯绘制(只保留核心灯体,取消复杂装饰) - light_radius = 40 - light_positions = [ - (img_width//2, img_height//3), - (img_width//2, img_height//2), - (img_width//2, 2*img_height//3) - ] - - for i, pos in enumerate(light_positions): - color = dark_color if not ( - (i==0 and light_color=="red") or - (i==1 and light_color=="yellow") or - (i==2 and light_color=="green") - ) else light_colors[light_color] - # 仅绘制核心灯体(取消光晕、简化边框) - draw.ellipse( - [pos[0]-light_radius, pos[1]-light_radius, - pos[0]+light_radius, pos[1]+light_radius], - fill=color, outline=(200,200,200), width=3 - ) - - # 快速转换为OpenCV格式 - return cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR) - -# -------------------------- 2. 优化识别逻辑(减少计算量) -------------------------- -def detect_traffic_light(frame): - hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) - - # 简化HSV阈值(减少判断耗时) - color_ranges = { - "red": [[(0, 120, 70), (10, 255, 255)], [(170, 120, 70), (180, 255, 255)]], - "yellow": [(22, 120, 70), (32, 255, 255)], - "green": [(45, 120, 70), (70, 255, 255)] - } - - light_detected = "unknown" - max_light_area = 0 - - for color, ranges in color_ranges.items(): - mask = np.zeros_like(hsv[:, :, 0]) - # 简化循环逻辑 - if color == "red": - mask = cv2.inRange(hsv, np.array(ranges[0][0]), np.array(ranges[0][1])) + \ - cv2.inRange(hsv, np.array(ranges[1][0]), np.array(ranges[1][1])) - else: - mask = cv2.inRange(hsv, np.array(ranges[0]), np.array(ranges[1])) - - # 缩小形态学核(减少运算量) - kernel = np.ones((5, 5), np.uint8) - mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel) - mask = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel) - - # 快速轮廓检测 - contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) - for cnt in contours: - area = cv2.contourArea(cnt) - perimeter = cv2.arcLength(cnt, True) - if perimeter == 0: - continue - circularity = 4 * np.pi * area / (perimeter ** 2) - # 适配小分辨率的面积阈值 - if area > 3000 and circularity > 0.65: - if area > max_light_area: - max_light_area = area - light_detected = color - - # 简化绘制标注 - cv2.putText( - frame, f"TL: {light_detected.upper()}", - (20, 40), cv2.FONT_HERSHEY_SIMPLEX, 1.2, (0, 255, 0), 3 - ) - return light_detected, frame - -# -------------------------- 3. 高速运行循环(无延迟切换) -------------------------- -def run_fast_simulation(): - print("🚀 快速版模拟启动(按 'q' 退出)") - light_sequence = ["red", "yellow", "green"] - index = 0 - frame_count = 0 # 按帧切换,无强制休眠 - - while True: - # 每15帧切换一次灯态(约0.3秒切换,流畅无延迟) - if frame_count % 15 == 0: - current_light = light_sequence[index % len(light_sequence)] - index += 1 - - # 快速生成+识别 - frame = generate_traffic_light_frame(current_light) - _, annotated_frame = detect_traffic_light(frame) - - # 高速显示(10ms刷新一次) - cv2.imshow("Fast Traffic Light Detection", annotated_frame) - frame_count += 1 - - # 按q立即退出 - if cv2.waitKey(10) & 0xFF == ord('q'): - break - - cv2.destroyAllWindows() - print("✅ 模拟结束") - -if __name__ == "__main__": - run_fast_simulation() diff --git a/src/Driving_Car/carla_obstacle_detection.py b/src/Driving_Car/carla_obstacle_detection.py deleted file mode 100644 index e69de29bb2..0000000000