2010-01-12 19 views
12

मेरे पास 250fps पर एक उच्च स्पीड फ्रेमग्रेबर से छवियों में लेने के लिए एक लूप है।दूसरे धागे, ओपनसीवी में छवि प्रदर्शित करें?

/** Loop processes 250 video frames per second **/ 
while(1){ 
    AcquireFrame(); 
    DoProcessing(); 
    TakeAction(); 
} 

साथ ही, मैं उपयोगकर्ता को यह देखने में सक्षम होना चाहता हूं कि क्या हो रहा है। उपयोगकर्ता को केवल 30 एफपीएस (या कम) पर छवियों को देखने की आवश्यकता है। मैं एक दूसरा धागा कैसे स्थापित करूं जो वर्तमान फ्रेम को हर बार प्रदर्शित करता है?

Thread(){ 
    cvShowImage(); 
    Wait(30); /** Wait for 30 ms **/ 
} 

मैं मिनीगब्लू, जीसीसी और ओपनसीवी 1.1 का उपयोग कर क्वाड कोर इंटेल मशीन पर विंडोज़ पर हूं। मुख्य मानदंड यह है कि डिस्प्ले थ्रेड को जितना संभव हो सके मेरे मुख्य प्रोसेसिंग लूप से थोड़ा समय लेना चाहिए। प्रत्येक मिलीसेकंद मायने रखता है।

मैंने CreateThread() का उपयोग cvShowImage() और cvWaitKey() और apparently those functions are not threadsafe के साथ एक नया धागा बनाने के लिए किया है।

मैं ओपनएमपी का उपयोग करने पर विचार कर रहा हूं, लेकिन कुछ लोग report problems with OpenMP and OpenCV। मैं डायरेक्टएक्स डायरेक्टड्रा का उपयोग करने की कोशिश करने पर भी विचार कर रहा हूं क्योंकि स्पष्ट रूप से यह बहुत तेज़ है। लेकिन यह looks complicated और स्पष्ट रूप से problems using Windows DLL's with MinGw हैं।

इनमें से कौन सा मार्ग शुरू करने के लिए सबसे अच्छी जगह होगी?

+0

क्या यह सिर्फ 8% कैप्चर (250/30) प्रदर्शित करने के लिए केवल एक शर्त और "गिनती" चर का उपयोग करने के लिए पर्याप्त नहीं है? –

+0

आह हाँ। लेकिन यदि आप ऐसा करते हैं, तो पूरा कार्यक्रम 8 वें कैप्चर को प्रदर्शित करते समय रोक लगाता है। CvShowImage का उपयोग करके एक छवि प्रदर्शित करने में ~ 10 एमएस लगते हैं। उस समय तक आप कुछ फ्रेम पहले ही चूक चुके हैं। – AndyL

+0

क्या आपको कैमरे से 250 एफपीएस मिल रहे हैं? यदि आप हैं तो आप मुझे बता सकते हैं कि आपने यह कैसे किया? वह बेहद तेज़ है। – bakalolo

उत्तर

10

ठीक है। तो शर्मनाक रूप से मेरा सवाल भी इसका जवाब है।

CreateThread(), CvShowImage() और CvWaitKey() का उपयोग करके मेरे प्रश्न में वर्णित अनुसार वास्तव में काम करता है - वेब पर कुछ पोस्टिंग के विपरीत जो अन्यथा सुझाव देते हैं।

/** Global Variables **/ 
bool DispThreadHasFinished; 
bool MainThreadHasFinished; 
iplImage* myImg; 

/** Main Loop that loops at >100fps **/ 
main() { 
    DispThreadHasFinished = FALSE; 
    MainThreadHasFinished = FALSE; 
    CreateThread(..,..,Thread,..); 

    while(IsTheUserDone()) { 
    myImg=AcquireFrame(); 
    DoProcessing(); 
    TakeAction(); 
    } 
    MainThreadHasFinished = TRUE; 

    while (!DisplayThreadHasFinished) { 
    CvWaitKey(100); 
    } 

    return; 
} 

/** Thread that displays image at ~30fps **/ 
Thread() { 
    while (!MainThreadHasFinished) { 
    cvShowImage(myImg); 
    cvWaitKey(30); 
    } 
DispThreadHasFinished=TRUE; 
return; 
} 

जब मैं मूल रूप से इस प्रश्न पोस्ट, मेरे कोड असंबंधित कारणों से असफल रहा था:

जो भी हो, मैं कुछ इस तरह से लागू किया। आशा है कि ये आपकी मदद करेगा!

4

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

+0

मैं इस समाधान से सहमत हूं - ऐसा लगता है कि यहां जटिलता इस तथ्य में निहित है कि मुख्य धागे पर प्रसंस्करण किया जा रहा है। यदि पृष्ठभूमि थ्रेड पर प्रसंस्करण किया गया था, तो अंतिम छवि पर संदर्भ सहेज रहा था, ui थ्रेड (या ui पर एक कार्यकर्ता धागा) उस अंतिम छवि को आपके द्वारा चुने गए किसी भी दर पर ले जा सकता है। –

0

मुझे खेद है कि मैं आपको अभी एक बेहतर उत्तर नहीं दे सकता, लेकिन ऐसा लगता है कि आपका प्रश्न आपके कार्यक्रम की संरचना के बारे में नहीं बल्कि मल्टीथ्रेडिंग को लागू करने के लिए उपयोग किए जाने वाले टूल के बारे में है। इसके लिए मैं Qt की सिफारिश करूंगा। मैं थोड़ी देर के लिए क्यूटी का उपयोग कर रहा हूं लेकिन मैं अभी मल्टीथ्रेडिंग में जा रहा हूं।

ऐसा लगता है कि आपकी सर्वश्रेष्ठ शर्त QReadWriteLock हो सकती है। यह आपको एक छवि से पढ़ने की अनुमति देता है लेकिन लेखक धागा के साथ आने पर पाठक धागा अपना ताला छोड़ देगा। इस मामले में आप पिछली बार प्रदर्शित छवि की प्रतिलिपि रख सकते हैं और छवि को लिखने के लिए लॉक होने पर इसे प्रदर्शित कर सकते हैं।

क्षमा करें कि मैं और अधिक विस्तृत नहीं हो सकता, लेकिन जैसा कि मैंने कहा, मैं बस इसमें भी शामिल हूं। मैं मूल रूप से वही काम करने की कोशिश कर रहा हूं जो आप हैं, लेकिन लगभग तेज़ नहीं :)। सौभाग्य!

0

मुझे यकीन नहीं है कि ऐसा क्यों होता है, लेकिन मैंने प्रत्येक cvShowImage के बाद एक cvWaitKey जोड़ा है और चित्र ठीक से प्रदर्शित किया गया था।

cvShowImage(myImage); 
cvWaitKey(1); 
संबंधित मुद्दे