图像旋转插值的问题

 

今天解决了图像旋转插值的问题,还是很开心的,虽然遇到了很多麻烦,最后感觉还是值得的。:)

先截图,有时间再补充。

主要就是坐标系的转换、亚像素点的坐标、线性插值 、旋转角度计算的公式、角度的正负、相对坐标、atan和atan2反正切回来角度的范围。

 

用亚像素点的像素对周围4个像素进行插值:

 

旋转之后,总有些点是没有值的,后来发现是坐标计算的方向反了,应该根据目标图像的坐标去找原图像中的亚像素点,然后插值,

这样一来在目标图像的每个像素点上就都有值了:

 

将图像沿着点(cenx, ceny)旋转delta度:(src已经分配内存,dest仅仅是指针,角度顺时针为正,只针对灰度图像)

void myRotateImg(IplImage* src, IplImage* dest, int cenx, int ceny,double delta)
{
    int row, col;
    int i,j;
    int height, width;
    double *temImg;

    int xmin, xmax, ymin, ymax;
    double fr, fx, fy;


    temImg = (double*)malloc(src->width*src->height*sizeof(double));
    memset(temImg, 0, src->width*src->height*sizeof(double));

    dest = cvCreateImage(cvGetSize(src), 8, 1);
    cvZero(dest);
    
    delta = delta*CV_PI/180;


    for (row = 0; row<src->height; row++)
    {
        for (col=0; col<src->width; col++)
        {
            double tem;
            double newOri;
            tem = 0;
            newOri = 0;
            if (col==cenx)
            {
                if (row> ceny) tem = CV_PI/2;
                if (row< ceny) tem = -CV_PI/2;
                //if (row == ceny) continue;
            }
            else
            {                
                tem = atan2((double)(row-ceny),(double)(col-cenx));//*180/CV_PI;
            }

            newOri = tem-delta;
            fr = sqrt((double)((col-cenx)*(col-cenx)+(row-ceny)*(row-ceny)));
            fx = fr*cos(newOri) + cenx;
            fy = fr*sin(newOri) + ceny;
            xmin = (fx>0) ? (int)fx : (int)(fx-1);
            xmax = (fx>0) ? (int)(fx+1) : (int)fx;
            ymin = (fy>0) ? (int)fy : (int)(fy-1);
            ymax = (fy>0) ? (int)(fy+1) : (int)fy;
            }
            if(xmin>=0 && ymin>=0 && xmax<src->width-1 && ymax<src->height-1) 
            {

                
                temImg[row*src->width+col] += -(fx-xmin+fy-ymin-2)*0.25*(unsigned char)src->imageData[ymin*src->widthStep+xmin];    
                temImg[row*src->width+col] += -(fx-xmin+ymax-fy-2)*0.25*(unsigned char)src->imageData[ymax*src->widthStep+xmin];        
                temImg[row*src->width+col] += -(xmax-fx+ymax-fy-2)*0.25*(unsigned char)src->imageData[ymax*src->widthStep+xmax];
                temImg[row*src->width+col] += -(xmax-fx+fy-ymin-2)*0.25*(unsigned char)src->imageData[ymin*src->widthStep+xmax];

            }
            //printf("fx %f, fy %f, xmin %d, xmax %d, ymin %d ymax %d \n", fx,fy,xmin, xmax, ymin, ymax);
        }
    }

    for (row=0; row<src->height; row++)
        for(col=0; col<src->width; col++)
        {
            dest->imageData[row*dest->widthStep+col] = (temImg[row*dest->width+col]>255) ? 255 : (temImg[row*dest->width+col]<0) ? 0 : temImg[row*dest->width+col];
        }

        dest->imageData[ceny*dest->widthStep+cenx] = src->imageData[ceny*src->widthStep+cenx];

        
        cvShowImage("src", src);
        cvShowImage("dest",dest);
        cvWaitKey(0);
        return ;
}

 

与上面基本类似,旋转后加上缩放:

void myRRImg(IplImage* src, IplImage* dest, int cenx, int ceny,double delta,double bigger)
{
    int row, col;
    int i,j;
    int height, width;
    double *temImg;
    IplImage* rotImg;

    int xmin, xmax, ymin, ymax;
    double fr, fx, fy;

    rotImg = cvCreateImage(cvGetSize(src), 8,1);
    cvZero(rotImg);

    temImg = (double*)malloc(src->width*src->height*sizeof(double));
    memset(temImg, 0, src->width*src->height*sizeof(double));

    dest = cvCreateImage(cvSize(src->width*bigger, src->height*bigger), 8, 1);
    cvZero(dest);
    
    delta = delta*CV_PI/180;


    for (row = 0; row<src->height; row++)
    {
        for (col=0; col<src->width; col++)
        {
            double tem;
            double newOri;
            tem = 0;
            newOri = 0;
            if (col==cenx)
            {
                if (row> ceny) tem = CV_PI/2;
                if (row< ceny) tem = -CV_PI/2;
                //if (row == ceny) continue;
            }
            else
            {                
                tem = atan2((double)(row-ceny),(double)(col-cenx));//*180/CV_PI;
            }

            newOri = tem-delta;
            fr = sqrt((double)((col-cenx)*(col-cenx)+(row-ceny)*(row-ceny)));
            fx = fr*cos(newOri) + cenx;
            fy = fr*sin(newOri) + ceny;
            xmin = (fx>0) ? (int)fx : (int)(fx-1);
            xmax = (fx>0) ? (int)(fx+1) : (int)fx;
            ymin = (fy>0) ? (int)fy : (int)(fy-1);
            ymax = (fy>0) ? (int)(fy+1) : (int)fy;
            if(xmin>=0 && ymin>=0 && xmax<src->width-1 && ymax<src->height-1) 
            {                
                temImg[row*src->width+col] += -(fx-xmin+fy-ymin-2)*0.25*(unsigned char)src->imageData[ymin*src->widthStep+xmin];    
                temImg[row*src->width+col] += -(fx-xmin+ymax-fy-2)*0.25*(unsigned char)src->imageData[ymax*src->widthStep+xmin];        
                temImg[row*src->width+col] += -(xmax-fx+ymax-fy-2)*0.25*(unsigned char)src->imageData[ymax*src->widthStep+xmax];
                temImg[row*src->width+col] += -(xmax-fx+fy-ymin-2)*0.25*(unsigned char)src->imageData[ymin*src->widthStep+xmax];
            }
            //printf("fx %f, fy %f, xmin %d, xmax %d, ymin %d ymax %d \n", fx,fy,xmin, xmax, ymin, ymax);
        }
    }

    for (row=0; row<src->height; row++)
        for(col=0; col<src->width; col++)
        {
            rotImg->imageData[row*rotImg->widthStep+col] = (temImg[row*rotImg->width+col]>255) ? 255 : (temImg[row*rotImg->width+col]<0) ? 0 : temImg[row*rotImg->width+col];
            //printf("%f ", temImg[row*dest->width+col]);
        }

        rotImg->imageData[ceny*rotImg->widthStep+cenx] = src->imageData[ceny*src->widthStep+cenx];
        
        cvResize(rotImg, dest,1);
        cvShowImage("src", src);
        cvShowImage("rotImg", rotImg);
        cvShowImage("dest",dest);
        cvWaitKey(0);

        cvReleaseImage(&rotImg);
        return ;
}

 

posted @ 2015-03-17 11:02  sunnycs  阅读(1260)  评论(0编辑  收藏  举报