OpenCV: объединение разделенных байеровских каналов JPEG

У меня есть камера, которая дает 4 отдельных изображения JPEG для 4 разных каналов Байера (B, G1, G2, R).

Я хочу преобразовать это в цветное изображение.

Что я делаю в данный момент, так это распаковываю jpeg, восстанавливаю «исходное» изображение вручную и преобразовываю его в цветное изображение с помощью cvtColor. Но это слишком медленно. Как я могу сделать это лучше?

    cv::Mat imgMat[4]=cv::Mat::zeros(616, 808, CV_8U); //height, width
    for (k=0;k<4;k++) {
        ........
        imgMat[k] = cv::imdecode(buffer, CV_LOAD_IMAGE_GRAYSCALE);
    }
    //Reconstruct the original image from the four channels! RGGB
    cv::Mat Reconstructed=cv::Mat::zeros(1232, 1616, CV_8U);
    int x,y;
    for(x=0;x<1616;x++){
        for(y=0;y<1232;y++){
            if(y%2==0){
                if(x%2==0){
                    //R
                    Reconstructed.at<uint8_t>(y,x)=imgMat[0].at<uint8_t>(y/2,x/2);
                }
                else{
                    //G1
                    Reconstructed.at<uint8_t>(y,x)=imgMat[1].at<uint8_t>(y/2,floor(x/2));
                }
            }
            else{
                if(x%2==0){
                    //G2
                    Reconstructed.at<uint8_t>(y,x)=imgMat[2].at<uint8_t>(floor(y/2),x/2);
                }
                else{
                    //B
                    Reconstructed.at<uint8_t>(y,x)=imgMat[3].at<uint8_t>(floor(y/2),floor(x/2));
                }
            }
        }
    }
    //Debayer
    cv::Mat ReconstructedColor;
    cv::cvtColor(Reconstructed, ReconstructedColor, CV_BayerBG2BGR);

Кажется очевидным, что для декодирования изображений в формате jpeg требуется больше времени. Есть ли у кого-нибудь совет/хитрость, которые я мог бы использовать, чтобы ускорить этот код?


person Josep Bosch    schedule 11.07.2013    source источник
comment
Вы уверены, что не можете настроить камеру на вывод необработанного байеровского изображения без разделения каналов и без сжатия jpg? Это может быть проблемой с точки зрения пропускной способности, но наверняка ускорит последующую проработку...   -  person Antonio    schedule 11.07.2013
comment
Да. Я могу сделать это, выбрав другой режим. Но тогда частота кадров, которую я получаю, очевидно, намного медленнее ... Я хотел бы работать с более высокой частотой кадров.   -  person Josep Bosch    schedule 11.07.2013
comment
Я бы проверил, где реально тратится время. Если он находится на этапе реконструкции изображения BGGR, у вас есть надежда. Если, с другой стороны, время действительно тратится на imdecode(), я не вижу способа его оптимизировать. Если этап реконструкции изображения BGGR занимает большую часть времени в ваших вычислениях, мое первое предположение состоит в том, что вам нужно заглянуть в код cvtColor и переписать собственное байеровское преобразование с другим типом ввода. Также убедитесь, что вы не тратите время на перераспределение памяти (все эти нули можно изменить с помощью setTo(0). )   -  person Antonio    schedule 11.07.2013
comment
Спасибо Антонио. Большая часть времени была потрачена на этап реконструкции, и я мог оптимизировать его с помощью ответа ниже. Это еще не так быстро, как хотелось бы, но я не думаю, что смогу улучшить какую-либо функцию imdecode или dvtColor. Ваше здоровье!   -  person Josep Bosch    schedule 11.07.2013


Ответы (1)


Во-первых, вы должны сделать профиль, чтобы увидеть, куда в основном уходит время. Может быть, все дело в imdecode(), как "кажется ясным", но вы можете ошибаться.

Если нет, то .at<>() немного медленный (и вы вызываете его почти 4 миллиона раз). Вы можете получить некоторое ускорение за счет более эффективного сканирования изображения. Также вам не нужно floor() - это позволит избежать преобразования int в double и обратно (2 миллиона раз). Что-то вроде этого будет быстрее:

int x , y;
for(y = 0; y < 1232; y++){
    uint8_t* row = Reconstructed.ptr<uint8_t>(y);
    if(y % 2 == 0){
        uint8_t* i0 = imgMat[0].ptr<uint8_t>(y / 2);
        uint8_t* i1 = imgMat[1].ptr<uint8_t>(y / 2);

        for(x = 0; x < 1616; ){
            //R
            row[x] = i0[x / 2];
            x++;

            //G1
            row[x] = i1[x / 2];
            x++;
        }
    }
    else {
        uint8_t* i2 = imgMat[2].ptr<uint8_t>(y / 2);
        uint8_t* i3 = imgMat[3].ptr<uint8_t>(y / 2);

        for(x = 0; x < 1616; ){
            //G2
            row[x] = i2[x / 2];
            x++;

            //B
            row[x] = i3[x / 2];
            x++;
        }
    }
}
person Bull    schedule 11.07.2013
comment
Спасибо! Это было здорово. После более точного наблюдения за временем я обнаружил, что время для образца кадра было следующим: Время чтения изображений: 0,008328 Время реконструкции изображения: 0,041352 Время дебайеризации: 0,004263 После использования вашего кода время было: Время чтения изображений: 0,008466 Время реконструкции изображения: 0,008402 Время дебайеризации : 0.004364 Это в 4 раза быстрее реконструирует изображения и экономит 3 сотые секунды! Я не думаю, что я могу стать лучше, чем это сейчас! - person Josep Bosch; 11.07.2013