web-dev-qa-db-ja.com

OpenCV:深度画像を視覚化する方法

私は、各ピクセルがmmでそのピクセルの深度値を格納する16ビットの符号なし整数である画像を含むデータセットを使用しています。以下を実行して、これをグレースケール深度画像として視覚化しようとしています。

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);

ただし、2つの色しか表示されていません。これは、すべての値が互いに近い、つまり150〜175の範囲+黒が表示される小さな値であるためです(以下を参照)。

rgb imagegreyscale image

これらの小さな深さの違いを強調するためにさまざまなグレーレベルを表示するように、このデータを正規化する方法はありますか?

22
Aly

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);
21
samota

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

20
Sam

If imshow入力に浮動小数点データ型がある場合、関数はピクセル値が[0; 1]範囲。結果として、1より大きいすべての値は白で表示されます。

したがって、divisorを255で割る必要はありません。

2
Andrey Kamaev

サミーの答えに加えて、元の範囲の色が[-min、max]であり、ヒストグラムの均等化を実行して深度の色を表示する場合、コードは次のようになります。

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);
2
Bud