所以,基本上我正在 Google Colab 中编写一个程序,该程序将使用 python 和 opencv2 通过网络摄像头检测人脸。“我有 Ubuntu 19.10,如果这有帮助的话”
import cv2
faceCascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")
video_capture = cv2.VideoCapture(0)
while True:
ret, frame = video_capture.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
Run Code Online (Sandbox Code Playgroud)
此时出现断言错误
Traceback (most recent call last)
<ipython-input-94-ca2ba51b9064> in <module>()
7 ret, frame = video_capture.read()
8
----> 9 gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
error: OpenCV(4.1.2) /io/opencv/modules/imgproc/src/color.cpp:182: error: (-215:Assertion failed) !_src.empty() in function 'cvtColor'
Run Code Online (Sandbox Code Playgroud)
当我运行此代码时,没有任何东西使用网络摄像头
!_src.empty()意味着你有空frame。
当cv2无法从相机/文件/流获取时frame,它不会显示错误,但它会设置-None并且您必须检查这些值之一frameFalseret
if frame is not None:
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# ... other code ...
else:
print("empty frame")
exit(1)
Run Code Online (Sandbox Code Playgroud)
或者
if ret: # if ret is True:
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# ... other code ...
else:
print("empty frame")
exit(1)
Run Code Online (Sandbox Code Playgroud)
或者
if not ret:
print("empty frame")
exit(1)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# ... other code ...
Run Code Online (Sandbox Code Playgroud)
或者
if frame is None:
print("empty frame")
exit(1)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# ... other code ...
Run Code Online (Sandbox Code Playgroud)
顺便说一句:你不能使用较短的if frame:,因为当它从相机获取图像时,它会frame尝试numpy.array()分别检查每个单元格中的值,并显示警告,要求使用.all()or .any()- 但.all()or可能会在is.any()时给出错误。frameNone
顺便说一句:有时cv2很难找到 haarcascades 文件。并且有一个特殊的变量,其文件夹路径带有.xml- cv2.data.haarcascades- 你可能需要
faceCascade = cv2.CascadeClassifier( os.path.join(cv2.data.haarcascades, "haarcascade_frontalface_default.xml") )
Run Code Online (Sandbox Code Playgroud)
编辑:(2022.05.10)
主要问题可能是 Google Colab 在服务器上运行代码,并且无法访问本地网络摄像头。只有网络浏览器可以访问本地网络摄像头,您必须使用 JavaScript 来访问该网络摄像头、拍摄图像并将其发送到服务器。
Google Colab 有示例如何对单个屏幕截图执行此操作。查看相机捕捉
我编写的代码也可以进行模拟VideoCapture()并cap.read()处理来自本地网络摄像头的视频。
https://colab.research.google.com/drive/1a2seyb864Aqpu13nBjGRJK0AIU7JOdJa?usp=sharing
#
# based on: https://colab.research.google.com/notebooks/snippets/advanced_outputs.ipynb#scrollTo=2viqYx97hPMi
#
from IPython.display import display, Javascript
from google.colab.output import eval_js
from base64 import b64decode, b64encode
import numpy as np
def init_camera():
"""Create objects and functions in HTML/JavaScript to access local web camera"""
js = Javascript('''
// global variables to use in both functions
var div = null;
var video = null; // <video> to display stream from local webcam
var stream = null; // stream from local webcam
var canvas = null; // <canvas> for single frame from <video> and convert frame to JPG
var img = null; // <img> to display JPG after processing with `cv2`
async function initCamera() {
// place for video (and eventually buttons)
div = document.createElement('div');
document.body.appendChild(div);
// <video> to display video
video = document.createElement('video');
video.style.display = 'block';
div.appendChild(video);
// get webcam stream and assing to <video>
stream = await navigator.mediaDevices.getUserMedia({video: true});
video.srcObject = stream;
// start playing stream from webcam in <video>
await video.play();
// Resize the output to fit the video element.
google.colab.output.setIframeHeight(document.documentElement.scrollHeight, true);
// <canvas> for frame from <video>
canvas = document.createElement('canvas');
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
//div.appendChild(input_canvas); // there is no need to display to get image (but you can display it for test)
// <img> for image after processing with `cv2`
img = document.createElement('img');
img.width = video.videoWidth;
img.height = video.videoHeight;
div.appendChild(img);
}
async function takeImage(quality) {
// draw frame from <video> on <canvas>
canvas.getContext('2d').drawImage(video, 0, 0);
// stop webcam stream
//stream.getVideoTracks()[0].stop();
// get data from <canvas> as JPG image decoded base64 and with header "data:image/jpg;base64,"
return canvas.toDataURL('image/jpeg', quality);
//return canvas.toDataURL('image/png', quality);
}
async function showImage(image) {
// it needs string "data:image/jpg;base64,JPG-DATA-ENCODED-BASE64"
// it will replace previous image in `<img src="">`
img.src = image;
// TODO: create <img> if doesn't exists,
// TODO: use `id` to use different `<img>` for different image - like `name` in `cv2.imshow(name, image)`
}
''')
display(js)
eval_js('initCamera()')
def take_frame(quality=0.8):
"""Get frame from web camera"""
data = eval_js('takeImage({})'.format(quality)) # run JavaScript code to get image (JPG as string base64) from <canvas>
header, data = data.split(',') # split header ("data:image/jpg;base64,") and base64 data (JPG)
data = b64decode(data) # decode base64
data = np.frombuffer(data, dtype=np.uint8) # create numpy array with JPG data
img = cv2.imdecode(data, cv2.IMREAD_UNCHANGED) # uncompress JPG data to array of pixels
return img
def show_frame(img, quality=0.8):
"""Put frame as <img src="data:image/jpg;base64,...."> """
ret, data = cv2.imencode('.jpg', img) # compress array of pixels to JPG data
data = b64encode(data) # encode base64
data = data.decode() # convert bytes to string
data = 'data:image/jpg;base64,' + data # join header ("data:image/jpg;base64,") and base64 data (JPG)
eval_js('showImage("{}")'.format(data)) # run JavaScript code to put image (JPG as string base64) in <img>
# argument in `showImage` needs `" "`
Run Code Online (Sandbox Code Playgroud)
class BrowserVideoCapture():
def __init__(self, src=None):
init_camera()
def read(self):
return True, take_frame()
Run Code Online (Sandbox Code Playgroud)
import cv2
cap = BrowserVideoCapture(0)
while True:
ret, frame = cap.read()
if ret:
show_frame(frame)
Run Code Online (Sandbox Code Playgroud)