【问题标题】:How can I capture iSight frames with Python in Snow Leopard?如何在 Snow Leopard 中使用 Python 捕获 iSight 帧?
【发布时间】:2010-12-07 06:57:12
【问题描述】:

我有以下 PyObjC 脚本:

from Foundation import NSObject
import QTKit
error = None
capture_session = QTKit.QTCaptureSession.alloc().init()
print 'capture_session', capture_session
device = QTKit.QTCaptureDevice.defaultInputDeviceWithMediaType_(QTKit.QTMediaTypeVideo)
print 'device', device, type(device)
success = device.open_(error)
print 'device open success', success, error
if not success:
    raise Exception(error)
capture_device_input = QTKit.QTCaptureDeviceInput.alloc().initWithDevice_(device)
print 'capture_device_input', capture_device_input, capture_device_input.device()
success = capture_session.addInput_error_(capture_device_input, error)
print 'session add input success', success, error
if not success:
    raise Exception(error)
capture_decompressed_video_output = QTKit.QTCaptureDecompressedVideoOutput.alloc().init()
print 'capture_decompressed_video_output', capture_decompressed_video_output
class Delegate(NSObject):
    def captureOutput_didOutputVideoFrame_withSampleBuffer_fromConnection_(self, captureOutput, videoFrame, sampleBuffer, connection):
        print videoFrame, sampleBuffer, connection
delegate = Delegate.alloc().init()
print 'delegate', delegate
capture_decompressed_video_output.setDelegate_(delegate)
print 'output delegate:', capture_decompressed_video_output.delegate()
success = capture_session.addOutput_error_(capture_decompressed_video_output, error)
print 'capture session add output success', success, error
if not success:
    raise Exception(error)
print 'about to run session', capture_session, 'with inputs', capture_session.inputs(), 'and outputs', capture_session.outputs()
capture_session.startRunning()
print 'capture session is running?', capture_session.isRunning()
import time
time.sleep(10)

程序没有报告任何错误,但 iSight 的绿灯从未被激活,并且委托的帧捕获回调从未被调用。这是我得到的输出:

$ python prueba.py 
capture_session <QTCaptureSession: 0x1006c16f0>
device Built-in iSight <objective-c class QTCaptureDALDevice at 0x7fff70366aa8>
device open success (True, None) None
capture_device_input <QTCaptureDeviceInput: 0x1002ae010> Built-in iSight
session add input success (True, None) None
capture_decompressed_video_output <QTCaptureDecompressedVideoOutput: 0x104239f10>
delegate <Delegate: 0x10423af50>
output delegate: <Delegate: 0x10423af50>
capture session add output success (True, None) None
about to run session <QTCaptureSession: 0x1006c16f0> with inputs (
    "<QTCaptureDeviceInput: 0x1002ae010>"
) and outputs (
    "<QTCaptureDecompressedVideoOutput: 0x104239f10>"
)
capture session is running? True

PS:请不要回答我应该尝试 PySight,我有但它不会工作,因为 Xcode 无法在 64 位编译 CocoaSequenceGrabber。

【问题讨论】:

    标签: python osx-snow-leopard pyobjc qtkit isight


    【解决方案1】:

    您的问题是您没有事件循环。如果你想把它作为一个独立的脚本来做,你必须弄清楚如何创建一个。 PyObjC XCode 模板会自动为您设置:

    from PyObjCTools import AppHelper
    AppHelper.runEventLoop()
    

    但是,尝试将其插入脚本顶部会显示 AppHelper(可能是 NSApplicationMain)中的某些内容需要一个 plist 文件来从中提取主类。您可以通过创建setup.py 文件并使用py2app 来获得它,类似于PyObjc talk 中的这个示例:

    from distutils.core import setup
    import py2app
    plist = dict(
        NSPrincipalClass='SillyBalls',
    )
    setup(
        plugin=['SillyBalls.py'],
        data_files=['English.lproj'],
        options=dict(py2app=dict(
            extension='.saver',
            plist=plist,
        )),
    )
    

    【讨论】:

    • @Dan:谢谢指点!这是我第一次使用 Mac OS X 编程,我完全一无所知。我让它工作调用AppHelper.runConsoleEventLoop(),而不是在脚本末尾,不需要Plist。现在我的问题是它接管了主线程并且永远不会返回。我希望以一种非侵入性的方式将它很好地包装在一个模块中。
    • 您可能会产生一个线程并在线程内处理它。 QT 不是线程安全的,但在这种情况下,这意味着您必须在一个线程中完成所有 QT 工作,而这不一定是主线程。您可能还会研究计时器,但我认为您可能仍然需要一个主循环。
    • 显然,它必须是主线程。如果我改为使用Thread(target=AppHelper.runConsoleEventLoop).start(),我会收到一堆错误并且没有任何效果:2009-10-20 12:58:32.075 Python[2054:4903] *** __NSAutoreleaseNoPool(): Object 0x1018065b0 of class NSCFString autoreleased with no pool in place - just leaking 2009-10-20 12:58:32.078 Python[2054:4903] *** __NSAutoreleaseNoPool(): Object 0x101821130 of class NSCFString autoreleased with no pool in place - just leaking 2009-10-20 12:58:32.078 Python[2054:4903] *** __NSAutoreleaseNoPool(): Object 0x101828df0 of class NSCFString autorelease
    【解决方案2】:

    您应该尝试一下来自 Andrew Straw 的 motmot's camiface 库。它也适用于火线相机,但也适用于 isight,这是您正在寻找的。​​p>

    来自教程:

    import motmot.cam_iface.cam_iface_ctypes as cam_iface
    import numpy as np
    
    mode_num = 0
    device_num = 0
    num_buffers = 32
    
    cam = cam_iface.Camera(device_num,num_buffers,mode_num)
    cam.start_camera()
    frame = np.asarray(cam.grab_next_frame_blocking())
    print 'grabbed frame with shape %s'%(frame.shape,)
    

    【讨论】:

    • 你可以在incm.cnrs-mrs.fr/LaurentPerrinet/SimpleCellDemo看到一些简单的例子
    • 有没有办法通过这个库直接录制到文件中?
    • motmotcamiface 很棒,但我想要一个低依赖性的解决方案,特别是直接录制视频。所以创建了这个:github.com/dashesy/pyavfcam 使用 AVFoundation 直接捕获视频和图像并将其记录到文件中。
    猜你喜欢
    • 2011-06-21
    • 2015-09-06
    • 1970-01-01
    • 1970-01-01
    • 2011-02-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-01
    • 2013-10-11
    相关资源
    最近更新 更多