OpenCV——图像金字塔
图像金字塔
- 一、图像金字塔概述
- 二、向下采样和向上采样
- 三、高斯金字塔
- 四、拉普拉斯金字塔
一、图像金字塔概述
有些情况下需要处理源自同一张图像的不同分辨率的图像集合。例如,在人脸检测时机器并不知道人脸的尺寸是多少,这时就需要建立不同分辨率的图像集合供机器在不同尺寸进行检测。这些不同分辨率的图像组成的集合称为图像金字塔。图像金字塔的底部是高分辨率图像,而顶部是低分辨率图像。层级越高,图像越小,分辨率越低,堆叠起来就像一个金字塔,如下图:
Level 0:1600*1600
Level 1:800*800
Level 2:400*400
Level 3:200*200
Level 4:100*100
...
常见的图像金字塔有高斯金字塔(GaussianPyramid)和拉普拉斯金字塔(Laplacian Pyramid)两种。高斯金字塔是指通过向下采样不断将图像尺寸缩小而构建起的多尺寸的图像集合。通常情况下,高斯金字塔的底层就是原始图像,每向下采样一次,图像的尺寸就缩减为原来的一半。拉普拉斯金字塔则是从金字塔底层图像出发用向上采样的方式来构建上层图像。
图像金字塔常用于图像分割。具体方法是先建立一个图像金字塔,然后在上下两层的像素之间建立“父子”关系,接着先在金字塔高层的低分辨率图像上进行分割,然后逐层分割加以优化。
二、向下采样和向上采样
构建高斯金字塔的过程就是不断向下采样的过程,而构建拉普拉斯金字塔的过程则是向上采样的过程。所谓向下采样和向上采样,是针对图像的尺寸而言的,向下采样时图像尺寸减半,向上采样时图像尺寸加倍,但是如果从金字塔的结构上讲,小尺寸的图像在上,大尺寸的图像在下,因此所谓的向下采样其实是从金字塔的底部往顶部变化的过程,而向上采样则是从金字塔的顶部向底部变换。
//对图像进行向下采样,输出图像的尺寸默认为输入图像的一半(行数、列数均减半)
void Imgproc.pyrDown(Mat src, Mat dst)
- src:输入图像
- dst:输出图像,数据类型和src相同。默认情况下,输出图像的尺寸是输入图像的一半
//对图像进行向上采样,输出图像的尺寸默认为输入图像的两倍(行数、列数均加倍)
void Imgproc.pyrUp(Mat src, Mat dst)
- src:输入图像
- dst:输出图像,数据类型和src相同。默认情况下,输出图像的尺寸是输入图像的加倍
三、高斯金字塔
高斯金字塔是通过向下采样将图像尺寸缩小(通常为减半)。向下采样时,先通过高斯滤波对图像进行平滑处理,然后将所有偶数行和列去除,这样尺寸就缩小了一半。
public class PyrDown {static {OpenCV.loadLocally(); // 自动下载并加载本地库}public static void main(String[] args) {//读取图像并显示Mat src = Imgcodecs.imread("F:/IDEAworkspace/opencv/src/main/java/demo/wang.png");HighGui.imshow("src", src);HighGui.waitKey(0);//对图像进行向下采样并显示Mat dst = new Mat();Imgproc.pyrDown(src, dst);HighGui.imshow("Down-1", dst);HighGui.waitKey(0);//对图像进行二次向下采样并显示Imgproc.pyrDown(dst, dst);HighGui.imshow("Down-2", dst);HighGui.waitKey(0);//将二次向下采样后的图像放大到原尺寸并显示Imgproc.resize(dst, dst, src.size());HighGui.imshow("Resize", dst);HighGui.waitKey(0);System.exit(0);}
}
原图:
一次向下采样:
二次向下采样:
二次采样后恢复原大小:
四、拉普拉斯金字塔
拉普拉斯金字塔通过向上采样来重建图像。由于向上采样后图像的行和列都会扩大到原来的两倍,因此新增的行与列的像素值需要先填充为0,如下所示:
15 27
3 90
//放大后如下
15 0 27 0
0 0 0 0
3 0 90 0
0 0 0 0
为了让像素之间过渡自然,在向上采样的过程中同样要进行高斯平滑。由于扩充后图像的行和列都是原来的两倍,新图像的像素是原来的四倍之多。也就是说,新图像中有四分之三的像素值都是0。为了保证计算出来的像素值在原有像素值的范围内,在进行高斯平滑时还需要将高斯核的系数乘以4,计算后得到的图像即为向上采样后的图像。向上采样后的图像与原来的图像相比会比较朦胧,因为在放大的过程中丢失了一些信息。
需要注意的是,PryUp和PryDown并非互逆操作。
拉普拉斯金字塔通常与高斯金字塔联合起来用(需要先建立高斯金字塔),拉普拉斯金字塔的第i层的计算过程如下:
- 通过向下采样将高斯金字塔第i层图像尺寸缩减一半
- 将向下采样后的图像进行向上采样使图像尺寸恢复原来大小
- 将经过两次采样后的图像与原图像进行相减获得差值图像,这就是拉普拉斯金字塔的第i层图像
拉普拉斯金字塔第i层的数学定义如下:Li=Gi-PyrUp(PyrDown(Gi))
- Li:拉普拉斯金字塔的第i层
- Gi:高斯金字塔的第i层
public class Pyramids {static {OpenCV.loadLocally(); // 自动下载并加载本地库}public static void main(String[] args) {//读取图像并显示Mat src = Imgcodecs.imread("F:/IDEAworkspace/opencv/src/main/java/demo/leaf.png");HighGui.imshow("src", src);HighGui.waitKey(0);//对图像进行向下采样并显示Mat dst = new Mat();Imgproc.pyrDown(src, dst);HighGui.imshow("Down", dst);HighGui.waitKey(0);//对向下采样后的图像进行向上采样并显示Imgproc.pyrUp(dst, dst);HighGui.imshow("Up", dst);HighGui.waitKey(0);//将两次采样后的图像与原图像相减(即拉普拉斯金字塔图)Mat mat = new Mat(src.size(), CvType.CV_64F);Core.subtract(dst, src, mat);HighGui.imshow("sub", mat);HighGui.waitKey(0);//进行反向操作并显示(便于观看)Core.bitwise_not(mat, mat);HighGui.imshow("Diff", mat);HighGui.waitKey(0);System.exit(0);}
}
原图:
向下采样(即高斯金字塔图):
再向上采样:
与原图的差(即拉普拉斯金字塔图):
取反,方便查看: