基于Deep Sort的视频车流量计数(一)

基于Deep Sort的视频车流量计数是一种基于计算机视觉技术的车流量计数方法。它主要利用了深度学习中的目标检测和跟踪技术,以及计算机视觉中的背景建模、目标检测和跟踪等技术。

具体实现流程如下:

  • 视频预处理:对输入视频进行预处理,如视频去噪、图像增强、边缘检测等。
  • 目标检测:对预处理后的视频图像进行目标检测,检测出图像中的车辆。
  • 目标跟踪:对检测到的车辆进行跟踪,利用Deep Sort算法进行多目标跟踪,并为每个车辆分配一个唯一的ID号。
  • 计数:在跟踪过程中,通过车辆在视频中的运动轨迹,可以得到车辆的通过数,从而实现车流量计数。
  • 结果输出:将计数结果输出到显示器、数据库等设备中,以便后续分析和处理。

1 视频预处理

1.1 视频去噪

1.1.1 基于高斯模糊的去噪方法

import cv2

def denoise_gaussian(image, kernel_size=5, sigma=1.5):
    """
    基于高斯模糊的去噪方法
    :param image: 输入图像,要求是灰度图像
    :param kernel_size: 高斯核大小,必须为正奇数
    :param sigma: 高斯核标准差
    :return: 去噪后的图像
    """
    if kernel_size % 2 == 0 or kernel_size <= 0:
        raise ValueError("Kernel size must be positive odd integer.")
    return cv2.GaussianBlur(image, (kernel_size, kernel_size), sigma)

def video_denoise_gaussian(video_path, output_path, kernel_size=5, sigma=1.5):
    """
    视频去噪,基于高斯模糊的方法
    :param video_path: 输入视频路径
    :param output_path: 输出视频路径
    :param kernel_size: 高斯核大小,必须为正奇数
    :param sigma: 高斯核标准差
    """
    cap = cv2.VideoCapture(video_path)
    fourcc = int(cap.get(cv2.CAP_PROP_FOURCC))
    fps = int(cap.get(cv2.CAP_PROP_FPS))
    width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
    out = cv2.VideoWriter(output_path, fourcc, fps, (width, height), isColor=False)
    while cap.isOpened():
        ret, frame = cap.read()
        if not ret:
            break
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        denoised = denoise_gaussian(gray, kernel_size=kernel_size, sigma=sigma)
        out.write(denoised)
    cap.release()
    out.release()

1.1.2 基于双边滤波的去噪方法

def denoise_bilateral(image, d=9, sigma_color=75, sigma_space=75):
    """
    基于双边滤波的去噪方法
    :param image: 输入图像,要求是灰度图像
    :param d: 双边滤波器窗口大小
    :param sigma_color: 双边滤波器空间高斯函数标准差
    :param sigma_space: 双边滤波器灰度值相似度高斯函数标准差
    :return: 去噪后的图像
    """
    return cv2.bilateralFilter(image, d, sigma_color, sigma_space)

def video_denoise_bilateral(video_path, output_path, d=9, sigma_color=75, sigma_space=75):
    """
    视频去噪,基于双边滤波的方法
    :param video_path: 输入视频路径
    :param output_path: 输出视频路径
    :param d: 双边滤波器窗口大小
    :param sigma_color: 双边滤波器空间高斯函数标准差
    :param sigma_space: 双边滤波器灰度值相似度高斯函数标准差
    """
    cap = cv2.VideoCapture(video_path)
    fourcc = int(cap.get(cv2.CAP_PROP_FOURCC))
    fps = int(cap.get(cv2.CAP_PROP_FPS))
    width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
    out = cv2.VideoWriter(output_path, fourcc, fps, (width, height), isColor=False)
    while cap.isOpened():
        ret, frame = cap.read()
        if not ret:
            break
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        denoised = denoise_bilateral(gray, d=d, sigma_color=sigma_color, sigma_space=sigma_space)
        out.write(denoised)
    cap.release()
    out.release()

1.1.3 基于中值滤波的去噪方法

def denoise_median(image, kernel_size=3):
    """
    基于中值滤波的去噪方法
    :param image: 输入图像,要求是灰度图像
    :param kernel_size: 中值滤波器大小,必须为正奇数
    :return: 去噪后的图像
    """
    if kernel_size % 2 == 0 or kernel_size <= 0:
        raise ValueError("Kernel size must be positive odd integer.")
    return cv2.medianBlur(image, kernel_size)

def video_denoise_median(video_path, output_path, kernel_size=3):
    """
    视频去噪,基于中值滤波的方法
    :param video_path: 输入视频路径
    :param output_path: 输出视频路径
    :param kernel_size: 中值滤波器大小,必须为正奇数
    """
    cap = cv2.VideoCapture(video_path)
    fourcc = int(cap.get(cv2.CAP_PROP_FOURCC))
    fps = int(cap.get(cv2.CAP_PROP_FPS))
    width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
    out = cv2.VideoWriter(output_path, fourcc, fps, (width, height), isColor=False)
    while cap.isOpened():
        ret, frame = cap.read()
        if not ret:
            break
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        denoised = denoise_median(gray, kernel_size=kernel_size)
        out.write(denoised)
    cap.release()
    out.release()

1.2 视频图像增强

视频图像增强方法主要包括直方图均衡化、灰度拉伸、滤波等方法。

1.2.1 直方图均衡化

import cv2
import numpy as np

# 读取视频文件
cap = cv2.VideoCapture("test.mp4")

# 获取视频帧率、宽度和高度信息
fps = int(cap.get(cv2.CAP_PROP_FPS))
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

# 输出视频文件参数信息
print("fps: ", fps)
print("width: ", width)
print("height: ", height)

# 创建一个VideoWriter对象,用于保存增强后的视频
fourcc = cv2.VideoWriter_fourcc(*"XVID")
out = cv2.VideoWriter("enhanced.avi", fourcc, fps, (width, height))

# 循环读取视频帧并进行直方图均衡化
while True:
    ret, frame = cap.read()

    if ret == True:
        # 将帧转换为灰度图像
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

        # 进行直方图均衡化
        equ = cv2.equalizeHist(gray)

        # 将均衡化后的图像转换为BGR格式,用于保存为视频文件
        res = cv2.cvtColor(equ, cv2.COLOR_GRAY2BGR)

        # 写入增强后的帧到输出视频文件中
        out.write(res)

        # 显示增强后的帧
        cv2.imshow("Enhanced", res)

        # 按下q键退出循环
        if cv2.waitKey(1) & 0xFF == ord("q"):
            break
    else:
        break

# 释放资源
cap.release()
out.release()
cv2.destroyAllWindows()

这段代码实现了对视频文件中每一帧图像的直方图均衡化,并将增强后的帧保存为一个新的视频文件。具体实现中,使用了OpenCV库提供的VideoCapture和VideoWriter对象来读取和保存视频文件,使用了cvtColor函数将帧转换为灰度图像,然后使用equalizeHist函数进行直方图均衡化,最后使用cvtColor函数将均衡化后的图像转换为BGR格式,用于保存为视频文件。在循环读取视频帧并增强的过程中,还加入了一个按下q键退出循环的功能,方便程序的使用。

1.2.2 灰度拉伸

视频序列的灰度拉伸方法可以将图像的亮度范围映射到更广的区间内,从而增强图像的对比度和清晰度。下面是一个使用Python实现的视频序列的灰度拉伸方法的示例代码。

import cv2
import numpy as np

# 读取视频文件
cap = cv2.VideoCapture("test.mp4")

# 获取视频帧率、宽度和高度信息
fps = int(cap.get(cv2.CAP_PROP_FPS))
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))

# 输出视频文件参数信息
print("fps: ", fps)
print("width: ", width)
print("height: ", height)

# 创建一个VideoWriter对象,用于保存增强后的视频
fourcc = cv2.VideoWriter_fourcc(*"XVID")
out = cv2.VideoWriter("enhanced.avi", fourcc, fps, (width, height))

# 设置灰度拉伸的参数
lower_percent = 5
upper_percent = 95

# 循环读取视频帧并进行灰度拉伸
while True:
    ret, frame = cap.read()

    if ret == True:
        # 将帧转换为灰度图像
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

        # 计算像素值的上下阈值
        lower = np.percentile(gray, lower_percent)
        upper = np.percentile(gray, upper_percent)

        # 进行灰度拉伸
        stretched = np.uint8(np.clip((gray - lower) / (upper - lower) * 255, 0, 255))

        # 将拉伸后的图像转换为BGR格式,用于保存为视频文件
        res = cv2.cvtColor(stretched, cv2.COLOR_GRAY2BGR)

        # 写入增强后的帧到输出视频文件中
        out.write(res)

        # 显示增强后的帧
        cv2.imshow("Enhanced", res)

        # 按下q键退出循环
        if cv2.waitKey(1) & 0xFF == ord("q"):
            break
    else:
        break

# 释放资源
cap.release()
out.release()
cv2.destroyAllWindows()

这段代码实现了对视频文件中每一帧图像的灰度拉伸,并将增强后的帧保存为一个新的视频文件。具体实现中,使用了OpenCV库提供的VideoCapture和VideoWriter对象来读取和保存视频文件,使用了cvtColor函数将帧转换为灰度图像,然后计算了像素值的上下阈值,并使用clip函数将像素值限制在0到255之间,最后使用cvtColor函数将拉伸后的图像转换为BGR格式,用于保存为视频文件。在循环读取视频帧并增强的过程中,还加入了一个按下q键退出循环的功能,方便程序的使用。

1.3 边缘检测

基于Python和OpenCV的视频序列边缘检测代码实现

import cv2

cap = cv2.VideoCapture('video.mp4') # 读取视频

while True:
    ret, frame = cap.read() # 读取视频帧
    if ret:
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # 将帧转为灰度图像
        edges = cv2.Canny(gray, 100, 200) # 边缘检测
        cv2.imshow('Edges', edges) # 显示边缘检测结果

        if cv2.waitKey(25) & 0xFF == ord('q'): # 按q键退出
            break
    else:
        break

cap.release() # 释放资源
cv2.destroyAllWindows() # 关闭窗口

代码解释:

  1. cv2.VideoCapture('video.mp4') 读取视频文件。
  2. cap.read() 循环读取视频帧,直到读取结束。
  3. cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 将彩色图像转为灰度图像。
  4. cv2.Canny(gray, 100, 200) 对灰度图像进行边缘检测,返回一个二值图像。
  5. cv2.imshow('Edges', edges) 显示边缘检测结果。
  6. cv2.waitKey(25) & 0xFF == ord('q') 每隔25毫秒等待键盘输入,如果按下了q键则退出循环。
  7. cap.release() 释放视频资源。
  8. cv2.destroyAllWindows() 关闭窗口。

2 目标检测

目标检测是计算机视觉领域中的一项重要任务,它旨在识别图像或视频中的物体,并定位它们的位置。以下是一些常见的目标检测算法:

  1. Haar级联检测器:基于Haar特征的机器学习算法,可以识别和定位物体。

  2. HOG(方向梯度直方图)特征+SVM(支持向量机)分类器:使用梯度方向直方图描述物体的形状特征,并使用支持向量机分类器进行分类。

  3. Faster R-CNN(Region-based Convolutional Neural Network):一种基于深度神经网络的目标检测算法,它使用了两个神经网络,一个用于候选区域的生成,另一个用于物体的分类和边界框回归。

  4. YOLO(You Only Look Once):一种基于深度神经网络的实时目标检测算法,它使用单个神经网络直接从整个图像中预测物体类别和边界框。

  5. SSD(Single Shot MultiBox Detector):一种基于深度神经网络的目标检测算法,它使用单个神经网络同时预测物体类别和边界框,而不需要候选区域的生成。

  6. Mask R-CNN:在Faster R-CNN的基础上增加了实例分割的功能,能够输出每个物体的精确掩码。

  7. RetinaNet:一种基于深度神经网络的目标检测算法,使用了一种新的损失函数来解决物体类别不平衡的问题。

这些算法都具有不同的优点和适用场景,具体选择哪个算法要根据具体的需求和应用场景进行评估。

2.1 Haar级联检测器

基于OpenCV的Haar级联检测器目标检测代码实现

import cv2

# 加载Haar分类器
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')

# 读取图像
img = cv2.imread('image.jpg')

# 将图像转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 检测人脸
faces = face_cascade.detectMultiScale(gray, 1.3, 5)

# 标记人脸
for (x,y,w,h) in faces:
    cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)

# 显示结果
cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

解释:

  1. cv2.CascadeClassifier('haarcascade_frontalface_default.xml') 加载Haar分类器。
  2. cv2.imread('image.jpg') 读取图像。
  3. cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 将图像转换为灰度图像。
  4. face_cascade.detectMultiScale(gray, 1.3, 5) 检测人脸。
  5. cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2) 标记人脸矩形框。
  6. cv2.imshow('img',img) 显示结果。
  7. cv2.waitKey(0) 等待按键。
  8. cv2.destroyAllWindows() 关闭窗口。

 2.2 HOG(方向梯度直方图)特征+SVM分类器

基于OpenCV的HOG+SVM目标检测代码实现:

import cv2

# 加载HOG分类器
hog = cv2.HOGDescriptor()
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())

# 读取图像
img = cv2.imread('image.jpg')

# 对图像进行缩放
img = cv2.resize(img, (640, 480))

# 检测目标
(rects, weights) = hog.detectMultiScale(img, winStride=(4, 4), padding=(8, 8), scale=1.05)

# 标记目标
for (x, y, w, h) in rects:
    cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)

# 显示结果
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

代码解释:

  1. cv2.HOGDescriptor() 加载HOG分类器。
  2. cv2.HOGDescriptor_setSVMDetector(hog, cv2.HOGDescriptor_getDefaultPeopleDetector()) 设置HOG分类器的SVM分类器。
  3. cv2.imread('image.jpg') 读取图像。
  4. cv2.resize(img, (640, 480)) 对图像进行缩放。
  5. hog.detectMultiScale(img, winStride=(4, 4), padding=(8, 8), scale=1.05) 检测目标。
  6. cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2) 标记目标矩形框。
  7. cv2.imshow('img', img) 显示结果。
  8. cv2.waitKey(0) 等待按键。
  9. cv2.destroyAllWindows() 关闭窗口。

此代码只是基础实现,可能需要对分类器参数进行调整,以提高检测精度。此外,HOG+SVM通常适用于人体检测,对于其他类型的目标检测,可能需要使用不同的特征描述算法和分类器。

2.3 Faster R-CNN

基于PyTorch和Faster R-CNN的目标检测代码实现示例

import torch
import torchvision
import numpy as np
import cv2

# 加载 Faster R-CNN 模型和对应的预训练权重
model = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True)

# 设置模型为评估模式
model.eval()

# 设置模型的设备为 GPU 或 CPU
device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')
model.to(device)

# 定义类别标签
labels = ['background', 'person', 'bicycle', 'car', 'motorcycle', 'airplane',
          'bus', 'train', 'truck', 'boat', 'traffic light', 'fire hydrant',
          'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse',
          'sheep', 'cow', 'elephant', 'bear', 'zebra', 'giraffe', 'backpack',
          'umbrella', 'handbag', 'tie', 'suitcase', 'frisbee', 'skis',
          'snowboard', 'sports ball', 'kite', 'baseball bat', 'baseball glove',
          'skateboard', 'surfboard', 'tennis racket', 'bottle', 'wine glass',
          'cup', 'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple',
          'sandwich', 'orange', 'broccoli', 'carrot', 'hot dog', 'pizza',
          'donut', 'cake', 'chair', 'couch', 'potted plant', 'bed',
          'dining table', 'toilet', 'tv', 'laptop', 'mouse', 'remote',
          'keyboard', 'cell phone', 'microwave', 'oven', 'toaster', 'sink',
          'refrigerator', 'book', 'clock', 'vase', 'scissors', 'teddy bear',
          'hair drier', 'toothbrush']

# 加载待检测的图像
image = cv2.imread('test_image.jpg')

# 将图像转换为 PyTorch 张量
image = torch.from_numpy(image.transpose(2, 0, 1)).float().div(255.0).unsqueeze(0)

# 将张量移动到设备上
image = image.to(device)

# 对图像进行预测
with torch.no_grad():
    predictions = model(image)

# 获取预测结果中的框和类别标签
boxes = predictions[0]['boxes'].cpu().numpy()
labels = predictions[0]['labels'].cpu().numpy()

# 在图像上绘制预测结果
for box, label in zip(boxes, labels):
    if label == 0:  # 忽略背景标签
        continue
    color = (0, 255, 0)  # 框的颜色为绿色
    thickness = 2  # 框的线条宽度为2
    x1, y1, x2, y2 = box.astype(np.int)
    cv2.rectangle(image, (x1, y1), (x2, y2), color, thickness)
    text = labels[label]  # 获取类别标签
    font = cv2.FONT_HERSHEY_SIMPLEX  # 设置字体
    font_scale = 0.5  # 设置字体缩放比例
    text_color = (255, 255, 255)  # 文本颜色为白色
    thickness = 1  # 文本线条宽度为1
    text_size = cv2.getTextSize(text, font, font_scale, thickness)[0]
    cv2.rectangle(image, (x1, y1 - text_size[1]), (x1 + text_size[0], y1), color, -1)
    cv2.putText(image, text, (x1, y1 - 5), font, font_scale, text_color, thickness)

# 将图像保存到文件中
cv2.imwrite('result_image.jpg', image)

上述代码实现了使用 Faster R-CNN 对图像进行目标检测的功能。在代码中,首先加载了 Faster R-CNN 模型和对应的预训练权重,然后将模型设置为评估模式,并将模型的设备设置为 GPU 或 CPU。接着,定义了类别标签,并加载待检测的图像。将图像转换为 PyTorch 张量后,将其移动到设备上。使用模型对图像进行预测后,从预测结果中获取框和类别标签,并在图像上绘制预测结果。最后将图像保存到文件中。

2.4 YOLO

基于PyTorch和YOLO的目标检测代码实现示例:

import torch
import torchvision
import numpy as np
import cv2

# 加载 YOLOv3 模型和对应的预训练权重
model = torchvision.models.detection.yolo3_mobilenet_v1(pretrained=True)

# 设置模型为评估模式
model.eval()

# 设置模型的设备为 GPU 或 CPU
device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')
model.to(device)

# 定义类别标签
labels = ['person', 'bicycle', 'car', 'motorbike', 'aeroplane', 'bus', 'train',
          'truck', 'boat', 'traffic light', 'fire hydrant', 'stop sign', 'parking meter',
          'bench', 'bird', 'cat', 'dog', 'horse', 'sheep', 'cow', 'elephant',
          'bear', 'zebra', 'giraffe', 'backpack', 'umbrella', 'handbag', 'tie',
          'suitcase', 'frisbee', 'skis', 'snowboard', 'sports ball', 'kite',
          'baseball bat', 'baseball glove', 'skateboard', 'surfboard',
          'tennis racket', 'bottle', 'wine glass', 'cup', 'fork', 'knife',
          'spoon', 'bowl', 'banana', 'apple', 'sandwich', 'orange', 'broccoli',
          'carrot', 'hot dog', 'pizza', 'donut', 'cake', 'chair', 'sofa',
          'pottedplant', 'bed', 'diningtable', 'toilet', 'tvmonitor', 'laptop',
          'mouse', 'remote', 'keyboard', 'cell phone', 'microwave', 'oven',
          'toaster', 'sink', 'refrigerator', 'book', 'clock', 'vase', 'scissors',
          'teddy bear', 'hair drier', 'toothbrush']

# 加载待检测的图像
image = cv2.imread('test_image.jpg')

# 将图像转换为 PyTorch 张量
image = torch.from_numpy(image.transpose(2, 0, 1)).float().div(255.0).unsqueeze(0)

# 将张量移动到设备上
image = image.to(device)

# 对图像进行预测
with torch.no_grad():
    predictions = model(image)

# 获取预测结果中的框、类别标签和置信度
boxes = predictions[0]['boxes'].cpu().numpy()
labels = predictions[0]['labels'].cpu().numpy()
scores = predictions[0]['scores'].cpu().numpy()

# 在图像上绘制预测结果
for box, label, score in zip(boxes, labels, scores):
    if score < 0.5:  # 忽略置信度低于0.5的框
        continue
    color = (0, 255, 0)  # 框的颜色为绿色
    thickness = 2  # 框的线条宽度为2
    x1, y1, x2, y2 = box.astype(np.int)
    cv2.rectangle(image, (x1, y1), (x2, y2), color, thickness)
    text = labels[label]  # 获取类别标签名称
    font = cv2.FONT_HERSHEY_SIMPLEX  # 设置字体类型
    font_scale = 0.5  # 设置字体缩放比例
    text_color = (255, 255, 255)  # 文本颜色为白色
    thickness = 1  # 文本线条宽度为1
    text_size = cv2.getTextSize(text, font, font_scale, thickness)[0]
    cv2.rectangle(image, (x1, y1 - text_size[1]), (x1 + text_size[0], y1), color, -1)
    cv2.putText(image, text, (x1, y1 - 5), font, font_scale, text_color, thickness)

# 将图像保存到文件中
cv2.imwrite('result_image.jpg', image)

上述代码实现了使用 YOLOv3 对图像进行目标检测的功能。在代码中,首先加载了 YOLOv3 模型和对应的预训练权重,然后将模型设置为评估模式,并将模型的设备设置为 GPU 或 CPU。接着,定义了类别标签,并加载待检测的图像。将图像转换为 PyTorch 张量后,将其移动到设备上。使用模型对图像进行预测后,从预测结果中获取框、类别标签和置信度,并在图像上绘制预测结果。最后将图像保存到文件中。

2.5 SSD

使用 PyTorch 和 SSD 进行目标检测的代码示例:

import torch
import torchvision.transforms as transforms
import cv2

# 定义类别标签
labels = ('background', 'aeroplane', 'bicycle', 'bird', 'boat',
          'bottle', 'bus', 'car', 'cat', 'chair', 'cow', 'diningtable',
          'dog', 'horse', 'motorbike', 'person', 'pottedplant', 'sheep',
          'sofa', 'train', 'tvmonitor')

# 加载 SSD 模型和对应的预训练权重
model = torch.hub.load('NVIDIA/DeepLearningExamples:torchhub', 'nvidia_ssd', model_math='fp32')
model.to('cuda').eval()

# 定义图像变换
transform = transforms.Compose([
    transforms.Resize((300, 300)),
    transforms.ToTensor(),
    transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225))
])

# 加载待检测的图像
image = cv2.imread('test_image.jpg')

# 将图像转换为 PyTorch 张量
image_tensor = transform(image).unsqueeze(0).to('cuda')

# 使用模型对图像进行预测
with torch.no_grad():
    detections = model(image_tensor)
    
# 从预测结果中获取框、类别标签和置信度
boxes = detections[0]['boxes'].cpu().numpy()
labels = detections[0]['labels'].cpu().numpy()
scores = detections[0]['scores'].cpu().numpy()

# 在图像上绘制预测结果
for box, label, score in zip(boxes, labels, scores):
    if score < 0.5:
        continue
    x1, y1, x2, y2 = map(int, box)
    color = (0, 255, 0)  # 绿色
    text = f'{labels[label]}: {score:.2f}'
    font = cv2.FONT_HERSHEY_SIMPLEX
    font_scale = 0.5
    text_color = (255, 255, 255)
    thickness = 1
    text_size = cv2.getTextSize(text, font, font_scale, thickness)[0]
    cv2.rectangle(image, (x1, y1), (x2, y2), color, 2)
    cv2.rectangle(image, (x1, y1 - text_size[1]), (x1 + text_size[0], y1), color, -1)
    cv2.putText(image, text, (x1, y1 - 5), font, font_scale, text_color, thickness)

# 将图像保存到文件中
cv2.imwrite('result_image.jpg', image)

上述代码实现了使用 SSD 对图像进行目标检测的功能。在代码中,首先加载了 SSD 模型和对应的预训练权重,然后将模型设置为评估模式,并将模型的设备设置为 GPU 或 CPU。接着,定义了类别标签,并加载待检测的图像。定义了图像变换,并将图像转换为 PyTorch 张量。使用模型对图像进行预测后,从预测结果中获取框、类别标签和置信度,并根据阈值筛选出置信度较高的检测结果。最后,在原图像上绘制检测结果,并将结果保存到文件中。

需要注意的是,上述代码中加载模型的方式是使用 Torch Hub,这需要联网下载模型文件。如果您已经下载了模型文件,也可以使用以下方式加载模型:

from ssd import build_ssd

# 加载 SSD 模型
model = build_ssd('test', 300, 21)
model.load_state_dict(torch.load('weights/ssd300_mAP_77.43_v2.pth'))
model.eval()

上述代码中使用了 SSD PyTorch 实现的 build_ssd 函数加载 SSD 模型,并加载了对应的预训练权重。加载模型时需要指定模型的类型('test' 或 'train')、输入图像的大小和类别数。在使用该方式加载模型时,不需要联网下载模型文件。

2.6 Mask R-CNN

使用 PyTorch 和 Mask R-CNN 进行目标检测的代码示例:

import torch
import torchvision.transforms as transforms
import cv2

# 定义类别标签
labels = ('background', 'person', 'bicycle', 'car', 'motorcycle',
          'airplane', 'bus', 'train', 'truck', 'boat', 'traffic light',
          'fire hydrant', 'stop sign', 'parking meter', 'bench', 'bird',
          'cat', 'dog', 'horse', 'sheep', 'cow', 'elephant', 'bear',
          'zebra', 'giraffe', 'backpack', 'umbrella', 'handbag', 'tie',
          'suitcase', 'frisbee', 'skis', 'snowboard', 'sports ball',
          'kite', 'baseball bat', 'baseball glove', 'skateboard',
          'surfboard', 'tennis racket', 'bottle', 'wine glass', 'cup',
          'fork', 'knife', 'spoon', 'bowl', 'banana', 'apple', 'sandwich',
          'orange', 'broccoli', 'carrot', 'hot dog', 'pizza', 'donut',
          'cake', 'chair', 'couch', 'potted plant', 'bed', 'dining table',
          'toilet', 'tv', 'laptop', 'mouse', 'remote', 'keyboard',
          'cell phone', 'microwave', 'oven', 'toaster', 'sink',
          'refrigerator', 'book', 'clock', 'vase', 'scissors',
          'teddy bear', 'hair drier', 'toothbrush')

# 加载 Mask R-CNN 模型和对应的预训练权重
model = torch.hub.load('facebookresearch/detectron2:main', 'mask_rcnn_R_50_FPN_3x')
model.to('cuda').eval()

# 定义图像变换
transform = transforms.Compose([
    transforms.ToPILImage(),
    transforms.Resize((800, 800)),
    transforms.ToTensor(),
    transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
])

# 加载待检测的图像
image = cv2.imread('test_image.jpg')

# 将图像转换为 PyTorch 张量
image_tensor = transform(image).unsqueeze(0).to('cuda')

# 使用模型对图像进行预测
with torch.no_grad():
    outputs = model(image_tensor)
    
# 从预测结果中获取掩模、框、类别标签和置信度
masks = outputs['instances'].pred_masks.cpu().numpy()
boxes = outputs['instances'].pred_boxes.tensor.cpu().numpy()
labels = outputs['instances'].pred_classes.cpu().numpy()
scores = outputs['instances'].scores.cpu().numpy()

# 在图像上绘制预测结果
for mask, box, label, score in zip(masks, boxes, labels, scores):
    if score < 0.5:
        continue
    x1, y1, x2, y2 = map(int, box)
    color = (0, 255, 0)  # 绿色
    mask = (mask > 0.5)
    image[mask] = image[mask] * 0.5 + color * 0.5
    text = f'{labels[label]}: {score:.2f}'
    cv2.rectangle(image, (x1, y1), (x2, y2), color, 2)
    cv2.putText(image, text, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
    
# 将结果保存到文件中
cv2.imwrite('result.jpg', image)

上述代码中,我们首先定义了类别标签。接着,使用 Torch Hub 加载了 Mask R-CNN 模型,并将模型移动到 GPU 上进行推理。定义了图像变换,加载了待检测的图像,并将图像转换为 PyTorch 张量。然后,使用模型对图像进行预测,并从预测结果中获取掩模、框、类别标签和置信度。最后,在原图像上绘制预测结果,并将结果保存到文件中。

需要注意的是,上述代码中使用了 Facebook 的 Detectron2 库,这需要先安装该库。安装命令如下:

pip install detectron2 -f https://dl.fbaipublicfiles.com/detectron2/wheels/cu111/torch1.9/index.html

除了使用 Detectron2 库之外,也可以使用 PyTorch 官方提供的 Mask R-CNN 实现来进行目标检测。下面是一个基于 PyTorch 官方实现的代码示例:

import torch
import torchvision
import numpy as np
import cv2

# 定义类别标签
class_labels = [
    '__background__', 'person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus',
    'train', 'truck', 'boat', 'traffic light', 'fire hydrant', 'N/A', 'stop sign',
    'parking meter', 'bench', 'bird', 'cat', 'dog', 'horse', 'sheep', 'cow',
    'elephant', 'bear', 'zebra', 'giraffe', 'N/A', 'backpack', 'umbrella', 'N/A',
    'N/A', 'handbag', 'tie', 'suitcase', 'frisbee', 'skis', 'snowboard',
    'sports ball', 'kite', 'baseball bat', 'baseball glove', 'skateboard',
    'surfboard', 'tennis racket', 'bottle', 'N/A', 'wine glass', 'cup', 'fork',
    'knife', 'spoon', 'bowl', 'banana', 'apple', 'sandwich', 'orange',
    'broccoli', 'carrot', 'hot dog', 'pizza', 'donut', 'cake', 'chair',
    'couch', 'potted plant', 'bed', 'N/A', 'dining table', 'N/A', 'N/A',
    'toilet', 'N/A', 'tv', 'laptop', 'mouse', 'remote', 'keyboard',
    'cell phone', 'microwave', 'oven', 'toaster', 'sink', 'refrigerator',
    'N/A', 'book', 'clock', 'vase', 'scissors', 'teddy bear', 'hair drier',
    'toothbrush'
]

# 加载预训练模型
model = torchvision.models.detection.maskrcnn_resnet50_fpn(pretrained=True)

# 将模型移动到 GPU 上进行推理
device = torch.device('cuda') if torch.cuda.is_available() else torch.device('cpu')
model.to(device)
model.eval()

# 定义图像变换
transform = torchvision.transforms.Compose([
    torchvision.transforms.ToTensor(),
])

# 加载待检测的图像
image = cv2.imread('test.jpg')
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

# 将图像转换为 PyTorch 张量
image_tensor = transform(image)
image_tensor = image_tensor.unsqueeze(0)
image_tensor = image_tensor.to(device)

# 使用模型对图像进行预测
with torch.no_grad():
    predictions = model(image_tensor)

# 从预测结果中获取掩模、框、类别标签和置信度
masks = predictions[0]['masks'].cpu().numpy()
boxes = predictions[0]['boxes'].cpu().numpy()
labels = predictions[0]['labels'].cpu().numpy()
scores = predictions[0]['scores'].cpu().numpy()

# 在原图像上绘制预测结果
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
for i in range(len(boxes)):
    if scores[i] > 0.5:
        mask = masks[i, 0]
       
        # 将掩模转换为二值图像
        mask = (mask > 0.5).astype(np.uint8) * 255

        # 绘制掩模
        contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
        cv2.drawContours(image, contours, -1, (0, 255, 0), 2)

        # 绘制边界框
        x1, y1, x2, y2 = boxes[i]
        cv2.rectangle(image, (x1, y1), (x2, y2), (0, 0, 255), 2)

        # 绘制类别标签和置信度
        label = class_labels[labels[i]]
        score = scores[i]
        cv2.putText(image, f'{label}: {score:.2f}', (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 1)

# 显示绘制结果
cv2.imshow('image', image)
cv2.waitKey(0)
cv2.destroyAllWindows()


在这个代码示例中,我们使用 PyTorch 提供的 `maskrcnn_resnet50_fpn` 预训练模型对一张测试图像进行目标检测。具体步骤如下:

1. 定义类别标签,包括 80 种常见物体。
2. 加载预训练模型,并将其移动到 GPU 上进行推理。
3. 定义图像变换,将图像转换为 PyTorch 张量。
4. 加载待检测的图像,并将其转换为 PyTorch 张量。
5. 使用模型对图像进行预测,并从预测结果中获取掩模、框、类别标签和置信度。
6. 在原图像上绘制预测结果,包括掩模、边界框、类别标签和置信度。

需要注意的是,Mask R-CNN 模型会为每个目标生成一个掩模,因此需要将掩模转换为二值图像,并使用 `cv2.findContours()` 函数找到掩模中的轮廓,最后使用 `cv2.drawContours()` 函数绘制轮廓。

另外,需要使用 `cv2.cvtColor()` 函数将图像从 RGB 格式转换为 BGR 格式,以便在 OpenCV 中正确显示图像。

2.7 RetinaNet

RetinaNet 是一种基于 Focal Loss 的单阶段目标检测器,具有高精度和高效率的优点。下面是一个基于 PyTorch 和 RetinaNet 的目标检测代码示例:

import torch
import cv2
import numpy as np
import torchvision.transforms as transforms
from torchvision.models.detection import retinanet_resnet50_fpn

# 定义类别标签
class_labels = ['background', 'person', 'bicycle', 'car', 'motorcycle', 'airplane',
                'bus', 'train', 'truck', 'boat', 'traffic light', 'fire hydrant',
                'stop sign', 'parking meter', 'bench', 'bird', 'cat', 'dog',
                'horse', 'sheep', 'cow', 'elephant', 'bear', 'zebra', 'giraffe',
                'backpack', 'umbrella', 'handbag', 'tie', 'suitcase', 'frisbee',
                'skis', 'snowboard', 'sports ball', 'kite', 'baseball bat',
                'baseball glove', 'skateboard', 'surfboard', 'tennis racket',
                'bottle', 'wine glass', 'cup', 'fork', 'knife', 'spoon', 'bowl',
                'banana', 'apple', 'sandwich', 'orange', 'broccoli', 'carrot',
                'hot dog', 'pizza', 'donut', 'cake', 'chair', 'couch',
                'potted plant', 'bed', 'dining table', 'toilet', 'tv', 'laptop',
                'mouse', 'remote', 'keyboard', 'cell phone', 'microwave', 'oven',
                'toaster', 'sink', 'refrigerator', 'book', 'clock', 'vase',
                'scissors', 'teddy bear', 'hair drier', 'toothbrush']

# 加载预训练模型
model = retinanet_resnet50_fpn(pretrained=True)
model.eval()

# 将模型移动到 GPU 上
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model.to(device)

# 定义图像变换
transform = transforms.Compose([
    transforms.ToTensor(),
])

# 加载待检测的图像
image = cv2.imread('test.jpg')

# 将图像转换为 PyTorch 张量
image_tensor = transform(image)
image_tensor = image_tensor.unsqueeze(0).to(device)

# 使用模型对图像进行预测
with torch.no_grad():
    outputs = model(image_tensor)

# 从预测结果中获取边界框、类别标签和置信度
boxes = outputs[0]['boxes'].detach().cpu().numpy()
labels = outputs[0]['labels'].detach().cpu().numpy()
scores = outputs[0]['scores'].detach().cpu().numpy()

# 在原图像上绘制预测结果
for i in range(len(boxes)):
    # 绘制边界框
    x1, y1, x2, y2 = boxes[i]
    cv2.rectangle(image, (x1, y1), (x2, y2), (0, 0, 255), 2)

    # 绘制类别标签和置信度
    label = class_labels[labels[i]]
    score = scores[i]
    cv2.putText(image, f'{label}: {score:.2f}', (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)

# 显示绘制结果
cv2.imshow('image', image)
cv2.waitKey(0)
cv2.destroyAllWindows()

上述代码中,我们首先加载了一个预训练的 RetinaNet 模型(在这里使用了 ResNet50-FPN 架构),并将其移动到 GPU 上。然后,我们加载了一个待检测的图像,并将其转换为 PyTorch 张量。接着,我们使用模型对图像进行预测,并从预测结果中获取边界框、类别标签和置信度。最后,我们在原图像上绘制预测结果,并显示绘制结果。

需要注意的是,为了运行上述代码,需要先安装好 PyTorch 和 OpenCV 库。此外,为了使代码更加简洁和易于理解,上述代码并未对边界框进行非极大值抑制(NMS)处理,实际使用中需要根据具体情况进行适当调整。
 

  • 1
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值