Установить ось ограничения цвета в OpenCV 4 (c ++), схожую с CAXIS от Matlab - PullRequest
0 голосов
/ 27 декабря 2018

Matlab предлагает возможность установить пределы цвета для текущей оси, используя CAXIS .OpenCV имеет applyColorMap , который можно использовать для выделения различий в интенсивности пикселей в полутоновом изображении, которое, как я считаю, отображает пиксели от 0 до 255.

Я новичок в Matlab / Image-processing и имеюбыло предложено портировать простую программу от MatLab, которая использует функцию CAXIS для изменения «яркости» цветовой карты.У меня нет опыта работы с Matlab, но похоже, что они используют эту функцию, чтобы «понизить» требования к интенсивности, необходимые для отображения пикселей на более интенсивный цвет на карте

, т. Е. Карта цветов с использованием «JET»

  • Когда яркость = 1, красный = 255
  • Когда яркость = 10, красный> = 25

Программа Matlab позволяет считывать 16-битные изображения иотображается, что дает более высокие значения пикселей, тогда как все, что я прочитал и сделал, указывает, что OpenCV поддерживает только 8-битные изображения (для цветных карт)

Поэтому мой вопрос заключается в том, возможно ли обеспечить аналогичную функциональность в OpenCV?Как установить предел оси для карты цветов / как масштабировать таблицу поиска цветовой карты, чтобы «менее» интенсивные пиксели масштабировались в более интенсивные области?

Аналогичный вопрос был спросил с ответом о том, что массив должен быть "нормализован", но, к сожалению, я не совсем знаю, как этого добиться, и не могу ответить на ответ, так как мне не хватает представителя!

Я пошел дальше и использовал cv :: normalize , чтобы установить максимальное значение в массиве равным maxPixelValue / яркости, но это не работает вообще.

Я также экспериментировали попытался преобразовать мое 16-битное изображение в CV_8UC1 с масштабным коэффициентом безрезультатно.Любая помощь будет принята с благодарностью!

Ответы [ 2 ]

0 голосов
/ 28 декабря 2018

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

мой код выглядел примерно такthis

cv::minMaxLoc(dst, &min, &max);

double axisThreshold = floor(max / contrastLevel);

 for (int i = 0; i < dst.rows; i++)
    {
        for (int j = 0; j < dst.cols; j++)
        {
            short pixel = dst.at<short>(i, j);
            if (pixel >= axisThreshold)
            {
                pixel = USHRT_MAX;
            }
            else
            {
                pixel *= (USHRT_MAX / axisThreshold);
            }
            dst.at<short>(i, j) = cv::saturate_cast<short>(pixel);
        }
    }

В моем примере у меня был ползунок, который регулировал контрастность / яркость (мы называли это контрастом, оригинальная реализация называла его яркостью).

Когда контрастность / яркость были измененыпрограмма извлекает максимальное значение пикселя, а затем вычисляет предел оси, выполняя

selectedThreshold = максимальное значение пикселя / контрастность

Каждый пиксель, превышающий пороговое значение, устанавливается равным MAX, каждый пиксель нижечем пороговое значение умножается на масштабный коэффициент, рассчитанный на

scale = MAX Pixel Value / рассчитанныйThreshold.

TBH Я не могу сказать, что я полностью понимаю математику, стоящую за ним.Я просто использовал метод проб и ошибок, пока он не сработал;любая помощь в этом отделе была бы признательна, ОДНАКО она, кажется, делает то, что я хочу!

Мое понимание первоначальной реализации Matlab и терминологии «яркость» фактически является их попыткой масштабировать цветовую карту так, чтобы ««Чем ярче» изображение, тем менее интенсивным должен быть каждый пиксель для отображения на определенный цвет в карте цветов.

Поскольку applycolourmap работает только на 8-битных изображениях, когда яркость увеличивается, а значения оси цветов уменьшаются, мынеобходимо обеспечить соответственно масштабирование значений пикселей, чтобы они теперь соответствовали «более высоким» значениям интенсивности на карте.

Я видел множество учебных пособий OPENCV, в которых используется этот подход для изменения контрастности / яркости, ноони часто способствуют использованию оптимизированного convertTo (особенно, если вы пытаетесь использовать графический процессор).Однако, насколько я вижу, convertTo применяет значения aplha / beta равномерно, а не по пикселям, поэтому я не могу использовать этот подход.

Я обновлю этот вопрос, если я найду более подходящие функции OPENCV для достижения того, чего я хочу.

0 голосов
/ 27 декабря 2018

По моему мнению, вы можете использовать cv::normalize, чтобы "обрезать" значения в исходном изображении до соответствующих значений в цветной карте, которая вас интересует. Допустим, вы хотите, чтобы ваше изображение было отображено в сине-голубую область карты цветов Jet.тогда вы должны сделать что-то вроде:

int minVal = 0, maxVal = 80;
cv::normalize(src,dst, minVal, maxVal, cv::NORM_MINMAX);

Если вы планируете применить какую-то пользовательскую карту, это довольно просто для 1-или 3-канального 8-битного изображения, вам нужно только создать LUT с 255 значениями (с соответствующим количеством каналов) и примените его, используя cv::LUT, подробнее об этом в этом блоге , также см. DOC о LUT

Если изображение выРабота имеет разную глубину, 16-битные данные или даже данные с плавающей запятой. Полагаю, все, что вам нужно, это написать такую ​​функцию:

template<class T> 
T customColorMapper(T input_pixel)
{
    T output_pixel = 0;
    // do something with output_pixel basing on intput_pixel
    return output_pixel;
}

и применить ее к каждому пикселю исходного изображения, например:

cv::Mat dst_image = src_image.clone(); //copy data
dst_image.forEach<TYPE>([](TYPE& input_pixel, const int* pos_row_col) -> void {
    input_pixel = customColorMapper<TYPE>(input_pixel);
});

конечно TYPE должен быть допустимым типом.Возможно, специализированная версия этой функции, принимающая cv::Scalar или cv::Vec3, может быть полезна, если вам нужно работать с несколькими каналами.

Надеюсь, это поможет!

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