Применить таблицу поиска openCV (LUT) к изображению с одним каналом - PullRequest
1 голос
/ 10 ноября 2019

Моя цель - взять изображение, преобразовать его в цветовое пространство LAB, а затем применить пользовательскую таблицу поиска только к каналу освещенности и отобразить его. LUT будет применять градиент от синего к красному - поэтому мое выходное изображение будет показывать самые яркие части изображения красным и самые темные синим.

void MainWindow::convertBGRMatToLAB(const cv::Mat inputMat)
{
    // Create lookup table (LUT)
    cv::Mat lookupTable(1, 256, CV_8UC(3));
    for (int i=0; i<256; i++)
    {
        lookupTable.at<cv::Vec3b>(i)[0]= 255-i; // first channel  (B)
        lookupTable.at<cv::Vec3b>(i)[1]= 0;     // second channel (G)
        lookupTable.at<cv::Vec3b>(i)[2]= 255+i; // ...            (R)
    }

    // Convert to LAB color space.
    cv::Mat convertedLAB;
    cv::cvtColor(inputMat, convertedLAB, CV_BGR2Lab);

    // Isolate the L, A, B channels.
    cv::Mat convertedLABSplit[3];
    cv::split(convertedLAB, convertedLABSplit);

    // Apply our custom lookup table to L channel.
    cv::Mat outputMat(inputMat.rows, inputMat.cols, CV_8UC3);
    cv::LUT(convertedLABSplit[0], lookupTable, outputMat); // Program crashes here.
    //cv::LUT(inputMat, lookupTable, outputMat); // This works (but not what I am looking to do).

    // Show the output image
    cv::imshow("Output Image", outputMat);
}

Но когда я запускаю свое приложение (Qt)Я получаю ошибку отладки библиотеки времени выполнения Microsoft Visual C ++: VC++ Runtime error

и:

OpenCV Error: Assertion failed ((lutcn == cn || lutcn == 1) && _lut.total() == 256 && _lut.isContinuous() && (depth == 0 || depth == 1)) in cv::LUT, file C:\OpenCV\3.4.0\source\opencv-3.4.0\modules\core\src\convert.cpp, line 4552

Я считаю, что проблема связана с применением LUT к одномуИзображение канала, как показано в приведенном выше коде, если применить LUT только к входному изображению. Поэтому вместо:

cv::LUT(convertedLABSplit[0], lookupTable, outputMat);

я изменяю его на:

cv::LUT(inputMat, lookupTable, outputMat);

Но я бы хотел применить свою LUT только к каналу L в цветовом пространстве LAB и отбросить A иКаналы B.

Связана ли проблема с тем, как я создаю свой LUT? Как я должен создать LUT, как это для одноканального изображения?

1 Ответ

1 голос
/ 10 ноября 2019

Благодаря комментарию @Dan Mašek выше. Я добавляю это как ответ здесь, чтобы вопрос мог быть помечен как отвеченный.

Для 3-канальной справочной таблицы вход также должен быть 3-канальным. Просто объедините 3 копии канала L обратно в трехканальный мат и примените LUT к результату.

Обновленный код:

void MainWindow::convertLightToDarkColorMap(const cv::Mat inputMat)
{
    // Create lookup table (LUT)

    cv::Mat lookupTable(1, 256, CV_8UC(3));
    for (int i=0; i<256; i++)
    {
        lookupTable.at<cv::Vec3b>(i)[0]= 255-i; // first channel  (B)
        lookupTable.at<cv::Vec3b>(i)[1]= 0;     // second channel (G)
        lookupTable.at<cv::Vec3b>(i)[2]= 255+i; // ...            (R)
    }

    // Convert to LAB color space.
    cv::Mat convertedLAB;
    cv::cvtColor(inputMat, convertedLAB, CV_BGR2Lab);

    // Isolate the L, A, B channels.
    cv::Mat convertedLABSplit[3];
    cv::split(convertedLAB, convertedLABSplit);

    // 3 channel LUT only works on a 3 channel input.  So take (3) copes of the L channel and merge them into one.
    cv::Mat trippleL;
    std::vector<cv::Mat> trippleLArr;
    trippleLArr.push_back(convertedLABSplit[0]);
    trippleLArr.push_back(convertedLABSplit[0]);
    trippleLArr.push_back(convertedLABSplit[0]);
    cv::merge( trippleLArr, trippleL);

    // Apply our custom lookup table to L channel.
    cv::Mat outputMat(inputMat.rows, inputMat.cols, CV_8UC3);
    cv::LUT(trippleL, lookupTable, outputMat);

    // Show the output image
    cv::imshow("Output", outputMat);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...