【零基础学AI】第31讲:目标检测 - YOLO算法
本节课你将学到
- YOLO算法的核心思想和工作原理
- 如何使用YOLO进行物体检测
- 构建一个简单的物体检测系统
开始之前
环境要求
- Python 3.8+
- 需要安装的包:
opencv-python
,numpy
,matplotlib
- 硬件要求:推荐使用GPU(非必须)
前置知识
- 基本Python编程能力
- 了解卷积神经网络(CNN)的基本概念(第24讲内容)
核心概念
什么是目标检测?
目标检测就像教计算机"看"图片中的物体。它不仅要知道图片中有什么物体,还要知道这些物体在哪里(用方框标出来)。
类比说明:
- 图像分类:告诉你这张照片里有一只猫
- 目标检测:告诉你照片里有一只猫,并指出猫在照片的哪个位置(用方框标出)
YOLO算法简介
YOLO(You Only Look Once)是一种快速的目标检测算法。它的特点是:
- 速度快:像它的名字一样,只需要"看一次"图片就能检测出所有物体
- 端到端:直接从图片输入到检测结果输出
- 实时性:可以在视频中实时检测物体(如自动驾驶、监控系统)
YOLO工作原理:
- 将图片分成网格(如7x7)
- 每个网格预测若干个边界框(bounding box)和对应的物体类别
- 通过非极大值抑制(NMS)去除重复的预测框
代码实战
1. 安装必要的库
# 安装OpenCV(用于图像处理)
# 在命令行中运行:
# pip install opencv-python numpy matplotlib
2. 加载预训练的YOLO模型
import cv2
import numpy as np# 下载YOLO的配置文件(yolov3.cfg)和权重文件(yolov3.weights)
# 可以从这里下载:https://pjreddie.com/darknet/yolo/
# 下载后放在项目文件夹的yolo/目录下# 加载YOLO模型
net = cv2.dnn.readNet("yolo/yolov3.weights", "yolo/yolov3.cfg")# 加载类别名称(80个类别)
with open("yolo/coco.names", "r") as f:classes = [line.strip() for line in f.readlines()]# 获取输出层名称
layer_names = net.getLayerNames()
output_layers = [layer_names[i[0] - 1] for i in net.getUnconnectedOutLayers()]
3. 进行目标检测
def detect_objects(img_path):# 读取图片img = cv2.imread(img_path)height, width, channels = img.shape# 预处理图片(缩放、归一化等)blob = cv2.dnn.blobFromImage(img, 0.00392, (416, 416), (0, 0, 0), True, crop=False)# 输入网络进行预测net.setInput(blob)outs = net.forward(output_layers)# 解析检测结果class_ids = []confidences = []boxes = []for out in outs:for detection in out:scores = detection[5:]class_id = np.argmax(scores)confidence = scores[class_id]if confidence > 0.5: # 只保留置信度大于50%的检测结果# 计算边界框坐标center_x = int(detection[0] * width)center_y = int(detection[1] * height)w = int(detection[2] * width)h = int(detection[3] * height)# 计算边界框的左上角坐标x = int(center_x - w / 2)y = int(center_y - h / 2)boxes.append([x, y, w, h])confidences.append(float(confidence))class_ids.append(class_id)# 应用非极大值抑制(NMS)去除重叠的边界框indexes = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.4)# 绘制检测结果font = cv2.FONT_HERSHEY_PLAINcolors = np.random.uniform(0, 255, size=(len(classes), 3))for i in range(len(boxes)):if i in indexes:x, y, w, h = boxes[i]label = str(classes[class_ids[i]])color = colors[class_ids[i]]cv2.rectangle(img, (x, y), (x + w, y + h), color, 2)cv2.putText(img, label, (x, y + 30), font, 3, color, 3)# 显示结果cv2.imshow("Image", img)cv2.waitKey(0)cv2.destroyAllWindows()# 保存结果cv2.imwrite("output/detection_result.jpg", img)print("检测结果已保存到 output/detection_result.jpg")
4. 运行检测
# 检测示例图片(请确保data目录下有测试图片)
detect_objects("data/test_image.jpg")
完整项目
项目文件结构:
lesson_31_yolo/
├── README.md
├── requirements.txt
├── main.py
├── yolo/
│ ├── yolov3.cfg
│ ├── yolov3.weights
│ └── coco.names
├── data/
│ └── test_image.jpg
└── output/└── detection_result.jpg
requirements.txt
opencv-python>=4.5.0
numpy>=1.19.0
matplotlib>=3.3.0
运行效果
控制台输出
检测结果已保存到 output/detection_result.jpg
生成的文件
output/detection_result.jpg
: 带有检测框和标签的图片
预期结果说明
- 图片中的物体(如人、车、动物等)会被方框标出
- 每个方框上方会显示物体类别名称
- 只有置信度大于50%的物体才会被检测出来
常见问题
Q1: 出现 “No such file or directory” 错误
解决方法:
- 确保yolo/目录下有yolov3.cfg、yolov3.weights和coco.names文件
- 确保data/目录下有测试图片test_image.jpg
- 检查文件路径是否正确
Q2: 检测结果不准确
解决方法:
- 尝试调整置信度阈值(代码中的0.5)
- 确保图片清晰,物体明显
- 可以尝试使用更高分辨率的YOLO模型(如yolov3-tiny)
Q3: 运行速度很慢
解决方法:
- 使用GPU加速(需要安装CUDA和cuDNN)
- 使用更小的模型(如yolov3-tiny)
- 减小输入图片的尺寸(修改代码中的(416, 416)为更小的值)
课后练习
- 尝试用摄像头实时检测物体(使用cv2.VideoCapture)
- 修改置信度阈值,观察检测结果的变化
- 尝试检测视频文件中的物体
- 添加新功能:统计图片中检测到的物体数量
技术支持
如遇问题,请检查:
- 所有必需文件是否已下载并放在正确位置
- OpenCV是否正确安装
- 图片路径是否正确