1

Я программист по обработке изображений, и я использую opencv C++. Как часть программы, которую я написал, у меня есть три вложенных. Первый - для разных изображений, второй - для строк изображений, а третий для столбцов изображений. Нет никакой зависимости между тремя, и они могут превзойти параллель (я имею в виду, что все пиксели всех изображений могут обрабатываться параллельно). Я не знаком с параллельным программированием, программированием на GPU, потоком, tbb, параллельным для цикла и .... Я нашел различные ссылки через Интернет, которые предлагали такие вещи. Я хочу знать, что является самым быстрым решением для моей проблемы? Моя ОС окно, и я использую Visual Studio 2015.Каков самый быстрый способ для выполнения трех вложенных циклов?

Мой код заключается в следующем:

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 х 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 свой рабочий поток, где вы делаете однопоточной (двойной цикл) итерации на нескольких изображениях одновременно. Ниже приведен пример, написанный на C#. Вам просто нужно подставить цикл цикла double для цикла для подпрограммы растрового изображения. Реализация 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. Используя параллельный цикл, вы можете использовать мощь вашего многоядерного процессора, где каждое ядро ​​будет переходить по отдельному подразделению изображения.

OpenCV также поддерживает CUDA, который является API параллельной обработки, созданным NVIDA, который использует мощность вашего GPU. Я не думаю, что этот подход - это путь к решению этой конкретной проблемы, но поскольку вы упоминаете, что вы программист по обработке изображений, он стоит искать в будущих проблемах.

+0

Спасибо за ваш ответ. Максимальное количество изображений - 20. Размер каждого мата составляет около 2000 * 3000 (строки * столбцы). – Shahab

+1

Parallel for в основном бесполезен для такого вида обработки, с таким количеством изображений. – Miki

+0

Хотя 20 изображений с 6 миллионами пикселей довольно малы, параллельная обработка все равно может сократить время обработки (с учетом незначительных издержек), если оно выполнено правильно. Если используется, например, обработка Intel I7 (8 ядер) и выполняется параллельный рабочий процесс. (параллельно обрабатывая несколько изображений), вы увидите улучшение времени, если на ПК не будут предприняты какие-либо другие интенсивные задачи. Я не пробовал этот шаблон на изображениях, но я сделал это с обработкой нескольких 100 М Байт-файлы и экономия времени действительно значительны по сравнению с последовательным рабочим процессом. –