【Opencv】2D射影儿何和变换——柱面投影,图像拼接柱面投影

引入二维空间(以下简称2D) 的射影变换

这些变换发生在用透视摄像机对平面摄像的时候.

该章偏重于入门介绍并为三维空间(以下简称3D) 几何铺路.

大多数的概念在2D 中比3D 中更容易理解和可视化. 

本章介绍射影变换,包括它的特殊悄况:仿射和相似变换; 

并把注意力主要集中在从透视图像中恢复仿射性质(例如平行钱)和度量性质(例如线之间的角度) .

[cpp]  view plain  copy
  1. // mapcyl.cpp : Defines the entry point for the console application.  
  2. //  
  3.   
  4. #include "stdafx.h"  
  5. #include <opencv/cv.h>  
  6. #include <opencv/highgui.h>  
  7.   
  8. cv::Point2f convert_pt(cv::Point2f point,int w,int h)  
  9. {  
  10.     //center the point at 0,0  
  11.     cv::Point2f pc(point.x-w/2,point.y-h/2);  
  12.   
  13.     //these are your free parameters  
  14.     //negative focal length since we are rear projecting  
  15.     float f = -w/2;  
  16.     float r = w;  
  17.   
  18.     float omega = w/2;  
  19.     float z0 = f - sqrt(r*r-omega*omega);  
  20.       
  21.     float zc = (2*z0+sqrt(4*z0*z0-4*(pc.x*pc.x/(f*f)+1)*(z0*z0-r*r)))/(2* (pc.x*pc.x/(f*f)+1));   
  22.       
  23.     cv::Point2f final_point(pc.x*zc/f,pc.y*zc/f);  
  24.     final_point.x += w/2;  
  25.     final_point.y += h/2;  
  26.       
  27.     return final_point;  
  28. }  
  29.   
  30. int _tmain(int argc, _TCHAR* argv[])  
  31. {  
  32.     cv::Mat imgMat = cv::imread("lena.jpg", CV_LOAD_IMAGE_GRAYSCALE);  
  33.     cv::copyMakeBorder(imgMat, imgMat, 175, 175, 175, 175, cv::BORDER_CONSTANT);    
  34.       
  35.     cv::namedWindow("Original",CV_WINDOW_AUTOSIZE);  
  36.     cv::imshow("Original", imgMat);  
  37.     cv::waitKey(0);  
  38.   
  39.     cv::Mat destImgMat(imgMat.size(), CV_8U);  
  40.   
  41.     for(int y = 0; y < imgMat.rows; y++)  
  42.     {  
  43.         for(int x = 0; x < imgMat.cols; x++)  
  44.         {  
  45.             cv::Point2f current_pos(x,y);  
  46.   
  47.             current_pos = convert_pt(current_pos, imgMat.cols, imgMat.rows);  
  48.   
  49.             cv::Point2i top_left((int)current_pos.x,(int)current_pos.y); //top left because of integer rounding  
  50.   
  51.             //make sure the point is actually inside the original image  
  52.             if(top_left.x < 0 || top_left.x > imgMat.cols-2 || top_left.y < 0 || top_left.y > imgMat.rows-2)  
  53.             {  
  54.                 continue;  
  55.             }  
  56.   
  57.             //bilinear interpolation  
  58.             float dx = current_pos.x-top_left.x;  
  59.             float dy = current_pos.y-top_left.y;  
  60.   
  61.             float weight_tl = (1.0 - dx) * (1.0 - dy);  
  62.             float weight_tr = (dx)       * (1.0 - dy);  
  63.             float weight_bl = (1.0 - dx) * (dy);  
  64.             float weight_br = (dx)       * (dy);  
  65.   
  66.             uchar value = weight_tl * imgMat.at<uchar>(top_left) +  
  67.             weight_tr * imgMat.at<uchar>(top_left.y,top_left.x+1) +  
  68.             weight_bl * imgMat.at<uchar>(top_left.y+1,top_left.x) +  
  69.             weight_br * imgMat.at<uchar>(top_left.y+1,top_left.x+1);  
  70.   
  71.             destImgMat.at<uchar>(y,x) = value;  
  72.         }  
  73.     }  
  74.       
  75.     cv::namedWindow("Cylindrical",CV_WINDOW_AUTOSIZE);  
  76.     cv::imshow("Cylindrical",destImgMat);  
  77.     cv::waitKey(0);  
  78.       
  79.     cv::imwrite( "cyl_lena.jpg", destImgMat );  
  80.   
  81.     return 0;  
  82. }  

结果:




参考文献:

https://stackoverflow.com/questions/12017790/warp-image-to-appear-in-cylindrical-projection?lq=1