目 录
摘 要 1
1 理论基础 2
1.1 传统的人群计数算法[1] 3
1.1.1 基于检测的方法 3
1.1.2 基于轨迹聚类的方法 3
1.1.3 基于回归的方法 3
1.2 基于深度学习的人群计数算法 4
1.2.1 YOLO v3 目标检测算法[2] 4
1.2.2 MCNN 人群计数算法[3] 5
1.2.3 LSC-CNN 人群计数算法[4] 5
1.2.4 视觉语言联合预训练的 12-in-1 模型[5] 6
2 实验结果及分析 8
2.1 YOLO v3 目标检测算法 9
2.1.1 低密度人群 9
2.1.2 高密度人群 9
2.2 MCNN 人群计数算法 9
2.2.1 低密度人群 9
2.2.2 高密度人群 10
2.3 LSC-CNN 人群计数算法 10
2.3.1 低密度人群 10
2.3.2 高密度人群 11
2.4 视觉语言联合预训练的 12-in-1 模型 11
2.4.1 低密度人群 11
2.4.2 高密度人群 10
3 实验总结 11
参考文献 13
3实验总结
本次实验中,我选用了基于目标检测的 YOLO v3 模型,基于多列卷积神经网络的
MCNN 模型,利用检测方法进行人群计数的 LSC-CNN 模型,以及多任务的视觉语言联合预训练的 12-in-1 模型,分别对低密度人群和高密度人群两段监测视频进行了人数统计实验。
从实现效果来看,YOLO v3 由于是目标检测的算法,所以在目标不是很多的低密度人群的计数任务中表现效果很好,但是在高密度人群计数中表现不佳,仅能检测出30-50 个目标,和实际相差太多。而 MCNN 模型作为较早的基于深度学习的人群计数算法,尽管在低密度人群计数中表现不如 YOLO v3,但是在高密度人群计数中效果要明显优于前者,不过却存在计数过多的问题。之后我还使用了较新的 LSC-CNN 模型进行了实验,该模型利用检测方法进行人群计数,在低密度人群计数中表现效果同样不好,但是在高密度人群计数中相较于 MCNN 模型有了一定的提高,不过检测效果受参数 NMS threshold 影响较大。本文转载自http://www.biyezuopin.vip/onews.asp?id=15259最后,我还使用了一个视觉语言联合预训练的 12-in-1 模型,将人群计数视为视觉问答 (VQA) 任务,输入监测视频的帧图像和问题“How many people are there in the picture?”来获得图像中的人数,该模型在低密度人群计数中表现不错,但是由于训练集和模型本身的限制无法处理高密度人群计数问题。
总的来说,通过这次实验,无论是从理论还是实践上都加深了我对视频人群计数的理解,帮助我对智能视频分析这门课程有了更深一步的了解。
import cv2
import os
import argparse
def video_to_images(input_video, save_dir):
if not os.path.exists(save_dir):
os.mkdir(save_dir)
vidcap = cv2.VideoCapture(input_video)
success,image = vidcap.read()
cv2.imwrite(save_dir + '/IMG_1.jpg', image)
count = 2
success = True
while success:
success,image = vidcap.read()
if image is None:
break
path = save_dir + '/IMG_' + str(count) + ".jpg"
print(path)
cv2.imwrite(path, image) # save frame as JPEG file
if cv2.waitKey(10) == 27:
break
count += 1
def images_to_video(args,frame_dir,output_video):
fps = 30 # 帧率
img_array = []
img_width = args.frame_width # 根据帧图像的大小进行修改
img_height = args.frame_height # 根据帧图像的大小进行修改
imdir = sorted(os.listdir(frame_dir))
imdir.sort(key=lambda x: int(x.split('.')[0][4:]))
print(len(imdir))
for idx in range(len(imdir)):
imgname = frame_dir + '/' + imdir[idx]
#print(imgname)
img = cv2.imread(imgname)
#cv2.imshow('img', img)
#cv2.waitKey(0)
img_array.append(img)
fourcc = cv2.VideoWriter_fourcc(*'XVID')
print(fourcc)
out = cv2.VideoWriter(output_video, fourcc, fps,(img_width,img_height))
for i in range(len(img_array)):
out.write(img_array[i])
out.release()
cv2.destroyAllWindows()
def main():
parser = argparse.ArgumentParser()
## Required parameters
parser.add_argument("--frame_dir", default=None, type=str,
help="The dir which saves frames")
parser.add_argument("--input_video", default=None, type=str,
help="The path of the input video")
parser.add_argument("--output_video", default=None, type=str,
help="The path of the output video")
parser.add_argument("--frame_width", type=int, default=720,
help="The width of frames")
parser.add_argument("--frame_height", type=int, default=576,
help="The height of frames")
parser.add_argument("--v2i", default=False, type=bool,
help="video_to_images:True")
parser.add_argument("--i2v", default=False, type=bool,
help="images_to_video:True")
args = parser.parse_args()
if args.v2i:
video_to_images(input_video=args.input_video, save_dir=args.frame_dir)
if args.i2v:
images_to_video(args, frame_dir=args.frame_dir, output_video=args.output_video)
if __name__ == "__main__":
main()
# python SplitCombine.py --frame_dir F:/SJTU_VideoAnalysis/frames --input_video F:/SJTU_VideoAnalysis/input_video/demo.avi --v2i True
# python SplitCombine.py --frame_dir F:/SJTU_VideoAnalysis/output_frames --output_video F:/SJTU_VideoAnalysis/output_video/demo_output.avi --i2v True