Day 11 - 视频转换成图片
今天要完成的工作是将搜集到的视频或是照片转换成 YOLOV3 可以接受的格式,所以要完成的工作如下:
- 建立目录结构
- 安装需要的套件
- 撰写程式
- 读写目录
- 视频转图片
- 变更尺寸为608
建立目录结构
将 github 上所下载的视频放在 video 文件夹,而 utils 文件夹放资料预处理的程式,如今天需要用到的将视频转成图片,images 用来放处理后的图片,labels 是用来存放标签文件,如下图所示。
图 1、 YOLOV3 资料预处理文件夹
安装需要的套件
将影片转换成图片的程式中需要用到 OpenCV 套件,所以需要安装 OpenCV。打开终端机,输入以下指令进行安装。
pip3 install opencv-python
python3
进入 Python 的交互画面,输入以下指令,确认是否可以正常使用 OpenCV,如果无法正常使用,那代表系统中安装多个 Python 版本,而环境变数 PYTHONPATH 没有设定正确,以至于进行汇入 (import) 时,会无法汇入 cv2,可以透过 sys.path 这个 Python 语法检查目前的设定。
import cv2
cv2.__version__
import sys
sys.path
下图是安装与确认画面,第一个方框显示套件下载的网站,第二个是套件所安装的目录,第三个方框是安装套件以及版本名称,第四个方框则是进入 Python 交互模式,第五个方框则是运行 Python 语法。
图 2、OpenCV 安装与汇入画面
撰写程式
撰写这个程式主要需考虑以下三点
- 读写目录:指定输入 (video) 与输出目录 (images)
- 视频转图片: 使用 openCV 进行转换,因为拍摄时时每秒 30 张,但这样的图片变化太少,所以是每 5 张图片取一张。
- 变更尺寸: YOLOV3 可以自行在 cfg 档中设定输入图片的尺寸,预设 416×416 、608×608 或任何大于 32 的 2 次方倍数尺寸,在尺寸的缩放上还需要注意的是长宽比,因为大多数的照片的是矩型,但 YOLOV3 接受的却是正方形,所以必须要针对长宽不足的地方进行处理,我们这边是直接填 0 ,也就是黑色。
import cv2
import glob
import os
# 变更到指定尺寸,长宽边不足者补黑色
def process_image(img, min_side = 608):
size = img.shape
h, w = size[0], size[1]
scale = max(w, h) / float(min_side)
new_w, new_h = int(w/scale), int(h/scale)
resize_img = cv2.resize(img, (new_w, new_h),cv2.INTER_AREA) # 变更尺寸
if new_w % 2 != 0 and new_h % 2 == 0:
top, bottom, left, right = (min_side-new_h)//2, (min_side-new_h)//2, (min_side-new_w)//2 + 1, (min_side-new_w)//2
elif new_h % 2 != 0 and new_w % 2 == 0:
top, bottom, left, right = (min_side-new_h)//2 + 1, (min_side-new_h)//2, (min_side-new_w)//2, (min_side-new_w)//2
elif new_h % 2 == 0 and new_w % 2 == 0:
top, bottom, left, right = (min_side-new_h)//2, (min_side-new_h)//2, (min_side-new_w)//2, (min_side-new_w)//2
else:
top, bottom, left, right = (min_side-new_h)//2 + 1, (min_side-new_h)//2, (min_side-new_w)//2 + 1, (min_side-new_w)//2
pad_img = cv2.copyMakeBorder(resize_img, top, bottom, left, right, cv2.BORDER_CONSTANT, value=[0,0,0])
return pad_img
# 读写目录
inputPath = '../video'
outputPath = '../images'
files = os.path.join(inputPath,'*.mp4')
files_grabbed = []
files_grabbed.extend(sorted(glob.iglob(files)))
for videoId in range(len(files_grabbed)):
print(files_grabbed[videoId])
raw = cv2.VideoCapture(files_grabbed[videoId])
fIndex = 1
fCount = 0
while 1:
# 视频转图片
ret,frame = raw.read()
fCount += 1
if (ret == True) :
if (fCount % 5) == 0:
img_pad = process_image(frame, min_side = 608)
cv2.imwrite('%s/%02d-frame-608x608-%04d.jpg' % (outputPath, videoId,fIndex), img_pad)
fIndex += 1
else:
break
下图显示在 VS Code 中的运行结果,显示处理了 video 目录下的三个视频,记得这个顺序很重要,因为会给予编号,第一个档案编号为 00 ,以此类推。
图 3、在 VS Code 中的运行结果
下图显示 images 文件夹内的图片讯息,00-frame-608x608-0036.jpg 表示的是标号为00 (黄金珍珠虎), frame-608x608 表示图片的尺寸,而 0036 则是第几张图片,从图片资讯中也的确看到这样的讯息,并且上下被填入黑色框。
图 4、处理完的图片
下图是原始的视频资讯,尺寸为 960x540 且长宽比为 16:9 ,每秒的祯片为 30。
图 5、原始视频资讯
参考资料
- python opencv 读取mov文件, https://blog.csdn.net/CAIYUNFREEDOM/article/details/100925882
- Python - Extracting and Saving Video Frames,https://stackoverflow.com/questions/33311153/
- OpenCV 擷取網路攝影機串流影像,處理並寫入影片檔案教學, https://blog.gtwang.org/programming/opencv-webcam-video-capture-and-file-write-tutorial/
- python/cv2对长方形图像进行等比例缩放及对周围常数值(0)填充zero padding, https://blog.csdn.net/u010397980/article/details/84889093
- 使用opencv對圖像進行crop,resize,pad, https://www.twblogs.net/a/5b80eccb2b71772165aa2307
- Environment variables,https://docs.python.org/3/using/cmdline.html?highlight=pythonpath#envvar-PYTHONPATH