图像缩小算法
图像缩小算法
来来叔叔 发表于3个月前
图像缩小算法
  • 发表于 3个月前
  • 阅读 0
  • 收藏 0
  • 点赞 0
  • 评论 0

腾讯云 十分钟定制你的第一个小程序>>>   

 

图像缩放的算法倒是挺多的,常见的有最近邻插值法、双线性插值法、三次卷积法等。其中双线性插值算法应该是应用比较广泛的一种方法,在缩放质量和速度上都比较折衷。在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;
   
   }
}

}

共有 人打赏支持
粉丝 0
博文 100
码字总数 55732
×
来来叔叔
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: