2011-12-06 15 views
3

画像を歪ませるツールで作業していますが、歪みの目的は画像を球面スクリーンに投影することです。希望する出力は次のようになります。画像歪みの高速アルゴリズム

私が使用するコードは、次のとおりです。 - 宛先領域内のすべての点(x、y)について、元の画像の対応するピクセル(sourceX、sourceY)を取得します。

しかし、私のテストでは、sunset.jpg(800 * 600)の処理には1500ms以上が必要です。数学的/三角法による計算を削除すると、cvGet2DとcvSet2Dだけを呼び出すと1200ms以上必要です。

これを行うより良い方法はありますか? Emue CV(OpenCVの.NETラッパーライブラリ)を使用していますが、他の言語の例もOKです。

private static void DistortSingleImage() 
{ 
    System.Diagnostics.Stopwatch stopWatch = System.Diagnostics.Stopwatch.StartNew(); 
    using (Image<Bgr, Byte> origImage = new Image<Bgr, Byte>("sunset.jpg")) 
    { 
     int frameH = origImage.Height; 
     using (Image<Bgr, Byte> distortImage = new Image<Bgr, Byte>(2 * frameH, 2 * frameH)) 
     { 
      MCvScalar pixel; 
      for (int x = 0; x < 2 * frameH; x++) 
      { 
       for (int y = 0; y < 2 * frameH; y++) 
       { 
        if (x == frameH && y == frameH) continue; 
        int x1 = x - frameH; 
        int y1 = y - frameH; 
        if (x1 * x1 + y1 * y1 < frameH * frameH) 
        { 
         double radius = Math.Sqrt(x1 * x1 + y1 * y1); 
         double theta = Math.Acos(x1/radius); 
         int sourceX = (int)(theta * (origImage.Width - 1)/Math.PI); 
         int sourceY = (int)radius; 
         pixel = CvInvoke.cvGet2D(origImage.Ptr, sourceY, sourceX); 
         CvInvoke.cvSet2D(distortImage, y, x, pixel); 
        } 
       } 
      } 
      distortImage.Save("Distort.jpg"); 
     } 
     Console.WriteLine(stopWatch.ElapsedMilliseconds); 
    } 
} 

The desired distortion

+0

画像が左右対称であるので、ほとんど忘れてしまったので、処理時間を半分に短縮するために左の部分だけを処理して右にコピーできますが、これでは十分ではありません。 – kennyzx

答えて

2

私の個人的な経験から、私はいくつかの立体視のものをやっていた、OpenCVの話をする最良の方法は、独自のラッパー経由で、あなたはCであなたの方法を置く++とC#から呼び出すことができ、 EmguがOpenCVデータを保持しているので、emguでイメージを作成し、それをネイティブに処理し、c#で処理されたイメージを再び楽しむことも可能です。

get/setメソッドは、GdiのGetPixel/SetPixelのように見えますが、ドキュメントによれば「遅いが安全な方法」です。唯一Emguに滞在するために

、ドキュメントでは、ピクセルを反復処理したい場合、あなたは.Dataプロパティにアクセスする必要があることを伝えます:

はあなたがイメージに取り組んでいると仮定し(遅い)安全な方法。 を呼び出すことによって、y行目とx列目のピクセルを得ることができます。Bgr color = img [y、x]; y番目の行とx番目の列のピクセルを設定することも簡単です img [y、x] = color;

速い方法

値は、Dataプロパティに格納された画像の画素は、3Dアレイ。イメージのピクセル値を反復処理する必要がある場合は、このプロパティを使用します。

+0

私はそれを試みます、ありがとう。 OpenCVにはAPIがあるので、私は迷っています。cvGetQuadrangleSubPixは変換行列を取ります。行列を使って歪めることは可能ですか? – kennyzx

+1

私はそう思っていますが、あなたの問題を解決するマトリクスを構築できるかどうか分からない場合は、cvRemapを使うこともできます。イメージを再マップする方法を含む2つのイメージサイズの配列を供給できます(x、y)= s(matrix1(x)、matrix2(y))しかし、あなたはこれらの配列を自分で構築しなければならないので、今持っているコードを最適化することに利点があるかどうか、 2つの呼び出しメソッドを呼び出す必要性を取り除くことによってN * N回。 –

+0

読み込み/書き込み。データ配列は約半分の時間を使用するcvSet2D/cvGet2D;) – kennyzx