概述
本文通过编写代码,采用 滑块方式 实现 卷积运算,对图片进行边缘检测
实验1
为了便于 理解 运算结果,使用下面 口字 图片(16*16像素):
本例只检测 竖线 和 横线
导入模块
import matplotlib.pyplot as plt
from PIL import Image
import numpy as np
读取图片
path=r"C:\Users\mym\Desktop\文件接收柜\kou_min.jpg"
im = Image.open(path).convert("L")
img=np.array(im)
print('输入图shape:',img.shape)
plt.imshow(img,cmap="gray")
卷积运算函数
# 卷积运算
def run_conv(data,kernel,step=1):
"""
data:要计算的图像数据
kernel:卷积核值
step:步长
"""
data_w=data.shape[1]
data_h=data.shape[0]
# print(data_w,data_h)
# 卷积核大小
kernel_w=kernel.shape[1]
kernel_h=kernel.shape[0]
# 结果大小
result_w=(data_w-kernel_w)//step+1
result_h=(data_h-kernel_h)//step+1
# 输入数据的滑块索引
data_w_index=0
data_h_index=0
result_data=np.zeros((result_h,result_w))
# print(result_h,result_w)
res_w_index=0
res_h_index=0
while (data_w_index+kernel_w)<=data_w:
while (data_h_index+kernel_h)<=data_h:
img_area=data[data_h_index:data_h_index+kernel_h,data_w_index:data_w_index+kernel_w]
result_data[res_h_index][res_w_index]=np.sum(img_area*kernel)
data_h_index+=step
res_h_index+=1
data_w_index+=step
data_h_index=0
res_w_index+=1
res_h_index=0
return result_data
定义打印矩阵值的函数
直接打印numpy数组,不能全部显示,定义此函数就是为了显示全部numpy数组
def myprint(arr):
h=arr.shape[0]
w=arr.shape[1]
for i in range(w):
for j in range(h):
print("%4s"%arr[i][j],end=" ")
print(" ")
打印图片的numpy结果
myprint(img)
定义检测竖线的卷积核
w=np.array([[-1,0,1],
[-1,0,1],
[-1,0,1]])
w.shape
进行卷积运算
res=run_conv(img,w,1)
myprint(res)
执行结果如下:
竖线 的结果是 非0值
定义检测横线的卷积核
w=np.array([[-1,-1,-1],
[0,0,0],
[1,1,1]])
w.shape
进行卷积运算
res=run_conv(img,w,1)
myprint(res)
执行结果如下:
横线 是 非0值
实验2
本例只检测 竖线 和 横线
导入模块
import matplotlib.pyplot as plt
from PIL import Image
import numpy as np
读取图片
path=r"C:\Users\mym\Desktop\文件接收柜\zhalan.jpg"
im = Image.open(path).convert("L")
img=np.array(im)
print('输入图shape:',img.shape)
plt.imshow(img,cmap="gray")
定义卷积函数
# 卷积运算
def run_conv(data,kernel,step=1):
"""
data:要计算的图像数据
kernel:卷积核值
step:步长
"""
data_w=data.shape[1]
data_h=data.shape[0]
# print(data_w,data_h)
# 卷积核大小
kernel_w=kernel.shape[1]
kernel_h=kernel.shape[0]
# 结果大小
result_w=(data_w-kernel_w)//step+1
result_h=(data_h-kernel_h)//step+1
# 输入数据的滑块索引
data_w_index=0
data_h_index=0
result_data=np.zeros((result_h,result_w))
# print(result_h,result_w)
res_w_index=0
res_h_index=0
while (data_w_index+kernel_w)<=data_w:
while (data_h_index+kernel_h)<=data_h:
img_area=data[data_h_index:data_h_index+kernel_h,data_w_index:data_w_index+kernel_w]
result_data[res_h_index][res_w_index]=np.sum(img_area*kernel)
data_h_index+=step
res_h_index+=1
data_w_index+=step
data_h_index=0
res_w_index+=1
res_h_index=0
return result_data
定义检测竖线的卷积核
w=np.array([[-1,0,1],
[-1,0,1],
[-1,0,1]])
w.shape
执行卷积运算
res=run_conv(img,w,1)
res
定义转换函数
经过 卷积核 运算后,其结果可能会 小于0,大于255
定义转换函数,将结果 映射到0-255之间
def convert(x):
mn=np.min(x)
mx=np.max(x)
r=(x-mn)/(mx-mn)
return r*255
执行转换运算
res2=convert(res)
res3=np.round(res2).astype("uint8")
res3
将卷积结果显示成图片
res_img=Image.fromarray(res3,"L")
res_img.save("检测垂直轮廓.jpg")
res_img
定义检测横线卷积核
w=np.array([[-1,-1,-1],
[0,0,0],
[1,1,1]])
w.shape
卷积运算并转换
res=run_conv(img,w,1)
res2=convert(res)
res3=np.around(res2)
res3=res3.astype("uint8")
res3
将卷积结果显示成图片
res_img=Image.fromarray(res3,"L")
res_img.save("水平边缘.jpg")
res_img







