c++ - procesamiento - OpenCV: Cómo visualizar una imagen de profundidad.
opencv crear imagen (4)
Agregando a la respuesta de Sammy, si el color del rango original es [-min, max] y desea realizar la ecualización del histograma y mostrar el color de la profundidad, el código debe ser como el siguiente:
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);
Estoy utilizando un conjunto de datos en el que tiene imágenes donde cada píxel es un int sin signo de 16 bits que almacena el valor de profundidad de ese píxel en mm. Intento visualizar esto como una imagen de profundidad de escala de grises haciendo lo siguiente:
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);
Sin embargo, solo muestra dos colores, esto se debe a que todos los valores están muy juntos, es decir, en el rango de 150-175 + los valores pequeños que aparecen en negro (ver más abajo).
¿Hay alguna forma de normalizar estos datos de modo que muestren varios niveles de gris para resaltar estas pequeñas diferencias de profundidad?
Agregando a la respuesta de samg, puede ampliar aún más el rango de su imagen mostrada.
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);
El resultado debería ser algo como el de abajo.
De acuerdo con la documentation , la función imshow se puede usar con una variedad de tipos de imágenes. Admite imágenes sin firmar de 16 bits, por lo que puede mostrar su imagen usando
cv::Mat map = cv::imread("image", CV_LOAD_IMAGE_ANYCOLOR | CV_LOAD_IMAGE_ANYDEPTH);
cv::imshow("window", map);
En este caso, el rango del valor de la imagen se asigna desde el rango [0, 255 * 256] al rango [0, 255].
Si su imagen solo contiene valores en la parte baja de este rango, observará una imagen oscura. Si desea utilizar el rango de visualización completo (de negro a blanco), debe ajustar la imagen para cubrir el rango dinámico esperado, una forma de hacerlo es
double min;
double max;
cv::minMaxIdx(map, &min, &max);
cv::Mat adjMap;
cv::convertScaleAbs(map, adjMap, 255 / max);
cv::imshow("Out", adjMap);
Si la entrada imshow
tiene un tipo de datos de punto flotante, la función asume que los valores de los píxeles están en [0; 1] rango. Como resultado, todos los valores superiores a 1 se muestran en blanco.
Entonces no necesitas dividir tu divisor
por 255.