2012-12-12 3 views
16

Я использую набор данных, в котором у него есть изображения, где каждый пиксель представляет собой 16-битный беззнаковый int, сохраняющий значение глубины этого пикселя в мм. Я пытаюсь представить себе это как градаций серого глубины изображения, выполнив следующие действия:OpenCV: Как визуализировать изображение глубины

cv::Mat depthImage; 
depthImage = cv::imread("coffee_mug_1_1_1_depthcrop.png", CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR); // Read the file 
depthImage.convertTo(depthImage, CV_32F); // convert the image data to float type 
namedWindow("window"); 
float max = 0; 
for(int i = 0; i < depthImage.rows; i++){ 
    for(int j = 0; j < depthImage.cols; j++){ 
     if(depthImage.at<float>(i,j) > max){ 
      max = depthImage.at<float>(i,j); 
     } 
    } 
} 
cout << max << endl; 


float divisor = max/255.0; 
cout << divisor << endl; 
for(int i = 0; i < depthImage.rows; i++){ 
    for(int j = 0; j < depthImage.cols; j++){ 
     cout << depthImage.at<float>(i,j) << ", "; 
     max = depthImage.at<float>(i,j) /= divisor; 
     cout << depthImage.at<float>(i,j) << endl; 
    } 
} 


imshow("window", depthImage); 
waitKey(0); 

Однако, это только показывает два цвета это происходит потому, что все значения будут близки друг к другу, то есть в диапазоне 150-175 + небольшие значения, которые отображаются черным цветом (см. ниже).

rgb image greyscale image

Есть ли способ, чтобы нормализовать эти данные так, что он будет показывать различные уровни серого, чтобы выделить эти небольшие различия глубины?

ответ

19

Согласно documentation, функция imshow может использоваться с различными типами изображений. Он поддерживает 16-битные неподписанные изображения, так что вы можете отобразить изображение с помощью

cv::Mat map = cv::imread("image", CV_LOAD_IMAGE_ANYCOLOR | CV_LOAD_IMAGE_ANYDEPTH); 
cv::imshow("window", map); 

В этом случае диапазон значений изображения отображается в диапазоне [0, 255 * 256] в диапазоне [0, 255] ,

Если ваше изображение содержит только значения в нижней части этого диапазона, вы увидите неясное изображение. Если вы хотите использовать полный диапазон отображения (от черного до белого), вы должны настроить изображение, чтобы покрыть ожидаемый динамический диапазон, один из способов сделать это

double min; 
double max; 
cv::minMaxIdx(map, &min, &max); 
cv::Mat adjMap; 
cv::convertScaleAbs(map, adjMap, 255/max); 
cv::imshow("Out", adjMap); 
+0

Я не понимаю, почему его масштабирование на 255/max (sam, когда я деля каждый элемент на max/255), он будет использовать весь диапазон. Я имею в виду, что это так, и я буду принимать ответ, но я просто не понимаю. Что еще делает эта функция? – Aly

+0

[convertScaleAbs] (http: //docs.opencv.org/modules/core/doc/operations_on_arrays.html? highlight = converttscaleabs # cv.ConvertScaleAbs) выполняет 3 операции: масштабирование, вычисление абсолютного значения и преобразование в неподписанный 8-битный тип. Вот почему коэффициент 255/max обеспечивает полный диапазон ([0-255] для беззнакового 8-битного). Кроме того, как отметил @sammy, динамический диапазон скорректированного изображения лучше использовать, учитывая минимальное значение ваших данных. – samota

2

Если вход imshow имеет тип данных с плавающей точкой, тогда функция предполагает, что значения пикселей находятся в [0; 1]. В результате все значения, превышающие 1, отображаются белыми.

Так что вам не нужно разделить ваш divisor на 255.

+0

После этих строк: 'depthImage = резюме :: imread ("coffee_mug_1_1_1_depthcrop.png", CV_LOAD_IMAGE_ANY DEPTH | CV_LOAD_IMAGE_ANYCOLOR); depthImage.convertTo (depthImage, CV_32F); 'Если я напечатаю значения, они находятся в диапазоне [0,1161], поэтому мой делитель равен 1161/255, чтобы получить все значения в диапазоне [0,255], возможно, если я тогда конвертирую это CV_8UC1? – Aly

+0

Ах да, это сработало. Плюс, если я использую гистограмму с выравниванием, это дает гораздо лучшее представление. – Aly

+0

Во-первых, функция 'imread' считывает ваши изображения, сохраняя исходные значения, поэтому 1161 - это Ok для 16 бит на пиксельное изображение. Во-вторых, метод «convertTo» по умолчанию не масштабирует значения, он только меняет тип и насыщает. Так что это объясняет, почему печатные значения настолько велики. –

17

Добавление к samg»ответа, вы можете расширить тем более диапазон отображаемого изображения.

double min; 
double max; 
cv::minMaxIdx(map, &min, &max); 
cv::Mat adjMap; 
// expand your range to 0..255. Similar to histEq(); 
map.convertTo(adjMap,CV_8UC1, 255/(max-min), -min); 

// this is great. It converts your grayscale image into a tone-mapped one, 
// much more pleasing for the eye 
// function is found in contrib module, so include contrib.hpp 
// and link accordingly 
cv::Mat falseColorsMap; 
applyColorMap(adjMap, falseColorsMap, cv::COLORMAP_AUTUMN); 

cv::imshow("Out", falseColorsMap); 

Результат должен быть что-то вроде того, ниже

enter image description here

+1

Возможно ли, что openCV выведет цветную шкалу со шкалой, как показано справа? –

+2

Нет. Это участок Матлаба. – Sam

+0

Cheers Sammy, оцените быстрый ответ –

2

Добавление Сэмми ответа, если исходный диапазон цвета [-MIN, макс], и вы хотите выполнить выравнивание гистограммы и отображения глубины цвета, код должен быть, как показано ниже:

double min; 
double max; 
cv::minMaxIdx(map, &min, &max); 
cv::Mat adjMap; 
// Histogram Equalization 
float scale = 255/(max-min); 
map.convertTo(adjMap,CV_8UC1, scale, -min*scale); 

// this is great. It converts your grayscale image into a tone-mapped one, 
// much more pleasing for the eye 
// function is found in contrib module, so include contrib.hpp 
// and link accordingly 
cv::Mat falseColorsMap; 
applyColorMap(adjMap, falseColorsMap, cv::COLORMAP_AUTUMN); 

cv::imshow("Out", falseColorsMap); 
Смежные вопросы