B(x,y)=A(x/4,y/4)(公式1)
对于B中的位置(4,4)、(4, 8)、(4, 16)...(256, 256),可以通过公式1计算出其在A中的位置,即可得到灰度值。 然而,对于B中的坐标点(1,1)、(1,2)、(1,3)…等,如果按照式1计算,那么它们在A中对应的坐标就不再是整数了。 例如,对于B中的坐标点(1,1),其在A中对应的坐标变为(0.25,0.25)。 对于数字图像来说,十进制坐标是没有意义的。
因此,必须考虑某种方法来获取B中像素在A中对应位置的灰度级。处理这个问题的方法称为图像灰度插值。
常用的插值方法有最近邻插值、双线性插值和双三次插值三种。 从理论上讲,最近邻插值效果最差,双三次插值效果最好,双线性插值效果介于两者之间。 然而,对于不太严格的图像插值要求,双线性插值通常就足够了。
在本文中,将使用一个实现双线性插值的程序。 双线性插值的原理如图2所示。图像之间的坐标映射有两种方式:如果将原始图像的坐标映射到目标图像,则称为前向映射,反之则称为后向映射。 前向映射是指通过源图像计算目标图像的像素,常用于图像平移和镜像操作。 反向映射是指源图像在目标图像中的反向映射。 如果找到对应的像素,则填充该像素。 如果没有找到,则使用插值算法计算该像素,然后插入。
显然,双线性插值使用向后映射。
下面将解释图2的具体含义。
首先,根据几何关系,由B图像中的坐标(x,y)得到A图像中的坐标(x/4,y/4)。 然而,映射后的坐标(x/4,y/4)并不是正好位于A图像中的整数坐标处,而是映射到了四个像素坐标(a,b),(a+1,b) , (a,b+1), (a+1,b+1) 所包围的矩形之间,其中a和b是A图像的整数坐标。 现在的问题是如何利用四个点A(a,b)、A(a+1,b)、A(a,b+1)、A(a+1,b+1)处的灰度值求A(x/4,y/4)处的灰度级。
双线性插值技术采用的方法是:假设图像A的灰度变化在纵向上呈线性变化,则根据线性方程或几何比例关系可以得到(a,y/4)和(a+)。坐标 1,y/4 处的灰度级 A(a,y/4) 和 A(a+1,y/4)。 然后,假设确定两个点 ((a,y/4),A(a,y/4)) 和 (a+1,y/4),A(a+1,y/4))直线上,灰度级仍然线性变化。 求出该直线的方程,即可求出(x/4,y/4)处的灰度级A(x/4,y/4)。
这就是双线性插值的基本思想。
使用的两个基本假设是:首先,灰度级在纵向上线性变化,然后假设灰度级在横向上也线性变化。
图1 图像缩放示意图
图2 双线性插值示意图
代码:
I=imread('geometricTransformationOfImage\sourceImg\cameraman.tif'); [m,n]=size(I); K=3; width = K * m; height = K * n; J = uint8(zeros(width,height)); % width scale and height scale widthScale = m/width; heightScale = n/height; % bilinear interplot for x = 5:width - 5 for y = 5:height - 5 xx = x * widthScale; yy = y * heightScale; if (xx/double(uint16(xx)) == 1.0) & (xx/double(uint16(xx)) == 1.0) J(x,y) = I(int16(xx),int16(yy)); else % a or b is not integer a = double(uint16(xx)); % (a,b) is the base-dot b = double(uint16(yy)); x11 = double(I(a,b)); % x11 <- I(a,b) x12 = double(I(a,b+1)); % x12 <- I(a,b+1) x21 = double(I(a+1,b)); % x21 <- I(a+1,b) x22 = double(I(a+1,b+1)); % x22 <- I(a+1,b+1) J(x,y) = uint8( (b+1-yy) * ((xx-a)*x21 + (a+1-xx)*x11) + (yy-b) * ((xx-a)*x22 +(a+1-xx) * x12)); % calculate J(x,y) end end end % 显示图像 imwrite(J, '放大的图像.jpg', 'jpg'); imshow(I),title('原图'); figure imshow(J),title('放大图');
此处提供源图像和结果
源图片:
运行结果: