OpenCV: не удается правильно прочитать одноканальное изображение png с 16-битной глубиной

#image #opencv #image-processing #png

#изображение #opencv #обработка изображений #png

Вопрос:

Я пытаюсь прочитать изображение png с одним каналом и 16-битной глубиной. Впоследствии я нахожу значения пикселей в строке:

 //read the image data in the file "MyPic.JPG" and store it in 'img'
Mat img = imread("sir.png",  CV_LOAD_IMAGE_ANYDEPTH); 

//Iterate through the line along which Intensity profile is required 
LineIterator it(img, Point(1,1), Point(20,20), 8);

vector<Vec3b> buf;   

for(int i=0; i<it.count; i  )
{
    buf.push_back( Vec3b(*it) );
    it  ;
}
//print pixel value on the selected line
cerr << Mat(buf) << endl;
  

Напечатанные значения всегда являются nos, которые меньше 255:

 156, 156, 164; 153, 153, 152; 154, 154, 139; 179, 179, 180; 182, 182, 176; 2
208, 167; 144, 144, 163; 204, 204, 206; 180, 180, 187; 174, 174, 170; 150, 1
162; 154, 154, 170; 157, 157, 181; 181, 181, 159; 164, 164, 152; 130, 130, 1
166, 166, 181; 153, 153, 170; 153, 153, 176; 180, 180, 198]
  

Это означает, что на самом деле это изображение считывается как 8-битное вместо 16-битного.

Я проверил свое изображение в MATLAB, и я вижу значения, которые действительны для 16 бит, такие как :

 d=imread('sir.png');
buf = improfile( d, [1 20], [1 20] )
  

которое выдает такие выходные данные, как:

65535
40092
39321
39578
46003
46774
53456
37008
52428
46260
44718
38550
39578
40349
46517
42148
33410
42662
39321
39321

Почему мой результат в opencv отличается от фактического? Как мне правильно прочитать изображение, чтобы оно отображало значения в 16 битах?

Обновить

Основываясь на ответе Роджера, я обновил свой код следующим образом:

 LineIterator it(img, Point(1,1), Point(20,20), 8);
vector<ushort> buf;

for(int i = 0; i < it.count; i  )
{
    buf.push_back(img.at<ushort>(it.pos()));
}

cerr << Mat(buf) << endl;
  

Но теперь ВСЕ мои значения пикселей равны 40092, что неверно по сравнению с выводом MATLAB.

Ответ №1:

Вы используете Vec3b для обработки пикселей, это разбивает его на 8-битные фрагменты.

Используйте Vec3s вместо Vec3b . Это даст вам 16-битные пиксели. Это предполагает, что у вас есть 3 16-битных канала, а не один канал с 16-битными оттенками серого (что, я думаю, вы получите из PNG), и в этом случае вы получили бы доступ, например, через at<ushort>(y,x) .

 LineIterator it(img, Point(1,1), Point(20,20), 8);

vector<ushort> buf;

for(int i = 0; i < it.count; i  , it  )
{
    buf.push_back(img.at<ushort>(it.pos()));
}
  

Комментарии:

1. итак, каково решение?

2. на самом деле исходное изображение представляет собой одноканальное 16-битное изображение, поэтому Vec3S не работает

3. Не могли бы вы, пожалуйста, поместить фрагмент кода для того, что я использую, вместо vec3b и далее. Мое изображение в одноканальном формате.

4. Это дает 20 одинаковых значений 40092, хотя это справедливо для 16-битного изображения, но неверно, если сравнивать с выводом MATLAB

5. Действительно, 40092 является одним из значений, как вы можете видеть в выходных данных MATLAB. Но почему все значения приходят именно так?