Dneska jsem si nainstaloval OpenCV, framework pro práci s obrázky. Mají k tomu skvělé tutoriály. Před chvílí jsem dokončil testy (měření výkonu) z jednoho tutorialu a chci se tu podělit s vámi s výsledky.
http://docs.opencv.org/3.1.0/db/da5/tutorial_how_to_scan_images.html#gsc.tab=0
Následuje tabulka s časy - průměr na zpracování jednoho souboru. U něj je to sloupec vlevo, u mě sloupce vpravo třetí a pátý sloupec zleva.
Počet px v barevném souboru:
jeho img 4096000
můj img 10210101 2,492700439 poměr velikosti
ČASY v ms:
přepočteno přepočteno
jeho: DEBUG MODE: MAX PERFORMANCE:
79,4 148 59,37335977 65,45 26,25666485
83,7 4742,7 1902,635361 126,8 50,86852716
93,7 7376,6 2959,280579 1002,15 402,0338682
32,6 197,7 79,31157586 190,7 76,50337641
Provedli jsme celkem 4 testy. Já svůj test opakoval jen 3x pro každou funkci protože to dlouho trvalo.
Výsledek mě překvapil. zatímco u něj vede metoda s použitím LUV tabulky (32.6ms) jako nejrychlejší způsob práce s obrazem, tak u mě je to jednoznačně céčkový styl (26ms). Luv tabulka u mě trvala 76ms. na druhém místě se u mě osvědčil iterátor (50ms). V poslední metoda I.at() totálně propadla. Testoval jsem na 8 jádrovém CPU s frekvencí 1.39Mhz (ale použito bylo jen jedno jádro).
Použité metody:
#include <opencv2/core.hpp>
#include <opencv2/core/utility.hpp>
#include "opencv2/imgcodecs.hpp"
#include <opencv2/highgui.hpp>
using namespace std;
using namespace cv;
//! [scan-c]
cv::Mat& ScanImageAndReduceC(cv::Mat& I, const uchar* const table)
{
// accept only char type matrices
CV_Assert(I.depth() == CV_8U);
int channels = I.channels();
int nRows = I.rows;
int nCols = I.cols * channels;
if (I.isContinuous())
{
nCols *= nRows;
nRows = 1;
}
int i,j;
uchar* p;
for( i = 0; i < nRows; ++i)
{
p = I.ptr<uchar>(i);
for ( j = 0; j < nCols; ++j)
p[j] = table[p[j]];
}
return I;
}
//! [scan-c]
//! [scan-iterator]
cv::Mat& ScanImageAndReduceIterator(cv::Mat& I, const uchar* const table)
{
// accept only char type matrices
CV_Assert(I.depth() == CV_8U);
const int channels = I.channels();
switch(channels)
{
case 1:
{
cv::MatIterator_<uchar> it, end;
for( it = I.begin<uchar>(), end = I.end<uchar>(); it != end; ++it)
*it = table[*it];
break;
}
case 3:
{
cv::MatIterator_<Vec3b> it, end;
for( it = I.begin<Vec3b>(), end = I.end<Vec3b>(); it != end; ++it)
{
(*it)[0] = table[(*it)[0]];
(*it)[1] = table[(*it)[1]];
(*it)[2] = table[(*it)[2]];
}
}
}
return I;
}
//! [scan-iterator]
//! [scan-random]
cv::Mat& ScanImageAndReduceRandomAccess(cv::Mat& I, const uchar* const table)
{
// accept only char type matrices
CV_Assert(I.depth() == CV_8U);
const int channels = I.channels();
switch(channels)
{
case 1:
{
for( int i = 0; i < I.rows; ++i)
for( int j = 0; j < I.cols; ++j )
I.at<uchar>(i,j) = table[I.at<uchar>(i,j)];
break;
}
case 3:
{
Mat_<Vec3b> _I = I;
for( int i = 0; i < I.rows; ++i)
for( int j = 0; j < I.cols; ++j )
{
_I(i,j)[0] = table[_I(i,j)[0]];
_I(i,j)[1] = table[_I(i,j)[1]];
_I(i,j)[2] = table[_I(i,j)[2]];
}
I = _I;
break;
}
} // end switch
return I;
}
//! [scan-random]
LUT:
for (int i = 0; i < times; ++i)
//! [table-use]
LUT(I, lookUpTable, J);