本篇记录了自己写的GIthub上的ImageProcessing 100 Wen的问题11-20的答案,注释里包含了一些自己的感悟。为了方便,注释是用英文写的。
这10个题目主要是各种滤波方法,本质上还是卷积运算,不同的滤波方法有不同的卷积核。
值得注意的是Zero Padding方法,以保持卷积运算后图像的大小不变。
LoG滤波中,卷积核要归一化。
问题序号 | 题目 |
---|---|
11 | 均值滤波 |
12 | 运动滤波(Motion Filter) |
13 | MAX-MIN 滤波 |
14 | 差分滤波 |
15 | Sobel 滤波 |
16 | Prewitt 滤波 |
17 | Laplacian 滤波 |
18 | Emboss 滤波 |
19 | LoG滤波 |
20 | 绘制直方图 |
Python答案如下,结尾包含了问题的验证。注意,引用了answer1(题目1-10的答案),主要用的是图像灰度化处理。
import cv2.cv2
import numpy as np
import matplotlib.pyplot as plt
import answer1
# Question 11
# Mean Filter
# use the mean of kernel to filter
# Answer
def mean_filter(img, k=3):
if len(img.shape) == 3:
H, W, C = img.shape
else:
np.expand_dims(img, axis=-1)
H, W, C = img.shape
# Zero Padding
pad = int((k - 1) / 2)
out = np.zeros((H + 2 * pad, W + 2 * pad, C), dtype=np.float)
out[pad:pad + H, pad:pad + W] = img.astype(np.float)
# Mean filter
out_old = out.copy()
for y in range(H):
for x in range(W):
for c in range(C):
out[pad + y, pad + x, c] = np.mean(out_old[y:y + k, x:x + k, c])
out = np.clip(out, 0, 255)
out = out[pad:pad + H, pad:pad + W].astype(np.uint8)
return out
# Question 12
# motion filter
# use the mean of values on the diagonal of kernel to filer
# Answer
def motion_filter(img, k=3):
if len(img.shape) == 3:
H, W, C = img.shape
else:
np.expand_dims(img, axis=-1)
H, W, C = img.shape
# Zero padding
pad = int((k - 1) / 2)
out = np.zeros((H + 2 * pad, W + 2 * pad, C), dtype=np.float)
out[pad:pad + H, pad:pad + W] = img.astype(np.float)
# Build the kernel
kernel = np.identity(k, dtype=np.float) / k
# Motion filter
out_old = 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(kernel * out_old[y:y + k, x:x + k, c])
out = np.clip(out, 0, 255)
out = out[pad:pad + H, pad:pad + W].astype(np.uint8)
return out
# Question 13
# max-min filter
# use the value of (max-min) in kernel to filter, available to gray
# Answer
def max_min_filter(img, k=3):
gray = answer1.RGB2GRAY(img)
if gray.shape == 3:
H, W, C = gray.shape
else:
gray = np.expand_dims(gray, axis=-1)
H, W, C = gray.shape
# Zero padding
pad = int((k - 1) / 2)
out = np.zeros((H + 2 * pad, W + 2 * pad, C), dtype=np.float)
out[pad:pad + H, pad:pad + W] = gray.astype(np.float)
# max-min filter
out_old = out.copy()
for y in range(H):
for x in range(W):
for c in range(C):
out[pad + y, pad + x, c] = np.max(out_old[y:y + k, x:x + k, c]) - np.min(out_old[y:y + k, x:x + k, c])
out = np.clip(out, 0, 255)
out = out[pad:pad + H, pad:pad + W].astype(np.uint8)
return out
# Question 14
# differential filter
# get the difference between two conjecture pixels
# Answer
def differential_filter(img):
k = 3
gray = answer1.RGB2GRAY(img)
H, W = gray.shape
# Zero padding
pad = int((k - 1) / 2)
out = np.zeros((H + 2 * pad, W + 2 * pad), dtype=np.float)
out[pad:pad + H, pad:pad + W] = gray.astype(np.float)
# Build vertical kernel
kernel_v = [[0., -1., 0.], [0., 1., 0.], [0., 0., 0.]]
# Build horizon kernel
kernel_h = [[0., 0., 0.], [-1., 1., 0.], [0., 0., 0.]]
# filter
out_v = out.copy()
out_h = out.copy()
for y in range(H):
for x in range(W):
out_v[pad + y, pad + x] = np.sum(kernel_v * out[y:y + k, x:x + k])
out_h[pad + y, pad + x] = np.sum(kernel_h * out[y:y + k, x:x + k])
out_v = np.clip(out_v, 0, 255)
out_v = out_v[pad:pad + H, pad:pad + W].astype(np.uint8)
out_h = np.clip(out_h, 0, 255)
out_h = out_h[pad:pad + H, pad:pad + W].astype(np.uint8)
return out_v, out_h
# Question 15
# soble filter
# Answer
def sobel_filter(img):
k = 3
gray = answer1.RGB2GRAY(img)
H, W = gray.shape
# Zero padding
pad = int((k - 1) / 2)
out = np.zeros((H + 2 * pad, W + 2 * pad), dtype=np.float)
out[pad:pad + H, pad:pad + W] = gray.astype(np.float)
# Build vertical kernel
kernel_v = [[1., 2., 1.], [0., 0., 0.], [-1., -2., -1.]]
# Build horizon kernel
kernel_h = [[1., 0., -1.], [2., 0., -2.], [1., 0., -1.]]
# filter
out_v = out.copy()
out_h = out.copy()
for y in range(H):
for x in range(W):
out_v[pad + y, pad + x] = np.sum(kernel_v * out[y:y + k, x:x + k])
out_h[pad + y, pad + x] = np.sum(kernel_h * out[y:y + k, x:x + k])
out_v = np.clip(out_v, 0, 255)
out_v = out_v[pad:pad + H, pad:pad + W].astype(np.uint8)
out_h = np.clip(out_h, 0, 255)
out_h = out_h[pad:pad + H, pad:pad + W].astype(np.uint8)
return out_v, out_h
# Question 16
# Prewitt filter
# Answer
def prewitt_filter(img):
k = 3
gray = answer1.RGB2GRAY(img)
H, W = gray.shape
# Zero padding
pad = int((k - 1) / 2)
out = np.zeros((H + 2 * pad, W + 2 * pad), dtype=np.float)
out[pad:pad + H, pad:pad + W] = gray.astype(np.float)
# Build vertical kernel
kernel_v = [[-1., -1., -1.], [0., 0., 0.], [1., 1., 1.]]
# Build horizon kernel
kernel_h = [[-1., 0., 1.], [-1., 0., 1.], [-1., 0., 1.]]
# filter
out_v = out.copy()
out_h = out.copy()
for y in range(H):
for x in range(W):
out_v[pad + y, pad + x] = np.sum(kernel_v * out[y:y + k, x:x + k])
out_h[pad + y, pad + x] = np.sum(kernel_h * out[y:y + k, x:x + k])
out_v = np.clip(out_v, 0, 255)
out_v = out_v[pad:pad + H, pad:pad + W].astype(np.uint8)
out_h = np.clip(out_h, 0, 255)
out_h = out_h[pad:pad + H, pad:pad + W].astype(np.uint8)
return out_v, out_h
# Question 17
# Laplacian filter
# Answer
def laplacian_filter(img):
k = 3
gray = answer1.RGB2GRAY(img)
H, W = gray.shape
# Zero padding
pad = int((k - 1) / 2)
out = np.zeros((H + 2 * pad, W + 2 * pad), dtype=np.float)
out[pad:pad + H, pad:pad + W] = gray.astype(np.float)
# Build vertical kernel
kernel = [[0., 1., 0.], [1., -4., 1.], [0., 1., 0.]]
# filter
out_old = out.copy()
for y in range(H):
for x in range(W):
out[pad + y, pad + x] = np.sum(kernel * out_old[y:y + k, x:x + k])
out = np.clip(out, 0, 255)
out = out[pad:pad + H, pad:pad + W].astype(np.uint8)
return out
# Question 18
# Emboss filter
# Answer
def emboss_filter(img):
k = 3
gray = answer1.RGB2GRAY(img)
H, W = gray.shape
# Zero padding
pad = int((k - 1) / 2)
out = np.zeros((H + 2 * pad, W + 2 * pad), dtype=np.float)
out[pad:pad + H, pad:pad + W] = gray.astype(np.float)
# Build vertical kernel
kernel = [[-2., -1., 0.], [-1., 1., 1.], [0., 1., 2.]]
# filter
out_old = out.copy()
for y in range(H):
for x in range(W):
out[pad + y, pad + x] = np.sum(kernel * out_old[y:y + k, x:x + k])
out = np.clip(out, 0, 255)
out = out[pad:pad + H, pad:pad + W].astype(np.uint8)
return out
# Question 19
# LoG filter
# Gaussian filter + Laplacian filter
# Answer
def log_filter(img, k=5, sigma=3):
gray = answer1.RGB2GRAY(img)
if len(gray.shape) == 3:
H, W, C = gray.shape
else:
gray = np.expand_dims(gray, axis=-1)
H, W, C = gray.shape
# Zero padding
pad = int((k - 1) / 2)
out = np.zeros((H + 2 * pad, W + 2 * pad, C), dtype=np.float)
out[pad:pad + H, pad:pad + W] = gray.astype(np.float)
# build filter
kernel = np.zeros((k, k), dtype=np.float)
for y in range(-pad, k - pad):
for x in range(-pad, k - pad):
kernel[pad + y, pad + x] = (np.square(x) + np.square(y) - np.square(sigma)) * (
np.exp((-(np.square(x) + np.square(y))) / (2 * np.square(sigma))))
kernel = kernel / (2 * np.pi * np.power(sigma, 6))
kernel = kernel / np.sum(kernel)
# filter
out_old = 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(kernel * out_old[y:y + k, x:x + k, c])
out = np.clip(out, 0, 255)
out = out[pad:pad + H, pad:pad + W].astype(np.uint8)
return out
# Question 20
# hist plot
# to present the times of piexl value
# Answer
def hist_plot(img):
plt.hist(img.ravel(), bins=255, rwidth=0.8, range=(0, 255))
plt.show()
# Test
# Answer 11
# img = cv2.imread("imori.jpg")
#
# img11 = mean_filter(img)
#
# cv2.imshow("Mean Filter", img11)
#
# cv2.waitKey(0)
# cv2.destroyAllWindows()
# Answer 12
# img = cv2.imread("imori.jpg")
#
# img12 = motion_filter(img)
#
# cv2.imshow("Mean Filter", img12)
#
# cv2.waitKey(0)
# cv2.destroyAllWindows()
# Annswer 13
# img = cv2.imread("imori.jpg")
#
# img13 = max_min_filter(img)
#
# cv2.imshow("Max-Min Filter", img13)
#
# cv2.waitKey(0)
# cv2.destroyAllWindows()
# Answer 14
# img = cv2.imread("imori.jpg")
#
# img14_v, img14_h = differential_filter(img)
# cv2.imshow("Mean Filter Vertical", img14_v)
# cv2.imshow("Mean Filter Horizon", img14_h)
#
# cv2.waitKey(0)
# cv2.destroyAllWindows()
# Answer 15
# img = cv2.imread("imori.jpg")
#
# img15_v, img15_h = sobel_filter(img)
# cv2.imshow("Sobel Filter Vertical", img15_v)
# cv2.imshow("Sobel Filter Horizon", img15_h)
#
# cv2.waitKey(0)
# cv2.destroyAllWindows()
# Answer 16
# img = cv2.imread("imori.jpg")
#
# img16_v, img16_h = prewitt_filter(img)
# cv2.imshow("Prewitt Filter Vertical", img16_v)
# cv2.imshow("Prewitt Filter Horizon", img16_h)
#
# cv2.waitKey(0)
# cv2.destroyAllWindows()
# Answer 17
# img = cv2.imread("imori.jpg")
#
# img17 = laplacian_filter(img)
# cv2.imshow("Laplacian Filter Vertical", img17)
#
# cv2.waitKey(0)
# cv2.destroyAllWindows()
# Answer 18
# img = cv2.imread("imori.jpg")
#
# img18 = emboss_filter(img)
# cv2.imshow("Laplacian Filter Vertical", img18)
#
# cv2.waitKey(0)
# cv2.destroyAllWindows()
# Answer 19
# img = cv2.imread("imori_noise.jpg")
#
# img19 = log_filter(img)
# cv2.imshow("LoG Filter Vertical", img19)
#
# cv2.waitKey(0)
# cv2.destroyAllWindows()
# Answer 20
# img = cv2.imread("imori_dark.jpg")
#
# hist_plot(img)