4

ため息申し訳ありませんが、作業中の画像処理コードでIntel IPL(画像処理ライブラリ)を使用しています。これは、画像を正しく回転させるのに苦労した話です。

  1. ソース画像があります。サイズ(w、h)は必ずしも正方形ではありません。
  2. 角度シータで回転します。
  3. 角度シータで回転したサイズ(w、h)の画像に合わせるために必要な出力サイズを計算しました。このサイズは(dw、dh)です。そのサイズの宛先バッファーを割り当てました。
  4. ソース画像の中心(w / 2、h / 2)を中心に角度シータでソース画像を回転させ、その回転した画像を宛先バッファの中心に配置したいと思います。

iplRotate ()は、 xShiftyShiftの2つのシフトパラメータを取ります。これらは、回転が実行された後、画像がx軸とy軸に沿ってシフトされる距離を示します。

問題は、回転した画像を宛先画像の中央に配置するようにiplRotateを取得できないことです。それは常に中心から外れています。

xShiftとyShiftがどうあるべきかについての私の最良の推測は、次のとおりです。

  • xShift = dw - w
  • yShift = dh - h

しかし、これは機能せず、 xShiftyShiftを計算するために他に何をすべきかわかりません。iplRotateを使用して私がやりたいことを行う方法について誰かが何か提案がありますか?

最後にもう1つ、 iplGetRotateShift()を使用してxShiftとyShiftを計算しようとしましたが、無駄になりました。私はこれがうまくいくと想像します:

iplGetRotateShift(dw / 2.0, dh / 2.0, theta, &xShift, &yShift);

しかし、そうではありません。


編集: IPLの代わりにIntel IPP 6.0を使用してコードを書き直しましたが、同じ間違った結果が表示されます。Intelが2つの異なるライブラリでローテーションを間違えたとは想像できないので、何か間違ったことをしているに違いありません。


編集: Dani van der Meerが提案した次の(IPP)コードを試しました:

xShift = (dw - w) / 2.0;
yShift = (dh - h) / 2.0;
ippiAddRotateShift(w / 2.0, h / 2.0, angle, &xShift, &yShift);

残念ながら、まだ運がありません。それも機能しません。

4

4 に答える 4

5

iplGetRotateShiftを使用する場合は、ソース画像の回転の中心を指定する必要があります。これは、ソースイメージとデスティネーションイメージのサイズが同じである場合にうまく機能します。

あなたの場合、目的の画像の中央に画像を配置するために追加のシフトが必要です。

xShift = (dw - w) / 2.0;
yShift = (dh - h) / 2.0;

2つのシフトを組み合わせるには、ippiGetRotateShiftの代わりにippiAddRotateShiftを使用する必要があります。

:これらの関数は、IPPライブラリバージョン5.3(私が持っているバージョン)を参照しています。AddRotateShiftがIPLで使用できるかどうかわかりません。しかし、あなたはIPPを使用して同じことを試したと質問で述べたので、うまくいけば、IPLの代わりにIPPを使用できます。

あなたはこのようなものを手に入れます

xShift = (dw - w) / 2.0;
yShift = (dh - h) / 2.0;
ippiAddRotateShift(w / 2.0, h / 2.0, angle, &xShift, &yShift);

ippiRotateの呼び出しでこれらのシフトを使用する場合、画像は宛先画像の中央に配置する必要があります。

これがお役に立てば幸いです。

編集: これが私がテストするために使用したコードです(wからdwへの変更とhからdhへの変更と回転角はちょうどランダムです):

//Ipp8u* dst_p; Initialized somewhere else in the code
//Ipp8u* src_p; Initialized somewhere else in the code
int w = 1032;
int h = 778;
int dw = w - 40; // -40 is just a random change
int dh = h + 200; // 200 is just a random change
int src_step = w * 3;
int dst_step = dw * 3;
IppiSize src_size = { w, h };
IppiRect src_roi  = { 0, 0, w, h };
IppiRect dst_rect = { 0, 0, dw, dh };
double xShift = ((double)dw - (double)w) / 2.0;
double yShift = ((double)dh - (double)h) / 2.0;
ippiAddRotateShift((double)w / 2, (double)h / 2, 37.0, &xShift, &yShift);
ippiRotate_8u_C3R(src_p, src_size, src_step, src_roi, 
          dst_p, dst_step, dst_rect, 37.0, xShift, yShift, IPPI_INTER_NN);
于 2009-05-20T16:04:11.230 に答える
1

私はこれまでIPLを使用したことがない(または聞いたことがない)ので、APIが何をするかを推測しているだけです。ただし、iplRotateが(0、0)を中心に回転し、iplGetRotateShiftも同様に回転する場合は、元の「ボックス」の他の3つのコーナーを回転させてみてください((0、0)はそのままなので、無視してください):(w、0)、( 0、h)、および(w、h)。

結果は、いくつかの負の値を持つ新しいボックスになります。あなたは「シフトバック」したいので、私が言っていることを理解すれば、あなたが持っているどんな負の値もゼロになるでしょう。

于 2009-05-18T21:52:40.347 に答える
1

ドキュメントを読んだことに基づいて、iplGetRotateShiftを間違って使用していると思います。特に、宛先画像ではなく、ソース画像で回転の中心を指定する必要があると思います。したがって、次のようになります。

iplGetRotateShift( w / 2.0,  h / 2.0, angle, &xShift, &yShift );
于 2009-05-19T05:32:51.873 に答える
1

それでも機能しない場合は、仮定が有効であることを確認できますか?特にポイント3。ここでdwとdhを計算します。

数学的に

dw = w * | cos(theta)| + h * | sin(theta)|
dh = h * | cos(theta)| + w * | sin(theta)|

つまり、theta = pi / 6の場合、w=100およびh=150の場合、おそらくdw = 162?

あなたが得ている間違った位置はシータによって異なりますか?おそらくそれはtheta=0で動作しますか?theta = pi/2とtheta=pi / 4はどうですか?

于 2009-05-25T20:44:58.980 に答える