1

私は画像処理プログラマーです。私はopencv C++を使用しています。私が書いたプログラムの一部として、私は3つの入れ子になっています。最初の画像は異なる画像用、2つ目は画像の行用、3つ目は画像の列用です。 3つの間の依存関係はありませんし、それらは並列にエスケープすることができます(つまり、すべての画像のすべてのピクセルを並行して処理できます)。私は、並列プログラミング、GPUプログラミング、スレッド、tbb、並列のためのループに精通していません。そのようなことを示唆したインターネット上のさまざまなリンクを見つけました。私は私の問題のために最速の解決策が何かを知りたいですか? 私のOSは、Windowsで、私は、Visual Studioを使用しています2015年私のコードが入っている3つのネストされたforループを実行する最速の方法は何ですか?

int prjResCol[MAX_NUMBER_OF_PROJECTOR]; 
int prjResRow[MAX_NUMBER_OF_PROJECTOR]; 
Mat prjCamCor[MAX_NUMBER_OF_PROJECTOR][2] 
Mat prjImgColored[MAX_NUMBER_OF_PROJECTOR]; 

for (int i = 0; i < numOfProjector; i++) 
{ 
    Mat tmp(prjResRow[i], prjResCol[i], CV_8UC3, Scalar(0, 0, 0)); 
    prjImgColored[i] = tmp; 

    for (int ii = 0; ii < prjResRow[i]; ii++) 
    { 
     double* ptrPrjCamIAnd0 = prjCamCor[i][0].ptr<double>(ii); 
     double* ptrPrjCamIAnd1 = prjCamCor[i][1].ptr<double>(ii); 
     Vec3b* ptrPrjImgColoredI = prjImgColored[i].ptr<Vec3b>(ii); 

     for (int jj = 0; jj < prjResCol[i]; jj++) 
     { 

      if ((ptrPrjCamIAnd0[jj] != NAN_VALUE) && (ptrPrjCamIAnd1[jj] != NAN_VALUE)) 
      { 
       ptrPrjImgColoredI[jj] = secondImgColored.at<Vec3b>(ptrPrjCamIAnd1[jj], ptrPrjCamIAnd0[jj]); 
      } 

     } 
    } 
    imwrite(mainAdr + "\\img" + to_string(i) + ".bmp", prjImgColored[i]); 
} 
+0

小型で完全なサンプルを提供してください。タイプ( 'Mat、' 'Vec3b')に関するいくつかの変数(名前が' prj'で始まるもののようなもの)と 'CV_8UC3'(それが何であれ)の重要な情報を除外しました。その情報は重要です。コードを最適化するためには、誰かがそのことを理解する必要があるからです。 – Peter

+1

プロファイルしましたか?あなたの制約は何ですか?画像は何枚ですか?大きさは?内部ループのどの処理ですか?これを知らずに「最適化」を開始するのは理にかなっていません。 – Miki

+0

イメージの最大数は20です。各マットサイズは約2000 * 3000(行*列)です。 – Shahab

答えて

0

あなたが最速の方法だろうピクセルを反復処理するために並列Forループを使用して書いたように大きな画像の場合並列アルゴリズムを使用する場合、小さな画像(256 x 256など)には、あなたが投稿した伝統的なループを使うほうが良いかもしれません。以下は

ビジュアルC++で記述された例です。

// Calls the provided function for each pixel in a Bitmap object. 
void ProcessImage(Bitmap* bmp, const function<void (DWORD&)>& f) 
{ 
    int width = bmp->GetWidth(); 
    int height = bmp->GetHeight(); 

    // Lock the bitmap. 
    BitmapData bitmapData; 
    Rect rect(0, 0, bmp->GetWidth(), bmp->GetHeight()); 
    bmp->LockBits(&rect, ImageLockModeWrite, PixelFormat32bppRGB, &bitmapData); 

    // Get a pointer to the bitmap data. 
    DWORD* image_bits = (DWORD*)bitmapData.Scan0; 

    // Call the function for each pixel in the image. 
    parallel_for (0, height, [&, width](int y) 
    {  
     for (int x = 0; x < width; ++x) 
     { 
     // Get the current pixel value. 
     DWORD* curr_pixel = image_bits + (y * width) + x; 

     // Call the function. 
     f(*curr_pixel); 
     } 
    }); 

    // Unlock the bitmap. 
    bmp->UnlockBits(&bitmapData); 
} 

あなたは、同時に複数の画像にシングルスレッド(ループダブル)反復を行っている作業の流れをparallelzeためにそれを取ることができる別のアプローチ。以下はC#で書かれた例です。あなたは、ビットマップフリップルーチンのためのループのためのシリアルダブルを置き換える必要があります。適切な並列ライブラリを使用すると、C++の実装は非常によく似ているはずです。

//デモンストレーションのための単純なソースです。必要に応じてこのパスを変更します。 String [] files = System.IO.Directory.GetFiles(@ "C:\ Users \ Public \ Pictures \ Sample Pictures"、 "* .jpg"); 文字列newDir = @ "C:\ Users \ Public \ Pictures \ Sample Pictures \ Modified"; System.IO.Directory.CreateDirectory(newDir);

// Method signature: Parallel.ForEach(IEnumerable<TSource> source, Action<TSource> body) 
    // Be sure to add a reference to System.Drawing.dll. 
    Parallel.ForEach(files, (currentFile) => 
    { 
     // The more computational work you do here, the greater 
     // the speedup compared to a sequential foreach loop. 
     String filename = System.IO.Path.GetFileName(currentFile); 
     var bitmap = new Bitmap(currentFile); 

     bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone); 
     bitmap.Save(Path.Combine(newDir, filename)); 

     // Peek behind the scenes to see how work is parallelized. 
     // But be aware: Thread contention for the Console slows down parallel loops!!! 

     Console.WriteLine("Processing {0} on thread {1}", filename, Thread.CurrentThread.ManagedThreadId); 
     //close lambda expression and method invocation 
     }); 

オープンCVは、少なくとも2.4.3以降のバージョンをサポートしています。並列ループを使用することにより、マルチコアCPUのパワーを活用して、各コアがイメージの別のサブセクションを反復処理します。

OpenCVはGPUの力を活用するNVIDAによって作成された並列処理APIであるCUDAもサポートしています。私はこのアプローチがこの特定の問題に行く方法ではないと思いますが、あなたはあなたが将来の問題を調べる価値のある画像処理プログラマーであると言いますから。

+0

あなたの答えをありがとう。イメージの最大数は20です。各マットのサイズは約2000 * 3000(行*列)です。 – Shahab

+1

Parallel forは基本的にこの種の処理には役に立たず、画像はほとんどありません。 – Miki

+0

6Millionピクセルの20枚の画像はかなり小さいですが、並列処理では、正しく実装されていれば、処理時間(わずかなオーバーヘッドを考慮して)を削減することができます。例えばIntel I7処理(8コア)を使用しており、並列ワークフローを実行している場合。 (複数の画像を並行して処理する場合)、PCが他の集中的なタスクを実行するためにプッシュされていない場合、時間の改善が見られます。このパターンは画像で試していませんが、バイトファイルと時間の節約は、シリアルワークフローに比べて非常に重要です。 –

関連する問題