视觉实验一 混合图像

目标是将用低通滤波与高通滤波处理的图像混合,生成新的图像。该图像放大时看到的以高频信号为主,缩小时看到的以低频信号为主,呈现出两种图像。实验需要通过python、numpy、OpenCV,设计函数实现图像卷积、高斯模糊、得到滤波处理后的图像。不能使用已有的卷积与滤波函数。

这个项目需要实现 5 个函数,每个函数都建立在前面函数的基础上:

  1. cross_correlation_2d :互相关函数
  2. convolve_2d :卷积函数
  3. gaussian_blur_kernel_2d :产生高斯核函数
  4. low_pass :图像与高斯核卷积,实现低通滤波
  5. high_pass :图像减去低通滤波,实现高通滤波

一、环境配置.


首先是安装python(这里使用的是python3)
安装pip,再通过pip安装numpy与opencv-python以及pillow
当然也可以使用conda或直接安装Anaconda
IDE我用的是pycharm

二、互相关函数.


这个函数是难度最大的部分,写出了这个函数剩下的就简单多了。为了方便测试,将test.py的互相关测试部分提取出来边做边测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import cv2
import numpy as np
import matplotlib.pylab as plt

# 生成大小两张灰度二维数组(图像),
small_height = 10
small_width = 8
height = 50
width = 40
big_img_grey = np.random.rand(height,width)
small_img_grey = np.random.rand(small_height,small_width)
img_rgb = np.random.rand(height,width,3)


identity = np.zeros((3,3))
identity[1,0] = 1

img = big_img_grey.copy()

numpy与图像处理基础:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import matplotlib.pyplot as plt
import numpy as np
import cv2

#导入图像
img = plt.imread('test.jpg')

#绘出图像
plt.imshow(img)
plt.show()

#图像的存储结构是一个numpy数组,灰度图是二维数组(高、宽),RGB图是三维数组(长、宽、色彩通道)
print(img.shape) #输出为(高,宽,通道)
print(img) #输出数组内容

# numpy对图像的基本处理
height = img.shape[0]
width = img.shape[1]
img = img[:,:,0] #图像分割/分通道
print(img.ndim) #n维数组
print(img.dtype) #值的类型

# numpy生成数组
img1 = np.zeros(im.shape) #生成一个结构与img相同,值全为0的数组
img2 = np.ones((3,3))) #生成一个结构为3*3,值全为1的二维数组
img3 = np.random.rand(height,width) #生成一个结构为height*width,值为0~1随机数的二维数组

# 通道分离与合成
b,g,r=cv2.split(img) #b,g,r分别对应Blue,Green,Red通道的图像
new_img = cv2.merge([b,g,r]) #将分离为b,g,r的通道的图像合并

先从简单的让灰度图像向右平移一个像素写起。

基本思路:生成一个3*3的数组,其[0,1]值为1,剩下值为0。让灰度图中以每个像素为中心的3*3图像与该数组做互相关运算(超出图像边界取零),得到的结果填入新的图像中对应位置。

测试成功后,将灰度图像换成RGB图像,加入通道分离与合并的部分,这样互相关函数就算做完了。


代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
def cross_correlation_2d(img, kernel):
height = img.shape[0]
width = img.shape[1]
new_img = np.zeros((height, width))

Channel = False
if img.ndim == 2:
pass
else:
Channel = True
b, g, r = cv2.split(img)
new_img_1 = np.zeros((height, width))
new_img_2 = np.zeros((height, width))
new_img_3 = np.zeros((height, width))

identity = kernel.copy()

id_height = identity.shape[0]
id_width = identity.shape[1]
id_go_height = id_height // 2
id_go_width = id_width // 2

def xg(a, v):
sum0 = 0
for x, y in zip(a.flat, v.flat):
sum0 += x * y
return sum0

def former_img(h, w, id, img):
new_value_sum = np.zeros(id.shape)
hh = 0
for nh in range(h - id_go_height, h + id_go_height + 1):
ww = 0
for nw in range(w - id_go_width, w + id_go_width + 1):
if (nh < 0) or (nh >= height) or (nw < 0) or (nw >= width):
new_value_sum[hh][ww] = 0
else:
new_value_sum[hh][ww] = img[nh][nw]
ww += 1
hh += 1
return new_value_sum

def run_img(identity, im):
new_image = np.zeros((height, width))
for h in range(0, height):
for w in range(0, width):
v = former_img(h, w, identity, im)
# print(v)
value = xg(former_img(h, w, identity, im), identity)
# print(value)
new_image[h][w] = value
return new_image

if Channel:
new_img_1 = run_img(identity, b).copy()
new_img_2 = run_img(identity, g).copy()
new_img_3 = run_img(identity, r).copy()
new_img = cv2.merge([new_img_1, new_img_2, new_img_3])
else:
new_img = run_img(identity, img)
return new_img

三、产生高斯核的函数.


根据公式写出lambda表达式,其中π是np.pi,e是np.e,注意高斯核要求的和为1.

1
2
3
4
5
6
7
8
9
10
11
12
13
def gaussian_blur_kernel_2d(sigma, height, width):
g_function = lambda s, x, y: (1 / (2 * np.pi * s ** 2)) * np.e ** (-1 * (x ** 2 + y ** 2) / (2 * s ** 2))
kernel = np.zeros((height, width))
go_height = height // 2
go_width = width // 2

for h in range(0 - go_height, go_height + 1):
for w in range(0 - go_width, go_width + 1):
kernel[h + go_height][w + go_width] = g_function(sigma, w, h)

change = 1.0 / np.sum(kernel)
kernel *= chang
return kernele

剩下的两个函数就非常简单了,其实整个实验做下来也不是特别难,对numpy更熟悉了一些。

完整的代码放在github上
https://github.com/Xiayue09/VisionExp

感谢您的阅读,本文由 XiaYue blog 版权所有。如若转载,请注明出处:XiaYue blog(http://yoursite.com/2019/10/06/BlogVE1/
Spring初探-核心特性与解耦
笔记-儒家思想中的政教关系