OpenCV_tutorials 01 core module -How to scan images, lookup tables and time measurement with OpenCV

 
#include <opencv2\opencv.hpp>

using namespace std;
using namespace cv;

void ScanImgaeAndReduceC(Mat &src, const uchar * const table, Mat &dst);
void ScanImageAndReduceIterator(Mat &src, const uchar * const table, Mat &dst);
void ScanImageAndReduceRandomAccess(Mat &src, const uchar * const table, Mat &dst);
void UseLUTFun(Mat &src, const uchar * const table, Mat &dst);

int main()
{
	Mat src = imread("C:\\Users\\dell\\Desktop\\xin1.jpg", 1);

	if (src.empty())
	{
		cout << "source image load failed." << endl;
		return -1;
	}

	int dividewidth = 10;
	//create look up table
	uchar table[256];
	for (int i = 0; i < 256; i++)
		table[i] = (uchar)((i / dividewidth) * dividewidth);

	Mat dst1;
	ScanImgaeAndReduceC(src, table, dst1);

	Mat dst2;
	ScanImageAndReduceIterator(src, table, dst2);

	Mat dst3;
	ScanImageAndReduceRandomAccess(src, table, dst3);

	Mat dst4;
	UseLUTFun(src, table, dst4);

	waitKey(0);
	return 0;
}

//The efficient way to scan image
void ScanImgaeAndReduceC(Mat &src, const uchar * const table, Mat &dst)
{
	double t = (double)getTickCount();

	//accept only uchar type matrixs
	CV_Assert(src.depth() == CV_8U);

	cout << src.depth() << " " << sizeof(uchar) << endl;

	int channels = src.channels();
	int nRows = src.rows;
	int nCols = src.cols * channels;

	if (src.isContinuous())
	{
		nCols = nRows * nCols;
		nRows = 1;
	}

	Mat I(src.size(), src.type());
	for (int i = 0; i < nRows; i++)
	{
		uchar *pSrc = src.ptr<uchar>(i);
		uchar *pI = I.ptr<uchar>(i);
		for (int j = 0; j < nCols; j++)
			pI[j] = table[pSrc[j]];
	}

	dst = I.clone();

	double tt = ((double)getTickCount() - t) / getTickFrequency();
	cout << "The efficient way cost time :  " << tt << "s." << endl;
}

//The iterator(safe) method to scan image
void ScanImageAndReduceIterator(Mat &src, const uchar * const table, Mat &dst)
{
	double t = (double)getTickCount();

	CV_Assert(src.depth() == CV_8U);

	int nchannels = src.channels();
	Mat I = src.clone();
	switch (nchannels)
	{
	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]];
			  }
		}
	}

	dst = I.clone();

	double tt = ((double)getTickCount() - t) / getTickFrequency();
	cout << "The iterator(safe) method cost time : " << tt << "s." << endl;
}

//On the fly address calculation with reference returning
void ScanImageAndReduceRandomAccess(Mat &src, const uchar * const table, Mat &dst)
{
	double t = (double)getTickCount();

	CV_Assert(src.depth() == CV_8U);

	int nchannels = src.channels();
	Mat I = src.clone();
	switch (nchannels)
	{
	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;
		}
	}

	dst = I.clone();

	double tt = ((double)getTickCount() - t) / getTickFrequency();
	cout << "On the fly address calculation cost time : " << tt << "s." << endl;
}

//Use LUT function
void UseLUTFun(Mat &src, const uchar * const table, Mat &dst)
{	
	CV_Assert(src.depth() == CV_8U);

	Mat LoopUpTable(1, 256, CV_8U);
	uchar *p = LoopUpTable.data;
	for (int i = 0; i < 256; i++)
		p[i] = table[i];

	double t = (double)getTickCount();

	LUT(src, LoopUpTable, dst);

	double tt = ((double)getTickCount() - t) / getTickFrequency();
	cout << "Use LUT function cost time : " << tt << "s." << endl;

}

注意,教程原版中CV_Assert(src.depth() != sizeof(uchar));这句话有误,输出观察一下,src.depth() = 0,表示的是CV_8U,而sizeof(uchar) = 1,表示uchar类型占1位,这个判断只能表示如果src.depth()!=1(CV_8S),断言就不会启用。src.depth()!=1,有可能是CV_16U、CV_32S等,并不能保证一定是CV_8U。看来即使是官方教程,也有可能出现错误。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值