一:问题描述:使用opencv库分别封装了拍照和录像函数,然后想实现一边拍照一边录像的效果,调用threading库来多线程运行时报错cv2.imwrite()为空
二:代码如下
import cv2
import threading
import time
import json
from datetime import datetime
with open("calibration.json", "r", encoding="utf-8") as load_f:
load = json.load(load_f)
def picture_shoot(image_name, image_path=r"E:\report") -> None:
'''
调用摄像头拍照并保存图片到本地
:param image_name: 图片名
:param image_path: 图片保存路径
:return: None
'''
cap = cv2.VideoCapture(0)
while (cap.isOpened()):
ret, frame = cap.read()
# cv2.imshow("Capture_Paizhao", frame) # 显示相机窗口
# k = cv2.waitKey(1) & 0xFF #通过键盘获取值并赋值给k
# if k == ord('s'): # 按下s键,进入下面的保存图片操作
# cv2.imwrite(image_path + '\\' + image_name + ".jpg", frame)
cv2.imwrite(image_path + '\\' + image_name, frame)
# print(cap.get(3))
# print(cap.get(4))
print("保存" + image_name + "成功!")
# elif k == ord('q'): # 按下q键,程序退出
break
cap.release()
cv2.destroyAllWindows()
def video_record(video_path) -> None:
'''
调用摄像头录制视频并保存到本地
:param video_path: 视频保存路径
:return: None
'''
FPS = 24.0
# 必须指定CAP_DSHOW(Direct Show)参数初始化摄像头,否则无法使用更高分辨率
cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
# 视频写入的图像尺寸与画布尺寸不对应会导致视频无法播放,需要实时获取
WIDTH = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
HEIGHT = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
# 设置摄像头设备分辨率
cap.set(cv2.CAP_PROP_FRAME_WIDTH, WIDTH)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, HEIGHT)
# 设置摄像头设备帧率,如不指定,默认600
cap.set(cv2.CAP_PROP_FPS, 24)
# 建议使用XVID编码,图像质量和文件大小比较都兼顾的方案
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter(video_path, fourcc, FPS, (WIDTH, HEIGHT))
start_time = datetime.now()
while (cap.isOpened()):
ret, frame = cap.read()
if ret:
out.write(frame)
# 显示预览窗口
# cv2.imshow('Preview_Window', frame) # 显示相机窗口
# 录制5秒后停止
if (datetime.now() - start_time).seconds == load['record_duration']:
cap.release()
print('视频录制成功!')
break
out.release()
cv2.destroyAllWindows()
if __name__ == '__main__':
path = r'E:\report' + '\\' + 'video.avi'
thread = threading.Thread(target=video_record, args=(path,))
thread.start()
picture_shoot(image_name='1.png', image_path=r'E:/report/AI2_reverse/standard_camera')
三:运行结果
D:\Python3.8.6\python.exe D:/PythonWorkSpace/Auto_test/Camera_Invoke.py
[ WARN:0] global D:\a\opencv-python\opencv-python\opencv\modules\videoio\src\cap_msmf.cpp (376) `anonymous-namespace'::SourceReaderCB::OnReadSample videoio(MSMF): OnReadSample() is called with error status: -1072875772
[ WARN:0] global D:\a\opencv-python\opencv-python\opencv\modules\videoio\src\cap_msmf.cpp (388) `anonymous-namespace'::SourceReaderCB::OnReadSample videoio(MSMF): async ReadSample() call is failed with error status: -1072875772
[ WARN:1] global D:\a\opencv-python\opencv-python\opencv\modules\videoio\src\cap_msmf.cpp (1022) CvCapture_MSMF::grabFrame videoio(MSMF): can't grab frame. Error: -1072875772
Traceback (most recent call last):
File "D:/PythonWorkSpace/Auto_test/Camera_Invoke.py", line 77, in <module>
picture_shoot(image_name='1.png', image_path=r'E:/report/AI2_reverse/standard_camera')
File "D:/PythonWorkSpace/Auto_test/Camera_Invoke.py", line 26, in picture_shoot
cv2.imwrite(image_path + '\\' + image_name, frame)
cv2.error: OpenCV(4.5.4) D:\a\opencv-python\opencv-python\opencv\modules\imgcodecs\src\loadsave.cpp:799: error: (-215:Assertion failed) !_img.empty() in function 'cv::imwrite'
视频录制成功!
[ WARN:1] global D:\a\opencv-python\opencv-python\opencv\modules\videoio\src\cap_msmf.cpp (438) `anonymous-namespace'::SourceReaderCB::~SourceReaderCB terminating async callback
Process finished with exit code 1
四:尝试过的方法
1、观察发现两个函数都实例化了cap对象,并发运行时可能会产生冲突,把其中一个函数的cap改成了cap_2,运行后仍然报同样的错误
2、两个函数都是通过cv2下的方法来实现拍照或者录像,但是cv2是三方库的内置函数,改不了名字
五:我想要达到的效果
能够一边录制视频一边拍照,并且可以控制视频什么时候结束