关于图像处理中的插值和旋转
2017-10-20 18:41
429 查看
关于图像处理中的插值和旋转
一.插值参考:http://blog.csdn.net/Real_Myth/article/details/49275999 在模板匹配问题中,涉及到角度插值和坐标插值(亚像素精度)问题。角度插值:得到最佳匹配模板左右相邻的模板的信息,二次拟合(x为角度,y为得分)
坐标插值:得到最佳匹配点的3*3邻域点的匹配情况,三次拟合(x,y坐标,y为得分)
确定拟合模型(什么方程)——》找到需要的信息(多少个点及其对应的值)——》求极值
注意: 相邻元素的确定。在我遇到的实际问题中,要找到同一尺度下的相邻角度的模板,而所有模板在制作保存时用到了并行,故需要遍历搜索。以三个角度为x,以它们同一点(变量的控制)处的得分为y。
【将点一次带入得到方程组/最小二乘法列出方程组】
三次拟合示例:a0+a1x+a2y+a3x^2+a4y^2+a5xy=zvoidfittingCurve3D(double *x,double *y,double *z,intn,double *index){ //直接把点带入方程,把方程组写成矩阵形式,结果用伪逆表示[inv(A'A)]A'b double *a =newdouble[n * 6];//已知点的信息矩阵,含xy double *b =newdouble[n];//已知点的信息矩阵,含z ///////构造a的一维数组,n*6 for (int i = 0; i <n * 6; ++i) { if (i % 6 == 0) { a[i]= 1; a[i+ 1] = x[i / 6];//x a[i+ 2] = y[i / 6];//y a[i+ 3] = x[i / 6] * x[i / 6];//x^2 a[i+ 4] = y[i / 6] * y[i / 6];//y^2 a[i+ 5] = x[i / 6] * y[i / 6];//x*y } } CvMat AMat = cvMat(n, 6,CV_64FC1, a);//变成矩阵AMat CvMat *ATransposedMat =cvCreateMat(AMat.cols, AMat.rows,CV_64FC1); cvTranspose(&AMat,ATransposedMat);//转置ATransposedMat///用于存储矩阵相乘结果,构造的数组n*n double *c =newdouble[6 * 6]; for (int i = 0; i < 6 *6; ++i) { c[i]= 0; } CvMat invMat1 = cvMat(6,6,CV_64FC1, c);//变成矩阵invMat1 cvGEMM(ATransposedMat,&AMat, 1, NULL, 0,&invMat1, 0);// ATransposedMat(转置)*AMat=invMat1 cvInvert(&invMat1,&invMat1, 0);//求invMat1的逆矩阵,invMat1 ///////构造b的一维数组,n*1 for (int i = 0; i <n; ++i) { b[i]= z[i]; } CvMat BMat = cvMat(n, 1,CV_64FC1, b);//变成矩阵BMat//用于存储矩阵相乘结果,构造的数组6*1 double *d =newdouble[6]; for (int i = 0; i < 6;++i) { d[i]= 0; } CvMat invMat2 = cvMat(6,1,CV_64FC1, d);//变成矩阵invMat2 cvGEMM(ATransposedMat,&BMat, 1, NULL, 0,&invMat2, 0);//AMat的转置矩阵 * BMat矩阵 = invMat2 CvMat indexMat = cvMat(6,1,CV_64FC1, index); cvGEMM(&invMat1,&invMat2, 1, NULL, 0,&indexMat, 0);//invMat1 * invMat2 = indexMat cvReleaseMat(&ATransposedMat); delete[] a; delete[] b; delete[] c; delete[] d;
}
各种曲面的拟合:如拟合球面 :x^2+ay^2+bz^2+cx+dy+ez+f=0
http://blog.csdn.net/hj199404182515/article/details/59480954
二.旋转
旋转算法原理:http://blog.csdn.net/liyuan02/article/details/6750828
正向映射://旋转后dst图像坐标系
double xtemp0 = c*x - s*y + (-0.5*c*(srcW - 1) + 0.5*s*(srcH - 1) +0.5*dstW);
double ytemp0 = s*x + c*y + (-0.5*s*(srcW - 1) -0.5*c*(srcH - 1) + 0.5*dstH);
逆向映射:(映射回原图的放大图temp)
double xtemp = c*i + s*j + (-c*(dstW - 1)*0.5 - s* (dstH - 1)*0.5+0.5*temp->width);
double ytemp = -s*i + c*j + (s*(dstW - 1)*0.5 - c* (dstH -1)*0.5+ 0.5*temp->height);
//将原图复制到临时图像temp中心 (保证原图可以任意角度旋转的最小尺寸 )
int tempLength =int( sqrt((double)width *width + (double)height *height) + 10);
int tempX = (tempLength + 1) / 2 - width /2;
int tempY = (tempLength + 1) / 2 - height /2;
IplImage* temp =cvCreateImage(cvSize(tempLength, tempLength), src->depth,src->nChannels);
memset(temp->imageData, 255, sizeof(char)*temp->imageSize);
cvSetImageROI(temp, cvRect(tempX, tempY,width, height));
cvCopy(src, temp, NULL);
cvResetImageROI(temp);
cvReleaseImage(&temp);
正向映射:输入图像上整数点坐标映射到输出图像之后,变成了非整数点坐标。因此,需要将其像素值按一定权重分配到其周围四个像素点上。遍历输出图像,对每个点,将每次映射分配而来的像素值叠加。
图像旋转中的插值:一般采用反向双线性插值
http://www.cnblogs.com/mlv5/archive/2012/02/02/2336321.html
示例:intImgBilinearInter(floatfx,floatfy,IplImage * img) { //参考函数cv::PicRotaryBilInear——双线性插值 int value; int x = floor(fx); int y = floor(fy); cv::Point P0 = Pixels_Bound(img, x, y); cv::Point P2 = Pixels_Bound(img, x + 1, y); cv::Point P1 = Pixels_Bound(img, x, y + 1); cv::Point P3 = Pixels_Bound(img, x + 1, y + 1);//边界饱和 float u =fx - x; float v =fy - y; float pm3 = u*v; float pm2 = u*(1 - v); float pm1 = v*(1 - u); float pm0 = (1 - u)*(1 -v); // 指向图像的指针 uchar* lp = (uchar *)img->imageData; int step =img->widthStep /sizeof(uchar); //value = (pm0*lp[P0.y*step + P0.x] + pm1*lp[P1.y *step +P1.x] + pm2*lp[P2.y *step + P2.x ] + pm3*lp[P3.y *step + P3.x ]); float value_float =(pm0*lp[P0.y*step + P0.x] + pm1*lp[P1.y *step + P1.x] + pm2*lp[P2.y *step +P2.x] + pm3*lp[P3.y *step + P3.x]); value= round(value_float); return value;
}cv::Point Pixels_Bound(IplImage *pic, intx0,inty0) { if (x0<0) {x0 = 0; } elseif (x0 >=pic->width) { x0 = pic->width - 1; } if (y0<0) {y0 = 0; } elseif (y0 >=pic->height) { y0 = pic->height - 1; } cv::Point P(x0,y0); return P;
}
双线性插值部分,边界元素的处理需注意。
相关文章推荐
- 图像处理之线性插值旋转算法(biline-interpolation rotate algorithm)
- 图像处理---关于像素坐标矩阵变换(平移,旋转,缩放,错切)
- Matlab 关于彩色图像的平移、旋转以及对称处理
- 图像处理---关于像素坐标矩阵变换(平移,旋转,缩放,错切)
- 图像处理之线性插值旋转算法(biline-interpolation rotate algorithm)
- python图像处理小工具(镜像,旋转正负30度)
- 图像处理 基于Visual C++编程 学习笔记 (4)图像旋转
- 【图像处理】关于掩模的作用
- C语言关于图像处理的函数
- 关于卷积,福利叶变换,图像处理关…
- 图形图像处理-之-高质量的快速的图像缩放 上篇 近邻取样插值和其速度优化
- 关于三星手机拍照 获取的照片旋转处理
- MATLAB批量读取文件夹下的图像,并对图像进行裁剪为指定大小,旋转,缩放,加噪声处理,rgb2hsv,批量保存
- 图像处理常用的插值方法
- C#图像处理(各种旋转、改变大小、柔化、锐化、雾化、底片、浮雕、黑白、滤镜效果)
- RGB图像旋转90度编程完成-视频处理基础(3)
- 图形图像处理-之-任意角度的高质量的快速的图像旋转 上篇 纯软件的任意角度的快速旋转
- 图形图像处理-之-高质量的快速的图像缩放 中篇 二次线性插值和三次卷积插值
- C#图像处理(各种旋转、改变大小、柔化、锐化、雾化、底片、浮雕、黑白、滤镜效果)
- 图像预处理SSE加速,90度旋转和垂直镜像