前言
参考:
从视频中提取图片:如何将视频逐帧提取成为一张张图片?
图片重命名:python文件批量改名
制作数据集:睿智的目标检测12——使用labeling进行目标检测数据集标注
批量修改标签名称:如何批量修改Pascal VOC数据集中xml标签中的标签名称
拍摄视频并提取图片
拍摄视频
getvedio.py
'''
python 录制mp4视频 by 郑瑞国
'''
import numpy as np
import cv2
cap = cv2.VideoCapture(0)
## some videowriter props
sz = (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)),
int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
fps = 20
# fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
# fourcc = cv2.VideoWriter_fourcc('m', 'p', 'e', 'g')
fourcc = cv2.VideoWriter_fourcc(*'mpeg')
## open and set props
out = cv2.VideoWriter()
out.open('getvedio/16.mp4', fourcc, fps, sz, True)
while (True):
ret, frame = cap.read()
out.write(frame)
cv2.imshow('frame', frame)
if cv2.waitKey(1) & 0xff == ord('q'):
break
out.release()
cap.release()
cv2.destroyAllWindows()
提取图片
方法1:视频帧差法提取图片
frame_extract.py
# -*- coding: utf-8 -*-
import cv2
import numpy as np
import os
import urllib
def frame_difference(frame1, frame2): #求取侦差
# f1, f2
f1 = cv2.resize(frame1, (416, 416))
f2 = cv2.resize(frame2, (416, 416))
f1 = cv2.cvtColor(f1, cv2.COLOR_BGR2GRAY)
f2 = cv2.cvtColor(f2, cv2.COLOR_BGR2GRAY) # 灰度化
f1 = cv2.threshold(f1, 128, 255, cv2.THRESH_BINARY)[1] # 二值化
f2 = cv2.threshold(f2, 128, 255, cv2.THRESH_BINARY)[1]
diff = cv2.absdiff(f1, f2) #求取差值
p = cv2.countNonZero(diff) / float(416 * 416)
return p
if __name__ == "__main__":
root = r'F:\0-0\Myyolo\vedio_img\getvedio'
threshold = 0.09 #阙值
frame_interval = 15 #帧间隔
save_root = r'F:\0-0\Myyolo\vedio_img\getvedio\img'
for c, path in enumerate(os.listdir(root)):
path = os.path.join(root, path)
video = cv2.VideoCapture(path)
count = 0
st, frame1 = video.read() #st,frame是获cv2.VideoCapture.read()方法的两个返回值。
st, frame2 = video.read() #其中st是布尔值,如果读取帧是正确的则返回True,如果文件读取到结尾,它的返回值就为False。frame就是每一帧的图像,是个三维矩阵。
while st:
if count % frame_interval == 0:
st, frame2 = video.read()
p = frame_difference(frame1, frame2) #求取侦差
print(p)
if p > threshold:
save_dir = os.path.join(save_root, os.path.splitext(os.path.basename(path))[0])
if not os.path.exists(save_dir): #如果目录不存在
os.makedirs(save_dir) #创建目录
print(save_dir)
#cv2.imencode(os.path.join(save_dir, str(count)+'.jpg'), frame1)
#cv2.imencode(str(count)+'.jpg', frame1)[1].tofile(save_dir)
cv2.imwrite(os.path.join(save_dir, str(count) + '.jpg'), frame1)
print('保存图片')
frame1 = frame2
st, frame2 = video.read()
count += 1
if st:
cv2.imshow("video%d"%c, frame2) #函数可以在窗口中显示图像。该窗口和图像的原始大小自适应(自动调整到原始尺寸)。
cv2.waitKey(100) #是一个和键盘绑定的函数,它的作用是等待一个键盘的输入(因为我们创建的图片窗口如果没有这个函数的话会闪一下就消失了,所以如果需要让它持久输出,我们可以使用该函数)。它的参数是毫秒级。该函数等待任何键盘事件的指定毫秒。如果您在此期间按下任何键,程序将继续进行。我们也可以将其设置为一个特定的键。
video.release() #发布软件资源 / 释放硬件资源
cv2.destroyAllWindows() #销毁我们创建的所有窗口。如果要销毁任何特定窗口,请使用函数cv2.destroyWindow(),其中传递确切的窗口名称作为参数。(应该是使用创建窗口时所使用的窗口名称,字符串类型。)
print("video%d"%c, "done!")
方法2:定时从视频截图
使用img_extract.py
# 每隔 多少 秒 提取视频中的图片到文件夹
# This is a sample Python script.
# Press Shift+F10 to execute it or replace it with your code.
# Press Double Shift to search everywhere for classes, files, tool windows, actions, and settings.
def print_hi(name):
# Use a breakpoint in the code line below to debug your script.
print(f'Hi, {name}') # Press Ctrl+F8 to toggle the breakpoint.
# Press the green button in the gutter to run the script.
if __name__ == '__main__':
print_hi('PyCharm')
# See PyCharm help at https://www.jetbrains.com/help/pycharm/
# -*- coding: utf-8 -*-
import os
import cv2 ##加载OpenCV模块
def video2frames(pathIn: object = '',
pathOut: object = '',
only_output_video_info: object = False,
extract_time_points: object = None,
initial_extract_time: object = 0,
end_extract_time: object = None,
extract_time_interval: object = -1,
output_prefix: object = 'frame',
jpg_quality: object = 100,
isColor: object = True) -> object:
'''
pathIn:视频的路径,比如:F:\python_tutorials\test.mp4
pathOut:设定提取的图片保存在哪个文件夹下,比如:F:\python_tutorials\frames1\。如果该文件夹不存在,函数将自动创建它
only_output_video_info:如果为True,只输出视频信息(长度、帧数和帧率),不提取图片
extract_time_points:提取的时间点,单位为秒,为元组数据,比如,(2, 3, 5)表示只提取视频第2秒, 第3秒,第5秒图片
initial_extract_time:提取的起始时刻,单位为秒,默认为0(即从视频最开始提取)
end_extract_time:提取的终止时刻,单位为秒,默认为None(即视频终点)
extract_time_interval:提取的时间间隔,单位为秒,默认为-1(即输出时间范围内的所有帧)
output_prefix:图片的前缀名,默认为frame,图片的名称将为frame_000001.jpg、frame_000002.jpg、frame_000003.jpg......
jpg_quality:设置图片质量,范围为0到100,默认为100(质量最佳)
isColor:如果为False,输出的将是黑白图片
'''
cap = cv2.VideoCapture(pathIn) ##打开视频文件
n_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) ##视频的帧数
fps = cap.get(cv2.CAP_PROP_FPS) ##视频的帧率
dur = n_frames/fps ##视频的时间
##如果only_output_video_info=True, 只输出视频信息,不提取图片
if only_output_video_info:
print('only output the video information (without extract frames)::::::')
print("Duration of the video: {} seconds".format(dur))
print("Number of frames: {}".format(n_frames))
print("Frames per second (FPS): {}".format(fps))
##提取特定时间点图片
elif extract_time_points is not None:
if max(extract_time_points) > dur: ##判断时间点是否符合要求
raise NameError('the max time point is larger than the video duration....')
try:
os.mkdir(pathOut)
except OSError:
pass
success = True
count = 0
while success and count < len(extract_time_points):
cap.set(cv2.CAP_PROP_POS_MSEC, (1000*extract_time_points[count]))
success,image = cap.read()
if success:
if not isColor:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) ##转化为黑白图片
print('Write a new frame: {}, {}th'.format(success, count+1))
cv2.imwrite(os.path.join(pathOut, "{}_{:06d}.jpg".format(output_prefix, count+1)), image, [int(cv2.IMWRITE_JPEG_QUALITY), jpg_quality]) # save frame as JPEG file
count = count + 1
else:
##判断起始时间、终止时间参数是否符合要求
if initial_extract_time > dur:
raise NameError('initial extract time is larger than the video duration....')
if end_extract_time is not None:
if end_extract_time > dur:
raise NameError('end extract time is larger than the video duration....')
if initial_extract_time > end_extract_time:
raise NameError('end extract time is less than the initial extract time....')
##时间范围内的每帧图片都输出
if extract_time_interval == -1:
if initial_extract_time > 0:
cap.set(cv2.CAP_PROP_POS_MSEC, (1000*initial_extract_time))
try:
os.mkdir(pathOut)
except OSError:
pass
print('Converting a video into frames......')
if end_extract_time is not None:
N = (end_extract_time - initial_extract_time)*fps + 1
success = True
count = 0
while success and count < N:
success,image = cap.read()
if success:
if not isColor:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
print('Write a new frame: {}, {}/{}'.format(success, count+1, n_frames))
cv2.imwrite(os.path.join(pathOut, "{}_{:06d}.jpg".format(output_prefix, count+1)), image, [int(cv2.IMWRITE_JPEG_QUALITY), jpg_quality]) # save frame as JPEG file
count = count + 1
else:
success = True
count = 0
while success:
success,image = cap.read()
if success:
if not isColor:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
print('Write a new frame: {}, {}/{}'.format(success, count+1, n_frames))
cv2.imwrite(os.path.join(pathOut, "{}_{:06d}.jpg".format(output_prefix, count+1)), image, [int(cv2.IMWRITE_JPEG_QUALITY), jpg_quality]) # save frame as JPEG file
count = count + 1
##判断提取时间间隔设置是否符合要求
elif extract_time_interval > 0 and extract_time_interval < 1/fps:
raise NameError('extract_time_interval is less than the frame time interval....')
elif extract_time_interval > (n_frames/fps):
raise NameError('extract_time_interval is larger than the duration of the video....')
##时间范围内每隔一段时间输出一张图片
else:
try:
os.mkdir(pathOut)
except OSError:
pass
print('Converting a video into frames......')
if end_extract_time is not None:
N = (end_extract_time - initial_extract_time)/extract_time_interval + 1
success = True
count = 0
while success and count < N:
cap.set(cv2.CAP_PROP_POS_MSEC, (1000*initial_extract_time+count*1000*extract_time_interval))
success,image = cap.read()
if success:
if not isColor:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
print('Write a new frame: {}, {}th'.format(success, count+1))
cv2.imwrite(os.path.join(pathOut, "{}_{:06d}.jpg".format(output_prefix, count+1)), image, [int(cv2.IMWRITE_JPEG_QUALITY), jpg_quality]) # save frame as JPEG file
count = count + 1
else:
success = True
count = 0
while success:
cap.set(cv2.CAP_PROP_POS_MSEC, (1000*initial_extract_time+count*1000*extract_time_interval))
success,image = cap.read()
if success:
if not isColor:
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
print('Write a new frame: {}, {}th'.format(success, count+1))
cv2.imwrite(os.path.join(pathOut, "{}_{:06d}.jpg".format(output_prefix, count+1)), image, [int(cv2.IMWRITE_JPEG_QUALITY), jpg_quality]) # save frame as JPEG file
count = count + 1
##### 测试
# pathIn = 'pathIn/1.1.avi'
# video2frames(pathIn, only_output_video_info = True) #只输出视频信息(长度、帧数和帧率),不提取图片
#
# pathOut = './frames1/'
# video2frames(pathIn, pathOut)
#
# pathOut = './frames2'
# video2frames(pathIn, pathOut, extract_time_points=(1, 2, 5)) #提取的时间点,单位为秒,为元组数据,比如,(2, 3, 5)表示只提取视频第2秒, 第3秒,第5秒图片
#
# pathOut = './frames3'
# video2frames(pathIn, pathOut,
# initial_extract_time=1, #提取的起始时刻,单位为秒,默认为0(即从视频最开始提取)
# end_extract_time=3, #提取的终止时刻,单位为秒,默认为None(即视频终点)
# extract_time_interval = 0.5) #提取的时间间隔,单位为秒,默认为-1(即输出时间范围内的所有帧)
#
# pathOut = './frames4/'
# video2frames(pathIn, pathOut, extract_time_points=(0.3, 2), isColor = False) #isColor:如果为False,输出的将是黑白图片
#
#
# pathOut = './frames5/'
# video2frames(pathIn, pathOut, extract_time_points=(0.3, 2), jpg_quality=50) #jpg_quality:设置图片质量,范围为0到100,默认为100(质量最佳)
#输出
# pathIn = 'pathIn/1.1.avi'
pathIn = '0'
pathOut = 'pathOut/1/'
video2frames(pathIn, pathOut, extract_time_interval = 5, jpg_quality=100)
整理文件并重命名
先设置文件夹名称,再用img_rename.py
import os
#将多个文件夹文件调到一个文件里面,并重命名
m = 0 # 文件夹名称
#for i in range(1,15): #对14个文件夹中的 图片 调用到一个文件夹中
for i in range(1,2):
m = 15
m += 1
# 输入路径
# path = input('请输入文件路径(结尾加上/):')
path = 'getvedio/img/' + str(m) + '/'
# 输出路径
path2 = 'getvedio/img_rename/'
# 获取该目录下所有文件,存入列表中
f = os.listdir(path)
#重命名
n = 1
for i in f:
# 设置旧文件名(就是路径+文件名)
oldname = path + f[n - 1]
# 设置新文件名
newname = path2 +str(m) + '_' + str(n) + '.JPG'
# 用os模块中的rename方法对文件改名
os.renames(oldname, newname)
print(oldname, '======>', newname)
n += 1
# #
# m = 1
# n = 1
# #输入路径
# # path = input('请输入文件路径(结尾加上/):')
# path = 'img_pre/' + str(m) + '/'
# #输出路径
# path2 = 'img_ed/'
# # 获取该目录下所有文件,存入列表中
# f = os.listdir(path)
#
# for i in f:
# # 设置旧文件名(就是路径+文件名)
# oldname = path + f[n - 1]
#
# # 设置新文件名
# newname = path2 + str(n) + '.JPG'
#
# # 用os模块中的rename方法对文件改名
# os.renames(oldname, newname)
# print(oldname, '======>', newname)
# n += 1
数据集制作
labelimg的安装及使用
- 安装及启动
安装:
pip install labelimg
启动命令:
labelimg
- 标记图片
JPEGimages储存原图片
数据集(.xml文件 )保存至 Annotations
然后 复制到 VOCdevkit/VOC2007 文件夹中。
批量修改标签名称
运行xml_rename.py
import os
import xml.etree.ElementTree as ET
#程序功能:批量修改VOC数据集中xml标签文件的标签名称
def changelabelname(inputpath):
listdir = os.listdir(inputpath)
for file in listdir:
if file.endswith('xml'):
file = os.path.join(inputpath,file)
tree = ET.parse(file)
root = tree.getroot()
for object1 in root.findall('object'):
for sku in object1.findall('name'): #查找需要修改的名称
if (sku.text == 'preName'): #‘preName’为修改前的名称
sku.text = 'TESTNAME' #‘TESTNAME’为修改后的名称
tree.write(file,encoding='utf-8') #写进原始的xml文件并避免原始xml中文字符乱码
else:
pass
else:
pass
if __name__ == '__main__':
inputpath = 'E:/Research/Dataset/Test/Annotations' #此处替换为自己的路径
changelabelname(inputpath)