Original Image Link |
In this section I will try to compare performance from some scanning method using OpenCV, the compare is about performance image scanning for manipulate per color data.
What will be compare on this section:
- Classic C style operator scanning method
- Iterator safe method scanning method
- On-the-fly address calculation with reference returning scanning method
- Use LUT() core function from OpenCV
this program is simple and will take 2 argument, first argument is image to be load and to be scan then second argument is number of reduced color to be apply to current loaded image.
The program I created using QT Creator, this program contain 3 file base:
- imagescanningcompare.h (this is class declaration and method declaration for current program)
- imagescanningcompare.cpp (this is method declaration from imagescanningcompare.h)
- TestOpenCV.cpp (this is main program main())
#ifndef IMAGESCANNINGCOMPARE_H
#define IMAGESCANNINGCOMPARE_H
#include <iostream>
#include <string>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
class ImageScanningCompare
{
public:
ImageScanningCompare(string filename, int reduction);
Mat& ScanImageAndReduceC(Mat& I, const uchar *const table);
Mat& ScanImageAndReduceIterator(Mat& I, const uchar* const table);
Mat& ScanImageAndReduceRandomAccess(Mat& I, const uchar* const table);
Mat& LookUpTable(Mat& I, const uchar* const table);
};
#endif // IMAGESCANNINGCOMPARE_H
code snippet for imagescanningcompare.cpp
code snippet for TestOpenCV.cpp
#include "imagescanningcompare.h"
#include <iostream>
#include <string>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
ImageScanningCompare::ImageScanningCompare(string filename, int reduction)
{
int devideWidth;
devideWidth = reduction;
Mat img, img2, img3, img4;
img = imread(filename, CV_LOAD_IMAGE_COLOR);
img2 = img.clone();
img3 = img.clone();
img4 = img.clone();
uchar table[256];
for(int i = 0; i < 256; ++i) {
table[i] = devideWidth * (i*devideWidth);
}
//time calculation
cout << "======================== compare performace =====================" << endl;
cout << "Classic C style operator: ";
double t = (double)getTickCount();
this->ScanImageAndReduceC(img, table);
t = ((double)getTickCount() - t)/getTickFrequency();
cout << "Times Passed in second " << t << endl;
cout << "=================================================================" << endl;
cout << "Iterator safe method: ";
t = (double)getTickCount();
this->ScanImageAndReduceIterator(img2, table);
t = ((double)getTickCount() - t)/getTickFrequency();
cout << "Times Passed in second " << t << endl;
cout << "=================================================================" << endl;
cout << "On-the-fly address calculation with reference returning: ";
t = (double)getTickCount();
this->ScanImageAndReduceRandomAccess(img3, table);
t = ((double)getTickCount() - t)/getTickFrequency();
cout << "Times Passed in second " << t << endl;
cout << "=================================================================" << endl;
cout << "Use LUT() core function: ";
t = (double)getTickCount();
this->LookUpTable(img4, table);
t = ((double)getTickCount() - t)/getTickFrequency();
cout << "Times Passed in second " << t << endl;
cout << "=================================================================" << endl;
}
Mat& ImageScanningCompare::ScanImageAndReduceC(Mat& I, const uchar *const table)
{
int channels = I.channels();
int nRows = I.rows * channels;
int nCols = I.cols;
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;
}
Mat& ImageScanningCompare::ScanImageAndReduceIterator(Mat& I, const uchar* const table)
{
const int channels = I.channels();
switch(channels)
{
case 1:
{
MatIterator_<uchar> it, end;
for( it = I.begin<uchar>(), end = I.end<uchar>(); it != end; ++it)
*it = table[*it];
break;
}
case 3:
{
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;
}
Mat& ImageScanningCompare::ScanImageAndReduceRandomAccess(Mat& I, const uchar* const table)
{
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;
}
}
return I;
}
Mat& ImageScanningCompare::LookUpTable(Mat& I, const uchar* const table)
{
Mat lookUpTable(1, 256, CV_8U);
Mat J;
uchar* p = lookUpTable.data;
for( int i = 0; i < 256; ++i)
p[i] = table[i];
LUT(I, lookUpTable, J);
}
//#include <opencv2/opencv.hpp>
//#include "displayimage.h"
//#include "displayimage2.h"
#include "imagescanningcompare.h"
#include <iostream>
#include <string>
int main(int argc, char** argv)
{
//DisplayImage di("/home/ar/Pictures/g4958.png");
//DisplayImage2 di2("/home/ar/Pictures/g4958.png");
int devideWidth;
stringstream s;
s << argv[2];
s >> devideWidth;
ImageScanningCompare isc(argv[1], devideWidth);
return 0;
}
After build the code we will get execute able binary TestOpenCV, then we can run this with this way:
ar@dream:~/Projects/QT/OpenCV$ ./OpenCV /home/ar/Pictures/freedom1680x1050.jpg 50from the result we can see that LUT() core function is more efficient then other method :)
======================== compare performace =====================
Classic C style operator: Times Passed in second 0.0636563
=================================================================
Iterator safe method: Times Passed in second 0.223594
=================================================================
On-the-?y address calculation with reference returning: Times Passed in second 0.214652
=================================================================
Use LUT() core function: Times Passed in second 0.0384888
=================================================================
this is the summary result:
Classic C style operator | 0.0636563 |
Iterator safe method | 0.223594 |
On-the-?y address calculation with reference returning | 0.214652 |
Use LUT() core function | 0.0384888 |
No comments:
Post a Comment