# 卷积神经网络可视化——Image Kernel

## 1. 导入库

```from PIL import Image, ImageDraw
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline```

## 2.1 助手函数

```def read_img(imgpath, gray=True):
img = Image.open(imgpath)
if gray:
img = img.convert("L")
return img```

```def resize_width(img, width):
w, h = img.size
height = int(width * h / w)
return img.resize((width, height))```

```def crop_center(img):
w, h = img.size
c_x, c_y = w/2, h/2
offset = min(w, h) / 2
crop_box = (c_x-offset, c_y-offset, c_x+offset, c_y+offset)
return img.crop(crop_box)```

### 2.2 指定 kernel 对图像处理

img 为 Image 对象；kernel 为进行卷积运算的矩阵；strides 为卷积运算单次平移步长；mean 为 False 时，求和，为 True 时，求平均值。

```def apply_img_kernel(img, kernel, strides=1, mean=False):
img = np.asarray(img)

h, w = img.shape[:2]
k_h, k_w = kernel.shape[:2]
x_range = range(0, w - k_w + 1, strides)
y_range = range(0, h - k_h + 1, strides)

if mean:
prosum = lambda a,b: min((a*b).mean(), 255)
else:
prosum = lambda a,b: min((a*b).sum(), 255)

cal = lambda img: np.array([[prosum(img[i:i+k_h, j:j+k_w], kernel)
for j in x_range]
for i in y_range]).astype(np.uint8)

if len(img.shape) == 2:
data = cal(img)
return Image.fromarray(data)
elif len(img.shape) == 3:
r, g, b = np.transpose(img, (2, 0, 1))
_r, _g, _b = cal(r), cal(g), cal(b)
return Image.merge('RGB', [Image.fromarray(d) for d in [_r, _g, _b]])```

## 3. 不同效果的 Image Kernel

### 3.1 亮化

```def identity_kernel(iden=1.0):
return np.array([[0, 0,    0],
[0, iden, 0],
[0, 0,    0]])```

### 3.2 锐化

```def sharpen_kernel(inner=5.0,  edge=-1.0):
return np.array([[0,    edge,  0],
[edge, inner, edge],
[0,    edge,  0]])```

### 3.3 模糊

```def blur_kernel(inner=0.25,  edge=0.125, corner=0.0625):
return np.array([[corner, edge,  corner],
[edge,   inner, edge],
[corner, edge,  corner]])```

### 3.4 浮雕

```def emboss_kernel(diag=2.0, iden=1.0):
return np.array([[-diag, -iden, 0],
[-iden, iden,  iden],
[0,     iden,  diag]])```

### 3.5 轮廓线

```def outline_kernel(inner=8.0, outer=-1.0):
return np.array([[outer, outer, outer],
[outer, inner, outer],
[outer, outer, outer]])```

### 3.6 边缘检测

```def sobel_kernel(direction, base=None, edge=2.0, corner=1.0):
if base is not None:
edge = base
corner = base / 2
if direction == 'top':
return np.array([[corner, edge, corner], [0, 0, 0], [-corner, -edge, -corner]])
elif direction == 'bottom':
return np.array([[-corner, -edge, -corner], [0, 0, 0], [corner, edge, corner]])
elif direction == 'left':
return np.array([[corner, 0, -corner], [edge, 0, -edge], [corner, 0, -corner]])
elif direction == 'right':
return np.array([[-corner, 0, corner], [-edge, 0, edge], [-corner, 0, corner]])

return identity_kernel()```

## 4. 使用效果

tips: gray 参数设置 True, 读取灰度图像。这里演示彩色图像效果。

```img = read_img('yuki.jpeg', gray=False)

img = crop_center(resize_width(img, 320))```

```def show2imgs(img1, img2, title=None):
fig = plt.figure(figsize=(10, 5))

if title is not None:
fig.suptitle(title)

plt.subplot(121)
plt.axis('off')
plt.imshow(img1)

plt.subplot(122)
plt.axis('off')
plt.imshow(img2)

plt.show()```

### 4.1 亮化

```img_identity = apply_img_kernel(img, identity_kernel(1.6))

show2imgs(img, img_identity)```

### 4.2 锐化

```img_sharpen = apply_img_kernel(img, sharpen_kernel(inner=1.7,  edge=-0.08))

show2imgs(img, img_sharpen)```

### 4.3 模糊

```img_blur = apply_img_kernel(img, blur_kernel())

show2imgs(img, img_blur)```

### 4.4 浮雕

```img_emboss = apply_img_kernel(img, emboss_kernel())

show2imgs(img, img_emboss)```

### 4.5 轮廓线

```img_outline = apply_img_kernel(img, outline_kernel(inner=8.9, outer=-1.29), mean=True)

show2imgs(img, img_outline)```

### 4.6 边缘检测

```img_sobel_top = apply_img_kernel(img, sobel_kernel('top', 0.03))
img_sobel_bottom = apply_img_kernel(img, sobel_kernel('bottom', 0.03))
img_sobel_left = apply_img_kernel(img, sobel_kernel('left', 0.03))
img_sobel_right = apply_img_kernel(img, sobel_kernel('right', 0.03))

show2imgs(img_sobel_top, img_sobel_bottom)
show2imgs(img_sobel_left, img_sobel_right)```

## 5. 开源

`pip install imgkernel`

39 篇文章16 人订阅

0 条评论