1

我是一名圖像處理程序員,我正在使用opencv C++。作爲我寫的一個程序的一部分,我有三個嵌套。第一個是用於不同的圖像,第二個用於圖像的行,第三個用於圖像的列。三者之間沒有任何依賴關係,他們可以並行執行(我的意思是,所有圖像的所有像素都可以並行處理)。我並不熟悉並行編程,GPU編程,線程,tbb,並行循環和...。我發現互聯網上的不同鏈接提出了這樣的建議。我想知道什麼是我的問題最快的解決方案? 我的操作系統是Windows和我使用的Visual Studio 2015年執行三個嵌套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

嘗試提供一個MCVE - 一個小但完整的樣本。你已經忽略了關於類型('Mat,''Vec3b')的幾個變量(像名稱以'prj'開始的變量)和'CV_8UC3'(不管那是什麼)的關鍵信息。這些信息是至關重要的,因爲爲了優化你的代碼,有人需要了解這些東西是什麼。 – Peter

+1

你有簡介嗎?你的約束是什麼?多少圖片?什麼尺寸?內循環中的哪些處理?如果不知道這一點,開始「優化」是沒有意義的。 – Miki

+0

圖像的最大數量是20.每個墊子大小約爲2000 * 3000(行*列)。 – Shahab

回答

0

當你寫使用並行for循環遍歷像素將是最快的方法爲大圖像。使用並行算法對於小圖像(例如256 x 256)有一定的開銷,您可能會更適合您發佈的傳統循環。

下面是用Visual 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,你同時做一個單線程(雙for循環)迭代上幾個圖像的工作流程的另一種方法。下面是用C#編寫的一個例子。您只需將您的串行double替換爲位圖翻轉例程的循環即可。一個C++實現應該使用適當的並行庫非常相似:

//一個簡單的來源用於演示目的。根據需要修改此路徑。 String [] files = System.IO.Directory.GetFiles(@「C:\ Users \ Public \ Pictures \ Sample Pictures」,「* .jpg」); String 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 
     }); 

Open CV支持並行至少從版本2.4.3開始。通過使用並行循環,您可以利用多核CPU的強大功能,其中每個核心將在圖像的一個單獨的子部分上迭代。

OpenCV還支持CUDA,它是由NVIDA創建的並行處理API,它利用了GPU的功能。我不認爲這種方法是解決這個問題的方法,但是既然你提到你是一個圖像處理程序員,它值得考慮未來的問題。

+0

感謝您的回答。圖像的最大數量是20.每個墊子大小約爲2000 * 3000(行*列)。 – Shahab

+1

對於這種處理來說,並行處理基本上是無用的,圖像很少。 – Miki

+0

儘管20個600萬像素的圖像相當小,但如果正確實施,並行處理仍然可以縮短處理時間(考慮到輕微的開銷)。如果有人正在使用Intel I7處理器(8個內核),並且正在執行並行工作流程。 (並行處理多個圖像),如果PC沒有被推動執行任何其他強化任務,您將看到時間改進。我沒有在圖像上嘗試過這種模式,但是我已經處理了幾個100M與串行工作流程相比,字節文件和節省時間非常重要。 –