图像缩小算法

图像缩放的算法倒是挺多的,常见的有最近邻插值法、双线性插值法、三次卷积法等。其中双线性插值算法应该是应用比较广泛的一种方法,在缩放质量和速度上都比较折衷。在xnview里面选择双线性方法对一幅图像进行0.5倍的缩小,发现效果还可以。看了一下算法原理,实现起来也不算困难。可是用自己实现的方法对图像进行0.5倍的缩小时,却发现效果远没有xnview的效果好。商业软件就是做得好啊,难到它所用的双线性方法不是一般书上所叙述的?还是我的实现方式有错?再从网上拷贝了一种双线性插值的实现,发现效果跟我的一样:比较差,锯齿较明显,文字笔画重叠而不可辨认。

原来缩小跟放大还是不一样的,双线性插值对放大来说,效果还不错。缩小时,如果倍数超过0.5,可能效果就要大打折扣了。而高质量的图像缩小算法,网上也没有比较好的资料,虽然有不少像我一样的人,也遇到了这个问题。照理来说,应该很普遍和容易实现才对啊。windows里面的缩略图、众多看图软件的缩放功能都做得那么好。

 

图像缩小算法_第1张图片

  原始图片

 图像缩小算法_第2张图片 图像缩小算法_第3张图片

             双线性插值                             xnview用双线性

下面说说双线性插值的原理和实现。
对于一个目的像素,设坐标通过反向变换得到的浮点坐标为(i+u,j+v),其中i、j均为非负整数,u、v为[0,1)区间的浮点数,则这个像素得值 f(i+u,j+v) 可由原图像中坐标为 (i,j)、(i+1,j)、(i,j+1)、(i+1,j+1)所对应的周围四个像素的值决定,即:
f(i+u,j+v) = (1-u)(1-v)f(i,j) + (1-u)vf(i,j+1) + u(1-v)f(i+1,j) + uvf(i+1,j+1)
其中f(i,j)表示源图像(i,j)处的的像素值,以此类推。

用一个函数表示,即:
__inline double bilinear(double a, double b, int uv, int u1v, int uv1, int u1v1)
{
return (double) (uv*(1-a)*(1-b)+u1v*a*(1-b)+uv1*b*(1-a)+u1v1*a*b);
}

对一幅图像每个像素的rgb分量进行如上操作,即是双线性插值。

//psrc, sw, sh:源数据及宽高

//pdst, dw, dh:目的数据及宽高

void zoomdata_bilinear(unsigned char* pdst, int dw, int dh, unsigned char* psrc, int sw, int sh)
{
unsigned char *ppdst;
unsigned char * ccsrc; 
int i, j;
ppdst = pdst;
ccsrc = psrc;


for(i=0;i

转载于:https://my.oschina.net/tofro/blog/1503087

你可能感兴趣的:(图像缩小算法)