Q.11. 均值滤波器
使用均值滤波器(3x3)来进行滤波。
均值滤波器使用网格内像素的平均值。
import cv2
import numpy as np
# 读取图片
img = cv2.imread("imori.jpg")
H, W, C = img.shape
# 中值滤波
K_size = 3
## 零填充
pad = K_size // 2
out = np.zeros((H + pad * 2, W + pad * 2, C), dtype=np.float)
out[pad:pad + H, pad:pad + W] = img.copy().astype(np.float)
tmp = out.copy()
#使用均值滤波器(3x3)来进行滤波
for y in range(H):
for x in range(W):
for c in range(C):
out[pad + y, pad + x, c] = np.mean(tmp[y:y + K_size, x:x + K_size, c])
out = out[pad:pad + H, pad:pad + W].astype(np.uint8)
# 保存结果
cv2.imwrite("out11.jpg", out)
cv2.imshow("result11", out)
cv2.waitKey(0)
cv2.destroyAllWindows()
输入:
输出:
Q.12. Motion Filter
使用3x3的 Motion Filter 来进行滤波。
Motion Filter 取对角线方向的像素的平均值,像下式这样定义:
1/3 0 0
[ 0 1/3 0 ]
0 0 1/3
import cv2
import numpy as np
# 读取图像
img = cv2.imread("imori.jpg")
H, W, C = img.shape
# 中值滤波
K_size = 3
K = np.diag( [1] * K_size ).astype(np.float)#提取对角线像素作为新的滤波
K /= K_size#对角线方向的像素的平均值
## 零填充
pad = K_size // 2
out = np.zeros((H + pad*2, W + pad*2, C), dtype=np.float)
out[pad:pad+H, pad:pad+W] = img.copy().astype(np.float)
tmp = out.copy()
for y in range(H):
for x in range(W):
for c in range(C):
out[pad+y, pad+x, c] = np.sum(K * tmp[y:y+K_size, x:x+K_size, c])
out = out[pad:pad+H, pad:pad+W].astype(np.uint8)
#保存图片
cv2.imwrite("out12.jpg", out)
cv2.imshow("result12", out)
cv2.waitKey(0)
cv2.destroyAllWindows()
**加粗样式**
输入:
输出:
Q.13. MAX-MIN 滤波器
用 MAX-MIN 滤波器来进行滤波。
MAX-MIN 滤波器使用网格内像素的最大值和最小值的差值对网格内像素重新赋值。通常用于边缘检测。边缘检测用于检测图像中的线。像这样提取图像中的信息的操作被称为特征提取。边缘检测通常在灰度图像上进行。
import cv2
import numpy as np
# 读取图像
img = cv2.imread("imori.jpg").astype(np.float)
H, W, C = img.shape
b = img[:, :, 0].copy()
g = img[:, :, 1].copy()
r = img[:, :, 2].copy()
#灰度图像
gray = 0.2126 * r + 0.7152 * g + 0.0722 * b
gray = gray.astype(np.uint8)
# MAX-MIN 滤波器
K_size = 3
## 零填充
pad = K_size // 2
out = np.zeros((H + pad*2, W + pad*2), dtype=np.float)
out[pad:pad+H, pad:pad+W] = gray.copy().astype(np.float)
tmp = out.copy()
#MAX-MIN 滤波器使用网格内像素的最大值和最小值的差值对网格内像素重新赋值。
for y in range(H):
for x in range(W):
out[pad+y, pad+x] = np.max(tmp[y:y+K_size, x:x+K_size]) - np.min(tmp[y:y+K_size, x:x+K_size])
out = out[pad:pad+H, pad:pad+W].astype(np.uint8)
# 保存结果
cv2.imwrite("out13.jpg", out)
cv2.imshow("result13", out)
cv2.waitKey(0)
cv2.destroyAllWindows()
输入:
输出:
Q.14. 微分滤波器
使用3x3的微分滤波器来进行滤波。
微分滤波器对图像亮度急剧变化的边缘有提取效果,可以获得邻接像素的差值。
(a)纵向 (b)横向
0 -1 0 0 0 0
K = [ 0 1 0 ] K = [ -1 1 0 ]
0 0 0 0 0 0
import cv2
import numpy as np
# 读取图像
img = cv2.imread("imori.jpg").astype(np.float)
H, W, C = img.shape
b = img[:, :, 0].copy()
g = img[:, :, 1].copy()
r = img[:, :, 2].copy()
# 灰度图像
gray = 0.2126 * r + 0.7152 * g + 0.0722 * b
gray = gray.astype(np.uint8)
# 滤波
K_size = 3
## 零填充
pad = K_size // 2
out = np.zeros((H + pad*2, W + pad*2), dtype=np.float)
out[pad:pad+H, pad:pad+W] = gray.copy().astype(np.float)
tmp = out.copy()
out_v = out.copy()
out_h = out.copy()
## 纵向滤波器
Kv = [[0., -1., 0.],[0., 1., 0.],[0., 0., 0.]]
## 横向滤波器
Kh = [[0., 0., 0.],[-1., 1., 0.], [0., 0., 0.]]
#进行微分滤波器
for y in range(H):
for x in range(W):
out_v[pad+y, pad+x] = np.sum(Kv * (tmp[y:y+K_size, x:x+K_size]))
out_h[pad+y, pad+x] = np.sum(Kh * (tmp[y:y+K_size, x:x+K_size]))
#out_v = np.abs(out_v)
#out_h = np.abs(out_h)
out_v[out_v < 0] = 0
out_h[out_h < 0] = 0
out_v[out_v > 255] = 255
out_h[out_h > 255] = 255
out_v = out_v[pad:pad+H, pad:pad+W].astype(np.uint8)
out_h = out_h[pad:pad+H, pad:pad+W].astype(np.uint8)
# 保存结果
cv2.imwrite("out_v141.jpg", out_v)
cv2.imshow("result141", out_v)
cv2.waitKey(0)
cv2.imwrite("out_h142.jpg", out_h)
cv2.imshow("result142", out_h)
cv2.waitKey(0)
cv2.destroyAllWindows()
输入:
输出:
Q.15. Sobel 滤波器
使用3x3的 Sobel 滤波器来进行滤波。
Sobel 滤波器可以提取特定方向的边缘,滤波器按下式定义:
(a)纵向 (b)横向
1 0 -1 1 2 1
K = [ 2 0 -2 ] K = [ 0 0 0 ]
1 0 -1 -1 -2 -1
import cv2
import numpy as np
# 读取图像
img = cv2.imread("imori.jpg").astype(np.float)
H, W, C = img.shape
b = img[:, :, 0].copy()
g = img[:, :, 1].copy()
r = img[:, :, 2].copy()
# 灰度图像
gray = 0.2126 * r + 0.7152 * g + 0.0722 * b
gray = gray.astype(np.uint8)
# 滤波
K_size = 3
## 零填充
pad = K_size // 2
out = np.zeros((H + pad*2, W + pad*2), dtype=np.float)
out[pad:pad+H, pad:pad+W] = gray.copy().astype(np.float)
tmp = out.copy()
out_v = out.copy()
out_h = out.copy()
## 纵向滤波
Kv = [[1., 0., -1.],[2., 0., -2.],[1., 0., -1.]]
## 横向滤波
Kh = [[1., 2., 1.],[0., 0., 0.], [-1., -2., -1.]]
#进行Sobel 滤波
for y in range(H):
for x in range(W):
out_v[pad + y, pad + x] = np.sum(Kv * (tmp[y:y + K_size, x:x + K_size]))
out_h[pad + y, pad + x] = np.sum(Kh * (tmp[y:y + K_size, x:x + K_size]))
out_v[out_v < 0] = 0
out_h[out_h < 0] = 0
out_v[out_v > 255] = 255
out_h[out_h > 255] = 255
out_v = out_v[pad:pad+H, pad:pad+W].astype(np.uint8)
out_h = out_h[pad:pad+H, pad:pad+W].astype(np.uint8)
# 保存结果
cv2.imwrite("out_v151.jpg", out_v)
cv2.imshow("result151", out_v)
cv2.waitKey(0)
cv2.imwrite("out_h152.jpg", out_h)
cv2.imshow("result152", out_h)
cv2.waitKey(0)
cv2.destroyAllWindows()
输入:
输出:
Q.16. Prewitt 滤波器
使用3x3的 Prewitt 滤波器来进行滤波吧。
Prewitt 滤波器是用于边缘检测的一种滤波器,使用下式定义:
(a)纵向 (b)横向
-1 -1 -1 -1 0 1
K = [ 0 0 0 ] K = [ -1 0 1 ]
1 1 1 -1 0 1
import cv2
import numpy as np
# 读取图像
img = cv2.imread("imori.jpg").astype(np.float)
H, W, C = img.shape
b = img[:, :, 0].copy()
g = img[:, :, 1].copy()
r = img[:, :, 2].copy()
# 灰度图像
gray = 0.2126 * r + 0.7152 * g + 0.0722 * b
gray = gray.astype(np.uint8)
# 滤波器
K_size = 3
## 零填充
pad = K_size // 2
out = np.zeros((H + pad*2, W + pad*2), dtype=np.float)
out[pad:pad+H, pad:pad+W] = gray.copy().astype(np.float)
tmp = out.copy()
## 纵向滤波器
K = [[-1., -1., -1.],[0., 0., 0.], [1., 1., 1.]]
## 横向滤波器
#K = [[-1., 0., 1.],[-1., 0., 1.],[-1., 0., 1.]]
for y in range(H):
for x in range(W):
out[pad+y, pad+x] = np.sum(K * (tmp[y:y+K_size, x:x+K_size]))
out[out < 0] = 0
out[out > 255] = 255
out = out[pad:pad+H, pad:pad+W].astype(np.uint8)
# 保存结果
cv2.imwrite("out16.jpg", out)
cv2.imshow("result16", out)
cv2.waitKey(0)
cv2.destroyAllWindows()
输入:
输出:
Q.17. Laplacian 滤波器
使用 Laplacian 滤波器来进行滤波。
Laplacian 滤波器是对图像亮度进行二次微分从而检测边缘的滤波器。由于数字图像是离散的,x 方向和 y 方向的一次微分分别按照以下式子计算:
Ix(x,y) = (I(x+1, y) - I(x,y)) / ((x+1)-x) = I(x+1, y) - I(x,y)
Iy(x,y) = (I(x, y+1) - I(x,y)) / ((y+1)-y) = I(x, y+1) - I(x,y)
因此二次微分按照以下式子计算:
Ixx(x,y) = (Ix(x,y) - Ix(x-1,y)) / ((x+1)-x) = Ix(x,y) - Ix(x-1,y)
= (I(x+1, y) - I(x,y)) - (I(x, y) - I(x-1,y))
= I(x+1,y) - 2 * I(x,y) + I(x-1,y)
Iyy(x,y) = … = I(x,y+1) - 2 * I(x,y) + I(x,y-1)
特此,Laplacian 表达式如下:
D^2 I(x,y) = Ixx(x,y) + Iyy(x,y)
= I(x-1,y) + I(x,y-1) - 4 * I(x,y) + I(x+1,y) + I(x,y+1)
如果把这个式子表示为卷积核是下面这样的:
0 1 0
K = [ 1 -4 1 ]
0 1 0
import cv2
import numpy as np
# 读取图片
img = cv2.imread("imori.jpg").astype(np.float)
H, W, C = img.shape
b = img[:, :, 0].copy()
g = img[:, :, 1].copy()
r = img[:, :, 2].copy()
# 灰度图像
gray = 0.2126 * r + 0.7152 * g + 0.0722 * b
gray = gray.astype(np.uint8)
# sobel滤波
K_size = 3
## 零填充
pad = K_size // 2
out = np.zeros((H + pad*2, W + pad*2), dtype=np.float)
out[pad:pad+H, pad:pad+W] = gray.copy().astype(np.float)
tmp = out.copy()
## Laplacian纵向滤波器
K = [[0., 1., 0.],[1., -4., 1.], [0., 1., 0.]]
for y in range(H):
for x in range(W):
out[pad+y, pad+x] = np.sum(K * (tmp[y:y+K_size, x:x+K_size]))
out[out < 0] = 0
out[out > 255] = 255
out = out[pad:pad+H, pad:pad+W].astype(np.uint8)
# 保存结果
cv2.imwrite("out17.jpg", out)
cv2.imshow("result17", out)
cv2.waitKey(0)
cv2.destroyAllWindows()
输入:
输出:
Q.18. Emboss 滤波器
使用 Emboss 滤波器来进行滤波。
Emboss 滤波器可以使物体轮廓更加清晰,按照以下式子定义:
-2 -1 0
K = [ -1 1 1 ]
0 1 2
import cv2
import numpy as np
# 读取图片
img = cv2.imread("imori.jpg").astype(np.float)
H, W, C = img.shape
b = img[:, :, 0].copy()
g = img[:, :, 1].copy()
r = img[:, :, 2].copy()
# 灰度图像
gray = 0.2126 * r + 0.7152 * g + 0.0722 * b
gray = gray.astype(np.uint8)
# 滤波器
K_size = 3
## 零填充
pad = K_size // 2
out = np.zeros((H + pad*2, W + pad*2), dtype=np.float)
out[pad:pad+H, pad:pad+W] = gray.copy().astype(np.float)
tmp = out.copy()
## Emboss 滤波器
K = [[-2., -1., 0.],[-1., 1., 1.], [0., 1., 2.]]
for y in range(H):
for x in range(W):
out[pad+y, pad+x] = np.sum(K * (tmp[y:y+K_size, x:x+K_size]))
out[out < 0] = 0
out[out > 255] = 255
out = out[pad:pad+H, pad:pad+W].astype(np.uint8)
# 保存图片
cv2.imwrite("out18.jpg", out)
cv2.imshow("result18", out)
cv2.waitKey(0)
cv2.destroyAllWindows()
输入:
输出:
Q.19. LoG 滤波器
使用 LoG 滤波器,来对imori_noise.jpg检测边缘!
LoG 即高斯-拉普拉斯( Laplacian of Gaussian )的缩写,使用高斯滤波器使图像平滑化之后再使用拉普拉斯滤波器使图像的轮廓更加清晰。
为了防止拉普拉斯滤波器计算二次微分会使得图像噪声更加明显,所以我们首先使用高斯滤波器来抑制噪声。
LoG 滤波器使用以下式子定义:
LoG(x,y) = (x^2 + y^2 - s^2) / (2 * pi * s^6) * exp(-(x2+y2) / (2*s^2))
import cv2
import numpy as np
# 读取图片
img = cv2.imread("imori_noise.jpg")
H, W, C = img.shape
b = img[:, :, 0].copy()
g = img[:, :, 1].copy()
r = img[:, :, 2].copy()
# 灰度图片
gray = 0.2126 * r + 0.7152 * g + 0.0722 * b
gray = gray.astype(np.uint8)
# 高斯滤波器
K_size = 5
s = 3
## 零填充
pad = K_size // 2
out = np.zeros((H + pad * 2, W + pad * 2), dtype=np.float)
out[pad:pad + H, pad:pad + W] = gray.copy().astype(np.float)
tmp = out.copy()
## 内核
K = np.zeros((K_size, K_size), dtype=np.float)
for x in range(-pad, -pad + K_size):
for y in range(-pad, -pad + K_size):
K[y + pad, x + pad] = (x ** 2 + y ** 2 - s ** 2) * np.exp(-(x ** 2 + y ** 2) / (2 * (s ** 2)))#LoG 滤波器
K /= (2 * np.pi * (s ** 6))
K /= K.sum()
for y in range(H):
for x in range(W):
out[pad + y, pad + x] = np.sum(K * tmp[y:y + K_size, x:x + K_size])
out = out[pad:pad + H, pad:pad + W].astype(np.uint8)
# 保存结果
cv2.imwrite("out19.jpg", out)
cv2.imshow("result19", out)
cv2.waitKey(0)
cv2.destroyAllWindows()
输入:
输出:
Q.20. 直方图
使用Matplotlib来绘制imori_dark.jpg的直方图!
直方图显示了不同数值的像素出现的次数。在Matplotlib中有hist()函数提供绘制直方图的接口。
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 读取图片
img = cv2.imread("imori_dark.jpg").astype(np.float)
# 显示直方图
plt.hist(img.ravel(), bins=255, rwidth=0.8, range=(0, 255))
plt.savefig("out20.png")
plt.show()
输入:
输出: