2011-02-03 24 views
10

मैं पाइथन (संस्करण 2.7 या 2.6) और पीओओबीजेसी (संस्करण 2.2) का उपयोग कर मैकबुक प्रो में निर्मित ऐप्पल आईसाइट कैमरा से एक फ्रेम को कैप्चर करने की कोशिश कर रहा हूं।पाइथन और पायओबीजेसी का उपयोग करके ऐप्पल iSight से फ़्रेम कैप्चर कैसे करें?

एक शुरुआती बिंदु के रूप में, मैंने this old StackOverflow प्रश्न का उपयोग किया। यह सत्यापित करने के लिए कि यह समझ में आता है, मैंने Apple's MyRecorder उदाहरण के विरुद्ध क्रॉस-रेफरेंस किया है, उदाहरण के लिए यह प्रतीत होता है। दुर्भाग्यवश, मेरी लिपि काम नहीं करती है।

मेरे बड़े सवाल हैं:

  • Am मैं सही ढंग से कैमरा प्रारंभ?
  • क्या मैं ईवेंट लूप को सही ढंग से शुरू कर रहा हूं?
  • क्या कोई अन्य सेटअप था जो मुझे करना था?

नीचे चिपकाए गए उदाहरण स्क्रिप्ट में, इच्छित ऑपरेशन यह है कि startImageCapture() को कॉल करने के बाद, मुझे कैप्चरडिलेगेट से "फ्रेम मिला ..." संदेश प्रिंट करना प्रारंभ करना चाहिए। हालांकि, कैमरे की रोशनी कभी चालू नहीं होती है और प्रतिनिधि का कॉलबैक कभी निष्पादित नहीं होता है।

इसके अलावा, startImageCapture() के दौरान कोई विफलता नहीं है, सभी फ़ंक्शन सफल होने का दावा करते हैं, और यह सफलतापूर्वक iSight डिवाइस को पाता है। पीडीबी में सत्र ऑब्जेक्ट का विश्लेषण करने से पता चलता है कि इसमें वैध इनपुट और आउटपुट ऑब्जेक्ट्स हैं, आउटपुट में एक प्रतिनिधि सौंपा गया है, डिवाइस किसी अन्य प्रक्रियाओं द्वारा उपयोग में नहीं है, और सत्र को प्रारंभ करने के बाद चलने के रूप में चिह्नित किया जाता है।() को कॉल किया जाता है।

कोड यह रहा:

#!/usr/bin/env python2.7 

import sys 
import os 
import time 
import objc 
import QTKit 
import AppKit 
from Foundation import NSObject 
from Foundation import NSTimer 
from PyObjCTools import AppHelper 
objc.setVerbose(True) 

class CaptureDelegate(NSObject): 
    def captureOutput_didOutputVideoFrame_withSampleBuffer_fromConnection_(self, captureOutput, 
                      videoFrame, sampleBuffer, 
                      connection): 
     # This should get called for every captured frame 
     print "Got a frame: %s" % videoFrame 

class QuitClass(NSObject): 
    def quitMainLoop_(self, aTimer): 
     # Just stop the main loop. 
     print "Quitting main loop." 
     AppHelper.stopEventLoop() 


def startImageCapture(): 
    error = None 

    # Create a QT Capture session 
    session = QTKit.QTCaptureSession.alloc().init() 

    # Find iSight device and open it 
    dev = QTKit.QTCaptureDevice.defaultInputDeviceWithMediaType_(QTKit.QTMediaTypeVideo) 
    print "Device: %s" % dev 
    if not dev.open_(error): 
     print "Couldn't open capture device." 
     return 

    # Create an input instance with the device we found and add to session 
    input = QTKit.QTCaptureDeviceInput.alloc().initWithDevice_(dev) 
    if not session.addInput_error_(input, error): 
     print "Couldn't add input device." 
     return 

    # Create an output instance with a delegate for callbacks and add to session 
    output = QTKit.QTCaptureDecompressedVideoOutput.alloc().init() 
    delegate = CaptureDelegate.alloc().init() 
    output.setDelegate_(delegate) 
    if not session.addOutput_error_(output, error): 
     print "Failed to add output delegate." 
     return 

    # Start the capture 
    print "Initiating capture..." 
    session.startRunning() 


def main(): 
    # Open camera and start capturing frames 
    startImageCapture() 

    # Setup a timer to quit in 10 seconds (hack for now) 
    quitInst = QuitClass.alloc().init() 
    NSTimer.scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_(10.0, 
                      quitInst, 
                      'quitMainLoop:', 
                      None, 
                      False) 
    # Start Cocoa's main event loop 
    AppHelper.runConsoleEventLoop(installInterrupt=True) 

    print "After event loop" 


if __name__ == "__main__": 
    main() 

किसी भी मदद प्रदान कर सकते हैं के लिए धन्यवाद!

उत्तर

15

ठीक है, मैंने पीओओबीजेसी की गहराई के माध्यम से एक दिन डाइविंग बिताया और इसे काम कर लिया।

भविष्य के रिकॉर्ड के लिए, प्रश्न में कोड काम नहीं करता है: परिवर्तनीय दायरा और कचरा संग्रहसत्र वैरिएबल हटा दिया गया था जब यह स्कोप से बाहर हो गया था, जो घटना प्रोसेसर भागने से पहले हुआ था। इसे बनाए रखने के लिए कुछ किया जाना चाहिए ताकि इसे चलाने के समय से पहले इसे मुक्त नहीं किया जा सके।

सबकुछ कक्षा में ले जाना और सत्र बनाना एक क्लास वैरिएबल ने कॉलबैक काम करना शुरू कर दिया। इसके अतिरिक्त, नीचे दिया गया कोड फ्रेम के पिक्सेल डेटा को बिटमैप प्रारूप में प्राप्त करने और इसे कोको कॉल के माध्यम से सहेजने का प्रदर्शन करता है, और यह भी इसे वापस पाइथन के विश्व-दृश्य में बफर या स्ट्रिंग के रूप में कॉपी करने का तरीका दिखाता है।

नीचे स्क्रिप्ट एक भी फ्रेम

#!/usr/bin/env python2.7 
# 
# camera.py -- by Trevor Bentley (02/04/2011) 
# 
# This work is licensed under a Creative Commons Attribution 3.0 Unported License. 
# 
# Run from the command line on an Apple laptop running OS X 10.6, this script will 
# take a single frame capture using the built-in iSight camera and save it to disk 
# using three methods. 
# 

import sys 
import os 
import time 
import objc 
import QTKit 
from AppKit import * 
from Foundation import NSObject 
from Foundation import NSTimer 
from PyObjCTools import AppHelper 

class NSImageTest(NSObject): 
    def init(self): 
     self = super(NSImageTest, self).init() 
     if self is None: 
      return None 

     self.session = None 
     self.running = True 

     return self 

    def captureOutput_didOutputVideoFrame_withSampleBuffer_fromConnection_(self, captureOutput, 
                      videoFrame, sampleBuffer, 
                      connection): 
     self.session.stopRunning() # I just want one frame 

     # Get a bitmap representation of the frame using CoreImage and Cocoa calls 
     ciimage = CIImage.imageWithCVImageBuffer_(videoFrame) 
     rep = NSCIImageRep.imageRepWithCIImage_(ciimage) 
     bitrep = NSBitmapImageRep.alloc().initWithCIImage_(ciimage) 
     bitdata = bitrep.representationUsingType_properties_(NSBMPFileType, objc.NULL) 

     # Save image to disk using Cocoa 
     t0 = time.time() 
     bitdata.writeToFile_atomically_("grab.bmp", False) 
     t1 = time.time() 
     print "Cocoa saved in %.5f seconds" % (t1-t0) 

     # Save a read-only buffer of image to disk using Python 
     t0 = time.time() 
     bitbuf = bitdata.bytes() 
     f = open("python.bmp", "w") 
     f.write(bitbuf) 
     f.close() 
     t1 = time.time() 
     print "Python saved buffer in %.5f seconds" % (t1-t0) 

     # Save a string-copy of the buffer to disk using Python 
     t0 = time.time() 
     bitbufstr = str(bitbuf) 
     f = open("python2.bmp", "w") 
     f.write(bitbufstr) 
     f.close() 
     t1 = time.time() 
     print "Python saved string in %.5f seconds" % (t1-t0) 

     # Will exit on next execution of quitMainLoop_() 
     self.running = False 

    def quitMainLoop_(self, aTimer): 
     # Stop the main loop after one frame is captured. Call rapidly from timer. 
     if not self.running: 
      AppHelper.stopEventLoop() 

    def startImageCapture(self, aTimer): 
     error = None 
     print "Finding camera" 

     # Create a QT Capture session 
     self.session = QTKit.QTCaptureSession.alloc().init() 

     # Find iSight device and open it 
     dev = QTKit.QTCaptureDevice.defaultInputDeviceWithMediaType_(QTKit.QTMediaTypeVideo) 
     print "Device: %s" % dev 
     if not dev.open_(error): 
      print "Couldn't open capture device." 
      return 

     # Create an input instance with the device we found and add to session 
     input = QTKit.QTCaptureDeviceInput.alloc().initWithDevice_(dev) 
     if not self.session.addInput_error_(input, error): 
      print "Couldn't add input device." 
      return 

     # Create an output instance with a delegate for callbacks and add to session 
     output = QTKit.QTCaptureDecompressedVideoOutput.alloc().init() 
     output.setDelegate_(self) 
     if not self.session.addOutput_error_(output, error): 
      print "Failed to add output delegate." 
      return 

     # Start the capture 
     print "Initiating capture..." 
     self.session.startRunning() 


    def main(self): 
     # Callback that quits after a frame is captured 
     NSTimer.scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_(0.1, 
                       self, 
                       'quitMainLoop:', 
                       None, 
                       True) 

     # Turn on the camera and start the capture 
     self.startImageCapture(None) 

     # Start Cocoa's main event loop 
     AppHelper.runConsoleEventLoop(installInterrupt=True) 

     print "Frame capture completed." 

if __name__ == "__main__": 
    test = NSImageTest.alloc().init() 
    test.main() 
+0

कूल मैन, बीटीडब्ल्यू आपको अपना स्वीकार्य 'स्वीकृत' के रूप में चिह्नित करना चाहिए :) –

+0

यह स्क्रिप्ट बहुत अच्छा काम करती है, लेकिन बाइट फ़ाइल लिखते समय विफल हो जाती है। बाइट मोड में फ़ाइल खोलने के लिए आपको खुले ('फ़ाइल नाम', 'डब्ल्यू') को खोलने के लिए ('filename', 'wb') को खोलना चाहिए, फिर यह काम करता है। – andli

0

QTKit बहिष्कृत है और PyObjC एक बड़ा निर्भरता है (और यदि आप इसे homebrew में चाहते हैं के निर्माण के लिए मुश्किल हो रहा है) पर कब्जा होगा। प्लस PyObjC में AVFoundation का अधिकतर हिस्सा नहीं था इसलिए मैंने a simple camera extension for Python बनाया जो वीडियो रिकॉर्ड करने या चित्र को स्नैप करने के लिए AVFoundation का उपयोग करता है, इसके लिए कोई निर्भरता की आवश्यकता नहीं होती है (साइथन इंटरमीडिएट फ़ाइलें अधिकांश उपयोगकर्ताओं के लिए साइथन की आवश्यकता से बचने के लिए प्रतिबद्ध होती हैं)।

यह इस तरह यह निर्माण संभव होना चाहिए:

pip install -e git+https://github.com/dashesy/pyavfcam.git 

फिर हम यह take a picture करने के लिए उपयोग कर सकते हैं:

import pyavfcam 

# Open the default video source 
cam = pyavfcam.AVFCam(sinks='image') 
frame = cam.snap_picture('test.jpg') # frame is a memory buffer np.asarray(frame) can retrieve 

इस सवाल से संबंधित नहीं है, लेकिन अगर AVFCam वर्ग उप है वर्गीकृत, ओवरराइड विधियों को परिणाम के साथ बुलाया जाएगा।

+0

पीआईपी इंस्टॉल मेरे लिए विफल रहता है: '' पीआईपी इंस्टॉल-गिट + https: //github.com/dashesy/pyavfcam.git - संपादन योग्य = गिट + https: //github.com/dashesy/pyavfcam। गिट सही प्रारूप नहीं है; इसमें # अंडे = पैकेज' होना चाहिए – DanHickstein