计算机视觉
第四章 形态变换
一、仿射变换
1. 什么是仿射变换
- 仿射变换是指图像可以通过一系列的几何变换来实现平移、旋转等多种操作。该变换能够保持图像的平直性和平行性。平直性是指图像经过仿射变换后,直线仍然是直线;平行性是指图像在完成仿射变换后,平行线仍然是平行线。

2. 平移
- 改变图像的x和y坐标,将所有x坐标的像素增加就是向右平移,减小就是向左平移,将所有y坐标的像素增加就是向下平移,减小就是向上平移

3. 镜像
- 水平镜像:改变的是每个像素的x坐标,x坐标关于y轴对称
- 垂直镜像:保持x轴坐标不变,改变它的y坐标

4. 旋转

5. 透视变换
- 透视变换是将图片投影到一个新的视平面,也称作投影映射。它是二维(x,y)到三维(X,Y,Z),再到另一个二维(x’,y’)空间的映射。
- 相对于仿射变换,它提供了更大的灵活性,将一个四边形区域映射到另一个四边形区域(不一定是平行四边形),透视变换可用于图像形状校正。

二、算数运算
1. 图像加法

2. 图像减法
- 图像减法是找出两幅图像的差异,可以在连续图像中实现消除背景和运动检测

三、图像缩放
1. 缩放

2. 图像缩小
- 图像缩小可以通过删除矩阵中的元素来实现,例如:下面的例子进行隔行、隔列删除后,高度、宽度均减小为原来的一半

3. 图像放大


四、腐蚀与膨胀
1. 图像腐蚀
- 腐蚀是最基本的形态学操作之一,它能够将图像的边界点消除,使图像沿着边界向内收缩,也可以将小于指定结构体元素的部分去除。腐蚀用来“收缩”或者“细化”二值图像中的前景,借此实现去除噪声、元素分割等功能。

2. 图像膨胀
- 图像膨胀是指根据原图像的形状,向外进行扩充。如果图像内两个对象的距离较近,那么在膨胀的过程中,两个对象可能会连通在一起。膨胀操作对填补图像分割后图像内所存在的空白相当有帮助。

3. 图像开运算
- 开运算进行的操作是先将图像腐蚀,再对腐蚀的结果进行膨胀。开运算可以用于去噪、计数等。

- 开运算可用于取出主题图像之间细小的连接

4. 图像闭运算
- 闭运算是先膨胀、后腐蚀的运算,它有助于关闭前景物体内部的小孔,或去除物体上的小黑点,还可以将不同的前景图像进行连接。


5. 形态学梯度
- 形态学梯度运算是用图像的膨胀图像减腐蚀图像的操作,该操作可以获取原始图像中前景图像的边缘。

6. 礼帽运算
- 礼帽运算是用原始图像减去其开运算图像的操作。礼帽运算能够获取图像的噪声信息,或者得到比原始图像的边缘更亮的边缘信息。

7. 黑帽运算
- 黑帽运算是用闭运算图像减去原始图像的操作。黑帽运算能够获取图像内部的小孔,或前景色中的小黑点,或者得到比原始图像的边缘更暗的边缘部分。

五、图像形态操作
1. 图像翻转
import cv2
im = cv2.imread("../data/Linus.png")
cv2.imshow("im", im)
im_flip0 = cv2.flip(im, 0)
cv2.imshow("im_flip0", im_flip0)
im_flip1 = cv2.flip(im, 1)
cv2.imshow("im_flip1", im_flip1)
cv2.waitKey()
cv2.destroyAllWindows()

2. 图像位置变换
import numpy as np
import cv2
def translate(im, x, y):
"""
对图像进行平移变换
:param im: 原始图像数据
:param x: 水平方向平移的像素
:param y: 垂直方向平移的像素
:return: 返回平移后的图像数据
"""
h, w = im.shape[:2]
M = np.float32([[1, 0, x],
[0, 1, y]])
shifted = cv2.warpAffine(im,
M,
(w, h))
return shifted
def rotate(im, angle, center=None, scale=1.0):
"""
图像旋转变换
:param im: 原始图像
:param angle: 旋转角度
:param center: 旋转中心
:param scale: 缩放比例
:return: 返回经过旋转后的图像
"""
h, w = im.shape[:2]
if center is None:
center = (w / 2, h / 2)
M = cv2.getRotationMatrix2D(center, angle, scale)
rotated = cv2.warpAffine(im, M, (w, h))
return rotated
if __name__ == "__main__":
im = cv2.imread("../data/Linus.png")
cv2.imshow("im", im)
shifted = translate(im, 0, 50)
cv2.imshow("shifted_1", shifted)
shifted = translate(im, -40, 50)
cv2.imshow("shifted_2", shifted)
rotated = rotate(im, 45)
cv2.imshow("rotated_1", rotated)
rotated = rotate(im, -90)
cv2.imshow("rotated_2", rotated)
cv2.waitKey()
cv2.destroyAllWindows()

3. 图像缩放
import cv2
im = cv2.imread("../data/Linus.png")
cv2.imshow("im", im)
h, w = im.shape[:2]
dst_size = (int(w/2), int(h/2))
resized = cv2.resize(im, dst_size)
cv2.imshow("reduce", resized)
dst_size = (200, 300)
resized = cv2.resize(im,
dst_size,
interpolation=cv2.INTER_NEAREST)
cv2.imshow("NEAREST", resized)
resized = cv2.resize(im,
dst_size,
interpolation=cv2.INTER_LINEAR)
cv2.imshow("LINEAR", resized)
cv2.waitKey()
cv2.destroyAllWindows()

4. 图像裁剪
import numpy as np
import cv2
def random_crop(im, w, h):
start_x = np.random.randint(0, im.shape[1])
start_y = np.random.randint(0, im.shape[0])
new_img = im[start_y:start_y + h, start_x:start_x + w]
return new_img
def center_crop(im, w, h):
start_x = int(im.shape[1] / 2) - int(w / 2)
start_y = int(im.shape[0] / 2) - int(h / 2)
new_img = im[start_y:start_y + h, start_x:start_x + w]
return new_img
if __name__ == "__main__":
im = cv2.imread("../data/banana_1.png", 1)
new_img = random_crop(im, 200, 200)
cv2.imshow("random_crop", new_img)
new_img2 = center_crop(im, 200, 200)
cv2.imshow("center_crop", new_img2)
cv2.waitKey()
cv2.destroyAllWindows()

5. 图像相加
import cv2
a = cv2.imread("../data/lena.jpg", 0)
b = cv2.imread("../data/lily_square.png", 0)
dst1 = cv2.add(a, b)
cv2.imshow("dst1", dst1)
dst2 = cv2.addWeighted(a, 0.6,
b, 0.4,
0)
cv2.imshow("dst2", dst2)
cv2.waitKey()
cv2.destroyAllWindows()

6. 图像相减
import cv2
a = cv2.imread("../data/3.png", 0)
b = cv2.imread("../data/4.png", 0)
dst = cv2.subtract(a, b)
cv2.imshow("a", a)
cv2.imshow("b", b)
cv2.imshow("dst", dst)
cv2.waitKey()
cv2.destroyAllWindows()

7. 图像透视变换
import cv2
import numpy as np
im = cv2.imread("../data/pers.png")
rows, cols = im.shape[:2]
print(rows, cols)
cv2.imshow("im", im)
pts1 = np.float32([[58, 2], [167, 9], [8, 196], [126, 196]])
pts2 = np.float32([[16, 2], [167, 8], [8, 196], [169, 196]])
M = cv2.getPerspectiveTransform(pts1, pts2)
dst = cv2.warpPerspective(im,
M,
(cols, rows))
cv2.imshow("dst", dst)
M = cv2.getPerspectiveTransform(pts2, pts1)
dst2 = cv2.warpPerspective(im,
M,
(cols, rows))
cv2.imshow("dst2", dst2)
cv2.waitKey()
cv2.destroyAllWindows()

8. 图像腐蚀
import cv2
import numpy as np
im = cv2.imread("../data/5.png")
cv2.imshow("im", im)
kernel = np.ones((3, 3), np.uint8)
erosion = cv2.erode(im,
kernel,
iterations=3)
cv2.imshow("erosion", erosion)
cv2.waitKey()
cv2.destroyAllWindows()

9. 图像膨胀
import cv2
import numpy as np
im = cv2.imread("../data/6.png")
cv2.imshow("im", im)
kernel = np.ones((3, 3), np.uint8)
dilation = cv2.dilate(im,
kernel,
iterations=5)
cv2.imshow("dilation", dilation)
cv2.waitKey()
cv2.destroyAllWindows()

10. 图像开运算
import cv2
import numpy as np
im1 = cv2.imread("../data/7.png")
im2 = cv2.imread("../data/8.png")
k = np.ones((10, 10), np.uint8)
r1 = cv2.morphologyEx(im1, cv2.MORPH_OPEN, k)
r2 = cv2.morphologyEx(im2, cv2.MORPH_OPEN, k)
cv2.imshow("im1", im1)
cv2.imshow("im2", im2)
cv2.imshow("r1", r1)
cv2.imshow("r2", r2)
cv2.waitKey()
cv2.destroyAllWindows()

11. 图像闭运算
import cv2
import numpy as np
im1 = cv2.imread("../data/9.png")
im2 = cv2.imread("../data/10.png")
k = np.ones((8, 8), np.uint8)
r1 = cv2.morphologyEx(im1, cv2.MORPH_CLOSE, k, iterations=2)
r2 = cv2.morphologyEx(im2, cv2.MORPH_CLOSE, k, iterations=2)
cv2.imshow("im1", im1)
cv2.imshow("im2", im2)
cv2.imshow("r1", r1)
cv2.imshow("r2", r2)
cv2.waitKey()
cv2.destroyAllWindows()

12. 形态学梯度
import cv2
import numpy as np
o = cv2.imread("../data/6.png")
k = np.ones((3, 3), np.uint8)
r = cv2.morphologyEx(o, cv2.MORPH_GRADIENT, k)
cv2.imshow("o", o)
cv2.imshow("r", r)
cv2.waitKey()
cv2.destroyAllWindows()
