2022-01-02 15:46:29 +08:00
|
|
|
|
# OpenCV Webcam Script v0.2
|
2021-12-29 10:51:27 +08:00
|
|
|
|
# 创建人:曾逸夫
|
2022-01-02 15:46:29 +08:00
|
|
|
|
# 创建时间:2022-01-02
|
2021-12-29 10:51:27 +08:00
|
|
|
|
|
|
|
|
|
import cv2
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
import argparse
|
|
|
|
|
import time
|
|
|
|
|
import os
|
|
|
|
|
import glob
|
|
|
|
|
import re
|
|
|
|
|
import os
|
|
|
|
|
|
2022-01-02 15:46:29 +08:00
|
|
|
|
|
|
|
|
|
def parse_args(known=False):
|
|
|
|
|
parser = argparse.ArgumentParser(description='OpenCV Webcam Script')
|
|
|
|
|
parser.add_argument('--device', '-dev', default=0,
|
|
|
|
|
type=int, help='device index for webcam')
|
|
|
|
|
parser.add_argument('--quit', '-q', default="q",
|
|
|
|
|
type=str, help='quit key for webcam')
|
|
|
|
|
parser.add_argument('--is_autoSaveFrame', '-isasf',
|
|
|
|
|
action='store_true', help='is auto save frame')
|
|
|
|
|
parser.add_argument('--is_headSaveFrame', '-ishsf',
|
|
|
|
|
action='store_true', help='is head save frame')
|
|
|
|
|
parser.add_argument('--is_resizeFrame', '-isrf',
|
|
|
|
|
action='store_true', help='is resize frame')
|
|
|
|
|
parser.add_argument('--frame_saveDir', '-fsd',
|
|
|
|
|
default="./WebcamFrame", type=str, help='save frame dir')
|
|
|
|
|
parser.add_argument('--frame_nSave', '-fns', default=1,
|
|
|
|
|
type=int, help='n frames save a frame (auto save frame)')
|
|
|
|
|
parser.add_argument('--frame_capKey', '-fck', default="a",
|
|
|
|
|
type=str, help='frame capture key (head save frame)')
|
|
|
|
|
parser.add_argument('--resize_frame', '-rf',
|
|
|
|
|
default=[640, 480], type=int, nargs='+', help='resize frame save')
|
|
|
|
|
parser.add_argument('--resizeRatio_frame', '-rrf',
|
|
|
|
|
default=1.0, type=float, help='resize ratio frame save')
|
|
|
|
|
parser.add_argument('--frame_namePrefix', '-fnp',
|
|
|
|
|
default="frame", type=str, help='frame name prefix')
|
|
|
|
|
parser.add_argument('--frame_saveStyle', '-fss',
|
|
|
|
|
default="jpg", type=str, help='frame save style')
|
|
|
|
|
parser.add_argument('--jpg_quality', '-jq',
|
|
|
|
|
default=95, type=int, help='frame save jpg quality (0-100) default 95')
|
|
|
|
|
parser.add_argument('--png_quality', '-pq',
|
|
|
|
|
default=3, type=int, help='frame save jpg quality (0-9) default 3')
|
2022-01-02 20:50:06 +08:00
|
|
|
|
parser.add_argument('--pause', '-p',
|
|
|
|
|
default="p", type=str, help='webcam pause')
|
2022-01-02 15:46:29 +08:00
|
|
|
|
|
|
|
|
|
args = parser.parse_known_args()[0] if known else parser.parse_args()
|
|
|
|
|
return args
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# 保存路径管理
|
2021-12-29 10:51:27 +08:00
|
|
|
|
def increment_path(path, exist_ok=False, sep='', mkdir=False):
|
|
|
|
|
# 引用:https://github.com/ultralytics/yolov5/blob/master/utils/general.py
|
|
|
|
|
path = Path(path) # os-agnostic
|
|
|
|
|
if path.exists() and not exist_ok:
|
|
|
|
|
suffix = path.suffix
|
|
|
|
|
path = path.with_suffix('')
|
|
|
|
|
dirs = glob.glob(f"{path}{sep}*") # similar paths
|
|
|
|
|
matches = [re.search(rf"%s{sep}(\d+)" % path.stem, d) for d in dirs]
|
|
|
|
|
i = [int(m.groups()[0]) for m in matches if m] # indices
|
|
|
|
|
n = max(i) + 1 if i else 2 # increment number
|
|
|
|
|
path = Path(f"{path}{sep}{n}{suffix}") # update path
|
|
|
|
|
dir = path if path.suffix == '' else path.parent # directory
|
|
|
|
|
if not dir.exists() and mkdir:
|
|
|
|
|
dir.mkdir(parents=True, exist_ok=True) # make directory
|
|
|
|
|
return path
|
|
|
|
|
|
|
|
|
|
|
2022-01-02 19:02:56 +08:00
|
|
|
|
# 帧保存
|
|
|
|
|
def frame_opt(frame, frame_savePath, frame_num, is_resizeFrame, resize_frame, resizeRatio_frame,
|
|
|
|
|
frame_namePrefix, frame_saveStyle, jpg_quality, png_quality):
|
|
|
|
|
if (is_resizeFrame): # resize frame
|
|
|
|
|
w_resize = int(
|
|
|
|
|
resize_frame[0] * resizeRatio_frame) # 重塑宽度
|
|
|
|
|
h_resize = int(
|
|
|
|
|
resize_frame[1] * resizeRatio_frame) # 重塑高度
|
|
|
|
|
frame_new = cv2.resize(
|
|
|
|
|
frame, (w_resize, h_resize), interpolation=cv2.INTER_AREA) # 重塑
|
|
|
|
|
|
|
|
|
|
if (frame_saveStyle == 'jpg'):
|
|
|
|
|
cv2.imwrite(
|
|
|
|
|
f'./{frame_savePath}/{frame_namePrefix}-{frame_num}.{frame_saveStyle}', frame_new,
|
|
|
|
|
[int(cv2.IMWRITE_JPEG_QUALITY), jpg_quality])
|
|
|
|
|
elif (frame_saveStyle == 'png'):
|
|
|
|
|
cv2.imwrite(
|
|
|
|
|
f'./{frame_savePath}/{frame_namePrefix}-{frame_num}.{frame_saveStyle}', frame_new,
|
|
|
|
|
[int(cv2.IMWRITE_PNG_COMPRESSION), png_quality])
|
|
|
|
|
else:
|
|
|
|
|
print(f'帧格式有问题!')
|
|
|
|
|
return
|
|
|
|
|
else:
|
|
|
|
|
if (frame_saveStyle == 'jpg'):
|
|
|
|
|
cv2.imwrite(
|
|
|
|
|
f'./{frame_savePath}/{frame_namePrefix}-{frame_num}.{frame_saveStyle}', frame,
|
|
|
|
|
[int(cv2.IMWRITE_JPEG_QUALITY), jpg_quality])
|
|
|
|
|
elif (frame_saveStyle == 'png'):
|
|
|
|
|
cv2.imwrite(
|
|
|
|
|
f'./{frame_savePath}/{frame_namePrefix}-{frame_num}.{frame_saveStyle}', frame,
|
|
|
|
|
[int(cv2.IMWRITE_PNG_COMPRESSION), png_quality])
|
|
|
|
|
else:
|
|
|
|
|
print(f'帧格式有问题!')
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
|
2021-12-29 10:51:27 +08:00
|
|
|
|
# webcam opencv
|
2022-01-02 20:50:06 +08:00
|
|
|
|
def webcam_opencv(device_index, quit_key, pause_key, is_autoSaveFrame, frame_saveDir, frame_nSave, is_headSaveFrame,
|
2022-01-02 15:46:29 +08:00
|
|
|
|
frame_capKey, is_resizeFrame, resize_frame, resizeRatio_frame, frame_namePrefix, frame_saveStyle,
|
|
|
|
|
jpg_quality, png_quality):
|
|
|
|
|
if (quit_key == frame_capKey): # 判断快捷键冲突
|
|
|
|
|
print(f'快捷键冲突! 程序结束!')
|
|
|
|
|
return
|
|
|
|
|
|
|
|
|
|
s_time = time.time() # 起始时间
|
|
|
|
|
cap = cv2.VideoCapture(device_index) # 连接设备
|
|
|
|
|
frame_width = cap.get(3) # 宽度
|
|
|
|
|
frame_height = cap.get(4) # 高度
|
|
|
|
|
fps = cap.get(5) # 帧率
|
2021-12-29 10:51:27 +08:00
|
|
|
|
print(f'宽度:{frame_width}, 高度:{frame_height}, FPS:{fps}')
|
2022-01-02 15:46:29 +08:00
|
|
|
|
success, _ = cap.read() # 读取设备
|
2021-12-29 10:51:27 +08:00
|
|
|
|
|
|
|
|
|
if success:
|
|
|
|
|
print(f'摄像头连接成功!')
|
|
|
|
|
|
2022-01-02 19:02:56 +08:00
|
|
|
|
# 帧保存路径管理
|
2021-12-29 10:51:27 +08:00
|
|
|
|
if is_autoSaveFrame or is_headSaveFrame:
|
2022-01-02 19:02:56 +08:00
|
|
|
|
frame_savePath = increment_path(
|
2022-01-02 15:46:29 +08:00
|
|
|
|
Path(f"{frame_saveDir}") / "frames", exist_ok=False) # 增量运行
|
2022-01-02 19:02:56 +08:00
|
|
|
|
frame_savePath.mkdir(parents=True, exist_ok=True) # 创建目录
|
2022-01-02 15:46:29 +08:00
|
|
|
|
|
|
|
|
|
frame_num = 0 # 帧数
|
2021-12-29 10:51:27 +08:00
|
|
|
|
while(1):
|
2022-01-02 21:00:26 +08:00
|
|
|
|
wait_key = cv2.waitKey(20) & 0xFF
|
2022-01-02 15:46:29 +08:00
|
|
|
|
ret, frame = cap.read() # 捕获画面
|
2021-12-29 10:51:27 +08:00
|
|
|
|
frame_num += 1
|
|
|
|
|
print(f'第{frame_num}帧')
|
2022-01-02 20:50:06 +08:00
|
|
|
|
cv2.imshow("opencv webcam", frame) # 显示画面
|
|
|
|
|
|
2022-01-02 15:46:29 +08:00
|
|
|
|
if (is_autoSaveFrame): # 自动保存
|
|
|
|
|
if (frame_num % frame_nSave == 0): # 每隔n帧保存一次
|
2022-01-02 19:02:56 +08:00
|
|
|
|
frame_opt(frame, frame_savePath, frame_num, is_resizeFrame, resize_frame, resizeRatio_frame,
|
|
|
|
|
frame_namePrefix, frame_saveStyle, jpg_quality, png_quality)
|
2022-01-02 15:46:29 +08:00
|
|
|
|
if (is_headSaveFrame): # 手动保存
|
2022-01-02 21:00:26 +08:00
|
|
|
|
if wait_key == ord(frame_capKey): # 保存键
|
2022-01-02 19:02:56 +08:00
|
|
|
|
frame_opt(frame, frame_savePath, frame_num, is_resizeFrame, resize_frame, resizeRatio_frame,
|
|
|
|
|
frame_namePrefix, frame_saveStyle, jpg_quality, png_quality)
|
2022-01-02 20:50:06 +08:00
|
|
|
|
|
2022-01-02 21:00:26 +08:00
|
|
|
|
if wait_key == ord(quit_key): # 退出 ord:字符转ASCII码
|
2021-12-29 10:51:27 +08:00
|
|
|
|
break
|
2022-01-02 21:00:26 +08:00
|
|
|
|
if wait_key == ord(pause_key):
|
2022-01-02 20:50:06 +08:00
|
|
|
|
print(f'已暂停!按任意键继续。。。')
|
|
|
|
|
cv2.waitKey(0) # 暂停,按任意键继续
|
2022-01-02 15:46:29 +08:00
|
|
|
|
|
2021-12-29 10:51:27 +08:00
|
|
|
|
print(f'一共处理了{frame_num}帧')
|
|
|
|
|
# 释放缓存
|
|
|
|
|
cap.release()
|
|
|
|
|
cv2.destroyAllWindows()
|
|
|
|
|
else:
|
|
|
|
|
print(f'摄像头连接异常!')
|
|
|
|
|
|
2022-01-02 15:46:29 +08:00
|
|
|
|
print(f'程序结束!')
|
|
|
|
|
e_time = time.time() # 终止时间
|
|
|
|
|
print(f'用时:{round((e_time - s_time), 3)}秒, {round((e_time - s_time)/60, 3)}分, {round((e_time - s_time)/3600, 3)}小时')
|
2021-12-29 10:51:27 +08:00
|
|
|
|
|
|
|
|
|
|
2022-01-02 15:46:29 +08:00
|
|
|
|
def main(args):
|
2021-12-29 10:51:27 +08:00
|
|
|
|
device_index = args.device
|
|
|
|
|
quit_key = args.quit
|
|
|
|
|
is_autoSaveFrame = args.is_autoSaveFrame
|
|
|
|
|
is_headSaveFrame = args.is_headSaveFrame
|
|
|
|
|
frame_saveDir = args.frame_saveDir
|
|
|
|
|
frame_nSave = args.frame_nSave
|
|
|
|
|
frame_capKey = args.frame_capKey
|
|
|
|
|
resize_frame = args.resize_frame
|
|
|
|
|
is_resizeFrame = args.is_resizeFrame
|
|
|
|
|
resizeRatio_frame = args.resizeRatio_frame
|
2022-01-02 15:46:29 +08:00
|
|
|
|
frame_namePrefix = args.frame_namePrefix
|
|
|
|
|
frame_saveStyle = args.frame_saveStyle
|
|
|
|
|
jpg_quality = args.jpg_quality
|
|
|
|
|
png_quality = args.png_quality
|
2022-01-02 20:50:06 +08:00
|
|
|
|
pause_key = args.pause
|
2022-01-02 15:46:29 +08:00
|
|
|
|
|
|
|
|
|
# 调用webcam opencv
|
2022-01-02 20:50:06 +08:00
|
|
|
|
webcam_opencv(device_index, quit_key, pause_key, is_autoSaveFrame, frame_saveDir, frame_nSave,
|
2022-01-02 15:46:29 +08:00
|
|
|
|
is_headSaveFrame, frame_capKey, is_resizeFrame, resize_frame, resizeRatio_frame,
|
|
|
|
|
frame_namePrefix, frame_saveStyle, jpg_quality, png_quality)
|
2021-12-29 10:51:27 +08:00
|
|
|
|
|
|
|
|
|
|
2022-01-02 15:46:29 +08:00
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
args = parse_args()
|
|
|
|
|
main(args)
|