您的位置:首页 > 其它

关于图像处理中的插值和旋转

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;
}
双线性插值部分,边界元素的处理需注意。
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  图像处理 c
相关文章推荐