2009-10-16 11 views
5

Je le script PyObjC suivant:Comment puis-je capturer des images iSight avec Python dans Snow Leopard?

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) 

Les rapports du programme sans erreurs, mais le feu vert iSight est jamais activé et le rappel de capture d'image du délégué est jamais appelé. Voici le résultat que je reçois:

$ 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: S'il vous plaît, je n'ai pas répondu que je devrais essayer PySight, mais il ne fonctionnera pas parce que Xcode ne peut pas compiler CocoaSequenceGrabber en 64bit.

Répondre

3

Votre problème ici est que vous n'avez pas de boucle d'événement. Si vous voulez faire cela en tant que script autonome, vous devrez trouver comment en créer un. Le PyObjC XCode modèles automatiquement que pour vous avec:

from PyObjCTools import AppHelper 
AppHelper.runEventLoop() 

Essayer d'insérer que dans le haut de votre script, cependant, montre que quelque chose à l'intérieur AppHelper (probablement NSApplicationMain) attend un fichier plist pour extraire la classe principale de. Vous pouvez obtenir ce en créant un fichier setup.py et en utilisant py2app, quelque chose comme cet exemple d'un 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, 
    )), 
) 
+1

@ Dan: Merci pour le pointeur! C'est ma première expérience avec la programmation Mac OS X et j'étais complètement désemparé. Je l'ai eu à travailler en invoquant 'AppHelper.runConsoleEventLoop()' à la fin du script, pas besoin de 'Plist'. Maintenant, mon problème est qu'il prend en charge le thread principal et ne retourne jamais. J'espérais bien l'intégrer dans un module de manière non intrusive. –

+0

Vous pourriez générer un fil et le manipuler dans le fil, probablement. QT n'est pas threadsafe, mais dans ce contexte tout ce que cela signifie est que vous devez faire tous vos trucs QT dans un thread, ce qui n'est pas nécessairement le thread principal. Vous pourriez aussi regarder dans les minuteries, mais je pense que vous avez probablement besoin d'une boucle principale pour cela. – Dan

+0

Apparemment, il doit être le fil principal. Si je fais Thread (target = AppHelper.runConsoleEventLoop) .start() 'à la place, je reçois un tas d'erreurs et rien ne fonctionne: ' 2009-10-20 12: 58: 32.075 Python [2054: 4903] *** __NSAutoreleaseNoPool(): Objet 0x1018065b0 de classe NSCFString libéré sans pool en place - juste fuite 2009-10-20 12: 58: 32.078 Python [2054: 4903] *** __NSAutoreleaseNoPool(): Objet 0x101821130 de la classe NSCFString libéré sans pool en place - juste fuite 2009-10-20 12: 58: 32.078 Python [2054: 4903] *** __NSAutoreleaseNoPool(): Objet 0x101828df0 de la classe NSCFString autorelease' –

2

Vous devriez donner un essai à motmot's camiface bibliothèque d'Andrew Straw. Il fonctionne également avec les caméras FireWire, mais il fonctionne également avec l'isight, qui est ce que vous recherchez.

du tutoriel:

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,) 
+0

cool! merci pour le lien –

+0

vous pouvez voir quelques exemples simples sur http://www.incm.cnrs-mrs.fr/LaurentPerrinet/SimpleCellDemo – meduz

+0

c'est la bibliothèque originale: https://github.com/motmot/libcamiface – dashesy