Изменить тип объекта Mat с CV_32F на CV_8U

Я попытался отобразить изображение типа CV_32F с помощью функции imshow, но оно показало БЕЛЫЕ изображения. В документации дано, что изображения с плавающей запятой будут отображаться в 0-255 и отображаться, но на нем было только белое изображение. Я попытался преобразовать его в CV_8U, используя

Mat A=Mat::ones(300,300,CV_32FC1)*1000;

выполнить некоторую обработку - присвоить значения с плавающей точкой пикселям в A

......

Мат B;

A.convertTo (В,CV_8U)

Когда я показываю "B", я получаю черно-белое изображение, в котором нет оттенков серого. Пиксели с плавающей точкой в ​​A правильно отображаются в 0-255? Я делаю что-то не так?

Немногочисленные значения в A равны 1000, а остальные представляют собой числа с плавающей запятой, которые назначаются во время обработки.

1 ответ

Решение

В OpenCV, если изображение имеет тип с плавающей запятой, то только те пиксели могут быть визуализированы с помощью imshow, которые имеют значение от 0,0 до 1,0, если значение больше 1,0, оно будет отображаться в виде белого пикселя, а если меньше 0,0, оно будет отображаться в виде черного пикселя. Чтобы визуализировать изображение с плавающей точкой, масштабируйте его значения до диапазона 0.0 - 1.0,

Что касается части преобразования.... При использовании с аргументами по умолчанию cv::Mat::convertTo Функция просто создает матрицу указанного типа, затем копирует значения из исходной матрицы и затем округляет их до ближайшего возможного значения целевого типа данных. Если значение выходит за пределы диапазона, оно фиксируется на минимальных или максимальных значениях.

В документации imshowнаписано что:

Если изображение является 32-битной плавающей точкой, значения пикселей умножаются на 255. То есть диапазон значений [0,1] отображается на [0,255].

Это означает, что только значения в диапазоне от 0,0 до 1,0 будут сопоставлены с 0 до 255. Если значение больше 1,0 и умножено на 255, оно станет больше 255. Чем оно будет зафиксировано в диапазоне CV_8U и в конечном итоге он также станет 255.

В вашем примере все значения, которые равны 1000, станут 255 в матрице назначения, поскольку тип назначения CV_8U и максимально возможное значение 255. Все значения с плавающей запятой будут floorредактор Автоматическое сопоставление не выполняется.

Чтобы правильно сопоставить значения с диапазоном CV_8U используйте 3-й и 4-й параметры функции cv::Mat::convertTo, так что значения масштабируются перед выполнением преобразования.

Предположим, матрица A имеет минимальные и максимальные значения Min а также Max, где Min!=Max,

Чтобы правильно масштабировать значения от 0 до 255, вы можете сделать следующее:

if (Min!=Max){ 
    A -= Min;
    A.convertTo(B,CV_8U,255.0/(Max-Min));
}

Вы также можете сделать это прямо так:

if (Min!=Max)
    A.convertTo(B,CV_8U,255.0/(Max-Min),-255.0*Min/(Max-Min));

(отредактировано с учетом комментария zhangxaochen)

Другие вопросы по тегам