Advertisement

(4-8)目标跟踪:基于OpenCV的行人检测系统(2)

阅读量:

(11)导入CSV文件mot_labels.csv后,在对其标签数据进行系统性分析和优化的基础上,在resultant DataFrame中新增了一列命名为 video_frame。The following steps were taken: 1) import the CSV file mot_labels.csv; 2) conduct a comprehensive analysis and optimization on the label data; 3) add a new column named video_frame to the resulting DataFrame. The resulting DataFrame now includes a new column named video_frame, which records the number of frames obtained through specific conversion techniques.

复制代码
 labels = pd.read_csv('../input/driving-video-with-object-tracking/mot_labels.csv',

    
                  low_memory=False)
    
 video_labels = (
    
     labels.query('videoName == "026c7465-309f6d33"').reset_index(drop=True).copy()
    
 )
    
 video_labels["video_frame"] = (video_labels["frameIndex"] * 11.9).round().astype("int")

通过 Pandas 的 value_counts() 方法对 'category' 列中的不同值进行计算并获取其出现次数的具体实现方式如下所示

复制代码
    video_labels["category"].value_counts()

执行后会输出:

复制代码
 car              3030

    
 pedestrian        847
    
 bicycle           381
    
 rider             320
    
 truck             194
    
 other vehicle     115
    
 bus               109
    
 other person       74
    
 motorcycle         67
    
 trailer            34
    
 Name: category, dtype: int64

通过调用OpenCV库打开指定视频文件,并在获取每帧图像的过程中对每个捕获到的帧进行编号记录。当当前处理到第1035个捕获帧时(或若当前处理到第1035个捕获帧时),将退出处理过程并释放开发出的对象

复制代码
 cap = cv2.VideoCapture("026c7465-309f6d33.mp4")

    
 n_frames = int(cap.get(cv2.cv2.CAP_PROP_FRAME_COUNT))
    
  
    
 img_idx = 0
    
 for frame in range(n_frames):
    
     ret, img = cap.read()
    
     if ret == False:
    
     break
    
     if frame == 1035:
    
     break
    
 cap.release()

(14)调用函数display_cv2_img(img) ,在 Matplotlib 中显示 OpenCV 图像。

复制代码
    display_cv2_img(img)

执行后的效果如图4-8所示。

图4-8 显示的OpenCV图像

根据以下代码创建对象img_example:它是img的一个拷贝,在第1035帧的位置添加了矩形框。这些矩形框的信息源自视频标签数据框。随后调用之前的display_cv2_img函数以展示带有这些矩形框的图像。

复制代码
 img_example = img.copy()

    
 frame_labels = video_labels.query('video_frame == 1035')
    
 for i, d in frame_labels.iterrows():
    
     pt1 = int(d['box2d.x1']), int(d['box2d.y1'])
    
     pt2 = int(d['box2d.x2']), int(d['box2d.y2'])
    
     cv2.rectangle(img_example, pt1, pt2, (0, 0, 255), 3)
    
  
    
 display_cv2_img(img_example)

执行后的效果如图4-8所示。

图4-8 绘制的带有矩形框的图像

基于分类目标的不同需求,在矩形框上赋予每个类别独特的色彩标记。这些色彩信息由预先设定好的color_map参数获取。

复制代码
 color_map = {

    
     "car": (0, 0, 255),
    
     "truck": (0, 0, 100),
    
     "pedestrian": (255, 0, 0),
    
     "other vehicle": (0, 0, 150),
    
     "rider": (200, 0, 0),
    
     "bicycle": (0, 255, 0),
    
     "other person": (200, 0, 0),
    
     "trailer": (0, 150, 150),
    
     "motorcycle": (0, 150, 0),
    
     "bus": (0, 0, 100),
    
 }
    
  
    
 img_example = img.copy()
    
 frame_labels = video_labels.query('video_frame == 1035')
    
 for i, d in frame_labels.iterrows():
    
     pt1 = int(d['box2d.x1']), int(d['box2d.y1'])
    
     pt2 = int(d['box2d.x2']), int(d['box2d.y2'])
    
     color = color_map[d['category']]
    
     cv2.rectangle(img_example, pt1, pt2, color, 3)
    
  
    
 display_cv2_img(img_example)

在上述代码中:

  • 目标类别被color_map对应到相应颜色。
  • 循环负责根据目标类别选择相应的颜色,并用cv2.rectangle绘制矩形框。
  • 通过这种操作, 不同类别被不同颜色标注.
    执行效果如图4-8所示.

图4-8 识别行人

为所有目标框顶端左侧区域标注类别信息,并通过调用OpenCV库中的cv2.putText函数实现了对这些区域的文字标记

复制代码
 frame_labels = video_labels.query("video_frame == @frame")

    
 font = cv2.FONT_HERSHEY_TRIPLEX
    
 img_example = img.copy()
    
 for i, d in frame_labels.iterrows():
    
     pt1 = int(d["box2d.x1"]), int(d["box2d.y1"])
    
     pt2 = int(d["box2d.x2"]), int(d["box2d.y2"])
    
     color = color_map[d["category"]]
    
     img_example = cv2.rectangle(img_example, pt1, pt2, color, 3)
    
     pt_text = int(d["box2d.x1"]) + 5, int(d["box2d.y1"] + 10)
    
     img_example = cv2.putText(img_example, d["category"], pt_text, font, 0.5, color)
    
 display_cv2_img(img_example)
    
 cap.release()

在上述代码中,OpenCV的text函数用于将文字标注在图像上。通过pt_text参数确定了文字的放置位置,在矩形框左上角显示目标类别名称(如图4-8所示)。

图4-8 在行人上写标签

(18)如下的代码段定义了一个名为 add_annotations 的函数。该函数接收三个参数:图像 img、帧索引 frame 以及包含标签的数据框 video_labels。其主要功能是将指定帧索引对应的标签信息叠加在图像上,并返回处理后的结果图像。

复制代码
 def add_annotations(img, frame, video_labels):

    
     max_frame = video_labels.query("video_frame <= @frame")["video_frame"].max()
    
     frame_labels = video_labels.query("video_frame == @max_frame")
    
     for i, d in frame_labels.iterrows():
    
     pt1 = int(d["box2d.x1"]), int(d["box2d.y1"])
    
     pt2 = int(d["box2d.x2"]), int(d["box2d.y2"])
    
     color = color_map[d["category"]]
    
     img = cv2.rectangle(img, pt1, pt2, color, 3)
    
     return img

该Unix/Linux指令用于移除文件或目录,在该指令中,-r参数表示递归移除,而out_test.mp4即为需要被移除的文件或目录名称。

复制代码
    !rm -r out_test.mp4

通过 OpenCV 构建一个视频写入器工具(cv2.VideoWriter),按帧输出带标签的图像序列至指定输出视频文件 "out_test.mp4"。

复制代码
 VIDEO_CODEC = "mp4v"

    
 fps = 59.94
    
 width = 1280
    
 height = 720
    
 out = cv2.VideoWriter("out_test.mp4",
    
             cv2.VideoWriter_fourcc(*VIDEO_CODEC),
    
             fps,
    
             (width, height))
    
  
    
 cap = cv2.VideoCapture("026c7465-309f6d33.mp4")
    
 n_frames = int(cap.get(cv2.cv2.CAP_PROP_FRAME_COUNT))
    
  
    
 for frame in tqdm(range(n_frames), total=n_frames):
    
     ret, img = cap.read()
    
     if ret == False:
    
     break
    
     img = add_annotations(img, frame, video_labels)
    
     out.write(img)
    
 out.release()
    
 cap.release()

在上述代码中,在初始化阶段使用cv2.VideoWriter实例化了一个视频写入器,并配置了指定的编解码算法、帧率以及输出分辨率参数。随后系统会遍历获取原始视频中的每帧图像块,并将这些图像块传递给add_annotations函数以完成标签注释的附加工作。整个流程结束后会执行资源管理步骤以释放该视频写入器以及用于处理原始输入流的对象资源。

通过执行以下Unix/Linux命令来获取所需的信息,并提供完整的相关信息

复制代码
    !ls -GFlash -color

执行后会输出:

复制代码
 total 91M

    
  72M -rw-r--r-- 1 root  72M Jun 13 01:53 out_test.mp4
    
 6.1M ---------- 1 root 6.1M Jun 13 01:53 __notebook__.ipynb
    
  14M -rw-r--r-- 1 root  14M Jun 13 01:52 026c7465-309f6d33.mp4
    
 4.0K drwxr-xr-x 6 root 4.0K Jun 13 01:51 ../
    
 4.0K drwxr-xr-x 2 root 4.0K Jun 13 01:52 ./

通过subprocess.run执行FFmpeg工具,并对生成的视频文件实施了缩减和重新编码处理。

复制代码
 tmp_output_path = "out_test.mp4"

    
 output_path = "out_test_compressed.mp4"
    
  
    
 subprocess.run(
    
     [
    
     "ffmpeg",               # FFmpeg 命令
    
     "-i",                   # 输入文件
    
     tmp_output_path,        # 输入文件路径
    
     "-crf",                 # 指定压缩质量(Constant Rate Factor),值越小质量越高
    
     "18",                   # 压缩质量参数
    
     "-preset",              # 编码速度预设
    
     "veryfast",             # 预设为 veryfast,表示速度较快
    
     "-vcodec",              # 指定视频编码器
    
     "libx264",              # 使用 libx264 编码器
    
     output_path,            # 输出文件路径
    
     '-loglevel',            # 设置日志级别
    
     'quiet'                 # 静默模式,减少输出信息
    
     ]
    
 )

执行后会输出:

复制代码
    CompletedProcess(args=['ffmpeg', '-i', 'out_test.mp4', '-crf', '18', '-preset', 'veryfast', '-vcodec', 'libx264', 'out_test_compressed.mp4', '-loglevel', 'quiet'], returncode=0)

请使用以下命令列出当前目录下的文件及子目录,并显示其详细信息如文件大小、权限设置及创建时间等。

复制代码
    !ls -GFlash --color

执行后会输出:

复制代码
 total 120M

    
 4.0K drwxr-xr-x 2 root 4.0K Jun 13 01:53 ./
    
 4.0K drwxr-xr-x 6 root 4.0K Jun 13 01:51 ../
    
  14M -rw-r--r-- 1 root  14M Jun 13 01:52 026c7465-309f6d33.mp4
    
 6.1M ---------- 1 root 6.1M Jun 13 01:53 __notebook__.ipynb
    
  72M -rw-r--r-- 1 root  72M Jun 13 01:53 out_test.mp4
    
  29M -rw-r--r-- 1 root  29M Jun 13 01:53 out_test_compressed.mp4

(24)使用 ipd.Video 显示压缩后的视频文件,展示出检测出的行人。

复制代码
    ipd.Video('out_test_compressed.mp4', width=600)

执行后在视频中显示展示出检测出的行人,如图4-8所示。

图4-8 检测出视频中的行人

全部评论 (0)

还没有任何评论哟~