图像旋转插值的问题
今天解决了图像旋转插值的问题,还是很开心的,虽然遇到了很多麻烦,最后感觉还是值得的。:)
先截图,有时间再补充。
主要就是坐标系的转换、亚像素点的坐标、线性插值 、旋转角度计算的公式、角度的正负、相对坐标、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 ; }
Trouble is a Friend