OpenCV: comment visualiser une image de profondeur

J’utilise un jeu de données dans lequel il contient des images dans lesquelles chaque pixel est un entier non signé de 16 bits stockant la valeur de profondeur de ce pixel en mm. J’essaie de visualiser cela comme une image en niveaux de gris en procédant comme suit:

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(i,j) > max){ max = depthImage.at(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(i,j) << ", "; max = depthImage.at(i,j) /= divisor; cout << depthImage.at(i,j) << endl; } } imshow("window", depthImage); waitKey(0); 

Cependant, il n’affiche que deux couleurs car toutes les valeurs sont proches, c’est-à-dire dans la plage de 150 à 175 + les petites valeurs qui apparaissent en noir (voir ci-dessous).

image rgbimage en niveaux de gris

Existe-t-il un moyen de normaliser ces données de manière à afficher différents niveaux de gris afin de mettre en évidence ces petites différences de profondeur?

Selon la documentation , la fonction imshow peut être utilisée avec différents types d’images. Il prend en charge les images non signées 16 bits, de sorte que vous pouvez afficher votre image à l’aide de

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

Dans ce cas, la plage de valeurs d’image est mappée de la plage [0, 255 * 256] à la plage [0, 255].

Si votre image ne contient que des valeurs dans la partie basse de cette plage, vous observerez une image obscure. Si vous souhaitez utiliser toute la plage d’affichage (du noir au blanc), vous devez ajuster l’image pour couvrir la plage dynamic attendue. Pour ce faire, procédez comme suit:

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

En ajoutant à la réponse de samg, vous pouvez élargir encore plus la plage de votre image affichée.

 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 consortingb module, so include consortingb.hpp // and link accordingly cv::Mat falseColorsMap; applyColorMap(adjMap, falseColorsMap, cv::COLORMAP_AUTUMN); cv::imshow("Out", falseColorsMap); 

Le résultat devrait ressembler à celui ci-dessous

entrez la description de l'image ici

Si l’entrée imshow a un type de données à virgule flottante, la fonction suppose que les valeurs de pixel sont dans [0; 1] gamme. En conséquence, toutes les valeurs supérieures à 1 sont affichées en blanc.

Vous n’avez donc pas besoin de diviser votre divisor par 255.

Si vous ajoutez à la réponse Sammy, si la couleur de la plage d’origine est [-min, max] et que vous souhaitez effectuer une égalisation de l’histogramme et afficher la couleur Profondeur, le code doit ressembler à celui ci-dessous:

 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 consortingb module, so include consortingb.hpp // and link accordingly cv::Mat falseColorsMap; applyColorMap(adjMap, falseColorsMap, cv::COLORMAP_AUTUMN); cv::imshow("Out", falseColorsMap);