opencv----计算图像旋转参数
2014-04-28 10:47
295 查看
弄这个弄了好几天,一直想的复杂了
其实很简单,其实并不难
先上代码吧,不过里面有很多多余的函数,不过之后计算平移+旋转的时候会用到
其实很简单,其实并不难
先上代码吧,不过里面有很多多余的函数,不过之后计算平移+旋转的时候会用到
// xuanzhuan.cpp : 定义控制台应用程序的入口点。 // #include "StdAfx.h" #include <opencv2/opencv.hpp> #include <opencv2/core/core.hpp> #include <opencv2/features2d/features2d.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/legacy/legacy.hpp> #include <iostream> #include <vector> using namespace cv; using namespace std; void fourier(cv::Mat in,cv::Mat &out_re,cv::Mat &out_im);//计算傅里叶变换,分别输出变换后结果的实部和虚部 void gonglvpu(cv::Mat in1,cv::Mat in2,cv::Mat out);//计算傅里叶变换后的功率谱 void pingyi(cv::Mat in_1,cv::Mat in_2,int &x,int &y); void cart2polar(cv::Mat in,cv::Mat &out); void polar2cart(cv::Mat in,cv::Mat out); void fft2(IplImage *src, IplImage *dst); void fft2shift(IplImage *src, IplImage *dst); void test(cv::Mat in,cv::Mat out);//本函数可以实现计算图像傅里叶变换后功率谱的功能 int _tmain(int argc, _TCHAR* argv[]) { cv::Mat image1=cv::imread("lena.bmp"); cv::Mat image2=cv::imread("5du.bmp"); cv::cvtColor(image1,image1,CV_RGB2GRAY); cv::cvtColor(image2,image2,CV_RGB2GRAY); cart2polar(image1,image1); //image1=image1(cv::Rect(0,0,200,200)); cart2polar(image2,image2); //image2=image2(cv::Rect(0,0,200,200)); cv::namedWindow("www"); cv::imshow("www",image2); int xx=0,yy=0; pingyi(image1,image2,xx,yy); cout<<xx<<" "<<yy<<endl; int theta=((double)(yy+1)/image1.rows)*360; cout<<"theta "<<theta<<endl; cv::waitKey(); /* cv::Mat src1s[]={Mat_<float>(image1),cv::Mat::zeros(image1.size(),CV_32FC1)}; cv::Mat FA1; cv::merge(src1s,2,FA1); //cv::dft(FA1,FA1); cv::split(FA1,src1s); cv::magnitude(src1s[0],src1s[1],src1s[0]); src1s[0]=src1s[0](cv::Rect(100,100,400,400)); cart2polar(src1s[0],src1s[0]); //polar2cart(src1s[0],src1s[0]); src1s[0]=src1s[0](cv::Rect(0,0,200,200)); cv::normalize(src1s[0],src1s[0],0,1,CV_MINMAX); cv::Mat src2s[]={Mat_<float>(image2),cv::Mat::zeros(image2.size(),CV_32FC1)}; cv::Mat FA2; cv::merge(src2s,2,FA2); //cv::dft(FA2,FA2); cv::split(FA2,src2s); cv::magnitude(src2s[0],src2s[1],src2s[0]); src2s[0]=src2s[0](cv::Rect(100,100,400,400)); cart2polar(src2s[0],src2s[0]); src2s[0]=src2s[0](cv::Rect(0,0,200,200)); cv::normalize(src2s[0],src2s[0],0,1,CV_MINMAX); //cv::normalize(src2s[0],src2s[0],0,1,CV_MINMAX); cv::namedWindow("test"); cv::imshow("test",src2s[0]); cv::waitKey(); int xx=0,yy=0; pingyi(src1s[0],src2s[0],xx,yy); cout<<xx<<" "<<yy<<endl; */ return 0; } void test(cv::Mat in,cv::Mat out) { IplImage ss=in; IplImage tt=in; IplImage *src=&in.operator IplImage(); //源图像 IplImage *Image=&out.operator IplImage(); IplImage *Fourier; //傅里叶系数 IplImage *dst ; IplImage *ImageRe; IplImage *ImageIm; IplImage *ImageIm1; IplImage *ImageDst; double m,M; double scale; double shift; //src = cvLoadImage("lena.bmp",0); //加载源图像,第二个参数表示将输入的图片转为单信道 Fourier = cvCreateImage(cvGetSize(src),IPL_DEPTH_64F,2); dst = cvCreateImage(cvGetSize(src),IPL_DEPTH_64F,2); ImageRe = cvCreateImage(cvGetSize(src),IPL_DEPTH_64F,1); ImageIm = cvCreateImage(cvGetSize(src),IPL_DEPTH_64F,1); ImageIm1 = cvCreateImage(cvGetSize(src),IPL_DEPTH_64F,1); //Image = cvCreateImage(cvGetSize(src),src->depth,src->nChannels); ImageDst = cvCreateImage(cvGetSize(src),src->depth,src->nChannels); fft2(src,Fourier); //傅里叶变换 fft2shift(Fourier, Image); //中心化 //cvDFT(Fourier,dst,CV_DXT_INV_SCALE);//实现傅里叶逆变换,并对结果进行缩放 cvSplit(dst,ImageRe,ImageIm,0,0); //cvNamedWindow("源图像",0); //cvShowImage("源图像",src); //对数组每个元素平方并存储在第二个参数中 cvPow(ImageRe,ImageRe,2); cvPow(ImageIm,ImageIm1,2); cvAdd(ImageRe,ImageIm1,ImageRe,NULL); cvPow(ImageRe,ImageRe,0.5); cvMinMaxLoc(ImageRe,&m,&M,NULL,NULL); scale = 255/(M - m); shift = -m * scale; //将shift加在ImageRe各元素按比例缩放的结果上,存储为ImageDst cvConvertScale(ImageRe,ImageDst,scale,shift); cvNormalize(ImageIm,ImageIm, 0, 1, CV_MINMAX); //cvNamedWindow("傅里叶谱",0); //cvShowImage("傅里叶谱",Image); //cvNamedWindow("傅里叶逆变换",0); //cvShowImage("傅里叶逆变换",ImageDst); //cvNamedWindow("test",0); //cvShowImage("test",ImageIm); cvWaitKey(0); //cvReleaseImage(&src); //cvReleaseImage(&Image); cvReleaseImage(&ImageIm); cvReleaseImage(&ImageRe); cvReleaseImage(&Fourier); cvReleaseImage(&dst); cvReleaseImage(&ImageDst); // cvDestroyAllWindows(); } void fourier(cv::Mat in,cv::Mat &out_re,cv::Mat &out_im) { Mat planes[] = {Mat_<float>(in), Mat::zeros(in.size(), CV_32FC1)}; Mat complexI; merge(planes, 2, complexI); cv::dft(complexI, complexI); cv::split(complexI, planes); out_re=planes[0]; out_im=planes[1]; } void gonglvpu(cv::Mat in1,cv::Mat in2,cv::Mat out) { cv::magnitude(in1,in2,out); /* IplImage data_1=in1; IplImage data_2=in2; IplImage data_3=out; IplImage* pI1 = &in1.operator IplImage(); IplImage* pI2 = &in2.operator IplImage(); IplImage* pI3 = &out.operator IplImage(); cvPow(pI1,pI1,2); cvPow(pI2,pI2,2); cvAdd(pI1,pI2,pI3); cvPow(pI3,pI3,0.5); */ } void pingyi(cv::Mat in_1,cv::Mat in_2,int &x,int &y) { cv::Mat padded=in_1; Mat planes[] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)}; Mat complexI; merge(planes, 2, complexI); cv::dft(complexI, complexI); cv::split(complexI, planes); ////////////////////////////////// cv::Mat padded2=in_2; Mat planes2[] = {Mat_<float>(padded2), Mat::zeros(padded2.size(), CV_32F)}; Mat complexI2; merge(planes2, 2, complexI2); cv::dft(complexI2, complexI2); cv::split(complexI2, planes2); //cv::normalize(planes[1],planes[1], 0, 1, CV_MINMAX); //////////////////////////////////////////////////////// //src1变换后实部 planes[0] 虚部planes[1] //src2变换后实部 planes2[0] 虚部planes2[1] //互功率谱存放矩阵 实部 planes3[0] 虚部planes3[1] ////////////////////////////////////////////////////////// Mat planes3[] = {Mat::zeros(in_1.size(), CV_32F), Mat::zeros(in_1.size(), CV_32F)}; for(int i=0;i<in_1.rows-1;i++) { for(int j=0;j<in_1.cols-1;j++) { double r1=planes[0].at<float>(j,i);//获取像素值 double i1=planes[1].at<float>(j,i); double r2=planes2[0].at<float>(j,i); double i2=planes2[1].at<float>(j,i); double r3 =r1*r2+i1*i2;//计算互功率谱的值 double i3 =r1*i2-r2*i1; double abs =sqrt((r3*r3)+(i3*i3)); double r_exp =r3/abs; double i_exp =i3/abs; planes3[0].at<float>(j,i)=r_exp; planes3[1].at<float>(j,i)=i_exp; } } Mat complexI3; merge(planes3, 2, complexI3); cv::dft(complexI3,complexI3,CV_DXT_INV_SCALE); cv::split(complexI3,planes3); magnitude(planes3[0], planes3[1], planes3[0]); complexI3=planes3[0]; complexI3 += Scalar::all(1); log(complexI3, complexI3); cv::normalize(complexI3,complexI3, 0, 1, CV_MINMAX); double max=0,min=0; cv::Point minLoc,maxLoc; cv::minMaxLoc(complexI3,&min,&max,&minLoc,&maxLoc); //cv::imwrite("complexI3.bmp",complexI3); x=maxLoc.x; y=maxLoc.y; cout<<min<<" "<<max<<endl; cout<<complexI3.at<float>(maxLoc)<<endl; } void cart2polar(cv::Mat in,cv::Mat &out) { IplImage tmp1=in; IplImage* pI1 = &in.operator IplImage(); IplImage tmp2=out; IplImage* pI2 = &out.operator IplImage(); cvLogPolar( pI1, pI2, cvPoint2D32f(pI1->width/2,pI1->height/2), 40, CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS ); //cvReleaseImage(&pI1); //cvReleaseImage(&pI2); } void polar2cart(cv::Mat in,cv::Mat out) { IplImage tmp1=in; IplImage* pI1 = &in.operator IplImage(); IplImage tmp2=out; IplImage* pI2 = &out.operator IplImage(); cvLogPolar( pI1, pI2, cvPoint2D32f(pI1->width/2,pI1->height/2), 40, CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS+CV_WARP_INVERSE_MAP ); } void fft2(IplImage *src, IplImage *dst) { IplImage *image_Re = 0, *image_Im = 0, *Fourier = 0; //实部、虚部 image_Re = cvCreateImage(cvGetSize(src), IPL_DEPTH_64F, 1); //实部 image_Im = cvCreateImage(cvGetSize(src), IPL_DEPTH_64F, 1); //虚部 Fourier = cvCreateImage(cvGetSize(src), IPL_DEPTH_64F, 2);//2 channels (image_Re, image_Im) cvConvertScale(src, image_Re, 1, 0);// Real part conversion from u8 to 64f (double) cvZero(image_Im);// Imaginary part (zeros) cvMerge(image_Re, image_Im, 0, 0, Fourier);// Join real and imaginary parts and stock them in Fourier image cvDFT(Fourier, dst, CV_DXT_FORWARD);// Application of the forward Fourier transform cvReleaseImage(&image_Re); cvReleaseImage(&image_Im); cvReleaseImage(&Fourier); } void fft2shift(IplImage *src, IplImage *dst) { IplImage *image_Re = 0, *image_Im = 0; int nRow, nCol, i, j, cy, cx; double scale, shift, tmp13, tmp24; image_Re = cvCreateImage(cvGetSize(src), IPL_DEPTH_64F, 1); image_Im = cvCreateImage(cvGetSize(src), IPL_DEPTH_64F, 1); cvSplit( src, image_Re, image_Im, 0, 0 ); //具体原理见冈萨雷斯数字图像处理p123 // Compute the magnitude of the spectrum Mag = sqrt(Re^2 + Im^2) //计算傅里叶谱 cvPow( image_Re, image_Re, 2.0); cvPow( image_Im, image_Im, 2.0); cvAdd( image_Re, image_Im, image_Re); cvPow( image_Re, image_Re, 0.5 ); //对数变换以增强灰度级细节(这种变换使以窄带低灰度输入图像值映射一宽带输出值,具体可见冈萨雷斯数字图像处理p62) // Compute log(1 + Mag); cvAddS( image_Re, cvScalar(1.0), image_Re ); // 1 + Mag cvLog( image_Re, image_Re ); // log(1 + Mag) //Rearrange the quadrants of Fourier image so that the origin is at the image center nRow = src->height; nCol = src->width; cx = nCol/2; cy = nRow/2; // image center //CV_IMAGE_ELEM为OpenCV定义的宏,用来读取图像的像素值,这一部分就是进行中心变换 for( j = 0; j < cy; j++ ){ for( i = 0; i < cx; i++ ){ //中心化,将整体份成四块进行对角交换 tmp13 = CV_IMAGE_ELEM( image_Re, double, j, i); CV_IMAGE_ELEM( image_Re, double, j, i) = CV_IMAGE_ELEM(image_Re, double, j+cy, i+cx); CV_IMAGE_ELEM( image_Re, double, j+cy, i+cx) = tmp13; tmp24 = CV_IMAGE_ELEM( image_Re, double, j, i+cx); CV_IMAGE_ELEM( image_Re, double, j, i+cx) =CV_IMAGE_ELEM( image_Re, double, j+cy, i); CV_IMAGE_ELEM( image_Re, double, j+cy, i) = tmp24; } } //归一化处理将矩阵的元素值归一为[0,255] //[(f(x,y)-minVal)/(maxVal-minVal)]*255 double minVal = 0, maxVal = 0; // Localize minimum and maximum values cvMinMaxLoc( image_Re, &minVal, &maxVal ); // Normalize image (0 - 255) to be observed as an u8 image scale = 255/(maxVal - minVal); shift = -minVal * scale; cvConvertScale(image_Re, dst, scale, shift); cvReleaseImage(&image_Re); cvReleaseImage(&image_Im); } /* for(int i=0;i<500;i++) { for(int j=0;j<500;j++) { if(i%20==0&&j%20==0) cout<<src1_f_re.at<float>(i,j)<<endl; } } */ /*string name1="lena.bmp"; string name2="90du.bmp"; cv::Mat src1=imread(name1); if(src1.channels()!=1) cv::cvtColor(src1,src1,CV_RGB2GRAY); cv::Mat src1_f_re =cv::Mat::zeros(src1.size(),CV_32FC1); cv::Mat src1_f_im =cv::Mat::zeros(src1.size(),CV_32FC1); cv::Mat src1_gonglv =cv::Mat::zeros(src1.size(),CV_32FC1); cv::Mat src1_g_log =cv::Mat::zeros(src1.size(),CV_32FC1); fourier(src1,src1_f_re,src1_f_im); gonglvpu(src1_f_re,src1_f_im,src1_gonglv); cart2polar(src1_gonglv,src1_g_log); cv::normalize(src1_g_log,src1_g_log, 0, 1, CV_MINMAX); cv::Mat src2=imread(name2); if(src2.channels()!=1) cv::cvtColor(src2,src2,CV_RGB2GRAY); cv::Mat src2_f_re =cv::Mat::zeros(src2.size(),CV_32FC1); cv::Mat src2_f_im =cv::Mat::zeros(src2.size(),CV_32FC1); cv::Mat src2_gonglv =cv::Mat::zeros(src2.size(),CV_32FC1); cv::Mat src2_g_log =cv::Mat::zeros(src2.size(),CV_32FC1); fourier(src2,src2_f_re,src2_f_im); gonglvpu(src2_f_re,src2_f_im,src2_gonglv); cart2polar(src2_gonglv,src2_g_log); cv::normalize(src2_g_log,src2_g_log, 0, 1, CV_MINMAX); int gx=0,gy=0; pingyi(src1_gonglv,src2_gonglv,gx,gy); //cout<<"max "<<max<<" min "<<min<<endl; cout<<gx<<" "<<gy<<endl; //pingyi(src1,src2,gx,gy); */
相关文章推荐
- opencv 图像仿射变换 计算仿射变换后对应特征点的新坐标 图像旋转、缩放、平移
- opencv 图像仿射变换 计算仿射变换后对应特征点的新坐标 图像旋转、缩放、平移
- opencv 图像仿射变换 计算仿射变换后对应特征点的新坐标 图像旋转、缩放、平移
- 利用opencv函数对图像旋转后,按旋转偏移新计算新的图像外接四边形绘制
- OpenCV计算物体的重心坐标(2值图像)
- opencv 拉伸、扭曲、旋转图像-仿射变换 opencv1 / opencv2 / python cv2(代码)
- 【OpenCV】计算图像的水平和垂直积分投影
- opencv2学习笔记:4.2计算图像直方图
- opencv3计算图像中轮廓的长度-滚动条
- OpenCV学习之六: 使用方向梯度直方图估计图像旋转角度
- opencv学习---计算图像的水平积分投影和垂直积分投影
- opencv之图像的旋转
- javacpp-opencv图像处理3:使用opencv原生方法遍历摄像头设备及调用(增加实时帧率计算方法)
- python opencv对图像进行旋转且不裁剪图片的方法
- 使用OpenCV2.x计算图像的水平和垂直积分投影
- OpenCV【4】---calcHist 计算图像的直方图
- ROS中利用opencv3完成四个视频流拼接成一副图像显示,并添加track条进行参数调节
- opencv3学习笔记(二)图像的截图,旋转与大小的变化
- OpenCV2:图像的几何变换,平移、镜像、缩放、旋转(2)
- OpenCV2:图像的几何变换,平移、镜像、缩放、旋转(2)