3

これと同様の質問があるようですが、私が求めていることに静かに答えないでください。ここに私の質問があります。

OpenCV を使用した C++ で、以下に示すコードを実行すると、平均ピクセル値 6.32 が返されます。ただし、画像を開いて MATLAB で mean 関数を使用すると、約 6.92ish の平均ピクセル強度が返されます。ご覧のとおり、OpenCV の値を double に変換してこの問題を緩和しようとしたところ、openCV がイメージを一連の整数としてロードするのに対し、MATLAB はイメージを 10 進数値としてロードすることがわかりました。 . 私の質問は、コーディングが初めてなので、どちらが正しいですか? 私は、MATLAB がより正確な値を返していると想定しています。その場合、不一致を回避するために同じ方法で画像を読み込む方法があるかどうかを知りたいです。

ありがとう、以下のコード

    Mat img = imread("Cells2.tif");
cv::cvtColor(img, img, CV_BGR2GRAY);
cv::imshow("stuff",img);
Mat dst;
if(img.channels() == 3)
{
    img.convertTo(dst, CV_64FC1);
}
else if (img.channels() == 1) 
{
    img.convertTo(dst, CV_64FC1);
}
cv::imshow("output",dst/255);
int NumPixels = img.total();


double avg;
double c = 0; 
double std;
    for(int y = 0; y < dst.cols; y++)
    { 

        for(int x = 0; x < dst.rows; x++)
        {
            c+=dst.at<double>(x,y)*255;
        }
    }

avg = c/NumPixels;
cout << "asfa = " << c << endl;
double deviation;

double var;
double z = 0;
double q;
    //for(int a = 0; a<= img.cols; a++)
for(int y = 0; y< dst.cols; y++)
    {
        //for(int b = 0; b<= dst.rows; b++)
        for(int x = 0; x< dst.rows; x++)
        {
            q=dst.at<double>(x,y);

            deviation = q - avg;
            z = z + pow(deviation,2);
            //cout << "q = " << q << endl;
        }

    }

var = z/(NumPixels);
std = sqrt(var);
cv::Scalar avgPixel = cv::mean(dst);

cout << "Avg Value = " << avg << endl;
cout << "StdDev = " << std << endl;
cout << "AvgPixel =" << avgPixel;

cvWaitKey(0);
return 0;

}

4

4 に答える 4

5

あなたのコメントによると、画像は16ビットの深さで保存されているようです。MATLAB は TIFF 画像をそのまま読み込みますが、既定ではOpenCVは画像を 8 ビットとして読み込みます。これにより、表示されている精度の違いが説明される場合があります。

以下を使用して、OpenCV でイメージを開きます。

cv::Mat img = cv::imread("file.tif", cv::IMREAD_ANYDEPTH|cv::IMREAD_ANYCOLOR);

MATLAB では、単純に次のようになります。

img = imread('file.tif');

次に、使用しているデータ型を認識する必要があります。OpenCV では CV_16U、MATLAB ではuint16. したがって、それに応じて型を変換する必要があります。

たとえば、MATLAB では次のようになります。

img2 = double(img) ./ double(intmax('uint16'));

double範囲[0,1]の値を持つ画像に変換します

于 2013-06-11T17:54:50.973 に答える
0

イメージをロードするときは、両方の環境 (MATLAB と OpenCV) で同様の方法を使用して、いずれかの環境で既定で実行される可能性のある変換を回避する必要があります。

于 2013-06-10T16:02:22.553 に答える
0
  1. 特定の条件が満たされている場合、画像を変換しています。これにより、一部の色の値が変更される可能性がありますが、MATLAB は画像を変換せずに生の画像を使用することを選択できます。
  2. 色はほとんどが 16 進形式で表現され、一般的な実装では 0xAARRGGBB または 0xRRGGBBAA の形式で表現されるため、32 ビット整数で十分です (符号なし/符号付きは関係ありません。16 進値は同じです)。64 ビット変数を作成し、すべてを追加します。 32ビット変数を一緒にしてピクセル数で割ると、非常に正確な結果が得られます(16384 x 16384ピクセルまでの画像の場合(32ビット値は1ピクセルの色を表します)、それより大きい場合は、 64 ビット整数では十分ではありません)。

    long long total = 0;
    long long divisor = image.width * image.height;
    for(int x = 0; x < image.width; ++x)
    {
        for(int y = 0; x < image.height; ++x)
        {
            total += image.at(x,y).color;
        }
    }
    double avg = total / divisor;
    std::cout << "Average color value: " << avg << std::endl;
    
于 2013-06-10T15:56:47.943 に答える
0

Matlab と OpenCV の平均値にどのような問題があるのか​​ わかりません。あなたの質問を正しく理解できれば、あなたの目標はmean(image(:))OpenCV で Matlab を実装することです。たとえば、Matlab では次のようにします。

>> image = imread('sheep.jpg')
>> avg = mean(image(:))

ans =

   119.8210

OpenCV で同じことを行う方法は次のとおりです。

Mat image = imread("sheep.jpg");
Scalar avg_pixel;
avg_pixel = mean(image);
float avg = 0;
cout << "mean pixel (RGB): " << avg_pixel << endl;

for(int i; i<image.channels(); ++i) {
    avg = avg + avg_pixel[i]; 
}
avg = avg/image.channels();
cout << "mean, that's equivalent to mean(image(:)) in Matlab: " << avg << endl;

OpenCV コンソール出力:

mean pixel (RGB): [77.4377, 154.43, 127.596, 0]
mean, that's equivalent to mean(image(:)) in Matlab: 119.821

したがって、結果は Matlab と OpenCV で同じです。

フォローアップ コードに問題が見つかりました。

  • OpenCV は、Matlab とは異なる方法でデータを保存します。OpenCV でピクセルにアクセスする方法についての大まかな説明については、この回答を参照してください。例えば:

    // NOT a correct way to access a pixel in CV_F32C3 type image
    double pixel = image.at<double>(x,y); 
    
    //The correct way (where the pixel value is stored in a vector)
    // Note that Vec3d is defined as: typedef Vec<double, 3> Vec3d;
    Vec3d pixel = image.at<Vec3d>(x, y);
    
  • 私が見つけた別のエラー

    if(img.channels() == 3)
    {
        img.convertTo(dst, CV_64FC1); //should be CV_64FC3, instead of CV_64FC1
    }
    

Mat要素へのアクセスは混乱を招く可能性があります。OpenCV に関する本を入手して開始することをお勧めします。たとえば、この 1 つ、 OpenCV のチュートリアルとドキュメントを読むことをお勧めします。お役に立てれば。

于 2013-06-10T20:24:39.897 に答える