图像旋转 双线性插值 c++
2015-12-08 14:38
555 查看
前面详细介绍了最近邻插值实现图像的旋转,但是我们都知道,最近邻插值对于图像的旋转效果不是特别的好。所以在本文中,我们详细讨论一下双线性插值算法。
首先,详细介绍一下什么事双线性插值,以及双线性插值为什么会比最近邻插值效果好一些。
为什么图像的旋转一定要插值,因为在旋转过程中,由于三角函数的影响,导致旋转后的点,并不是每一个点都可以在原图像中找到对应点(如:计算出(3.5,4.4)将对应哪个点呢?),所以这些点的灰度值如何确定,就需要我们利用插值算法来进行处理,最近邻插值,想法比较简单,直接四舍五入,显然这种方法不是最理想的。那么双线性插值是什么呢?首先看图:
如上图,假如,我们计算后得到的像素点为p,但是这个点并没有在图像中有点与之对应,因为它的值可能是小数的,那么,我们如何确定它的灰度值呢?
双线性插值的想法也比较简单,双线性,顾名思义,利用了2次线性插值。那是哪两次呢?这时,我们便利用上了其周围的像素点O12 O22 O11 O 21 .通过O12 O22 计算出R2点的灰度值,然后通过O11 O21计算出R1点的灰度值,然后再根据R1 R2计算出P点的灰度值。这样相比最近邻方法,更加充分的利用了周围的像素点,可以取得较好的效果。
那么我们编程如何计算呢?
首先,对p点坐标进行取整,得到O21点坐标,然后像素值+1 便得到O22的坐标,然后利用比例计算,便可以得到R2的灰度值,同理可以得到R1灰度值,再根据比例计算,便可以得到p点的灰度值。
具体代码如下:
/*
双线性插值图像旋转函数 , 旋转之后 图像不改变大小 信息有些丢失
输入参数:
img: 原图像 width:原图像的宽度 height:原图像的高度
result:旋转后的图像
sita:旋转角度(弧度制)
xr,yr : 旋转中心
BackGray:背景灰度值
*/
int TwinRotate(BYTE *img,int width,int height,BYTE *result,double sita,double xr,double yr,BYTE BackGray)
{
double SinTheta = sin(sita);double CosTheta = cos(sita);
if(result)
delete []result;
result = new BYTE[width*height];
// if(ResultTemp==NULL)
// return -1;
memset( result, BackGray, width*height*sizeof(BYTE) );
int x, y, px, py;
double tx,ty,p1,p2,p3,p4,p1_2,p3_4;
double ConstX= -xr*CosTheta + yr*SinTheta + xr ;
double ConstY= -yr*CosTheta - xr*SinTheta + yr ;
BYTE *pRes=result, *p;
for(y=0;y<height;y++)
{
tx = - y*SinTheta - CosTheta + ConstX ;
ty = y*CosTheta - SinTheta + ConstY ;
for(x=0;x<width;x++)
{
tx += CosTheta; //x*CosTheta - y*SinTheta + ConstX; (x-xr)*CosTheta - (y-yr)*SinTheta + xr
ty += SinTheta; //y*CosTheta + x*SinTheta + ConstY; (y-yr)*CosTheta + (x-xr)*SinTheta + yr
px = (int)tx;
py = (int)ty;
if( px<0 || px>width-2 || py<0 || py>height-2 )
{
pRes++;
continue;
}
p1 = img[py*width+px]; //此处求出周围点的值
p2 = img[py*width+px+1];
p3 = img[(py+1)*width+px];
p4 = img[(py+1)*width+px+1];
p1_2 = p1 + (tx-px)*(p2-p1);
p3_4 = p3 + (tx-px)*(p4-p3);
*pRes = p1_2 + (ty - py)*(p3_4 - p1_2);
pRes++;
}
}
return true;
}
首先,详细介绍一下什么事双线性插值,以及双线性插值为什么会比最近邻插值效果好一些。
为什么图像的旋转一定要插值,因为在旋转过程中,由于三角函数的影响,导致旋转后的点,并不是每一个点都可以在原图像中找到对应点(如:计算出(3.5,4.4)将对应哪个点呢?),所以这些点的灰度值如何确定,就需要我们利用插值算法来进行处理,最近邻插值,想法比较简单,直接四舍五入,显然这种方法不是最理想的。那么双线性插值是什么呢?首先看图:
如上图,假如,我们计算后得到的像素点为p,但是这个点并没有在图像中有点与之对应,因为它的值可能是小数的,那么,我们如何确定它的灰度值呢?
双线性插值的想法也比较简单,双线性,顾名思义,利用了2次线性插值。那是哪两次呢?这时,我们便利用上了其周围的像素点O12 O22 O11 O 21 .通过O12 O22 计算出R2点的灰度值,然后通过O11 O21计算出R1点的灰度值,然后再根据R1 R2计算出P点的灰度值。这样相比最近邻方法,更加充分的利用了周围的像素点,可以取得较好的效果。
那么我们编程如何计算呢?
首先,对p点坐标进行取整,得到O21点坐标,然后像素值+1 便得到O22的坐标,然后利用比例计算,便可以得到R2的灰度值,同理可以得到R1灰度值,再根据比例计算,便可以得到p点的灰度值。
具体代码如下:
/*
双线性插值图像旋转函数 , 旋转之后 图像不改变大小 信息有些丢失
输入参数:
img: 原图像 width:原图像的宽度 height:原图像的高度
result:旋转后的图像
sita:旋转角度(弧度制)
xr,yr : 旋转中心
BackGray:背景灰度值
*/
int TwinRotate(BYTE *img,int width,int height,BYTE *result,double sita,double xr,double yr,BYTE BackGray)
{
double SinTheta = sin(sita);double CosTheta = cos(sita);
if(result)
delete []result;
result = new BYTE[width*height];
// if(ResultTemp==NULL)
// return -1;
memset( result, BackGray, width*height*sizeof(BYTE) );
int x, y, px, py;
double tx,ty,p1,p2,p3,p4,p1_2,p3_4;
double ConstX= -xr*CosTheta + yr*SinTheta + xr ;
double ConstY= -yr*CosTheta - xr*SinTheta + yr ;
BYTE *pRes=result, *p;
for(y=0;y<height;y++)
{
tx = - y*SinTheta - CosTheta + ConstX ;
ty = y*CosTheta - SinTheta + ConstY ;
for(x=0;x<width;x++)
{
tx += CosTheta; //x*CosTheta - y*SinTheta + ConstX; (x-xr)*CosTheta - (y-yr)*SinTheta + xr
ty += SinTheta; //y*CosTheta + x*SinTheta + ConstY; (y-yr)*CosTheta + (x-xr)*SinTheta + yr
px = (int)tx;
py = (int)ty;
if( px<0 || px>width-2 || py<0 || py>height-2 )
{
pRes++;
continue;
}
p1 = img[py*width+px]; //此处求出周围点的值
p2 = img[py*width+px+1];
p3 = img[(py+1)*width+px];
p4 = img[(py+1)*width+px+1];
p1_2 = p1 + (tx-px)*(p2-p1);
p3_4 = p3 + (tx-px)*(p4-p3);
*pRes = p1_2 + (ty - py)*(p3_4 - p1_2);
pRes++;
}
}
return true;
}
相关文章推荐
- makefile多目录的.c 格式.cpp混合编译
- c++ final关键字
- C++11 并发实战阅读笔记(1)
- C语言:折半插入排序与二分查找
- C与C++的标准发展
- C++ virtual
- C++文件操作详解(ifstream、ofstream、fstream)
- 大话设计模式_命令模式c++实现
- c++ 条件变量
- 值得推荐的C/C++框架和库
- c++ weak_ptr
- C++动态库获取自身路径
- C和C++:open("/dev/dcm/0raw",O_WRONLY);
- 使用VC++编译器静态编译Qt5.5
- 关于[]静态数组和new分配的动态数组的区别
- 详解数组名和指针的区别
- C语言 指针例解
- MyC语言练习
- C++ string占多少个字节测试
- C++STL 常用 函数 用法