Opencv-Python学习笔记(八):图像金字塔

本篇博客记录学习OpenCV中的图像金字塔。

  • 使用图像金字塔创建一个新的水果“ 橘子苹果”。
  • 将要学习的函数为:cv2.pyrUp()cv2.pyrDown()。

一般情况下,我们要处理的是一副具有固定分辨率的图像。但是有些情况下,我们需要对同一图像的不同分辨率的子图像进行处理。比如,我们要在一幅图像中查找某个目标,比如脸,我们不知道目标在图像中的尺寸大小。这种情况下,我们需要创建一组具有不同分辨率的图像,我们把这组图像叫做图像金字塔(简单来说就是同一图像的不同分辨率的子图集合)。如果我们把最大的图像放在底部,最小的放在顶部,看起来就像一座金字塔,故而得名图像金字塔。
图像金字塔有两类:高斯金字塔和拉普拉斯金字塔
高斯金字塔的顶部是通过将底部图像中连续的行和列去除得到的。顶部图像中的每个像素值等于下一层图像中 5 个像素的高斯加权平均值。这样操作一次一个 MxN 的图像就变成了一个 M/2xN/2 的图像。所以这幅图像的面积就变为原来图像面积的四分之一。这被称为 Octave。连续进行这样的操作我们就会得到一个分辨率不断下降的图像金字塔。我们可以使用函cv2.pyrDown() cv2.pyrUp() 构建图像金字塔。函数 cv2.pyrDown() 从一个高分辨率大尺寸的图像向上构建一个金子塔(尺寸变小,分辨率降低)。

  • 高斯金字塔:向下采样方法(缩小)(等于 高斯模糊+降采样

操作分为两步:

  1. 将Gi与高斯内核卷积,例如:\frac{1}{16}\begin{bmatrix} 1 &4 &6 & 4 &1 \\ 4&16 &24 &16 &4 \\ 6& 24 & 36 &24 & 6\\ 4& 16 & 24& 16&4 \\ 1& 4 & 6& 4 &1 \end{bmatrix}
  2. 将所有偶数行和列去除
  • 高斯金字塔:向上采样方法(放大)(等于 扩大+卷积

操作同样分为两步:

例如:

\begin{bmatrix} 10 &30 \\ 59 & 96 \end{bmatrix}\Rightarrow \begin{bmatrix} 10 & 0 & 30 &0 \\ 0& 0 & 0 & 0\\ 56&0 & 96&0 \\ 0& 0& 0& 0 \end{bmatrix}

  1. 将图像在每个方向扩大为原来的两倍,新增的行和列用0填充。
  2. 使用先前同样的内核(乘以四)与放大后的图像卷积,得到近似值。

接下来我们看一下各自的效果:

上采样:

代码:

# -*- coding: utf-8 -*-
# @Time    : 2019/10/19 21:32
# @Author  : MMagicLoren
# @Email   : [email protected]
# @File    : 图像金字塔.py
# @Software: PyCharm
import cv2 as cv
import numpy as np


if __name__ == '__main__':
    src = cv.imread("F:/Pycharm/opencv_exercises-master/images/CrystalLiu4.jpg")  # 读入图片放进src中
    cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)  # 创建窗口, 窗口尺寸自动调整
    cv.imshow("input image", src)
    print(src.shape)  # 原始图像大小
    up = cv.pyrUp(src)
    cv.imshow("up image", up)
    print(up.shape)

    cv.waitKey(0)  # 等有键输入或者1000ms后自动将窗口消除,0表示只用键输入结束窗口
    cv.destroyAllWindows()

下采样:

代码:

# -*- coding: utf-8 -*-
# @Time    : 2019/10/19 21:32
# @Author  : MMagicLoren
# @Email   : [email protected]
# @File    : 图像金字塔.py
# @Software: PyCharm
import cv2 as cv
import numpy as np


if __name__ == '__main__':
    src = cv.imread("F:/Pycharm/opencv_exercises-master/images/CrystalLiu4.jpg")  # 读入图片放进src中
    cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)  # 创建窗口, 窗口尺寸自动调整
    cv.imshow("input image", src)
    print(src.shape)  # 原始图像大小
    # up = cv.pyrUp(src)
    # cv.imshow("up image", up)
    # print(up.shape)
    down = cv.pyrDown(src)
    cv.imshow("down image", down)
    print(down.shape)
    cv.waitKey(0)  # 等有键输入或者1000ms后自动将窗口消除,0表示只用键输入结束窗口
    cv.destroyAllWindows()

 我们再用更形象的一种方法进行展示。

# -*- coding: utf-8 -*-
# @Time    : 2019/10/19 21:32
# @Author  : MMagicLoren
# @Email   : [email protected]
# @File    : 图像金字塔.py
# @Software: PyCharm
import cv2 as cv
import numpy as np


def pyramids_demo(image):
    level = 3
    temp = image.copy()
    pyramid_images = []  # 定义一个图像list

    for i in range(level):
        dst = cv.pyrDown(temp)
        pyramid_images.append(dst)
        cv.imshow("pyramid_down_"+str(i+1), dst)
        temp = dst.copy()
    return pyramid_images


if __name__ == '__main__':
    src = cv.imread("F:/Pycharm/opencv_exercises-master/images/CrystalLiu4.jpg")  # 读入图片放进src中
    cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)  # 创建窗口, 窗口尺寸自动调整
    cv.imshow("input image", src)
    print(src.shape)  # 原始图像大小
    # up = cv.pyrUp(src)
    # cv.imshow("up image", up)
    # print(up.shape)
    # down = cv.pyrDown(src)
    # cv.imshow("down image", down)
    # print(down.shape)
    pyramids_demo(src)
    cv.waitKey(0)  # 等有键输入或者1000ms后自动将窗口消除,0表示只用键输入结束窗口
    cv.destroyAllWindows()

同理,我们也可以得到上采样的图像。

注意,当我们对一幅图像先做上采样再做下采样(或者先做下采样后做上采样)后得到的图像与原图像是不相等的。

接下来我们再看拉普拉斯金字塔:

     拉普拉斯金字塔由高斯金字塔形成。没有专用功能。拉普拉斯金字塔图像仅像边缘图像。它的大部分元素为零。它们用于图像压缩。拉普拉斯金字塔的层由高斯金字塔的层与高斯金字塔的上层的扩展版本之间的差形成。计算公式为:

L_{i}=G_{i}-PyrUp(PyrDown(G_{i}))

# -*- coding: utf-8 -*-
# @Time    : 2019/10/19 21:32
# @Author  : MMagicLoren
# @Email   : [email protected]
# @File    : 图像金字塔.py
# @Software: PyCharm
import cv2 as cv
import numpy as np


def laplace_demo(image):  # 注意:图片必须是满足2^n这种分辨率
    down = cv.pyrDown(image)
    down_up = cv.pyrUp(down)
    lpls = image - down_up
    cv.imshow("lpls image", lpls)


if __name__ == '__main__':
    src = cv.imread("F:/Pycharm/opencv_exercises-master/images/messi5.jpg")  # 读入图片放进src中
    cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)  # 创建窗口, 窗口尺寸自动调整
    cv.imshow("input image", src)
    print(src.shape)  # 原始图像大小
    # up = cv.pyrUp(src)
    # cv.imshow("up image", up)
    # print(up.shape)
    # down = cv.pyrDown(src)
    # cv.imshow("down image", down)
    # print(down.shape)
    # pyramids_demo(src)
    laplace_demo(src)
    cv.waitKey(0)  # 等有键输入或者1000ms后自动将窗口消除,0表示只用键输入结束窗口
    cv.destroyAllWindows()

# -*- coding: utf-8 -*-
# @Time    : 2019/10/19 21:32
# @Author  : MMagicLoren
# @Email   : [email protected]
# @File    : 图像金字塔.py
# @Software: PyCharm
import cv2 as cv
import numpy as np


def laplace_demo(image):  # 注意:图片必须是满足2^n这种分辨率
    pyramid_images = pyramids_demo(image)
    level = len(pyramid_images)

    for i in range(level-1, -1, -1):
        if i-1 < 0:
            expand = cv.pyrUp(pyramid_images[i], dstsize=image.shape[:2])
            lpls = cv.subtract(image, expand)
            cv.imshow("laplace_demo"+str(i), lpls)
        else:
            expand = cv.pyrUp(pyramid_images[i], dstsize=pyramid_images[i-1].shape[:2])
            lpls = cv.subtract(pyramid_images[i-1], expand)
            cv.imshow("laplace_demo"+str(i), lpls)


if __name__ == '__main__':
    src = cv.imread("F:/Pycharm/opencv_exercises-master/images/lena.jpg")  # 读入图片放进src中
    cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)  # 创建窗口, 窗口尺寸自动调整
    cv.imshow("input image", src)
    print(src.shape)  # 原始图像大小
    # up = cv.pyrUp(src)
    # cv.imshow("up image", up)
    # print(up.shape)
    # down = cv.pyrDown(src)
    # cv.imshow("down image", down)
    # print(down.shape)
    # pyramids_demo(src)
    laplace_demo(src)
    cv.waitKey(0)  # 等有键输入或者1000ms后自动将窗口消除,0表示只用键输入结束窗口
    cv.destroyAllWindows()

完整工程代码:

# -*- coding: utf-8 -*-
# @Time    : 2019/10/19 21:32
# @Author  : MMagicLoren
# @Email   : [email protected]
# @File    : 图像金字塔.py
# @Software: PyCharm
import cv2 as cv
import numpy as np


def pyramids_demo(image):
    level = 3
    temp = image.copy()
    pyramid_images = []  # 定义一个图像list

    for i in range(level):
        dst = cv.pyrDown(temp)
        pyramid_images.append(dst)
        cv.imshow("pyramid_down_"+str(i+1), dst)
        temp = dst.copy()
    return pyramid_images


def laplace_demo(image):  # 注意:图片必须是满足2^n这种分辨率
    pyramid_images = pyramids_demo(image)
    level = len(pyramid_images)

    for i in range(level-1, -1, -1):
        if i-1 < 0:
            expand = cv.pyrUp(pyramid_images[i], dstsize=image.shape[:2])
            lpls = cv.subtract(image, expand)
            cv.imshow("laplace_demo"+str(i), lpls)
        else:
            expand = cv.pyrUp(pyramid_images[i], dstsize=pyramid_images[i-1].shape[:2])
            lpls = cv.subtract(pyramid_images[i-1], expand)
            cv.imshow("laplace_demo"+str(i), lpls)


if __name__ == '__main__':
    src = cv.imread("F:/Pycharm/opencv_exercises-master/images/lena.jpg")  # 读入图片放进src中
    cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)  # 创建窗口, 窗口尺寸自动调整
    cv.imshow("input image", src)
    print(src.shape)  # 原始图像大小
    # up = cv.pyrUp(src)
    # cv.imshow("up image", up)
    # print(up.shape)
    # down = cv.pyrDown(src)
    # cv.imshow("down image", down)
    # print(down.shape)
    # pyramids_demo(src)
    laplace_demo(src)
    cv.waitKey(0)  # 等有键输入或者1000ms后自动将窗口消除,0表示只用键输入结束窗口
    cv.destroyAllWindows()
发布了29 篇原创文章 · 获赞 83 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/l59565455/article/details/102642149