计算机视觉实验1 混合图像
一、环境的搭建
-
系统:win10
-
编译器:vscode
-
语言:python3.7
-
库:numpy,opencv-python
用pip下载好库后就可以进行程序的编写。
pip的时候发现了报错,可能是以前下载python的时候某个地方出了问题,最后用pip3.7成功下载。
二、opencv对图片的基本操作
函数
img=cv2.imread(dirpath)//参数为文件的路径
后面为0表示灰度图像,为1表示BGR图像
将图片存储为数组,数组内存放像素值
sp=img.shape
sp[0]//存储图片像素的行数
sp[1]//存储图片像素的列数
cv2.imshow('image', img)//窗口显示图片,前面的字符串是窗口名
img.imwrite(dirpath)//保存图片
三、numpy数组的基本操作
将图片转换为numpy数组:
img=np.array(img)
图片的翻转
img=np.flip(img,0)//上下翻转
img=np.flip(img,1)//左右翻转
数组添加元素
line.append(x)//line数组添加元素x
数组求和
np.sum(a)//a数组各个元素和,返回一个值
相同规格的数组按位置乘积
np.multiply(a,kernel)//返回的是一个数组
求数组维数
img.ndim//返回数组的维度数
生成全0数组
np.zeros(x)//x表示0的个数
选取元素,左闭右开
a=img[i-half_k_h:i+half_k_h,j-half_k_w:j+half_k_w]//左闭右开
//只有冒号表示全取
r=img[:,:,0]
g=img[:,:,1]
b=img[:,:,2]
四、互相关函数 cross_correlation_2d 实现
互相关的含义
将图像记为F, 以H表示权重核(大小为(2K+1)*(2K+1)), 并记G为输出图像,则
G
[
i
,
j
]
=
∑
u
=
−
k
k
∑
v
=
−
k
k
H
[
u
,
v
]
F
[
i
+
u
,
j
+
v
]
G[i,j] = \sum_{u=-k}^k\sum_{v=-k}^k H[u,v]F[i+u,j+v]
G[i,j]=∑u=−kk∑v=−kkH[u,v]F[i+u,j+v]
思路
卷积的时候需要图片的部分邻域,但是在边界时,因为越界,这个部分邻域的规格会和权重核不一样,所以要对图片的信息进行扩展(增加加全0行与列),使得可以进行矩阵按位乘积,得到互相关后的结果。
代码
假设输入的图片是已经扩展的图片。
def cross_correlation_2d(img, kernel):
img_sp=img.shape()
k_sp=kernel.shape()
img_h=img_sp[0]
img_w=img_sp[1]
k_h=k_sp[0]
k_w=k_sp[1]
half_k_h=k_h//2
half_k_w=k_w//2
img_new=[]
for i in range(half_k_h,img_h-1-half_k_h):
line=[]
for j in range(half_k_w,img_w-1-half_k_w):
a=img[i-half_k_h:i+half_k_h,j-half_k_w:j+half_k_w]
line.append(np.sum(np.multiply(a,kernel)))
img_new.append(line)
return img_new
五、卷积函数convolve_2d实现
卷积的含义
卷积的含义与互相关近似, 只是权重核“翻转”(水平和垂直),
G
[
i
,
j
]
=
∑
u
=
−
k
k
∑
v
=
−
k
k
H
[
u
,
v
]
F
[
i
−
u
,
j
−
v
]
G[i,j] = \sum_{u=-k}^k\sum_{v=-k}^k H[u,v]F[i-u,j-v]
G[i,j]=∑u=−kk∑v=−kkH[u,v]F[i−u,j−v]
在互相关或卷积时,若所用像素位于图像以外,其值设置为0。
思路
由于图片的存储时,可能是每个像素用RGB存储,或者用灰度值存储,所以可以将rgb三个参数分开来处理,实现一个图像扩展函数再调用即可。返回的是卷积后的图像。
代码
extension 图像扩展函数
def extension(img,kernel):
img=np.array(img)
img=np.flip(img,0)
img=np.flip(img,1)
k=np.array(kernel)
img_sp=img.shape
img_h=img_sp[0]
img_w=img_sp[1]
k_sp=k.shape
k_h=k_sp[0]
k_w=k_sp[1]
h=k_h//2
w=k_w//2
for i in range(h):
img=np.row_stack(img,np.zeros(img_w))
img=np.row_stack(np.zeros(img_w),img)
for i in range(w):
img=np.column_stack(img,np.zeros(img_h+h*2))
img=np.column_stack(np.zeros(img_h+h*2),img)
return img
convolve_2d
def convolve_2d(img, kernel):
img=np.array(img)
if img.ndim==3:
r=img[:,:,0]
g=img[:,:,1]
b=img[:,:,2]
r_ex=extension(r,kernel)
g_ex=extension(g,kernel)
b_ex=extension(b,kernel)
r_new=cross_correlation_2d(r_ex,kernel)
g_new=cross_correlation_2d(g_ex,kernel)
b_new=cross_correlation_2d(b_ex,kernel)
img[:,:,0]=r_new
img[:,:,1]=g_new
img[:,:,2]=b_new
return img
else:
img_ex=extension(img,kernel)
img=cross_correlation_2d(img_ex,kernel)
return img
六、gaussian_blur_kernel_2d实现
思路
高斯模糊是相邻像素的一种特殊加权平均,权值与像素离卷积核中心距离的关系可用高斯函数来描述,
其中x为该像素距离卷积核中心的水平距离,y为该像素距离卷积核中心的垂直距离,σ为参数(标准差),前面的系数使总和为1(事实上,你要保证所有权值之和为1)。
为了实现高斯模糊,将实现一个函数gaussian_blur_kernel_2d,该函数产生一个给定高度和宽度的高斯核,之后将会把该高斯核与图像一起传递给convolve_2d函数,以产生图像的模糊版本。
代码
def gaussian_blur_kernel_2d(sigma, height, width):
xs=1.0/(2*math.pi*math.pow(sigma,2))
midh=height//2
midw=width//2
kernel=[]
for i in range(height):
line=[]
for j in range(width):
line.append(xs*math.exp(-1*(math.pow(i-midh,2)+math.pow(j-midw,2))/(2*math.pow(sigma,2))))
kernel.append(line)
return kernellation_2d(img_ex,kernel)