मेरे पास टीएफ में एक पूर्व-प्रशिक्षित नेटवर्क है और मैं इसे नेटवर्क पर भेजने से पहले इनपुट छवि को प्रीप्रोसेस करना चाहता हूं (एकल चैनल फ्लोट32 में कनवर्ट करें और इसे [-1 1] पर सामान्यीकृत करें)।

//initialize network
    dnn::Net net = readNetFromTensorflow(modelFile);
    assert(!net.empty());

    Mat frame = imread(imageFile, IMREAD_GRAYSCALE);

    cv::equalizeHist(frame, frame);   
    Mat procFrame(frame.size(), CV_32FC1);

क्या प्रीप्रोसेसिंग करने के निम्नलिखित दो तरीकों और कौन सा अधिक कुशल है, के बीच कोई प्रदर्शन अंतर है?

// preprocess 1st way

    for (int i = 0;  i < frame.rows; i++) {
        for (int j = 0; j < frame.cols; j++){
            procFrame.at<float>(i, j) = frame.at<uint8_t>(i, j)*(2. / 255.) - 1.;
        }
    }

या

// preprocess 2nd way                   
    procFrame = frame*(2./ 255.);                                                           
    procFrame -= 1.;
0
fufuzz 10 मार्च 2020, 14:12
5
यह देखते हुए कि आपके पास दोनों समाधान हैं, क्या आपने निष्पादन समय को प्रोफाइल करने का प्रयास किया है?
 – 
Oliver.R
10 मार्च 2020, 14:19
procFrame.at<float>(i, j) वास्तव में अक्षम है। यदि आप वास्तव में सभी पिक्सेल पर मैन्युअल रूप से लूप लिखना चाहते हैं, तो पॉइंटर्स का उपयोग करें।
 – 
Cris Luengo
10 मार्च 2020, 18:21

2 जवाब

कॉपी करने का पहला तरीका बेहतर है क्योंकि आप मूल चर पर वापस लिखने के बजाय केवल एक दिशा में फ़्लोट को कॉपी और कनवर्ट करते हैं।

दूसरा तरीका जो आप अंकगणित करते हैं वह बहुत बेहतर है क्योंकि ओपनसीवी में अपने स्वयं के लूप को रोल करना बिल्टिन अंकगणितीय कार्यों का उपयोग करने से लगभग हमेशा धीमा होता है क्योंकि ओपनसीवी को सिम वेक्टराइजेशन और असेंबली स्तर पर अनुकूलन के कई अन्य रूपों का उपयोग करने के लिए संकलित किया जाता है।

लेकिन ये दोनों मेमोरी आवंटन (महत्वपूर्ण मंदी) के संबंध में अक्षम हैं यदि आप समय से पहले जानते हैं कि आपके फ्रेम किस आकार के होंगे क्योंकि आप रूपांतरण के लिए फ्लोट मैट्रिक्स को लगातार आवंटित और हटाते हैं।

procFrame को स्टेटिक (static Mat) घोषित करके और इसे ठीक उसी तरह बना कर जैसे आप उचित आकार के लिए कर रहे हैं, इससे बचने के लिए एक प्रीआलोकेटेड फ्लोट मैट्रिक्स को मेमोरी में रखें।

    static Mat procFrame(frame.size(), CV_32FC1);
    cv::equalizeHist(frame, frame);
    frame.convertTo(procFrame, CV_32FC1);                                   
    procFrame = procFrame*(2./ 255.);                                                           
    procFrame -= 1.;

यदि आपके फ्रेम का आकार रनटाइम के दौरान बदलता है, तो इसे स्थिर घोषित न करें।

1
Alex 10 मार्च 2020, 14:25
किसी भी समय! कृपया मेरे उत्तर को स्वीकार करें या अपवोट करें ताकि अगर आपको कोई आपत्ति नहीं है तो मुझे क्रेडिट मिलेगा!
 – 
Alex
10 मार्च 2020, 15:19
procFrame *= 2./ 255.;, procFrame = procFrame*(2./ 255.); की तुलना में अधिक कुशल होने की संभावना है, क्योंकि यह जगह पर काम कर सकता है।
 – 
Cris Luengo
10 मार्च 2020, 18:19

प्रदर्शन हमेशा अंतिम लक्ष्य नहीं होता है। यदि आप दूसरे दृष्टिकोण का उपयोग करते हैं, तो आप मैट के असाइनमेंट ऑपरेटर का उपयोग करेंगे। इसका मतलब है कि ऑपरेशन के दौरान किसी भी अपवाद को Mat& operator= (const Mat &m) के अंदर संभाला जाएगा जो पेशेवरों द्वारा लिखा गया है।

वैसे भी, मेरा मानना ​​है कि Mat& operator= (const Mat &m) का उपयोग करना सबसे कुशल और कम से कम त्रुटि प्रवण असाइनमेंट का तरीका है। Mat तत्वों पर पुनरावृति करके इसे स्वयं लिखने का प्रयास न करें।

1
Ali 10 मार्च 2020, 15:13