数字图像的缩放,是一个十分有趣的问题,又是一个看似简单,但又有些复杂的问题。许多朋友在具备一定的计算机图形编程的基础知识以后,都可以自己设计出一些简单的位图缩放算法。在计算机图形学和数字图像处理等学科里面,已经详细的研究过了数字图像缩放这个问题,并且已经有了成熟的算法。一些朋友由于没有学习过计算机图形学和数字图像处理,所以凭借自己的想法设计的位图缩放算法存在许多缺陷。在本文中,我将和大家一起来研究这个问题,并且学习前人所总结出来的算法。图像的概念很容易理解,你睁开眼睛,所看到的都是图像了。而一幅画、一张照片,则是现实生活中记录图像的手段和载体。在科学上,我们需要对我们的研究对象建立起数学模型,因此有必要建立起图像的数学模型。一幅图像的数学模型可以简单的定义如下:+—————————————————–+ Image = f(x, y); 其中 x, y 为 [0, 1] 上的实数 对于灰度图像 Image 也为 [0, 1] 上的实数 对于彩色图像 Image 则由 R, G, B 三个分量组成+—————————————————–+由于定义域和值域都在 [0, 1] 上,因此被称为连续图像模型连续图像模型可以精确而完整的刻画所要描述的图像,然而在现实世界中,绝大多数图像都是无法通过这个数学模型进行描述的,因为现实世界中的图像,是不可能通过函数解析式的方法进行描述的。更多的时候,我们只能使用相机将现实图像的一部分信息,保存在胶片上,或者是使用画笔在画纸上绘制出图像。正是由于图像的这个特点,我们所建立的连续的图像模型,对研究图像而言,并没有什么用武之地,而传统的数学研究方法也因此无法用运用到图像上。为了更加有效的研究和处理图像,我们利用离散数学的理论知识,为现实图像建立起了数字图像模型,并且使用计算这个强大的工具来帮组我们研究和处理图像。数字图像模型的定义如下:+—————————————————–+ Image = array(i, j); 通常情况下 i 是大于等于 0, 小于等于 w 的整数 而 j 是大于等于 0, 小于等于 h 的整数 array 可以理解为一个矩阵 Image 的取值范围为大于等于 0, 小于等于 255 的整数 对于灰度图像 Image 表示某点的亮度值 对于彩色图像 Image 则由 R, G, B 三个分量组成+—————————————————–+其中的 w, h 通常被称为一幅数字图像的宽度和高度。这里,数字图像的宽度和高度,与一幅数字图像在显示器上实际的宽度和高度,有着一定的对应关系的,这个大家应该都很容易理解。我们所要讨论的数字图像的缩放问题,就是要改变一幅图像的宽度和高度,并且使 array(i, j) 这个矩阵中的数据相应的改变,使得图像按比例的进行缩放。在数字图像处理上,数字图像的缩放又被称作重采样滤波,这很抽象但是却又深刻揭示出数字图像缩放的本质。当你将重采样滤波这个概念理解了,你会发现位图缩放是如此的简单明了,并会惊奇的发现重采样滤波是如此的神奇而深刻。现在为了叙述的方便,我们将现实生活中所遇到的图像称为现实图像,将照片等称为物理图像,将连续图像模型成为连续图像,将数字图像模型成为数字图像或位图。那么,我们来看看一幅数字图像的产生过程。首先,需要使用相机对现实图像进行拍照,产生照片,即物理图像。在物理图像中,仅仅记录了现实图像中的一部分信息。然后要将照片放到扫描仪上进行扫描,这个过程中图像从物理图像变换为了数字图像,在计算机中产生通常所说的位图。在图像从物理图像变换为数字图像这个过程中,最关键的地方就是采样与量化,这两个概念大家也许都非常熟悉,但是我们仍然需要深刻的理解和思考。假如说,在扫描的过程中,我们将扫描的分辨率设置较大,也就是采样率设置较大,则扫描出来的数字图像的分辨率也较大,也就是图像的宽度和高度都较大,反之,则是变小。让我们再来深刻的理解下重采样滤波这个概念,所谓重采样滤波,指的是根据数字图像,以某种方式重建出物理图像,并且对这个重建出来的物理图像,以所需要的采样率进行重新采样。让我们来设想这样一个过程,我们有一幅宽高分别为 (w1, h1) 的位图 A,我们想要将其缩放为宽高为 (w2, h2) 的位图 B. 我们可以通过这样的手段来完成缩放,也就是花一千块左右,买一台佳能的彩色激光打印机,将位图 A 用打印机打印出来。然后再买一个惠普的扫描仪,以 (w2, h2) 的扫描分辨率,将前面打印出来的图片扫描到电脑。这样,我们就顺利地完成了位图的缩放。当然,这样的做法成本太高,先后需要花去一千多块的大洋,而且费时又费力,是个理论上可行却不实用的办法。但是,这个办法,足以生动而清晰地说明数字图像缩放的本质和方法。让我们再来体会一下重采样滤波的深刻吧,即重建物理图像,然后以你所需要的分辨率进行重新采样。在计算机世界里,数字图像是很容易描述的,用一个二维数组就可以简单的描述一幅数字图像。然而,我们怎样才能从已有的数字图像,重建其物理图像呢?好好想想吧,想不出来就只快点准备两千块大洋,去买打印机和扫描仪吧。不是吧大哥,难道我真要去买打印机,赶快揭晓答案。好吧不开玩笑了,现在揭晓答案。在计算机中,重建物理图像其实是一种计算模型而已,物理图像在计算机世界里面是无法真正的重建的,毕竟计算机是离散系统,而物理图像是连续的事物,计算机无法完整而精确的进行描述。然而我们却可以找到多种的计算模型,来描述我们需要重建的物理图像。需要注意的是,我们找到的是计算模型,然后我们要根据这个计算模型,来进行重新采样。图像从现实图像到物理图像再到数字图像的变换过程,是一个不可逆的变换过程,在每一次变换过程中,都会丢失掉大量的信息,是不可逆的。如果想要从数字图像重建物理图像,其实是在已有的数字图像数据的基础上,对物理图像做出的一种近似而已。对于已有的数字图像,我们有多种计算模型,来重建物理图像,而这个重建的物理图像,一般都是通过前面所讲的连续图像模型来描述。先介绍最简单的计算模型,最近邻算法。请大家思考这样一些问题: 1. 我有一张 320 * 240 * 24bit 色的 BMP 图片,对于图片上任一点 (i, j) 我们都可以知道它的 RGB 颜色值,但是如果我想知道 (101.3, 98.6) 点的颜色值,我们该怎么办呢? 2. 我希望将一张 320 * 240 * 24bit 色的 BMP 图片,缩放为 1005 * 754 * 24bit 色的 BMP 图片,该如何进行重新采样呢?第一个问题,也就是数字图像缩放的第一步,重建物理图像。如果我们采用最近邻算法,对于一个非整数的坐标点,我们选取距离这个点最近的整数坐标点的颜色值,作为其颜色值。也就是说,我们简单的将 (101.3, 98.6) 的颜色值取为点 (101, 99) 的颜色值。解决了这个问题,我们的脑子里面其实就放着一幅连续的图像了,并且对于这个连续图像上的任意一个像素点,我们都可以计算出其颜色值。第二个问题,则是如何在重建起来的物理图像上进行重采样。所谓采样,就是要取得每个需要采样的颜色值,也就是要用一个二重循环,处理完 1005 * 754 个点,并且计算出每个点的颜色值。简单的代码如下:+————————————————————————-+
DWORD color; int i; int j; for (j=0; j
// 将采样点绘制到目的位图上 } }+————————————————————————-+对于每个重采样点的颜色值的计算方法,则是需要根据原始的数字图像、你所选用的计算模型和由计算模型所重建的物理图像来共同决定。对于我们上面的例子,可以先计算出宽高缩放比,进而建立起原始图像和目的图像中像素点的对应关系和变换公式,根据变换公式,计算出目的图像中 (i, j) 点在 原始图像中对应的点的坐标 (x, y),根据重建物理图像的计算模型,计算出原始图像中 (x, y) 点的颜色值 c,然后将 c 作为结果绘制到目的图像中的 (i, j) 上。当你处理完目的图像中的每一个像素点,也就完成了数字图像的缩放了。对于我们所举的例子,可以写出如下的代码:+————————————————————————-+
int w1 = 320; int h1 = 240; int w2 = 1005; int h2 = 754; float xratio = (float) w1 / w2; float yratio = (float) h1 / h2; int i; int j; float x; float y; for (j=0; j
+————————————————————————-+其中 | x = i * xratio; y = j * yratio; | 两句代码体现采样的位置,即在重建出来的图像的什么位置进行采样,而 | color = getpixel(srcbmp, (int)(x + 0.5), (int)(y + 0.5)); | 这句代码则体现了采样的结果,即在重建出来的图像的 (x, y) 处的采样的颜色值到底是多少。请大家认真体会其中的深刻意义,所谓重建物理图像,实际上是无法真正重建的,也就是说这只是一种计算模型,一种方法。而重采样滤波,则是在计算模型的基础上进行的重新采样。数字图像缩放的精妙和深刻之处,就被重采样滤波这样一段话,简短而深刻地概括了。通过以上的介绍,大家应当明白了数字图像缩放的基本原理和实现方法,并且能够利用最近邻法的计算模型,写出通用的位图缩放程序。可以看到,位图缩放的算法框架其实是非常简单的,关键还是需要理解其中的原理和方法。位图缩放的最近邻算法,在我的图形库中已经实现,大家可以在我的图形库中找到代码进行参考。接下来介绍更多的重建物理图像的计算模型。除了最近邻点算法之外,还有双线性插值算法和曲面插值算法。其中双线性插值算法比较简单,且易于计算,因此在工程上得到了广泛的运用。而曲面插值可以得到更好的图像效果,但是其插值原理和计算方法都比较复杂,本文不再介绍。所谓线性插值,大家应该不陌生,举个最简单的例子来说明问题。f(99) = 32, f(100) = 65, 用线性插值法求 f(99.3) 的值。方法如下:
f(100) - f(99) f(100) - f(99.3)----------------- = -------------------- 100 - 99
100 – 99.3根据以上方程即可求出 f(99.3) 的值。之所以称为线性,是由于三个点都位于一条直线上。将以上的线性插值推广到二维情况,即是我们通常所说的双线性插值。同样用一个例子说明问题:f(123, 221) = 231, f(124, 221) = 35f(123, 222) = 213, f(124, 222) = 86求 f(123.8, 221.2) 的颜色值。解,利用一维的线性插值,根据 f(123, 221) 和 f(123, 222) 求得 f(123, 221.2) 利用一维的线性插值,根据 f(124, 221) 和 f(124, 222) 求得 f(124, 221.2) 利用一维的线性插值,根据 f(123, 221.2) 和 f(124, 221.2) 求得 f(123.8, 221.2) 问题得解。在双线性茶值中,大家可以证明先沿 x 坐标计算和先沿 y 坐标计算,最终的结果都是一样的。当然,在实际运用中,大家还需要推算出通用的计算公式,在这里仅仅是以例子说明问题。讲了这么多,应该是把数字图像缩放这个问题介绍得比较清楚了。大家关键还是需要理解数字图像的本质,采样和量化的概念,以及根据数字图像重建物理图像和重采样,即重采样滤波。最后再告诉大家两个概念,即数字图像的缩小,被称为降采样滤波,而放大则称为过采样滤波(这个不知道是不是这样叫的,就算我自己发明的叫法吧)。希望大家再看完本文以后,能够有所收获,理解数字图像缩放的原理和方法,并且实现自己的位图缩放程序。
服务器托管,北京服务器托管,服务器租用 http://www.fwqtg.net
机房租用,北京机房租用,IDC机房托管, http://www.fwqtg.net
相关推荐: 如何在 🤗 Space 上托管 Unity 游戏
你知道吗?Hugging Face Space 可以托管自己开发的 Unity 游戏!惊不惊喜,意不意外?来了解一下吧! Hugging Face Space 是一个能够以简单的方式来构建、托管和分享项目或应用样例的平台。虽然通常更多地是应用在机器学习样例中,…