commit e2d8be035665d8fc0653368dbbe849849476cf9b Author: grtsinry43 Date: Sat Jan 17 02:33:38 2026 +0800 first commit diff --git a/main.py b/main.py new file mode 100644 index 0000000..ce3cc84 --- /dev/null +++ b/main.py @@ -0,0 +1,77 @@ +import cv2 +from ultralytics import YOLO +import time + + +def detect_bikes_modern(video_path, output_path=None): + # 1. 加载模型 + # yolov8n.pt 是 "Nano" 版本,速度最快,适合 CPU 运行 + # 第一次运行时会自动从互联网下载该文件 (约 6MB) + print("正在加载 YOLOv8 模型...") + model = YOLO('yolov8n.pt') + + # 2. 打开视频 + cap = cv2.VideoCapture(video_path) + if not cap.isOpened(): + print(f"错误: 无法打开视频 {video_path}") + return + + # 获取视频参数 + width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) + height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) + fps = cap.get(cv2.CAP_PROP_FPS) + + # 3. 设置保存 (可选) + out = None + if output_path: + # 现代环境通常使用 mp4v 或 avc1 + fourcc = cv2.VideoWriter_fourcc(*'mp4v') + out = cv2.VideoWriter(output_path, fourcc, fps, (width, height)) + print(f"结果将保存到: {output_path}") + + print("开始检测... 按 'q' 退出") + + while True: + ret, frame = cap.read() + if not ret: + break + + # 4. 核心检测逻辑 + # stream=True 让处理更流畅 + # classes=[1] 意思是我们只检测 COCO 数据集中的第 1 类 (0是人, 1是自行车, 2是汽车...) + # conf=0.3 意思是置信度大于 0.3 才算检测到 + results = model.predict(frame, conf=0.2, classes=[1], verbose=False) + + # 5. 在图上画框 + # result.plot() 会自动把检测框画在 frame 上 + annotated_frame = results[0].plot() + + # 显示计数 + bike_count = len(results[0].boxes) + cv2.putText(annotated_frame, f"Bikes: {bike_count}", (20, 40), + cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2) + + # 显示画面 + cv2.imshow("Modern Bike Detection", annotated_frame) + + # 保存画面 + if out: + out.write(annotated_frame) + + if cv2.waitKey(1) & 0xFF == ord('q'): + break + + cap.release() + if out: + out.release() + cv2.destroyAllWindows() + print("处理完成。") + + +if __name__ == "__main__": + # 替换成你的视频路径 + # 注意:这里我们不再需要那个 lowerFAR.xml 文件了,直接扔掉它 + video_source = "intersection.avi" + output_file = "result_modern.mp4" + + detect_bikes_modern(video_source, output_file) \ No newline at end of file diff --git a/main2.py b/main2.py new file mode 100644 index 0000000..3b16b08 --- /dev/null +++ b/main2.py @@ -0,0 +1,82 @@ +import cv2 +import numpy as np + + +def run_optical_flow(video_path): + # 1. 打开视频 + cap = cv2.VideoCapture(video_path) + if not cap.isOpened(): + print(f"错误: 无法打开视频 {video_path}") + return + + # 2. 读取第一帧并转换为灰度 + ret, first_frame = cap.read() + if not ret: + print("错误: 视频无法读取") + return + prev_gray = cv2.cvtColor(first_frame, cv2.COLOR_BGR2GRAY) + + # 3. 设置可视化参数 + step = 16 # 步长:不需要每个像素都画箭头,每隔 16 个像素画一个 + scale = 1 # 缩放因子:控制箭头的长度,如果箭头太短看不清,把这个改大 (例如 2 或 3) + color = (0, 255, 0) # 绿色箭头 + + print("按 'q' 退出...") + + while True: + ret, frame = cap.read() + if not ret: + break + + # 转换为灰度图 + gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) + + # 4. 计算稠密光流 (Farneback 算法) + # flow 是一个 (h, w, 2) 的数组,flow[..., 0] 是水平移动(dx),flow[..., 1] 是垂直移动(dy) + flow = cv2.calcOpticalFlowFarneback(prev_gray, gray, None, + pyr_scale=0.5, levels=3, winsize=15, + iterations=3, poly_n=5, poly_sigma=1.2, flags=0) + + # 5. 可视化:在原图上画箭头 + # 创建网格点 (只在 step 的倍数位置画) + h, w = gray.shape + y, x = np.mgrid[step / 2:h:step, step / 2:w:step].reshape(2, -1).astype(int) + + # 获取这些网格点对应的 dx, dy + fx, fy = flow[y, x].T + + # 创建画线的图层 + vis_frame = frame.copy() + + # 绘制线条 + lines = np.vstack([x, y, x + fx * scale, y + fy * scale]).T.reshape(-1, 2, 2) + lines = np.int32(lines + 0.5) + + # 遍历绘制箭头 (cv2.arrowedLine) + for (x1, y1), (x2, y2) in lines: + # 只有当运动幅度超过一定阈值才画,减少噪点 (对应 MATLAB 的 NoiseThreshold) + if np.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2) > 1: + cv2.arrowedLine(vis_frame, (x1, y1), (x2, y2), color, 1, tipLength=0.3) + + # 6. 显示结果 + cv2.imshow('Optical Flow (Dense)', vis_frame) + + # 更新上一帧 + prev_gray = gray + + # 按 'q' 退出 + if cv2.waitKey(20) & 0xFF == ord('q'): # waitKey(20) 控制播放速度 + break + + cap.release() + cv2.destroyAllWindows() + + +if __name__ == "__main__": + # 请确保目录下有 thumb.avi,或者改成 0 使用摄像头测试 + video_file = "thumb.avi" + + # 如果没有视频文件,想用摄像头测试,取消下面这行的注释: + # video_file = 0 + + run_optical_flow(video_file) \ No newline at end of file