2

opencvで画像ピクセルにfloat配列としてアクセスしたい。私は次のことをしました:

Mat input = imread("Lena.jpg",CV_LOAD_IMAGE_GRAYSCALE);
int height = input.rows;
int width = input.cols;

Mat out;
input.convertTo(input, CV_32FC1);
copyMakeBorder(input, input, 3, 3, 3, 3, 0);

out = Mat(height, width, input.type());

float *outdata = (float*)out.data;
float *indata = (float*)input.data;

for(int j = 0; j < height; j++){
    for(int i =0; i < width; i++){
        outdata[j*width + i] = indata[(j* width + i)];
    }
}


normalize(out, out,0,255,NORM_MINMAX,CV_8UC1);

imshow("output", out);
waitKey();

これにより、元の画像が「アウト」に返されるはずですが、奇妙な画像が得られます。コードの何が問題なのか誰でも説明できますか。ステップサイズ(widthStep)を使用する必要があると思います。ありがとう。

4

4 に答える 4

1

問題が何であるかを明らかにするために、16 x 16 の画像を想像してください。ここで、線形表現のピクセル番号 17 について考えてみましょう。

17は素数です。行または列の幅が 16 の場合、ピクセル 17 でソース画像をインデックス化するものはありませんj*i。したがって、17、19、23 などの要素は初期化されないか、せいぜい 0 になり、「奇妙な」出力になります。

線形表現のピクセル 8 はどうでしょうか。対照的に、これはループによって 4 回、つまり 1x8、2x4、4x2、および 8x1 でヒットします。

@NateKohl が回答で示したインデックス作成は、行の位置に行の長さを掛けてから、単に列に沿って移動するため、それを修正します。

于 2013-01-16T15:34:41.093 に答える
1

いくつかのアイデア:


のようなものoutdata[j*width + i]は、この種のより標準的なパターンです。


opencv documentationによるとMat::at(int y, int x)、行列の個々の要素にアクセスできるテンプレート化されたメソッドがあります。

float f = input.at<float>(0, 0); 

これには、基になるマトリックス タイプが必要であることに注意floatしてください。変換は行われません。


または、次の例のように、行ごとにデータにアクセスすることもできます。この例ではM、タイプ の行列の正の要素を合計していdoubleます。

double sum=0;
for(int i = 0; i < M.rows; i++)
{
    const double* Mi = M.ptr<double>(i);
    for(int j = 0; j < M.cols; j++)
        sum += std::max(Mi[j], 0.);
}

これらのいずれも機能しない場合は、既知の値を持つ小さなマトリックス (たとえば、1 つの黒ピクセルと 3 つの白ピクセルを持つ 2x2 マトリックス) を作成し、それを使用してコードをデバッグすることをお勧めします。

于 2013-01-16T15:38:18.257 に答える
1

このループを試すことができます...

    for(int row=0;row<height;row++)
    {
        for(int col=0;col<width;col++)
        {
            float float_data = input.at<float>(row,col);
            // do some processing with value of float_data
            out.at<float>(row,col) = float_data;
        }
    }

Matsのucharポインタinputをfloat ポインタにキャストする必要はありますか?out

于 2013-01-16T16:13:59.573 に答える
1

この線

    copyMakeBorder(input, input, 3, 3, 3, 3, 0);

入力の次元を変更すると、画像に 6 行 6 列が追加されます。これは、out を定義して入力の値をループしようとすると、高さと幅の変数が間違った値を保持していることを意味します。

順序を変更すると

copyMakeBorder(input, input, 3, 3, 3, 3, 0);

int height = input.rows;
int width = input.cols;

それはうまくいくはずです。

于 2013-01-16T16:28:42.757 に答える