Изменить тип объекта 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)