一、在窗口中显示摄像头帧
摄像头帧流也可以用VideoCapture对象来表示。但是,对于摄像头,我们通过传递摄像头设备索引(而不是视频文件名称)来构造VideoCapture对象。
OpenCV允许使用namedWindow、imshow和destroyWindow函数来创建、重新绘制和注销指定的窗口。此外,任何窗口都可以通过waitKey函数捕获键盘输入,通过setMouseCallBack函数捕获鼠标输入。
代码编写
import cv2 as cv
clicked = False
def onMouse(event, x, y, flags, param):
global clicked
if event == cv.EVENT_LBUTTONUP:
clicked = True
cameraCapture = cv.VideoCapture(0)
cv.namedWindow("Camera")
cv.setMouseCallback("Camera", onMouse)
success, frame = cameraCapture.read()
while success and cv.waitKey(1) == -1 and not clicked:
cv.putText(frame, "Click Window or press any key to stop!",
(0, 450), cv.FONT_HERSHEY_COMPLEX, 0.7, (255, 0, 0))
cv.imshow("Camera", frame)
success, frame = cameraCapture.read()
cv.destroyWindow("Camera")
cameraCapture.release()
传递给setMouseCallBack的鼠标回调应有5个参数,如代码示例所示,把回调的param参数设置为setMouseCallBack的第三个可选参数,默认情况下为0.
回调的事件参数是以下操作之一:
-
cv2_EVENT_MOUSEMOVE 滑动
cv2_EVENT_LBUTTONDOWN 左键点击
cv2_EVENT_RBUTTONDOWN 右键点击
cv2_EVENT_MBUTTONDOWN 中间点击
cv2_EVENT_LBUTTONUP 左键释放
cv2_EVENT_RBUTTONUP 右键释放
cv2_EVENT_MBUTTONUP 中间释放
cv2_EVENT_LBUTTONDBLCLK 左键双击
cv2_EVENT_RBUTTONDBLCLK 右键双击
cv2_EVENT_MBUTTONDBLCLK 中间释放
鼠标回调的flag参数可能是以下事件的一些按位组合:
cv2_EVENT_FLAG_LBUTTON 左键拖拽
cv2_EVENT_FLAG_RBUTTON 右键拖拽
cv2_EVENT_FLAG_MBUTTON 中间拖拽
cv2_EVENT_FLAG_CTRLKEY 按Ctrl不放事件
cv2_EVENT_FLAG_SHIFTKEY 按Shift不放事件
cv2_EVENT_FLAG_ALTKEY 按Alt不放事件
二、捕捉摄像头帧
下面我们从摄像头抓取10秒的视频,并将其写入AVI文件
代码编写
import cv2 as cv
camera_number = 0
cameraCapture = cv.VideoCapture(camera_number + cv.CAP_DSHOW)
fps = 30
size = (int(cameraCapture.get(cv.CAP_PROP_FRAME_WIDTH)),
int(cameraCapture.get(cv.CAP_PROP_FRAME_HEIGHT)))
out = cv.VideoWriter("E:\\MyOutput001.avi", cv.VideoWriter_fourcc('D', 'I', 'V', 'X'),
fps, size)
success, frame = cameraCapture.read()
numFrameRemaining = 10 * fps - 1 # 10秒
while success and cv.waitKey(1) and numFrameRemaining > 0:
out.write(frame)
success, frame = cameraCapture.read()
cv.imshow("camera", frame)
numFrameRemaining -= 1
if numFrameRemaining == 0:
print("保存成功!!!")
cameraCapture.release()
out.release()
cv.destroyAllWindows()
OpenCV不提供任何查询摄像头数量或者摄像头属性的方法,如果用无效的索引构造VideoCapture类,VideoCapture类将不会产生任何帧,它的read方法返回(False,None),要试图避免从未正确打开的VideoCapture对象检索帧。
当我们需要同步一组摄像头或者多摄像头相机(如立体摄像机)时,read 方法是不合适的。我们可以改用 grab 和 retrieve 方法。对于一组(两台)摄像机,可以使用类似下面的代码:
success0 = cameraCapture.grab()
success1 = cameraCapture.grab()
if success0 and success1:
frame0 = cameraCapture.retrieve()
frame1 = cameraCapture.retrieve()