Bilinear image scaling is about the same as nearest neighbor image scaling except with interpolation. Instead of copying the neighboring pixels (which often results in jaggy image), interpolation technique based on surrounding pixels is used to produce much smoother scaling.
Although bilinear scaling is not exactly complicated, it is a composite algorithm based on other more basic function. As the name might have suggested, the algorithm is a combination of two linear interpolations. It is not mandatory to know what linear interpolation is but doing is not really that bad. I suggest the reader to follow through at least the brief explanation.

Linear Interpolation (a brief explanation)

Linear interpolation is a method to estimate an arbitrary point between two other points. Consider two points of colors on a canvas, red and green. Imagine a straight line between the dots, and somewhere on this imaginary line put a new dot. What is a suitable color for this new dot? Any color is fine really, but we are talking about interpolation so we should be doing that. Putting our little imaginary line in perspective,

Figure 1: What is a suitable color for Y?

In this illustration, a yet unknown color dot Y is placed somewhere between A (red) and B (green). Other only known thing is the distance between A and B which is L and the distance between A and Y which is l. This information is sufficient to construct the so called linear interpolation function.

Figure 2: Linear interpolation equation

This function will be able to tell what Y's color is. If you are interested to know the expected color for Y, check the full article for Linear Interpolation.

Texture

Going back to the original topic, the other trivial but still important term is the texture. This is not about the whole image itself but only a small portion of it. In the simplest of bilinear scaling, the usual texture dimension is only two by two, a texture containing only four pixels. The illustration below should help with getting the idea for this,

Figure3: 2 by 2 texture

That small texture with A, B, C, and D is what we are talking about. Keep in mind there will be many smaller textures like this composing the entire image. This also means the algorithm has many smaller textures to work with.

The algorithm

Scaling an image goes in two ways, making it larger or to make it smaller. By enlarging an image, some new pixels are constructed by means of interpolation. By shrinking, we are tempted to think the right pixels are selected to keep while the others are thrown away, but this is not the case. Unlike nearest neighbor shrinking where pixels are thrown, bilinear shrinking estimates a smaller resolution of the original image. Even though details are lost, almost all the new pixels in the shrunk image do not come directly from their original, but interpolated, indirectly keeping the properties of lost pixels. It should be understood this is not always the case, shrinking image to half size (and smaller) significantly reduce image quality – not much different from nearest neighbor shrinking. This also applies to sizing up more than double the original size.

Figure4:Enlarged image introduces "white spaces"

For the purpose of this article, explanation will follow the making-it-larger path because that is probably why people are reading this anyway. So we start by enlarging a small texture such as shown in figure 4. Note: this is not to be mistaken as a requirement to enlarge every single texture found in an image. The objective is finding the colors for all white spaces, including i, j, and Y. Here linear interpolation comes into play, first find the relation between A, i, and B. Using linear interpolation function that we derived at the beginning (figure 2), we get this equation,

Do the same for C, j, and D and we get,

Now we have two linear interpolation equations. Next is to combine the two equations forming a single equation that is called the bilinear function.

Substituting equation 1 and 2 into 3 we get,

Using this last equation, all white spaces can now be interpolated!! That's it!!

Implementation

Yeah right. Putting the idea on paper is all nice and convenient but actually doing it is an entirely different thing. This time we discuss how a basic implementation is worked out.
Two things must be understood before we proceed, first is the actual code for scaling the image. Secondly is the code for interpolation process. These two are distinct, the first as mentioned is for the enlargement and at the same time introducing all the white spaces. The second part which is the interpolation process decides the color for these white spaces. Nearest neighbor algorithm share similar code for scaling, just missing the interpolation part.
Here is a Java snippet for 1 channel (grayscale) bilinear image scaling. Each pixel is an int and has a range from 0 to 255.

/*
* Bilinear resize grayscale image.
* pixels is an array of size w * h.
* Target dimension is w2 * h2.
* w2 * h2 cannot be zero.
*
* @param pixels Image pixels.
* @param w Image width.
* @param h Image height.
* @param w2 New width.
* @param h2 New height.
* @return New array with size w2 * h2.
*/
public int[] resizeBilinearGray(int[] pixels, int w, int h, int w2, int h2) {
int[] temp = new int[w2*h2] ;
int A, B, C, D, x, y, index, gray ;
float x_ratio = ((float)(w-1))/w2 ;
float y_ratio = ((float)(h-1))/h2 ;
float x_diff, y_diff, ya, yb ;
int offset = 0 ;
for (int i=0;i<h2;i++) {
for (int j=0;j<w2;j++) {
x = (int)(x_ratio * j) ;
y = (int)(y_ratio * i) ;
x_diff = (x_ratio * j) - x ;
y_diff = (y_ratio * i) - y ;
index = y*w+x ; // range is 0 to 255 thus bitwise AND with 0xff
A = pixels[index] & 0xff ;
B = pixels[index+1] & 0xff ;
C = pixels[index+w] & 0xff ;
D = pixels[index+w+1] & 0xff ; // Y = A(1-w)(1-h) + B(w)(1-h) + C(h)(1-w) + Dwh
gray = (int)(
A*(1-x_diff)*(1-y_diff) + B*(x_diff)*(1-y_diff) +
C*(y_diff)*(1-x_diff) + D*(x_diff*y_diff)
) ; temp[offset++] = gray ;
}
}
return temp ;
}

Here is a Java snippet for 4 channels (color) bilinear image scaling. Each pixel is a packed int containing alpha, red, green, and blue information.

/*
* Bilinear resize ARGB image.
* pixels is an array of size w * h.
* Target dimension is w2 * h2.
* w2 * h2 cannot be zero.
*
* @param pixels Image pixels.
* @param w Image width.
* @param h Image height.
* @param w2 New width.
* @param h2 New height.
* @return New array with size w2 * h2.
*/
public int[] resizeBilinear(int[] pixels, int w, int h, int w2, int h2) {
int[] temp = new int[w2*h2] ;
int a, b, c, d, x, y, index ;
float x_ratio = ((float)(w-1))/w2 ;
float y_ratio = ((float)(h-1))/h2 ;
float x_diff, y_diff, blue, red, green ;
int offset = 0 ;
for (int i=0;i<h2;i++) {
for (int j=0;j<w2;j++) {
x = (int)(x_ratio * j) ;
y = (int)(y_ratio * i) ;
x_diff = (x_ratio * j) - x ;
y_diff = (y_ratio * i) - y ;
index = (y*w+x) ;
a = pixels[index] ;
b = pixels[index+1] ;
c = pixels[index+w] ;
d = pixels[index+w+1] ; // blue element
// Yb = Ab(1-w)(1-h) + Bb(w)(1-h) + Cb(h)(1-w) + Db(wh)
blue = (a&0xff)*(1-x_diff)*(1-y_diff) + (b&0xff)*(x_diff)*(1-y_diff) +
(c&0xff)*(y_diff)*(1-x_diff) + (d&0xff)*(x_diff*y_diff); // green element
// Yg = Ag(1-w)(1-h) + Bg(w)(1-h) + Cg(h)(1-w) + Dg(wh)
green = ((a>>8)&0xff)*(1-x_diff)*(1-y_diff) + ((b>>8)&0xff)*(x_diff)*(1-y_diff) +
((c>>8)&0xff)*(y_diff)*(1-x_diff) + ((d>>8)&0xff)*(x_diff*y_diff); // red element
// Yr = Ar(1-w)(1-h) + Br(w)(1-h) + Cr(h)(1-w) + Dr(wh)
red = ((a>>16)&0xff)*(1-x_diff)*(1-y_diff) + ((b>>16)&0xff)*(x_diff)*(1-y_diff) +
((c>>16)&0xff)*(y_diff)*(1-x_diff) + ((d>>16)&0xff)*(x_diff*y_diff); temp[offset++] =
0xff000000 | // hardcode alpha
((((int)red)<<16)&0xff0000) |
((((int)green)<<8)&0xff00) |
((int)blue) ;
}
}
return temp ;
}

Caveat
Bilinear scaling performs best when the desired output dimension is no more than double or half its original size. If that is the case however, it might be good to implement additional technique called Mip Mapping on top of the existing algorithm.

========================================================
转载请注明出处:http://blog.csdn.net/songzitea/article/details/10781359
========================================================

【图像处理】Bilinear Image Scaling的更多相关文章

  1. FFmpeg源码简单分析:libswscale的sws_scale()

    ===================================================== FFmpeg的库函数源码分析文章列表: [架构图] FFmpeg源码结构图 - 解码 FFm ...

  2. FFmpeg源代码简单分析:libswscale的sws_scale()

    ===================================================== FFmpeg的库函数源代码分析文章列表: [架构图] FFmpeg源代码结构图 - 解码 F ...

  3. 数字图像处理实验(4):PROJECT 02-04 [Multiple Uses],Zooming and Shrinking Images by Bilinear Interpolation 标签: 图像处理MATLAB

    实验要求: Zooming and Shrinking Images by Bilinear Interpolation Objective To manipulate another techniq ...

  4. Python图像处理库(PIL)

    官方:(详细)http://pillow.readthedocs.io/en/3.1.x/reference/ImageDraw.html http://pillow.readthedocs.io/e ...

  5. 杂项之图像处理pillow

    杂项之图像处理pillow 本节内容 参考文献 生成验证码源码 一些小例子 1. 参考文献 http://pillow-cn.readthedocs.io/zh_CN/latest/ pillow中文 ...

  6. Atitit  图像处理Depixelizing Pixel Art像素风格画的矢量化

    Atitit  图像处理Depixelizing Pixel Art像素风格画的矢量化 在去年的时候,偶然看到hqx算法. 一个高质量的插值放大算法. 与双线性插值等插值算法相比,这个算法放大后对人眼 ...

  7. Atitit (Sketch Filter)素描滤镜的实现  图像处理  attilax总结

    Atitit (Sketch Filter)素描滤镜的实现  图像处理  attilax总结 1.1. 素描滤镜的实现方法比较简单,这里我们直接写出算法过程如下:1 1.2. 颜色减淡COLOR_DO ...

  8. Atitit 图像处理 常用8大滤镜效果 Jhlabs 图像处理类库 java常用图像处理类库

    Atitit 图像处理 常用8大滤镜效果 Jhlabs 图像处理类库 java常用图像处理类库1.1. 5种常用的Photoshop滤镜,分别针对照片的曝光.风格色调.黑白照片处理.锐利度.降噪这五大 ...

  9. Matlab图像处理入门

    1. Matlab基础 1.1     数据格式 Matlab默认的数据格式为双精度浮点数的矩阵或数组,同时支持其它数据类型.Matlab将单变量看作1´1的数组.Matlab支持的数据类型如下: 索 ...

随机推荐

  1. 在前端页面中使用@font-face来显示web自定义字体【转】

    本文转自W3CPLUS 的<CSS @font-face> @font-face是CSS3中的一个模块,他主要是把自己定义的Web字体嵌入到你的网页中,随着@font-face模块的出现, ...

  2. 基于visual Studio2013解决面试题之1310随机数

     题目

  3. protected的一些功能

    java的访问限制有private.protected.public.这里只想进一步认识一下protected. 我对protected有4个疑问: 1,在相同包中,是否可以调用其它类的protect ...

  4. Hauntbox:用于控制你的自己主动化、电子创意家居的开源硬件盒子

    Hauntbox 是一个开源硬件控制器,能够满足用随意传感器和控制器建立复杂的.自己主动化的萦绕在心头的电子项目. 它不须要焊接或者预先学什么知识.是全然可控制.并与Arduino插板兼容. 无需编程 ...

  5. 14.10.1 InnoDB Disk I/O

    14.10 InnoDB Disk IO and File Space Management InnoDB 磁盘IO和文件空间管理: 14.10.1 InnoDB Disk I/O 14.10.2 F ...

  6. 基于visual Studio2013解决C语言竞赛题之1059最大平台

       题目 解决代码及点评 /* 功能:编写求最大平台问题的程序. 有n个整数a1,a2, ... an, 若满足a1≤a2≤ ... ≤ an , 则认为在这n个数中有最大平台.在这种情 ...

  7. OpenCV编程-&gt;Windows7下调用iPhnoe摄像头

    //////////////////////////////////////////////////////////////  指尖热度原创,转载请注明来自http://blog.csdn.net/s ...

  8. Android手势识别(单击 双击 抬起 短按 长按 滚动 滑动)

    对于触摸屏,其原生的消息无非按下.抬起.移动这几种,我们只需要简单重载onTouch或者设置触摸侦听器setOnTouchListener即可进行处理.不过,为了提高我们的APP的用户体验,有时候我们 ...

  9. Selenium webdriver 常见问题

    出现java.lang.NoClassDefFoundError: org/w3c/dom/ElementTraversal 是因为缺少 xml jar ,如果使用的是maven 可以依赖 <d ...

  10. map对象建立家族姓氏查询

    题目:定义一个map对象,其元素的键是家族姓氏,而值是存储该家族孩子名字的vector对象.为这个map容器输入至少六个条目.通过基于家族姓氏的查询检测你的程序,查询应输出该家族所有孩子的名字. // ...