2010-11-23 15 views
8

मैं आईफोन पर कुछ छवि प्रसंस्करण करने की कोशिश कर रहा हूँ। मैं कैमरे के फ्रेम को कैप्चर करने के लिए http://developer.apple.com/library/ios/#qa/qa2010/qa1702.html का उपयोग कर रहा हूं।आईफोन वीडियो आउटपुट छवि बफर accesing कम एफपीएस

मेरी समस्या यह है कि जब मैं कब्जा कर लिया गया बफर तक पहुंचने की कोशिश कर रहा हूं, तो कैमरा एफपीएस 30 से 20 तक गिर जाता है। क्या कोई जानता है कि मैं इसे कैसे ठीक कर सकता हूं?

मैं सबसे कम कैप्चर गुणवत्ता का उपयोग करता हूं जो मुझे मिल सकता है (AVCaptureSessionPresetLow = 192x144) kCVPixelFormatType_32BGRA प्रारूप में। अगर कोई कम गुणवत्ता जानता है तो मैं इसका उपयोग कर सकता हूं, मैं इसे आजमाने की कोशिश करता हूं।

जब मैं सिम्बियन की तरह अन्य प्लेटफार्मों पर एक ही छवि पहुंच करता हूं, तो यह ठीक काम करता है।

यहाँ मेरी कोड है:

#pragma mark - 
#pragma mark AVCaptureSession delegate 
- (void)captureOutput:(AVCaptureOutput *)captureOutput 
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer 
    fromConnection:(AVCaptureConnection *)connection 
{ 
/*We create an autorelease pool because as we are not in the main_queue our code is 
    not executed in the main thread. So we have to create an autorelease pool for the thread we are in*/ 
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 

    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
//Lock the image buffer 
    if (CVPixelBufferLockBaseAddress(imageBuffer, 0) == kCVReturnSuccess) 
    { 

    // calculate FPS and display it using main thread 
    [self performSelectorOnMainThread:@selector(updateFps:) withObject: (id) nil waitUntilDone:NO]; 


    UInt8 *base = (UInt8 *)CVPixelBufferGetBaseAddress(imageBuffer); //image buffer start address 

    size_t width = CVPixelBufferGetWidth(imageBuffer); 
    size_t height = CVPixelBufferGetHeight(imageBuffer); 

    int size = (height*width); 
    UInt8* pRGBtmp = m_pRGBimage; 

     /* 
     Here is the problem; m_pRGBimage is RGB image I want to process. 
     In the 'for' loop I convert the image from BGRA to RGB. As a resault, the FPS drops to 20. 
     */ 
    for (int i=0;i<size;i++) 
    { 
    pRGBtmp[0] = base[2]; 
    pRGBtmp[1] = base[1]; 
    pRGBtmp[2] = base[0]; 
    base = base+4; 
    pRGBtmp = pRGBtmp+3;  
    } 


    // Display received action 
    [self performSelectorOnMainThread:@selector(displayAction:) withObject: (id) nil waitUntilDone:NO]; 
    //[self displayAction:&eyePlayOutput]; 
    //saveFrame(imageBuffer); 

    //unlock the image buffer 
    CVPixelBufferUnlockBaseAddress(imageBuffer,0); 

} 


[pool drain]; 
} 

एक अनुवर्ती पर उत्तर देने के लिए के रूप में, मैं वास्तविक समय में छवि पर कार्रवाई करने की जरूरत है, यह प्रदर्शित किया जा रहा है।

मैंने देखा है कि जब मैं AVCaptureSessionPresetHigh, सबसे सरल बात करते हैं, की तरह का उपयोग करें:

for (int i=0;i<size;i++) 
    x = base[0]; 

फ़्रेमरेट 4-5 एफपीएस के लिए ड्रॉप करने का कारण बनता है। मुझे लगता है क्योंकि उस आकार में एक छवि कैश नहीं है।

असल में मुझे 96x48 छवि की आवश्यकता है। कैमरा आउटपुट छवि को डाउनस्केल करने का एक आसान तरीका है, एक तरीका जो हार्डवेयर त्वरण का उपयोग करता है, इसलिए मैं छोटे से काम कर सकता हूं?

उत्तर

8

कोई भी चीज जो एक छवि में प्रत्येक पिक्सेल से अधिक iterates काफी सभी लेकिन सबसे तेजी से IOS उपकरणों पर धीमी गति से हो जाएगा की प्राथमिकता को कम करने की कोशिश कर सकते नहीं है यदि। उदाहरण के लिए, मैंने एक साधारण प्रति-पिक्सेल रंग परीक्षण के साथ 640 x 480 वीडियो फ्रेम (307,200 पिक्सेल) में प्रत्येक पिक्सेल पर पुनरावर्तित किया और पाया कि यह केवल आईफोन 4 पर लगभग 4 एफपीएस पर चलता है।

आप अपने मामले में 27,648 पिक्सेल प्रोसेसिंग की तलाश में, जो आईफोन 4 पर 30 एफपीएस हिट करने के लिए पर्याप्त तेज़ी से चलना चाहिए, लेकिन यह मूल आईफोन और आईफोन 3 जी में जो कुछ भी था उससे कहीं ज्यादा तेज़ प्रोसेसर है। आईफोन 3 जी शायद इस प्रसंस्करण लोड के साथ अभी भी संघर्ष करेगा। आप यह भी नहीं कहते कि प्रोसेसर आपके सिम्बियन उपकरणों में कितना तेज़ था।

मैं कलरस्पेस रूपांतरण से बचने के लिए अपने प्रसंस्करण एल्गोरिदम को पुन: कार्य करने का सुझाव दूंगा। उन्हें संसाधित करने के लिए रंग घटकों को पुन: व्यवस्थित करने की आवश्यकता नहीं होनी चाहिए।

इसके अतिरिक्त, आप छवियों की पंक्तियों और स्तंभों के भीतर कुछ अंतराल पर नमूना करके केवल कुछ पिक्सेल को चुन सकते हैं।

अंत में, यदि आप ओपनजीएल ईएस 2.0 (आईफोन 3 जी एस और नए) के लिए समर्थन रखने वाले नए आईओएस डिवाइस को लक्षित कर रहे हैं, तो आप पूरी तरह से जीपीयू पर वीडियो फ्रेम को संसाधित करने के लिए एक जीएलएसएल खंड शेडर का उपयोग करना चाहेंगे। मैं रीयलटाइम कलर-आधारित ऑब्जेक्ट ट्रैकिंग के लिए नमूना कोड के साथ here प्रक्रिया का वर्णन करता हूं। जीपीयू इस तरह की प्रसंस्करण को अपने बेंचमार्क में सीपीयू की तुलना में 14 से 28 गुना तेजी से संभाल सकता है।

1

अस्वीकरण: इस उत्तर के एक अनुमान :)

आप काफी बहुत काम कर रहे हैं, जबकि बफर बंद कर दिया है, क्या यह थ्रेड को पकड़ रहा है जो कैमरे से छवि को कैप्चर कर रहा है?

आप बफर से बाहर डेटा की प्रतिलिपि जब तुम उस पर काम तो तुम अगर यह ताला कि कब्जा को पकड़े रहा है तो यह मदद करनी चाहिए है इसे ASAP की तरह

if (CVPixelBufferLockBaseAddress(imageBuffer, 0) == kCVReturnSuccess) { 
    // Get the base address and size of the buffer 
    UInt8 *buffer_base = (UInt8 *)CVPixelBufferGetBaseAddress(imageBuffer); //image buffer start address 
    size_t width = CVPixelBufferGetWidth(imageBuffer); 
    size_t height = CVPixelBufferGetHeight(imageBuffer); 

    // Copy it's contents out 
    Uint8 *base = malloc(width * height * 4); 
    memcpy(base, buffer_base, size); 

    // Unlock the buffer 
    CVPixelBufferUnlockBaseAddress(imageBuffer,0); 

    // base now points to a copy of the buffers' data - do what you want to it . . . 
    ... 

    // remember to free base once you're done ;) 
    free(base); 

अर्थात कुछ अनलॉक कर सकते हैं कर सकते हैं।

एनबी यदि आप जानते हैं कि सभी बफर एक ही आकार के होंगे तो आप इसे गति दे सकते हैं, फिर आप स्मृति प्राप्त करने के लिए केवल मॉलोक को कॉल कर सकते हैं और फिर इसे हर बार पुन: उपयोग कर सकते हैं और जब आप सभी बफर को संसाधित करना समाप्त कर देते हैं तो केवल इसे मुक्त करें ।


या कि समस्या आप इस थ्रेड

[NSThread setThreadPriority:0.25]; 
+0

मैं मानता हूं कि यह पूरी तरह से धीमी प्रसंस्करण है जो पूरे कैप्चर को खींच रहा है, लेकिन मुझे यकीन नहीं है कि जल्दी ही लॉक जारी करने से मदद मिलेगी। 30 एफपीएस पर फ्रेम से निपटने के लिए, प्रत्येक फ्रेम के लिए कॉलबैक को एक सेकंड के 1/30 वें से कम में पूरा करने की आवश्यकता होगी। यदि ऐसा नहीं होता है, तो प्रोसेसिंग ऑपरेशंस सिर्फ उस धागे को जाम कर देगा जो वे चल रहे हैं। –

+0

यदि यह निर्माता के रूप में काम नहीं करता-> उपभोक्ता पैटर्न - कॉलबैक सिर्फ कतारबद्ध हो जाएगा - यह सब संशोधित छवि के साथ क्या कर रहा है इस पर निर्भर करता है। अगर यह सिर्फ इसे बचा रहा है तो हे, इसे कहीं बफर में बैक अप दें। यदि इसे प्रदर्शित किया जा रहा है तो उसे एक समस्या मिली है :) – deanWombourne

+0

मैंने एक समर्पित बफर पर memcpy की कोशिश की है, लेकिन यह वास्तव में मदद नहीं की थी, वास्तव में यह धीमा था :( – akaru

0

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

कैमरा फ्रेम डेटा का मेमोरी पता देखें। मेरे डिवाइस पर कैमरा बफर 0x63ac000 पर है। इसका मतलब मेरे लिए कुछ भी नहीं है, सिवाय इसके कि अन्य ढेर ऑब्जेक्ट 0x1300000 के करीब पते में हैं। लॉक सुझाव ने मेरी मंदी को हल नहीं किया, लेकिन memcpy किया।

+0

मैंने इस गति में सुधार नहीं देखा है। मामले में, नकली चीजों को थोड़ा सा धीमा कर देता है, प्रतिलिपि के ऊपरी हिस्से के कारण। कोई सुझाव? – akaru

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