OpenCV(-215:断言失败)!_src.empty()在函数'cvtColor中

-3 python opencv

所以,基本上我正在 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)

当我运行此代码时,没有任何东西使用网络摄像头

fur*_*ras 5

!_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)