用pyside/opencv访问网络摄像头

1 投票
1 回答
7017 浏览
提问于 2025-04-17 17:42

我在一个使用pyside和opencv的项目中遇到了访问摄像头的问题。

这是一个简化的例子,能展示我遇到的问题:

from PySide import QtCore, QtGui
import cv, cv2, time, ImageQt

app = QtGui.QApplication([])

while True:
    camcapture = cv.CaptureFromCAM(0)
    cv.SetCaptureProperty(camcapture,cv.CV_CAP_PROP_FRAME_WIDTH, 1280)
    cv.SetCaptureProperty(camcapture,cv.CV_CAP_PROP_FRAME_HEIGHT, 720);

    frame = cv.QueryFrame(camcapture)
    image = QtGui.QImage(frame.tostring(), frame.width, frame.height, QtGui.QImage.Format_RGB888).rgbSwapped()
    pixmap = QtGui.QPixmap.fromImage(image)

app.exec_()

我发现这里有两个问题。首先:显然我在使用v4l2访问摄像头时遇到了问题,而这个摄像头在其他Python应用中正常工作:

python ./test.py 
VIDIOC_QUERYMENU: Invalid argument
[... and countless more entries which don#t worry me ...]
VIDIOC_QUERYMENU: Invalid argument
libv4l2: error setting pixformat: Device or resource busy
HIGHGUI ERROR: libv4l unable to ioctl S_FMT
libv4l2: error setting pixformat: Device or resource busy
libv4l1: error setting pixformat: Device or resource busy
HIGHGUI ERROR: libv4l unable to ioctl VIDIOCSPICT

然后还有一个关闭的问题,这个问题不太清楚,但现在不是我主要关注的问题:

*** glibc detected *** python: double free or corruption (fasttop): 0x00000000029368f0 ***
======= Backtrace: =========
/lib64/libc.so.6(+0x78b66)[0x7f3539f06b66]
/usr/lib64/tls/libnvidia-tls.so.304.64(+0x1cc1)[0x7f352e448cc1]
======= Memory map: ========
00400000-00401000 r-xp 00000000 08:02 3937950                            /usr/bin/python2.7
00600000-00601000 r--p 00000000 08:02 3937950                            /usr/bin/python2.7
00601000-00602000 rw-p 00001000 08:02 3937950                            /usr/bin/python2.7
01631000-03cd3000 rw-p 00000000 00:00 0                                  [heap]
7f351b6dc000-7f351b6dd000 rw-p 00000000 00:00 0 
7f351b6dd000-7f351b773000 rw-s 001c2000 00:05 5759                       /dev/video0
7f351b773000-7f351b809000 rw-s 0012c000 00:05 5759                       /dev/video0
[... and so on ... and so on ... ]

我的问题是? 我对输出的结果感到困惑。我尝试了很多不同的代码变体,但通常都会遇到同样的问题。所以我猜这不是某个特定的代码细节,而是我设置或方法上的一些普遍问题。 我的环境是: - Linux操作系统(openSUSE-12.2),在x86-64平台上(MacBook Pro) - opencv 2.4.3 - libqt4 4.8.4 - python 2.7.3

这里有什么问题?我的代码和网上那些例子差不多,都是各种变体。我缺少了什么呢?

1 个回答

3

首先,你不应该把 cv.CaptureFromCAM(0) 放在循环里面,因为这样会导致“资源忙碌”的错误和内存溢出。

你可能需要让你的循环速度慢一些。可以使用 cv2.waitKey() 或者 time.sleep() 来实现。

之后,你还需要完成你的 Qt 实现。(这似乎是另一个问题。)

下面是你例子的一个简化版本:

import cv, cv2, time, sys

camcapture = cv.CaptureFromCAM(0)
cv.SetCaptureProperty(camcapture,cv.CV_CAP_PROP_FRAME_WIDTH, 1280)
cv.SetCaptureProperty(camcapture,cv.CV_CAP_PROP_FRAME_HEIGHT, 720)

while True:
    frame = cv.QueryFrame(camcapture)
    ... GUI stuff ...
    time.sleep(.05)

改用 cv2 的话:

camcapture = cv2.VideoCapture(0)
while True:
    _, frame = camcapture.read()
    ... GUI stuff ...
    time.sleep(.05)

撰写回答