Каковы различия между CV_8U и CV_32F и что я должен беспокоиться при конвертации между ними?
У меня есть код, который действует, и я подозреваю, потому что я работаю с неправильными типами данных или плохо переключаюсь между ними.
Он смешивает объекты cv::Mat
типов CV_8U
(это то, что создается при чтении jpg в оттенках серого с помощью cv::imread
), CV_32F
и CV_32S
.
Каковы различия между этими типами данных и что мне нужно знать при конвертации между ними?
Ответы
Ответ 1
CV_8U без знака 8 бит/пиксель - то есть пиксель может иметь значения 0-255, это нормальный диапазон для большинства форматов изображений и видео.
CV_32F - float - пиксель может иметь любое значение между 0-1.0, это полезно для некоторых наборов вычислений данных - но его нужно преобразовать в 8 бит для сохранения или отображения путем умножения каждого пикселя на 255.
CV_32S - это подписанное 32-битное целочисленное значение для каждого пикселя - снова полезно, что вы делаете целочисленные математические вычисления на пикселях, но снова необходимо преобразовать в 8 бит для сохранения или отображения. Это сложнее, так как вам нужно решить, как преобразовать гораздо больший диапазон возможных значений (+/- 2billion!) В 0-255
Ответ 2
В основном они просто описывают, что представляют собой отдельные компоненты:
-
CV_8U
: 1-байтовое целое без знака (unsigned char
).
-
CV_32S
: 4-байтовое целое число со знаком (int
).
-
CV_32F
: 4-байтная с плавающей запятой (float
).
Что вы всегда должны иметь в виду, так это то, что вы не можете просто отбрасывать их из одного в другой (или, вероятно, не будет делать то, что вы хотите), особенно между типами разных размеров.
Поэтому всегда убедитесь, что вы используете реальные функции преобразования для преобразования между ними, например cv::convert
или cv::Mat::convertTo
. Не просто пытайтесь получить доступ к элементам, например. a cv::Mat
типа CV_8U
с использованием, например, cv::Mat::at<float>
или cv::Mat_<float>
.
Или, если вы просто хотите преобразовать отдельные элементы и не хотите создавать новую матрицу другого типа, обратитесь к элементам с помощью соответствующей функции (в примере cv::Mat::at<unsigned char>
) и преобразуйте результат в float
.
Кроме того, существует также разница между количеством компонентов и типом cv::Mat
типа CV_8UC3
, отличным от образа типа CV_8UC1
и не должен (как правило,) недоступен cv::Mat::at<unsigned char>
, а через cv::Mat::at<cv::Vec3b>
.
РЕДАКТИРОВАТЬ: Увидев ответ Мартина, возможно, вы знаете об этом, и его объяснения - это то, что вы искали.