opencv 图像畸变矫正加速、透视变换加速方法总结

转载自http://blog.csdn.net/hust_bochu_xuchao/article/details/54585200,校正镜头畸变,校正透视畸变,加速计算。

1、畸变矫正  

 相机标定完成后,我们得到内参和畸变系数。每次从相机得到一张源图,我们都需要进行一次畸变矫正。

 之前博主都是采用   undistort函数,直接输入内参和畸变系数,输入为源图,输出为矫正后的图像。

  1. undistort(picture, dst, intrinsic, distortion_coeff);//这一步骤需要耗费300多ms的时间,为最主要耗费时间的步骤  
undistort(picture, dst, intrinsic, distortion_coeff);//这一步骤需要耗费300多ms的时间,为最主要耗费时间的步骤
当仅仅处理一张照片,300多ms看不到任何问题,但是,当需要流畅的视频帧数,也即在40ms内处理完一张照片时,300多ms的时间耗费,简直不能够接受啊。

所以,想办法优化时间啊。所幸找到了解决办法。

解决办法为:

initUndistortRectifyMap(intrinsic, distortion_coeff, Mat(), Mat(),image_size, 0, map1, map2);此函数根据内参和畸变系数,建立了一个查找表,map1 map2设置为全局变量,所以这个函数只需要运行一次就好。

remap(picture, dst, map1, map2, CV_INTER_LINEAR, cv::BORDER_CONSTANT, cv::Scalar(0, 0, 0));此函数根据map1 map2进行畸变矫正,时间耗费在10多ms

好的,畸变矫正的加速,就这么解决了。

2、透视变换

同样的现象,cv::warpPerspective,一次透视变换的时间,需要耗费100多ms,这显然也是不能接受的。

解决办法,原理同上。建立查找表,一次就好。之后,每张图片调用remap函数。

主要参考链接

代码奉上。

  1. void perspective_to_maps(const cv::Mat &perspective_mat, const cv::Size img_size,  
  2.     cv::Mat &map1, cv::Mat &map2)  
  3. {  
  4.     // invert the matrix because the transformation maps must be  
  5.     // bird's view -> original  
  6.     cv::Mat inv_perspective(perspective_mat.inv());  
  7.     inv_perspective.convertTo(inv_perspective, CV_32FC1);  
  8.   
  9.     // create XY 2D array  
  10.     // (((0, 0), (1, 0), (2, 0), ...),  
  11.     //  ((0, 1), (1, 1), (2, 1), ...),  
  12.     // ...)  
  13.     cv::Mat xy(img_size, CV_32FC2);  
  14.     float *pxy = (float*)xy.data;  
  15.     for (int y = 0; y < img_size.height; y++)  
  16.         for (int x = 0; x < img_size.width; x++)  
  17.         {  
  18.             *pxy++ = x;  
  19.             *pxy++ = y;  
  20.         }  
  21.   
  22.     // perspective transformation of the points  
  23.     cv::Mat xy_transformed;  
  24.     cv::perspectiveTransform(xy, xy_transformed, inv_perspective);  
  25.   
  26.        //Prevent errors when float32 to int16  
  27.         float *pmytest = (float*)xy_transformed.data;  
  28.     for (int y = 0; y < xy_transformed.rows; y++)  
  29.         for (int x = 0; x < xy_transformed.cols; x++)  
  30.         {  
  31.             if (abs(*pmytest) > 5000) *pmytest = 5000.00;  
  32.             pmytest++;  
  33.             if (abs(*pmytest) > 5000) *pmytest = 5000.00;  
  34.             pmytest++;  
  35.         }  
  36.   
  37.     // split x/y to extra maps  
  38.     assert(xy_transformed.channels() == 2);  
  39.     cv::Mat maps[2]; // map_x, map_y  
  40.     cv::split(xy_transformed, maps);  
  41.   
  42.     // remap() with integer maps is faster  
  43.     cv::convertMaps(maps[0], maps[1], map1, map2, CV_16SC2);  
  44. }  
void perspective_to_maps(const cv::Mat &perspective_mat, const cv::Size img_size,
	cv::Mat &map1, cv::Mat &map2)
{
	// invert the matrix because the transformation maps must be
	// bird's view -> original
	cv::Mat inv_perspective(perspective_mat.inv());
	inv_perspective.convertTo(inv_perspective, CV_32FC1);

	// create XY 2D array
	// (((0, 0), (1, 0), (2, 0), ...),
	//  ((0, 1), (1, 1), (2, 1), ...),
	// ...)
	cv::Mat xy(img_size, CV_32FC2);
	float *pxy = (float*)xy.data;
	for (int y = 0; y < img_size.height; y++)
		for (int x = 0; x < img_size.width; x++)
		{
			*pxy++ = x;
			*pxy++ = y;
		}

	// perspective transformation of the points
	cv::Mat xy_transformed;
	cv::perspectiveTransform(xy, xy_transformed, inv_perspective);

       //Prevent errors when float32 to int16
        float *pmytest = (float*)xy_transformed.data;
	for (int y = 0; y < xy_transformed.rows; y++)
		for (int x = 0; x < xy_transformed.cols; x++)
		{
			if (abs(*pmytest) > 5000) *pmytest = 5000.00;
			pmytest++;
			if (abs(*pmytest) > 5000) *pmytest = 5000.00;
			pmytest++;
		}

	// split x/y to extra maps
	assert(xy_transformed.channels() == 2);
	cv::Mat maps[2]; // map_x, map_y
	cv::split(xy_transformed, maps);

	// remap() with integer maps is faster
	cv::convertMaps(maps[0], maps[1], map1, map2, CV_16SC2);
}


3、好的,畸变矫正和透视变换的加速问题解决了。那么,是否可以把畸变矫正和透视变换放在一起计算呢。经过了解和研究后,是可以的。

代码如下:

  1. void perspective_to_maps(const cv::Mat &perspective_mat, const cv::Size img_size, cv::Mat distortion_map1, cv::Mat distortion_map2,  
  2.     cv::Mat &map1, cv::Mat &map2)  
  3. {  
  4.     // invert the matrix because the transformation maps must be  
  5.     // bird's view -> original  
  6.     cv::Mat inv_perspective(perspective_mat.inv());  
  7.     inv_perspective.convertTo(inv_perspective, CV_32FC1);  
  8.   
  9.     // create XY 2D array  
  10.     // (((0, 0), (1, 0), (2, 0), ...),  
  11.     //  ((0, 1), (1, 1), (2, 1), ...),  
  12.     // ...)  
  13.     cv::Mat xy(img_size, CV_32FC2);  
  14.     float *pxy = (float*)xy.data;  
  15.     for (int y = 0; y < img_size.height; y++)  
  16.         for (int x = 0; x < img_size.width; x++)  
  17.         {  
  18.             *pxy++ = x;  
  19.             *pxy++ = y;  
  20.         }  
  21.   
  22.     // perspective transformation of the points  
  23.     cv::Mat xy_transformed;  
  24.     cv::perspectiveTransform(xy, xy_transformed, inv_perspective);  
  25.   
  26.        //Prevent errors when float32 to int16  
  27.         float *pmytest = (float*)xy_transformed.data;  
  28.     for (int y = 0; y < xy_transformed.rows; y++)  
  29.         for (int x = 0; x < xy_transformed.cols; x++)  
  30.         {  
  31.             if (abs(*pmytest) > 5000) *pmytest = 5000.00;  
  32.             pmytest++;  
  33.             if (abs(*pmytest) > 5000) *pmytest = 5000.00;  
  34.             pmytest++;  
  35.         }  
  36.   
  37.     // split x/y to extra maps  
  38.     assert(xy_transformed.channels() == 2);  
  39.     cv::Mat maps[2]; // map_x, map_y  
  40.     cv::split(xy_transformed, maps);  
  41.   
  42.     // remap() with integer maps is faster  
  43.     //cv::convertMaps(maps[0], maps[1], map1, map2, CV_16SC2);  
  44.     cv::convertMaps(maps[0], maps[1], map1, map2, CV_16SC2);  
  45.   
  46.     short int *pt = (short int *)map1.data;  
  47.     short int *dispt = (short int *)distortion_map1.data;  
  48.     for (int i = 0; i < map1.rows; i++)  
  49.     {  
  50.         for (int j = 0; j < map1.cols; j++)  
  51.         {  
  52.             Point tem1;  
  53.             tem1.x = *pt++;  
  54.             tem1.y = *pt++;  
  55.                         if ((tem1.x<0) || (tem1.x>distortion_map1.cols - 1) || (tem1.y<0) || (tem1.y>distortion_map1.rows - 1)) continue;  
  56.   
  57.             int tem2 = (tem1.y*distortion_map1.cols + tem1.x) * 2;  
  58.             dispt += tem2;  
  59.             Point tem3;  
  60.             tem3.x = *dispt++;  
  61.             tem3.y = *dispt++;  
  62.             dispt -= tem2+2;  
  63.   
  64.             *(--pt) = tem3.y;  
  65.             *(--pt) = tem3.x;  
  66.             pt++;  
  67.             pt++;  
  68.         }  
  69.     }  
  70.   
  71. }  
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值