图像缩小算法

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

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

原始图片

双线性插值 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<dh;i++)
{
   for(j=0;j<dw;j++)
   {
    int ii,jj,di;
    double u,v,r,g,b;
    v = (i*sh)/(double)(dh);
    u = (j*sw)/(double)(dw);
    ii = (int)(v);
    jj = (int)(u);
   
    b = bilinear(u-jj, v-ii, 
     ccsrc[ii*sw*3+jj*3], 
     ccsrc[ii*sw*3+(jj+1)*3],
     ccsrc[(ii+1)*sw*3+jj*3],
     ccsrc[(ii+1)*sw*3+(jj+1)*3]);
    g = bilinear(u-jj, v-ii, 
     ccsrc[ii*sw*3+jj*3+1], 
     ccsrc[ii*sw*3+(jj+1)*3+1],
     ccsrc[(ii+1)*sw*3+jj*3+1],
     ccsrc[(ii+1)*sw*3+(jj+1)*3+1]);
    r = bilinear(u-jj, v-ii, 
     ccsrc[ii*sw*3+jj*3+2], 
     ccsrc[ii*sw*3+(jj+1)*3+2],
     ccsrc[(ii+1)*sw*3+jj*3+2],
     ccsrc[(ii+1)*sw*3+(jj+1)*3+2]);
   
    ppdst[i*dw*3+j*3+2] = r;
    ppdst[i*dw*3+j*3+1] = g;
    ppdst[i*dw*3+j*3+0] = b;
   
   }
}

}

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值