实验:卷积运算-滑块方式(灰度图)

概述

本文通过编写代码,采用 滑块方式 实现 卷积运算,对图片进行边缘检测

实验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


原文出处:/show_1EF4aAOjPTKa.html