Я пытаюсь извлечь пиксели из OpenCV Mat
объект. Когда я извлекаю их как Vec4b
, это работает хорошо, но когда я использую Scalar
, который является стандартом (afaik), то я получаю странные цифры. Как пользоваться Scalar
и правильно интерпретировать числа?
Код для извлечения пикселя (0, 0), один раз как Vec4b
объявление сразу как Scalar
(который находится в Scalar_<double>
):
cv::Vec4b vec = stroke.at<cv::Vec4b>(0, 0);
printf("vec: %i, %i, %i\n", vec[0], vec[1], vec[2]);
cv::Scalar sca = stroke.at<cv::Scalar>(0, 0);
printf("sca: %5.1f, %5.1f, %5.1f\n", sca[0], sca[1], sca[2]);
Выход:
vec: 223, 178, 77
sca: -91331626426359316704088074967484318223735050578187982644502863694523413598032925912253837118690612448172200441235555626964757579094862898778997953403371230682094365379726071857064466448183314663075981261984082516073752896735112503485663679145991425485597914964276617645535969580912538709979773360278601728.0, ...
Я ожидаю немного кремового желтого цвета, так что я думаю, что Vec3b
верно.
Ну это интересно
Для серой шкалы вы обычно используете cv::Scalar
вот так:
Scalar myColor = stroke.at<uchar>(Point(x, y));
std::cout << myColor.val[0] << std::endl;;
За 3-channel
цветное изображение вам нужно cv::vec3b
вот так:
Vec3b myColor = stroke.at<Vec3b>(Point(x, y));
for(int i = 0; i < 3; i++) std::cout << myColor.val[i] << " ";
Как следует из названия (как видно Вот) скаляр — это единое целое, а не векторная единица. Что может быть путано с показанной документацией Вот. Но что вы можете сделать, если вы должны иметь свои ценности себя как cv::Scalar
типа, вы можете просто назначить каждому vec3b
Индекс к своему собственному скаляру. то есть:
cv::Scalar b = vec[0];
cv::Scalar g = vec[1];
cv::Scalar r = vec[2];
Для .at<_Tp>()
Для корректной работы функции необходимо правильно указать тип данных компонента матрицы изображения. Если вам этого не нужно, двоичные данные пикселя будут неверно истолкованы, и вы получите неожиданные результаты.
После того как вы извлекли значение пикселя правильно, вы можете преобразовать его в любой другой универсальный Scalar_<_Tp>
типа хочешь. Обычно вы конвертируете его в Scalar
который на самом деле является псевдонимом для Scalar_<double>
, Преобразование неявным образом выполняется с помощью оператора присваивания (=
).
Больше деталей:
Большинство матриц изображения поставляются с кодом типа CV_8UC4
(4 канала, красный, зеленый, синий и альфа). Например. при загрузке цветного изображения из файла JPG матрица изображения будет иметь этот формат. 8U
означает «8 бит на канал, целое число без знака» и C4
означает «4 канала на матричный элемент». Соответствующий тип C ++ элементов Scalar_<uchar>
, Вы должны приспособить это к универсальному .at<_Tp>()
Функция, чтобы заставить это работать:
mat.at<Scalar_<uchar>(y, x)
После правильного извлечения Scalar_<uchar>
, вы можете автоматически преобразовать его в Scalar
(что на самом деле Scalar_<double>
) просто по назначению:
cv::Scalar scalar = mat.at<cv::Scalar_<uchar>>(0, 0);