cvtColor失败断言scn == 3 || scn == 4,但图像确实有3个通道并且存在

时间:2014-05-20 17:02:37

标签: python opencv numpy pygame webcam

我试图在Raspberry Pi上运行人脸检测,所以我试图找到最快的方法来做所有事情。 (每毫秒计算700MHz处理器!)

我快速测试了我需要检查的各种选项,其中包括:

  • 获取网络摄像头图片(选项为pygame.camera或openCV' s cv2.VideoCapture)
  • 调整大小,转换为灰度,然后(如果需要)转换为numpy并旋转。

这听起来很奇怪,但是为了捕捉图片,pygame.camera比树莓派上的openCV快约60ms。

假设从pygame表面到numpy的额外转换加上90度旋转,花费不到60ms,那么混合使用是值得的。

这里的问题是我得到了一个奇怪的cvtColor错误,声称我的numpy ndarray(目前opencv 2.0的后端)没有3或4个频道。

这很奇怪,因为我在调用cvtColor之前打印出ndarray的形状,它有3个通道。我只能假设我错过了一些非常明显的东西。

这是削减的代码。

import pygame
import cv2
import numpy
from pygame import camera

pygame.init()
pygame.camera.init()

#get one shot from pygame camera
cam_list = pygame.camera.list_cameras()
pywebcam = pygame.camera.Camera(cam_list[0],(640,480))
pywebcam.start()
image = pywebcam.get_image()

for z in xrange(50):
    image = pywebcam.get_image()

pywebcam.stop()

if image:
    #numpy (convert to numpy as fast as possible)
    numpy_image=pygame.surfarray.array3d(image)

    print(numpy_image.shape)
    numpy_image=cv2.cvtColor(numpy_image,cv2.COLOR_BGR2GRAY)
    numpy_image = cv2.resize(numpy_image, (0,0), fx=0.25, fy=0.25)
    numpy_image = numpy.rot90(numpy_image,3)

编辑:删除了一堆代码。新代码删除了所有分析。

我从这个程序得到的输出是:

Average time in range: 58.64 ms.

Pausing to ensure webcam is freed.

Average time in range: 115.56 ms.

(480, 640, 3)
Pure NumPy
  0     ms to printing shape.
  39    ms to convert to grayscale.
  16    ms to resize.
  0     ms to rotate.
  58 total ms.

(640, 480, 3)
OpenCV Error: Assertion failed (scn == 3 || scn == 4) in cvtColor, file /build/opencv-XZa2gn/opencv-2.3.1/modules/imgproc/src/color.cpp, line 2834
Traceback (most recent call last):
  File "profile.py", line 72, in <module>
    numpy_image=cv2.cvtColor(numpy_image,cv2.COLOR_BGR2GRAY)
cv2.error: /build/opencv-XZa2gn/opencv-2.3.1/modules/imgproc/src/color.cpp:2834: error: (-215) scn == 3 || scn == 4 in function cvtColor

这里发生了什么?

1 个答案:

答案 0 :(得分:1)

找到答案。显然,numpy在你工作时并没有真正更新ndarray,它只是暂时改变了想法。事情很好,也很快。

虽然opencv 2.0的C ++版本可以处理这个问题,但是python绑定无法 - 并且由于pygame的surfrayray代码在numpy上工作,所以你去pygame-&gt; opencv的任何情况都会遇到这个问题

说到这里,你需要做的就是在调用pygame.surfarray.array3d()之后调用numpy.copy()。

新副本不会有这些临时更改。出于这个原因,不要打扰array3d(),只需使用pixels3d() - 无论如何你必须复制,所以不要做两个。

有关更多信息,我认为暂时的变化被称为“大踏步”&#39;或类似的东西。