Мне нужно преобразовать изображение CV_8U с 3 каналами в изображение, которое должно быть одним каналом CV_32S. Но когда я пытаюсь это сделать, изображение, которое я получаю, полностью черное. Я не понимаю, почему мой код не работает.
Я имею в виду изображение в градациях серого, поэтому я делю трехканальное изображение на вектор одноканального изображения, а затем обрабатываю только первый канал.
//markers->Image() returns a valid image, so this is not the problem
cv::Mat dst(markers->Image().size(), CV_32SC1);
dst = cv::Scalar::all(0);
std::vector<cv::Mat> vectmp;
cv::split(markers->Image(), vectmp);
vectmp.at(0).convertTo(dst, CV_32S);
//vectmp.at(0) is ok, but dst is black...?
Заранее спасибо.
Вы пытались получить значения результирующего изображения? Как это:
for (int i=0; i<result.rows; i++)
{
for (int j=0; j<result.cols; j++)
{
cout << result.at<int>(i,j) << endl;
}
}
Я преобразовал (также использовал convertTo
) случайное серое одноканальное изображение для CV_32S
(это 32-битное целое значение со знаком для каждого пикселя) мой вывод был таким:
80
111
132
И когда я попытался показать это, я также получил черное изображение. От документация:
Если изображение является 16-разрядным без знака или 32-разрядным целым числом, пиксели
делится на 256. То есть диапазон значений [0,255 * 256] отображается на
[0255].
Таким образом, если вы разделите эти маленькие числа на 255, то вы получите 0 (int
тип). Вот почему imshow
отображает черное изображение.
Если вы хотите отобразить 32-битное изображение и увидеть значимый результат, вам нужно умножить все его элементы на 256 до вызова imshow
, Иначе, imshow
уменьшит ваши значения до нуля, и вы получите черное изображение (как указал Астор).
Поскольку исходные значения являются 8-битными без знака, они должны быть меньше 255. Поэтому умножение их на 256 безопасно и не будет переполнять 32-битное целое число.
РЕДАКТИРОВАТЬ Я только что понял, что ваш тип вывода подписанный 32-разрядное целое число, но оригинальный тип неподписанный 8-битное целое число. В этом случае вам необходимо соответствующим образом масштабировать ваши значения (посмотрите на scaleAdd).
Наконец, вы можете убедиться, что ваше изображение в формате YCbCr, прежде чем вы начнете выбрасывать каналы изображения.
У меня была та же проблема, я решил ее косвенным путем, пытаясь преобразовать 8UC1 в 32S вместо 8UC3.
RgbToGray принимает создание серого изображения, используя тип элемента 8UC3 или 8UC1.
8UC1 — это мой маркер.
Я сделал это в Opencvsharp:
Mat buf3 = new Mat(iplImageMarker);
buf3.ConvertTo(buf3, MatType.CV_32SC1);
iplImageMarker= (IplImage)buf3;
iplImageMarker=iplImageMarker* 256;
Я считаю, что это то, что вы ищете. Преобразуйте ваше изображение в этот 8-битный одноканальный канал. CV_8UC1. Вы начинаете с 8-битного изображения и меняете его на 32-битный одноканальный? Зачем? Держите это 8 бит.