Есть ли существенная разница в производительности между использованием конструктора назначения копирования и итерацией по элементам для модификации Mat? - PullRequest
0 голосов
/ 10 марта 2020

У меня есть предварительно обученная сеть в TF, и я хочу предварительно обработать входное изображение (преобразовать в одноканальный float32 и нормализовать его до [-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.;

Ответы [ 2 ]

1 голос
/ 10 марта 2020

Производительность не всегда является конечной целью. Если вы используете второй подход, вы будете использовать оператор присваивания мата. Это означает, что любые исключения во время операции будут обрабатываться внутри Mat& operator= (const Mat &m), написанного профессионалами.

В любом случае, я считаю, что использование Mat& operator= (const Mat &m) является наиболее эффективным и наименее подвержен ошибкам способ назначения. Не пытайтесь писать это самостоятельно, перебирая элементы Mat.

1 голос
/ 10 марта 2020

Первый способ копирования предпочтительнее, потому что вы копируете и конвертируете в плавающее в одном направлении, а не записываете обратно в исходную переменную.

Второй способ выполнения арифметики c - ОЧЕНЬ СУПЕР потому что прокатка ваших собственных циклов в OpenCV почти всегда медленнее, чем использование встроенных арифметических c функций, потому что OpenCV скомпилирован для использования векторизации SIMD и многих других форм оптимизации на уровне сборки.

Но оба они неэффективны о распределении памяти (значительное замедление), если вы заранее знаете, каким будет размер ваших кадров, потому что вы постоянно выделяете и освобождаете матрицу с плавающей запятой для преобразования. procFrame as stati c (static Mat) и его создание сразу же, как вы делаете, чтобы получить правильный размер.

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

Если размер вашего кадра изменяется во время выполнения, не объявляйте его as stati c.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...