2010-08-30 16 views
6

मैं कोड का एक टुकड़ा है कि OpenCV का उपयोग कर तख्ते पर कार्रवाई करने के कैमरे से एक पर कब्जा सत्र सेट और फिर फ्रेम से एक उत्पन्न UIImage साथ एक UIImageView की छवि गुण सेट है। जब ऐप शुरू होता है, तो छवि दृश्य की छवि शून्य होती है और जब तक मैं स्टैक पर कोई अन्य व्यू कंट्रोलर नहीं दबाता तब तक कोई फ्रेम दिखाई नहीं देता है और फिर इसे पॉप करता है। तब छवि तब तक रहती है जब तक कि मैं इसे दोबारा नहीं करता। एनएसएलओजी के बयान बताते हैं कि कॉलबैक को लगभग सही फ्रेम दर पर बुलाया जाता है। कोई विचार क्यों नहीं दिखता है? मैंने फ्रेमरेट को दूसरी तरफ 2 फ्रेम तक कम कर दिया। क्या यह पर्याप्त तेज़ प्रसंस्करण नहीं कर रहा है?AVCaptureSession केवल iPhone के लिए एक फ्रेम हो रही 3GS

- (void)setupCaptureSession { 
    NSError *error = nil; 

    // Create the session 
    AVCaptureSession *session = [[AVCaptureSession alloc] init]; 

    // Configure the session to produce lower resolution video frames, if your 
    // processing algorithm can cope. We'll specify medium quality for the 
    // chosen device. 
    session.sessionPreset = AVCaptureSessionPresetLow; 

    // Find a suitable AVCaptureDevice 
    AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 

    // Create a device input with the device and add it to the session. 
    AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device 
                     error:&error]; 
    if (!input) { 
     // Handling the error appropriately. 
    } 
    [session addInput:input]; 

    // Create a VideoDataOutput and add it to the session 
    AVCaptureVideoDataOutput *output = [[[AVCaptureVideoDataOutput alloc] init] autorelease]; 
    output.alwaysDiscardsLateVideoFrames = YES; 
    [session addOutput:output]; 

    // Configure your output. 
    dispatch_queue_t queue = dispatch_queue_create("myQueue", NULL); 
    [output setSampleBufferDelegate:self queue:queue]; 
    dispatch_release(queue); 

    // Specify the pixel format 
    output.videoSettings = 
    [NSDictionary dictionaryWithObject: 
    [NSNumber numberWithInt:kCVPixelFormatType_32BGRA] 
           forKey:(id)kCVPixelBufferPixelFormatTypeKey]; 


    // If you wish to cap the frame rate to a known value, such as 15 fps, set 
    // minFrameDuration. 
    output.minFrameDuration = CMTimeMake(1, 1); 

    // Start the session running to start the flow of data 
    [session startRunning]; 

    // Assign session to an ivar. 
    [self setSession:session]; 
} 

// Create a UIImage from sample buffer data 
- (UIImage *) imageFromSampleBuffer:(CMSampleBufferRef) sampleBuffer { 
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
    // Lock the base address of the pixel buffer 
    CVPixelBufferLockBaseAddress(imageBuffer,0); 

    // Get the number of bytes per row for the pixel buffer 
    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); 
    // Get the pixel buffer width and height 
    size_t width = CVPixelBufferGetWidth(imageBuffer); 
    size_t height = CVPixelBufferGetHeight(imageBuffer); 

    // Create a device-dependent RGB color space 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    if (!colorSpace) 
    { 
     NSLog(@"CGColorSpaceCreateDeviceRGB failure"); 
     return nil; 
    } 

    // Get the base address of the pixel buffer 
    void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer); 
    // Get the data size for contiguous planes of the pixel buffer. 
    size_t bufferSize = CVPixelBufferGetDataSize(imageBuffer); 

    // Create a Quartz direct-access data provider that uses data we supply 
    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, baseAddress, bufferSize, 
                   NULL); 
    // Create a bitmap image from data supplied by our data provider 
    CGImageRef cgImage = 
    CGImageCreate(width, 
        height, 
        8, 
        32, 
        bytesPerRow, 
        colorSpace, 
        kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Little, 
        provider, 
        NULL, 
        true, 
        kCGRenderingIntentDefault); 
    CGDataProviderRelease(provider); 
    CGColorSpaceRelease(colorSpace); 

    // Create and return an image object representing the specified Quartz image 
    UIImage *image = [UIImage imageWithCGImage:cgImage]; 
    CGImageRelease(cgImage); 

    CVPixelBufferUnlockBaseAddress(imageBuffer, 0); 

    return image; 
} 


// Delegate routine that is called when a sample buffer was written 
- (void)captureOutput:(AVCaptureOutput *)captureOutput 
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer 
     fromConnection:(AVCaptureConnection *)connection { 
    // Create a UIImage from the sample buffer data 
    UIImage *image = [self imageFromSampleBuffer:sampleBuffer]; 
    [self.delegate cameraCaptureGotFrame:image]; 
} 

उत्तर

6

यह सूत्रण-प्रयास करें से संबंधित हो सकता:

[self.delegate performSelectorOnMainThread:@selector(cameraCaptureGotFrame:) withObject:image waitUntilDone:NO]; 
+0

हो सकता है। मैं इसे आज़माउंगा और आपको बता दूंगा। –

+0

मुझे एक खराब पहुंच त्रुटि मिलती है। –

+0

[self.delegate performSelectorOnMainThread: @selector (cameraCaptureGotFrame :) withObject: image waitUntilDone: हाँ]; प्रतीक्षा बदलना जब तक हाँ इसे काम नहीं करता है। अब मुझे यह पता लगाने की जरूरत है कि अभिविन्यास परिदृश्य कैसे बनाया जाए। धन्यवाद! –

0

आप प्रत्येक नई छवि संपत्ति अपडेट के बाद UIImageView पर एक setNeedsDisplay कर रहे हैं:

यहाँ कोड है?

संपादित करें:

कहां और कब आप अपनी छवि को ध्यान में रखते पृष्ठभूमि छवि संपत्ति अद्यतन कर रहे हैं?

+0

ने कोशिश की, काम नहीं किया। सेट नेड्सडेआउट भी कोशिश की –

3

यह एक सूत्रण मुद्दा तरह दिखता है। आप मुख्य धागे की तुलना में किसी भी अन्य धागे में अपने विचारों को अपडेट नहीं कर सकते हैं। आपके सेटअप में, जो अच्छा है, प्रतिनिधि समारोह कैप्चरऑटपुट: didOutputSampleBuffer: को द्वितीयक धागे में बुलाया जाता है। तो आप वहां से छवि दृश्य सेट नहीं कर सकते हैं। यदि आप खराब पहुंच त्रुटि से छुटकारा पा सकते हैं तो आर्ट गिलेस्पी का जवाब इसे हल करने का एक तरीका है।

एक और तरीका है captureOutput में नमूना बफर संशोधित करने के लिए है: didOutputSampleBuffer: और है अपने कब्जा सत्र के लिए एक AVCaptureVideoPreviewLayer उदाहरण जोड़कर दिखाया गया है। यह निश्चित रूप से पसंदीदा तरीका है यदि आप केवल छवि के एक छोटे से भाग को संशोधित करते हैं जैसे कुछ हाइलाइट करना।

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

अद्यतन: ठीक से, छवि को बनाए रखने captureOutput में संदर्भ संख्या में वृद्धि करने के लिए: (द्वितीय थ्रेड में) और cameraCaptureGotFrame में यह घटती: didOutputSampleBuffer (मुख्य थ्रेड में)।

// Delegate routine that is called when a sample buffer was written 
- (void)captureOutput:(AVCaptureOutput *)captureOutput 
     didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer 
     fromConnection:(AVCaptureConnection *)connection 
{ 
    // Create a UIImage from the sample buffer data 
    UIImage *image = [self imageFromSampleBuffer:sampleBuffer]; 

    // increment ref count 
    [image retain]; 
    [self.delegate performSelectorOnMainThread:@selector(cameraCaptureGotFrame:) 
     withObject:image waitUntilDone:NO]; 

} 

- (void) cameraCaptureGotFrame:(UIImage*)image 
{ 
    // whatever this function does, e.g.: 
    imageView.image = image; 

    // decrement ref count 
    [image release]; 
} 

आप संदर्भ संख्या नहीं बढ़ाते हैं, तो छवि cameraCaptureGotFrame से पहले दूसरी धागे की ऑटो रिहाई पूल द्वारा मुक्त किया जाता है: मुख्य थ्रेड में कहा जाता है। यदि आप इसे मुख्य धागे में कम नहीं करते हैं, तो छवियों को कभी भी मुक्त नहीं किया जाता है और आप कुछ सेकंड के भीतर स्मृति से बाहर हो जाते हैं।

+0

की पहली पंक्ति में कोई लाभ नहीं लिया है, जो मुख्य थ्रेड पर कॉल करने वाले विधि में बनाए रखने की कोशिश करेगा और आपको जल्द ही बताएगा। –

+0

कला के उत्तर पर एक पैरामीटर बदलना काम किया। इनपुट –

+0

के लिए धन्यवाद ठीक है, आप वहां मेरा कोड देखते हैं। यदि आप ठीक से बनाए रखने और एक्सेस त्रुटियों को ठीक करने के तरीके के साथ आते हैं, तो मैं आपको 50 प्वाइंट बक्षीस दूंगा। –

संबंधित मुद्दे