最近邻方法进行图像旋转 c++代码 旋转后图像内容无损失

        在前一篇文章中,实现了最近邻方法的图像旋转,但是旋转后,由于图像的大小没有改变,所以图像的部分内容有丢失。

在本文章中,我们同样采用最近邻的方法进行图像旋转,保全图像内容,使图像比旋转前的要大,默认旋转中心为图像中心。


图像旋转后,新的图像的 width 以及 height计算方法如下:(其中,width.height 分别为原图像的宽与高)

 newWidth = (abs(width/2*CosTheta) + abs(height/2*SinTheta))*2;     //计算新图像的长宽
 newHeight = (abs(height/2*CosTheta) + abs(width/2*SinTheta))*2;

并且,坐标归一化后,我们得到下面的旋转公式:(其中,xr yr 为旋转前的旋转中心坐标 , xr2  yr2 为旋转后新图像的旋转中心坐标)

(x0 - xr) = (x1 - xr2)*cos(a) - (y1-yr2)*sin(a) ;

(y0 - yr) = (x1 - xr2)*sin(a) - (y1-yr2)*cos(a) ;

根据该公式,我们便可以得到旋转的代码如下:

/*
函数功能:采用最近邻的方式,实现灰度图像的旋转,旋转后,图像的大小改变,保全图像内容。
参数介绍:
      src: 原图像  width:原图像的宽度  height:原图像的高度
 dst:旋转后的图像
 theta:旋转角度(弧度制)
 newWidth,newHeight : 旋转后的图像的高度和宽度
 backgroundGray:背景灰度值

注意事项:该函数对于传入函数内部的dst指针开辟了空间,所以对于空间的开辟释放要注意
*/
int nearestRotate3(BYTE *src ,int width , int height , BYTE * dst , double theta, int &newWidth,int &newHeight,BYTE backgroundGray)
{


double SinTheta = sin(theta);
double CosTheta = cos(theta);


newWidth = (abs(width/2*CosTheta) + abs(height/2*SinTheta))*2;   //计算新图像的长宽
newHeight = (abs(height/2*CosTheta) + abs(width/2*SinTheta))*2;




int xr = width/2;
int yr = height/2;      //旋转前的图像中心


int xr2 = newWidth/2;   //旋转后的图像中心
int yr2 = newHeight/2;


if(dst)
delete []dst;
dst = new BYTE[newWidth*newHeight];
BYTE * tempImg = new BYTE[newWidth*newHeight];
if(!tempImg)
return -1;
memset(tempImg,backgroundGray,newWidth*newHeight*sizeof(BYTE));


double ConstX = -xr2*CosTheta + yr2*SinTheta + xr + 0.5;
double ConstY = -yr2*CosTheta - xr2*SinTheta + yr + 0.5;


BYTE *p = tempImg;
double x1;
double y1;
int x0;
int y0;
for(int y=0;y<newHeight;y++)
{
x1 = - y*SinTheta - CosTheta + ConstX ; 
        y1 =   y*CosTheta - SinTheta + ConstY ; 
for(int x=0;x<newWidth;x++)
{
x1 += CosTheta; 
            y1 += SinTheta; 


x0 = int(x1);
y0 = int(y1);


if(x0<0||x0>width-1 || y0<0||y0>height-1)
{
p++;
continue;
}
*p = src[y0 * width + x0];
p++;
}
}
memcpy(dst,tempImg,newWidth*newHeight*sizeof(BYTE));
return 1;
}

原图以及旋转后的图像效果如下:(逆时针旋转45度)



     

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值