OpenCV-Python学习(八):图像的几何变换及形态学操作

2020-06-25  本文已影响0人  星光下的胖子

目录:


一、resize/transpose/flip

函数:

    1)图像缩放: resize()函数
        resize(src, dsize, dst=None, fx=None, fy=None, interpolation=None)

        dsize: 输出图像的大小,如 Size(width, height)。
            若dsize=0,则需指定fx和fy的值,且fx>0,fy>0。
            此时, dsize = Size(round(fx*src.cols), round(fy*src.rows))
            fx=0.5,fy=0.5与dsize=(cols//2, rows//2)效果一样。
        interpolation: 指定插值的方式。图像缩放后,需要重新计算像素,这个参数指定重新计算像素的方式。
            有以下几种插值类型:
                INTER_LINEAR: 双线性插值(默认)
                INTER_NEAREST: 最邻近插值
                INTER_CUBIC: 基于4x4像素邻域内的三次样条插值
                INTER_LANCZOS4: 基于8x8像素邻域内的Lanczos插值

    2)转置: transpose()函数
        transpose(src, dst=None)

    3)翻转/镜像: flip()函数
        flip(src, flipCode, dst=None)

        flipCode: 控制翻转效果。
            flipcode = 0:绕x轴翻转,即上下颠倒
            flipcode > 0(如1):绕y轴翻转,翻转
            flipcode < 0(如-1):绕x,y轴同时翻转,即上下+左右翻转
1.图片缩放——resize():
import cv2

img = cv2.imread("image/1.jpg")
rows, cols, channels = img.shape

# 图片缩放: resize()
resie_1 = cv2.resize(img, dsize=(cols // 2, rows //2))
resie_2 = cv2.resize(img, dsize=(0, 0), fx=2, fy=2)

# 几种插值方式:
# 1.双线性插值(默认)
linear = cv2.resize(img, dsize=(cols // 2, rows //2), interpolation=cv2.INTER_LINEAR)
# 2.最邻近插值
nearest = cv2.resize(img, dsize=(cols //2, rows //2), interpolation=cv2.INTER_NEAREST)
# 3.基于4x4像素邻域内的三次样条插值
cubic = cv2.resize(img, dsize=(cols//2, rows // 2), interpolation=cv2.INTER_CUBIC)
# 4.基于8x8像素邻域内的Lanczos插值
lanczos = cv2.resize(img, dsize=(cols//2, rows // 2), interpolation=cv2.INTER_LANCZOS4)

cv2.imshow("image", img)
cv2.imshow("resie_1", resie_1)
cv2.imshow("resie_2", resie_2)
cv2.imshow("linear", linear)
cv2.imshow("nearest", nearest)
cv2.imshow("cubic", cubic)
cv2.imshow("lanczos", lanczos)
cv2.waitKey(0)
cv2.destroyAllWindows()
2.转置——transpose():
import cv2

src = cv2.imread("image/1.jpg")
dst = cv2.transpose(src)
cv2.imshow("src", src)
cv2.imshow("dst", dst)
cv2.waitKey(0)
cv2.destroyAllWindows()
3.翻转/镜像——flip():
import cv2

src = cv2.imread("image/1.jpg")
# 翻转: flipCode用来控制翻转效果
dst1 = cv2.flip(src, flipCode=0)  # flipCode=0:绕x轴翻转,即上下颠倒
dst2 = cv2.flip(src, flipCode=1)  # flipcode>0:绕y轴翻转,翻转
dst3 = cv2.flip(src, flipCode=-1)  # flipcode<0:绕x,y轴同时翻转,即上下+左右翻转

cv2.imshow("src", src)
cv2.imshow("dst1", dst1)
cv2.imshow("dst2", dst2)
cv2.imshow("dst3", dst3)
cv2.waitKey(0)
cv2.destroyAllWindows()

二、仿射变换(线性变换): 包括 平移、缩放、旋转、倾斜、翻转/镜像

任意一个二维图像,乘以一个仿射矩阵,就能的得到仿射变换后的图像。
仿射矩阵变换效果如下图所示:

仿射变换效果图.png

函数:

    1.调用warpAffine()函数进行仿射变换:
    dst = warpAffine(src, M, dsize, dst=None, flags=None, borderMode=None, borderValue=None)
    参数:
    M: 仿射变换矩阵
    dsize: 指定输出图片的大小

    2.对于旋转操作, 一般调用getRotationMatrix2D()函数获取仿射矩阵:
    M = getRotationMatrix2D(center, angle, scale)
    参数:
    center是旋转的中心点;
    angle是旋转角度(正数表示逆时针),如angle=15表示逆时针旋转15度;
    scale标量是缩放因子,0.5表示缩小,2表示放大一倍,-2表示放大一倍后再做(上下+左右)翻转。

示例:

import cv2
import numpy

img = cv2.imread("image/2.jpg")
rows, cols, channels = img.shape

# 1.创建仿射变换矩阵
# 1)平移
M1 = numpy.float32([[1, 0, 20], [0, 1, 80]])  # 沿x轴平移+20,沿y轴平移+80
# 2)缩放
M2 = numpy.float32([[0.8, 0, 0], [0, 0.5, 0]])  # x轴变为0.8倍,y轴变为0.5倍
# 3)旋转:调用getRotationMatrix2D()获取仿射矩阵
M3 = cv2.getRotationMatrix2D((cols//2, rows//2), 15, scale=0.5)  # angle=15表示逆时针旋转15度。scale=0.5表示缩小到原来的一半。
# 4)倾斜
M4 = numpy.float32([[1, 0.5, 0], [0, 1, 0]])# 沿x轴倾斜0.5倍
M5 = numpy.float32([[1, 0, 0], [1, 1, 0]])# 沿y轴倾斜1倍
# 5)翻转/镜像
M6 = numpy.float32([[-0.5, 0, cols //2], [0, 0.5, 0]])  # x轴变为0.5倍并绕y转翻转,y轴变为0.5倍,最后沿x轴平移(cols//2)个像素单位
M7 = numpy.float32([[-1, 0, cols], [0, -1, rows]])  # 绕y转翻转、绕x转翻转,最后沿x轴平移cols个像素单位、沿y轴平移rows个像素单位

# 2.进行仿射变换
dst1 = cv2.warpAffine(img, M1, dsize=(cols, rows))  # 平移
dst2 = cv2.warpAffine(img, M2, dsize=(cols, rows))  # 缩放
dst3 = cv2.warpAffine(img, M3, dsize=(cols, rows))  # 旋转
dst4 = cv2.warpAffine(img, M4, dsize=(cols * 2, rows * 2))  # 倾斜
dst5 = cv2.warpAffine(img, M5, dsize=(cols * 2, rows * 2))  # 倾斜
dst6 = cv2.warpAffine(img, M6, dsize=(cols, rows))  # 翻转/镜像
dst7 = cv2.warpAffine(img, M7, dsize=(cols, rows))  # 翻转/镜像

cv2.imshow("img pic", img)
cv2.imshow("dst1 pic", dst1)
cv2.imshow("dst2 pic", dst2)
cv2.imshow("dst3 pic", dst3)
cv2.imshow("dst4 pic", dst4)
cv2.imshow("dst5 pic", dst5)
cv2.imshow("dst6 pic", dst6)
cv2.imshow("dst7 pic", dst7)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果如下:

三、透视变换(非线性变换): 一般用于矫正变形的图像

函数:

    1.获取透视变换矩阵M:
    M = getPerspectiveTransform(src, dst, solveMethod=None)
    参数:
    src:源图像中四边形顶点的坐标。
    dst:目标图像中对应的四边形顶点的坐标。

    2.调用warpPerspective()函数进行透视变换:
    dst = warpPerspective(src, M, dsize, dst=None, flags=None, borderMode=None, borderValue=None)‘
    参数:
    M: 透视变换矩阵
    dsize: 指定输出图片的大小

示例:

import cv2
import numpy

src = cv2.imread("image/2.jpg")
rows, cols, channel = src.shape
print(cols, rows) # 200 201

# 1.获取透视变换矩阵M: getPerspectiveTransform(src, dst)
pts1 = numpy.array([[25, 30], [179, 25], [12, 188], [189, 190]], dtype=numpy.float32)
pts2 = numpy.float32([[0, 0], [200, 0], [0, 200], [200, 200]])
M = cv2.getPerspectiveTransform(pts1, pts2)
# 2.进行透视变换: warpPerspective(src, M, dsize)
dst = cv2.warpPerspective(src, M, dsize=(200, 200))

cv2.imshow("src pic", src)
cv2.imshow("dst pic", dst)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果如下:

四、形态学操作:膨胀/腐蚀/开/闭/梯度/礼帽/黑帽

函数:

    1.构造一个特定形状和大小的结构元素(核),用于形态学操作。
    kernel = getStructuringElement(shape, ksize, anchor=None)
    参数:
    shape: 核的形状。
        MORPH_RECT = 0: 矩形
        MORPH_CROSS = 1: 交叉形
        MORPH_ELLIPSE = 2: 椭圆形
    ksize: 核的结构大小

    2.膨胀: 原图部分区域(A)与核(B)进行卷积,求局部最大值,并将局部最大值赋值给指定像素,从而增长高亮区域。
    dilate(src, kernel, dst=None, anchor=None, iterations=None, borderType=None, borderValue=None)
    3.腐蚀: 与膨胀相反,用局部极小值替换当前像素,从而缩短高亮区域。
    erode(src, kernel, dst=None, anchor=None, iterations=None, borderType=None, borderValue=None)

    4.更多形态学操作
    morphologyEx(src, op, kernel, dst=None, anchor=None, iterations=None, borderType=None, borderValue=None)
    参数:
    op: 形态学操作类型。
        cv2.MORPH_DILATE: 膨胀。-->增长高亮部分。
        cv2.MORPH_ERODE: 腐蚀。-->缩短高亮部分。
        cv2.MORPH_GRADIENT: 梯度,(膨胀-腐蚀)。-->提取轮廓。
        cv2.MORPH_OPEN: 开,先腐蚀在膨胀。-->去除噪点。
        cv2.MORPH_CLOSE: 闭,先膨胀再腐蚀。-->填补漏洞。
        cv2.MORPH_TOPHAT: 顶帽/礼帽,(原图-开)。-->获取噪点。
        cv2.MORPH_BLACKHAT: 黑帽,(闭-原图)。-->获取漏洞。

示例:

import cv2
import matplotlib.pyplot as plt

img1 = cv2.imread("image/3.jpg")
img2 = cv2.imread("image/4.jpg")

# 1.获取指定形状和大小的结构元素(核): getStructuringElement(shape, ksize)
kernel = cv2.getStructuringElement(shape=cv2.MORPH_RECT, ksize=(3, 3))  # 矩形
cross_kernel = cv2.getStructuringElement(shape=cv2.MORPH_CROSS, ksize=(3, 3))  # 交叉形
ellipse_kernel = cv2.getStructuringElement(shape=cv2.MORPH_ELLIPSE, ksize=(3, 3))  # 椭圆形

# 2.形态学操作
dilate = cv2.dilate(img1, kernel)  # 膨胀
erode = cv2.erode(img1, kernel)  # 腐蚀
morph_dilate = cv2.morphologyEx(img1, cv2.MORPH_DILATE, kernel)  # 膨胀
morph_erode = cv2.morphologyEx(img1, cv2.MORPH_ERODE, kernel)  # 腐蚀
morph_gradient = cv2.morphologyEx(img1, cv2.MORPH_GRADIENT, kernel)   # 梯度: 膨胀-腐蚀, 用于提取轮廓

morph_open = cv2.morphologyEx(img2, cv2.MORPH_OPEN, kernel)  # 开: 先腐蚀再膨胀,用于去噪
morph_close = cv2.morphologyEx(img2, cv2.MORPH_CLOSE, kernel)  # 闭: 先膨胀后腐蚀,用于填补漏洞
morph_tophat = cv2.morphologyEx(img2, cv2.MORPH_TOPHAT, kernel)  # 顶帽/礼帽: 原图-开,用于获取噪点
morph_blackhat = cv2.morphologyEx(img2, cv2.MORPH_BLACKHAT, kernel)  # 黑帽: 闭-原图,用于填补漏洞

# 结合matplotlib展示多张图片
titles = ['Image', 'DILATE', 'ERODE', 'MORPH_DILATE', 'MORPH_ERODE', 'MORPH_GRADIENT']
images = [img1, dilate, erode, morph_dilate, morph_erode, morph_gradient]
for i in range(6):
    plt.subplot(2, 3, i + 1)
    plt.imshow(images[i], cmap="gray")
    plt.title(titles[i])
    plt.xticks([])
    plt.yticks([])
plt.show()

titles = ['Image', 'MORPH_OPEN', 'MORPH_CLOSE', 'MORPH_TOPHAT', 'MORPH_BLACKHAT']
images = [img2, morph_open, morph_close, morph_tophat, morph_blackhat]
for i in range(5):
    plt.subplot(2, 3, i + 1)
    plt.imshow(images[i], cmap="gray")
    plt.title(titles[i])
    plt.xticks([])
    plt.yticks([])
plt.show()

结果如下:

上一篇下一篇

猜你喜欢

热点阅读