2022-01-25 17:53:15 +08:00
|
|
|
|
# OpenCV Webcam Script v0.5
|
2021-12-29 10:51:27 +08:00
|
|
|
|
# 创建人:曾逸夫
|
2022-01-25 17:53:15 +08:00
|
|
|
|
# 创建时间:2022-01-25
|
2021-12-29 10:51:27 +08:00
|
|
|
|
|
|
|
|
|
import cv2
|
|
|
|
|
from pathlib import Path
|
|
|
|
|
import argparse
|
|
|
|
|
import time
|
|
|
|
|
import os
|
2022-01-04 13:57:49 +08:00
|
|
|
|
import sys
|
2022-01-03 13:36:25 +08:00
|
|
|
|
from utils.ows_path import increment_path
|
2022-01-17 20:11:59 +08:00
|
|
|
|
from utils.hotkey import hotkey_judge
|
2022-01-04 14:09:39 +08:00
|
|
|
|
from utils.frame_opt import frame_opt
|
2022-01-15 15:37:36 +08:00
|
|
|
|
from utils.log import is_logSuffix, log_management
|
2022-01-16 07:58:53 +08:00
|
|
|
|
from utils.args_yaml import argsYaml
|
2022-01-19 18:12:57 +08:00
|
|
|
|
from utils.compress import webcam_compress, is_compressFile
|
2022-01-21 09:27:18 +08:00
|
|
|
|
from utils.time_format import time_format
|
|
|
|
|
|
2022-01-19 09:08:16 +08:00
|
|
|
|
|
|
|
|
|
ROOT_PATH = sys.path[0] # 项目根目录
|
2022-01-25 17:53:15 +08:00
|
|
|
|
OWS_VERSION = 'OpenCV Webcam Script v0.5' # 版本号
|
2021-12-29 10:51:27 +08:00
|
|
|
|
|
2022-01-10 21:23:57 +08:00
|
|
|
|
|
2022-01-02 15:46:29 +08:00
|
|
|
|
def parse_args(known=False):
|
2022-01-25 17:53:15 +08:00
|
|
|
|
parser = argparse.ArgumentParser(description='OpenCV Webcam Script v0.5')
|
2022-01-08 09:54:23 +08:00
|
|
|
|
parser.add_argument('--device', '-dev', default='0',
|
|
|
|
|
type=str, help='device index for webcam, 0 or rtsp')
|
2022-01-02 15:46:29 +08:00
|
|
|
|
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')
|
2022-01-02 21:02:41 +08:00
|
|
|
|
parser.add_argument('--is_handSaveFrame', '-ishsf',
|
|
|
|
|
action='store_true', help='is hand save frame')
|
2022-01-02 15:46:29 +08:00
|
|
|
|
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')
|
2022-01-08 09:54:23 +08:00
|
|
|
|
parser.add_argument('--frame_dirName', '-fdn',
|
|
|
|
|
default="frames", type=str, help='save frame dir name')
|
2022-01-02 15:46:29 +08:00
|
|
|
|
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",
|
2022-01-02 21:02:41 +08:00
|
|
|
|
type=str, help='frame capture key (hand save frame)')
|
2022-01-02 15:46:29 +08:00
|
|
|
|
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-03 14:29:47 +08:00
|
|
|
|
parser.add_argument('--auto_frameNum', '-afn',
|
|
|
|
|
default=0, type=int, help='auto save number of frames')
|
2022-01-16 08:39:24 +08:00
|
|
|
|
|
2022-01-14 19:58:01 +08:00
|
|
|
|
# 日志
|
|
|
|
|
parser.add_argument('--logName', '-ln',
|
2022-01-26 10:33:30 +08:00
|
|
|
|
default="ows.log", type=str, help='log save name')
|
2022-01-14 19:58:01 +08:00
|
|
|
|
parser.add_argument('--logMode', '-lm',
|
2022-01-16 06:56:41 +08:00
|
|
|
|
default="a", type=str, help='log write mode')
|
2022-01-19 09:08:16 +08:00
|
|
|
|
# 压缩
|
2022-01-19 17:39:36 +08:00
|
|
|
|
parser.add_argument('--is_compress', '-isc',
|
2022-01-19 09:08:16 +08:00
|
|
|
|
action='store_true', help='is compress file')
|
2022-01-19 17:39:36 +08:00
|
|
|
|
parser.add_argument('--compressStyle', '-cs',
|
|
|
|
|
default="zip", type=str, help='compress style')
|
|
|
|
|
parser.add_argument('--is_autoCompressName', '-isacn',
|
|
|
|
|
action='store_true', help='is auto compress name')
|
|
|
|
|
parser.add_argument('--compressName', '-cn',
|
2022-01-26 10:33:30 +08:00
|
|
|
|
default="ows", type=str, help='compress save name')
|
2022-01-19 17:39:36 +08:00
|
|
|
|
parser.add_argument('--compressMode', '-cm',
|
2022-01-19 18:00:22 +08:00
|
|
|
|
default="w", type=str, help='compress save mode, tar w:gz')
|
2022-01-02 15:46:29 +08:00
|
|
|
|
args = parser.parse_known_args()[0] if known else parser.parse_args()
|
|
|
|
|
return args
|
|
|
|
|
|
|
|
|
|
|
2022-01-03 13:36:25 +08:00
|
|
|
|
# Webcam OpenCV
|
2022-01-16 08:39:24 +08:00
|
|
|
|
def webcam_opencv(device_index="0",
|
|
|
|
|
quit_key="q",
|
|
|
|
|
pause_key="p",
|
|
|
|
|
is_autoSaveFrame=False,
|
|
|
|
|
frame_saveDir="./WebcamFrame",
|
|
|
|
|
frame_dirName="frames",
|
|
|
|
|
frame_nSave=1,
|
|
|
|
|
auto_frameNum=0,
|
|
|
|
|
is_handSaveFrame=False,
|
|
|
|
|
frame_capKey="a",
|
|
|
|
|
is_resizeFrame=False,
|
|
|
|
|
resize_frame=[640, 480],
|
|
|
|
|
resizeRatio_frame=1.0,
|
|
|
|
|
frame_namePrefix="frame",
|
|
|
|
|
frame_saveStyle="jpg",
|
|
|
|
|
jpg_quality=95,
|
|
|
|
|
png_quality=3,
|
2022-01-26 10:35:03 +08:00
|
|
|
|
logName="ows.log",
|
2022-01-19 09:08:16 +08:00
|
|
|
|
logMode="a",
|
|
|
|
|
is_compress=False,
|
2022-01-19 17:39:36 +08:00
|
|
|
|
compressStyle="zip",
|
|
|
|
|
is_autoCompressName=False,
|
2022-01-26 10:35:03 +08:00
|
|
|
|
compressName="ows",
|
2022-01-19 17:39:36 +08:00
|
|
|
|
compressMode="w"):
|
2022-01-04 13:57:49 +08:00
|
|
|
|
|
|
|
|
|
keyList = [quit_key, frame_capKey, pause_key] # 快捷键列表
|
|
|
|
|
hotkey_judge(keyList) # 快捷键冲突判断
|
2022-01-02 15:46:29 +08:00
|
|
|
|
|
2022-01-10 21:11:17 +08:00
|
|
|
|
# 日志文件
|
2022-01-15 19:48:28 +08:00
|
|
|
|
is_logSuffix(logName) # 检测日志格式
|
2022-01-10 21:23:57 +08:00
|
|
|
|
logTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) # 日志时间
|
2022-01-14 19:58:01 +08:00
|
|
|
|
log_management(f'{logTime}\n', logName, logMode) # 记录日志时间
|
2022-01-16 06:56:41 +08:00
|
|
|
|
|
2022-01-19 18:00:22 +08:00
|
|
|
|
is_compressFile(compressStyle) # 检测压缩文件格式
|
2022-01-19 17:39:36 +08:00
|
|
|
|
|
2022-01-22 09:46:42 +08:00
|
|
|
|
# time_list = [1, 60, 3600] # 时间参数列表
|
2022-01-16 07:19:44 +08:00
|
|
|
|
|
2022-01-05 11:40:46 +08:00
|
|
|
|
# ------------------程序开始------------------
|
2022-01-02 15:46:29 +08:00
|
|
|
|
s_time = time.time() # 起始时间
|
2022-01-08 09:54:23 +08:00
|
|
|
|
dev_index = eval(device_index) if device_index.isnumeric(
|
|
|
|
|
) else device_index # 设备选择 (usb 0,1,2; rtsp)
|
2022-01-16 06:56:41 +08:00
|
|
|
|
cap = cv2.VideoCapture(dev_index) # 设备连接
|
2022-01-10 21:11:17 +08:00
|
|
|
|
is_capOpened = cap.isOpened() # 判断摄像头是否正常启动
|
2021-12-29 10:51:27 +08:00
|
|
|
|
|
2022-01-16 06:56:41 +08:00
|
|
|
|
if is_capOpened: # 设备连接成功
|
2021-12-29 10:51:27 +08:00
|
|
|
|
print(f'摄像头连接成功!')
|
2022-01-10 21:11:17 +08:00
|
|
|
|
bufferSize = cap.get(cv2.CAP_PROP_BUFFERSIZE)
|
|
|
|
|
# cap.set(cv2.CAP_PROP_BUFFERSIZE,10) # 1-10
|
|
|
|
|
|
2022-01-16 06:56:41 +08:00
|
|
|
|
frame_width = cap.get(3) # 帧宽度
|
|
|
|
|
frame_height = cap.get(4) # 帧高度
|
2022-01-10 21:11:17 +08:00
|
|
|
|
fps = cap.get(5) # 帧率
|
|
|
|
|
print(f'宽度:{frame_width}, 高度:{frame_height}, FPS:{fps}, 缓存数:{bufferSize}')
|
|
|
|
|
# cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)
|
|
|
|
|
# cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)
|
|
|
|
|
|
2022-01-06 20:53:09 +08:00
|
|
|
|
frame_savePath = "" # 保存路径
|
2022-01-02 21:02:41 +08:00
|
|
|
|
if is_autoSaveFrame or is_handSaveFrame:
|
2022-01-03 13:49:51 +08:00
|
|
|
|
# 帧保存路径管理
|
2022-01-02 19:02:56 +08:00
|
|
|
|
frame_savePath = increment_path(
|
2022-01-08 09:54:23 +08:00
|
|
|
|
Path(f"{frame_saveDir}") / frame_dirName, 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
|
|
|
|
|
2022-01-17 20:49:15 +08:00
|
|
|
|
frame_num = 0 # 总帧数
|
|
|
|
|
frame_hand_num = 0 # 手动保存帧数
|
2022-01-20 16:25:26 +08:00
|
|
|
|
while(is_capOpened):
|
2022-01-03 13:49:51 +08:00
|
|
|
|
wait_key = cv2.waitKey(20) & 0xFF # 键盘监听
|
2022-01-20 16:25:26 +08:00
|
|
|
|
_, frame = cap.read() # 捕获画面
|
2022-01-03 13:49:51 +08:00
|
|
|
|
frame_num += 1 # 帧计数
|
2022-01-16 07:07:34 +08:00
|
|
|
|
print(f'帧ID:{frame_num}') # 输出帧ID信息
|
2022-01-20 16:25:26 +08:00
|
|
|
|
cv2.imshow(OWS_VERSION, frame) # 显示画面
|
2022-01-02 20:50:06 +08:00
|
|
|
|
|
2022-01-02 15:46:29 +08:00
|
|
|
|
if (is_autoSaveFrame): # 自动保存
|
2022-01-03 14:29:47 +08:00
|
|
|
|
if (auto_frameNum > 0 and frame_num > auto_frameNum):
|
|
|
|
|
# 设置自动最大保存帧数
|
2022-01-18 08:45:44 +08:00
|
|
|
|
frame_num -= 1 # 修复帧数显示问题
|
2022-01-03 14:29:47 +08:00
|
|
|
|
break
|
2022-01-02 15:46:29 +08:00
|
|
|
|
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-26 10:33:30 +08:00
|
|
|
|
elif (is_handSaveFrame): # 手动保存
|
2022-01-02 21:00:26 +08:00
|
|
|
|
if wait_key == ord(frame_capKey): # 保存键
|
2022-01-17 20:49:15 +08:00
|
|
|
|
frame_hand_num += 1 # 手动帧计数
|
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-26 10:33:30 +08:00
|
|
|
|
elif 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
|
|
|
|
|
2022-01-17 20:49:15 +08:00
|
|
|
|
if (is_autoSaveFrame):
|
2022-01-18 08:01:31 +08:00
|
|
|
|
# 帧保存信息(自动版)
|
|
|
|
|
frameSaveMsg = f'自动版:共计{frame_num}帧,已保存在:{frame_savePath}'
|
2022-01-10 21:23:57 +08:00
|
|
|
|
print(frameSaveMsg)
|
2022-01-14 19:58:01 +08:00
|
|
|
|
log_management(f'{frameSaveMsg}\n', logName, logMode) # 记录帧保存信息
|
2022-01-17 20:49:15 +08:00
|
|
|
|
elif (is_handSaveFrame):
|
2022-01-18 08:01:31 +08:00
|
|
|
|
# 帧保存信息(手动版)
|
|
|
|
|
frameSaveMsg = f'手动版:共计{frame_hand_num}帧,已保存在:{frame_savePath}'
|
2022-01-17 20:49:15 +08:00
|
|
|
|
print(frameSaveMsg)
|
|
|
|
|
log_management(f'{frameSaveMsg}\n', logName, logMode) # 记录帧保存信息
|
2022-01-08 16:16:19 +08:00
|
|
|
|
|
|
|
|
|
cap.release() # 释放缓存资源
|
|
|
|
|
cv2.destroyAllWindows() # 删除所有窗口
|
2022-01-03 13:49:51 +08:00
|
|
|
|
else: # 连接设备失败
|
2021-12-29 10:51:27 +08:00
|
|
|
|
print(f'摄像头连接异常!')
|
2022-01-16 06:56:41 +08:00
|
|
|
|
|
2022-01-05 11:40:46 +08:00
|
|
|
|
# ------------------程序结束------------------
|
2022-01-02 15:46:29 +08:00
|
|
|
|
print(f'程序结束!')
|
|
|
|
|
e_time = time.time() # 终止时间
|
2022-01-16 07:07:34 +08:00
|
|
|
|
total_time = e_time - s_time # 程序用时
|
2022-01-21 09:32:19 +08:00
|
|
|
|
# outTimeMsg = f'用时:{total_time/time_list[0]:.3f}秒, {total_time/time_list[1]:.3f}分, {total_time/time_list[2]:.3f}小时' # 适用于细微记录
|
2022-01-25 17:53:15 +08:00
|
|
|
|
outTimeMsg = f'用时:{time_format(total_time)}' # 格式化时间格式,便于观察
|
2022-01-10 21:23:57 +08:00
|
|
|
|
print(outTimeMsg)
|
2022-01-14 19:58:01 +08:00
|
|
|
|
log_management(f'{outTimeMsg}\n', logName, logMode) # 记录用时
|
2021-12-29 10:51:27 +08:00
|
|
|
|
|
2022-01-19 09:08:16 +08:00
|
|
|
|
# ------------------压缩文件------------------
|
2022-01-19 15:57:20 +08:00
|
|
|
|
if (is_compress and (is_autoSaveFrame or is_handSaveFrame)):
|
2022-01-25 21:02:30 +08:00
|
|
|
|
compress_msg = webcam_compress(compressStyle, is_autoCompressName,
|
2022-01-26 08:20:42 +08:00
|
|
|
|
compressName, frame_savePath, compressMode)
|
2022-01-25 21:02:30 +08:00
|
|
|
|
log_management(f'{compress_msg}\n', logName, logMode) # 记录用时
|
2022-01-19 17:39:36 +08:00
|
|
|
|
|
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
|
2022-01-02 21:02:41 +08:00
|
|
|
|
is_handSaveFrame = args.is_handSaveFrame
|
2021-12-29 10:51:27 +08:00
|
|
|
|
frame_saveDir = args.frame_saveDir
|
2022-01-08 09:54:23 +08:00
|
|
|
|
frame_dirName = args.frame_dirName
|
2021-12-29 10:51:27 +08:00
|
|
|
|
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-03 14:29:47 +08:00
|
|
|
|
auto_frameNum = args.auto_frameNum
|
2022-01-19 09:08:16 +08:00
|
|
|
|
|
|
|
|
|
# 日志
|
2022-01-14 19:58:01 +08:00
|
|
|
|
logName = args.logName
|
|
|
|
|
logMode = args.logMode
|
2022-01-02 15:46:29 +08:00
|
|
|
|
|
2022-01-19 09:08:16 +08:00
|
|
|
|
# 压缩
|
|
|
|
|
is_compress = args.is_compress
|
2022-01-19 17:39:36 +08:00
|
|
|
|
compressStyle = args.compressStyle
|
|
|
|
|
is_autoCompressName = args.is_autoCompressName
|
|
|
|
|
compressName = args.compressName
|
|
|
|
|
compressMode = args.compressMode
|
2022-01-19 09:08:16 +08:00
|
|
|
|
|
2022-01-16 08:35:54 +08:00
|
|
|
|
argsYaml(args) # 脚本参数
|
|
|
|
|
|
2022-01-02 15:46:29 +08:00
|
|
|
|
# 调用webcam opencv
|
2022-01-16 08:39:24 +08:00
|
|
|
|
webcam_opencv(device_index,
|
|
|
|
|
quit_key,
|
|
|
|
|
pause_key,
|
|
|
|
|
is_autoSaveFrame,
|
|
|
|
|
frame_saveDir,
|
|
|
|
|
frame_dirName,
|
|
|
|
|
frame_nSave,
|
|
|
|
|
auto_frameNum,
|
|
|
|
|
is_handSaveFrame,
|
|
|
|
|
frame_capKey,
|
|
|
|
|
is_resizeFrame,
|
|
|
|
|
resize_frame,
|
|
|
|
|
resizeRatio_frame,
|
|
|
|
|
frame_namePrefix,
|
|
|
|
|
frame_saveStyle,
|
|
|
|
|
jpg_quality,
|
|
|
|
|
png_quality,
|
|
|
|
|
logName,
|
2022-01-19 09:08:16 +08:00
|
|
|
|
logMode,
|
|
|
|
|
is_compress,
|
2022-01-19 17:39:36 +08:00
|
|
|
|
compressStyle,
|
|
|
|
|
is_autoCompressName,
|
|
|
|
|
compressName,
|
|
|
|
|
compressMode)
|
2021-12-29 10:51:27 +08:00
|
|
|
|
|
|
|
|
|
|
2022-01-02 15:46:29 +08:00
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
args = parse_args()
|
|
|
|
|
main(args)
|