【Numpy】图像处理——腐蚀与膨胀


前言

  我们选择对全局二值化后的图像进行腐蚀、膨胀操作。
  腐蚀与膨胀类似于滤波算法,只不过腐蚀的滤波运算结果是二值图像某一邻域内的最小值,也可理解为该邻域内像素的相与运算结果。膨胀的滤波运算结果是二值化图像某一邻域内的最大值,即该邻域内像素的或运算结果。


腐蚀

import numpy as np
from PIL import Image
import matplotlib.pyplot as plt

#步骤一:获取图像的灰度直方图数据

#读取图像数据
img = Image.open("TIGA.jpg")

plt.title("image_origin")
plt.imshow(img,cmap="brg")
plt.show()

#将图像数据转化成numpy类型的数组
img_arr = np.array(img)

#将图像转化成灰度图
image = img_arr[:,:,0] * 0.299 + img_arr[:,:,1] * 0.587 + img_arr[:,:,2] * 0.114
image = np.ceil(image)   #对数组数据向上取整

plt.title("image_gray")
plt.imshow(image,cmap="gray")
plt.show()

height,width = image.shape


# #生成图像的直方图数据
hist = np.zeros((256,1))
for i in range(height):
    for j in range(width):
        hist[int(image[i,j]),0] += 1

        
#步骤二:类间方差计算
        
#获取灰度级
grayscale = range(256)

#像素总数
num_pixels = height * width
        
#根据直方图数据计算灰度值的总和
total_gray = np.dot(hist[:,0],grayscale)

#计算整个图像的平均灰度值,以作为预设的灰度值阈值初值
m = total_gray / num_pixels  

#创建存储类间方差的数组(两个集合一共是由256种不同的阈值分割的,因此产生的类间方差也就有256种)
sigma_array = np.zeros(256)

#根据阈值处置生成两个集合(当然循环操作)
for T in range(256):
    num_G1 = np.sum(hist[:T,0])  #统计G1的像素数量
    sum_G1 = np.dot(hist[:T,0],range(T))   #统计G1的灰度值总和
    num_G2 = num_pixels - num_G1     #统计G2的像素数量
    sum_G2 = total_gray - sum_G1     #统计G2的灰度值总和
    
    P1 = num_G1 / num_pixels
    P2 = num_G2 / num_pixels
    
    #分别求两个集合的平均灰度(记得一定要取整)
    m1 = (sum_G1 / num_G1) if  num_G1 > 0 else 0
    m2 = (sum_G2 / num_G2) if  num_G2 > 0 else 0
    
    #计算当前迭代所用阈值得到的类间方差
    sigma_array[T] = P1 * (m1 - m) ** 2  + P2 * (m2 - m) ** 2

#步骤三:根据上一步骤得到的类间方差数组,找寻最大类间方差对应的阈值,作为最优阈值。
max = np.max(sigma_array)
max_index = np.argmax(sigma_array)    # numpy.argmax()  Returns the indices of the maximum values along an axis.

T = max_index

print("使用的Otsu后的全局最优阈值:" + str(T))

#步骤四:阈值处理

#创建阈值处理后的新图像
image_threshold = np.zeros((height,width))
for i in range(height):
    for j in range(width):
        if image[i,j] < T:
            image_threshold[i,j] = 0
        else:
            image_threshold[i,j] = 255

plt.title("image_threshold_total_Ostu")
plt.imshow(image_threshold,cmap="gray")
plt.show()

#步骤五:腐蚀

  
#滤波运算法进行腐蚀
def filter_erode(img,filter_size):
    #获取原图高和宽
    height,width = img.shape
    
    #根据原图大小创建新图
    img_erode = np.ones((height,width))
    
    #根据参数filter_size,即滤波核大小,创建滤波器
    filter = np.ones((filter_size,filter_size))
    
    #新图像最外围的((filter_size - 1) / 2)圈不赋值,默认都是1就行。
    for i in range(int((filter_size-1)/2),height-int((filter_size-1)/2)):
        for j in range(int((filter_size-1)/2),width-int((filter_size-1)/2)):
            img_erode[i][j] = np.min(np.dot(img[i-int((filter_size-1)/2):i+int((filter_size-1)/2)+1,j-int((filter_size-1)/2):j+int((filter_size-1)/2)+1],filter))
            
    return img_erode

#3*3滤波的一次腐蚀
img_erode = filter_erode(image_threshold,3)

plt.title("image_eorde(3*3_one_times)")
plt.imshow(img_erode,cmap="gray")
plt.show()

#3*3滤波的两次腐蚀
img_erode_2 = filter_erode(filter_erode(image_threshold,3),3)

plt.title("image_eorde(3*3_two_times)")
plt.imshow(img_erode_2,cmap="gray")
plt.show()

#9*9滤波的一次腐蚀
img_erode_3 = filter_erode(image_threshold,9)

plt.title("image_eorde(9*9_one_times)")
plt.imshow(img_erode_3,cmap="gray")
plt.show()

#9*9滤波的两次腐蚀
img_erode_4 = filter_erode(filter_erode(image_threshold,9),9)

plt.title("image_eorde(9*9_two_times)")
plt.imshow(img_erode_4,cmap="gray")
plt.show()

print(img_erode_4)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

[[1. 1. 1. ... 1. 1. 1.]
 [1. 1. 1. ... 1. 1. 1.]
 [1. 1. 1. ... 1. 1. 1.]
 ...
 [1. 1. 1. ... 1. 1. 1.]
 [1. 1. 1. ... 1. 1. 1.]
 [1. 1. 1. ... 1. 1. 1.]]

  尽管出现了虚影,但仍旧是二值化图像。


膨胀

import numpy as np
from PIL import Image
import matplotlib.pyplot as plt

#步骤一:获取图像的灰度直方图数据

#读取图像数据
img = Image.open("TIGA.jpg")

plt.title("image_origin")
plt.imshow(img,cmap="brg")
plt.show()

#将图像数据转化成numpy类型的数组
img_arr = np.array(img)

#将图像转化成灰度图
image = img_arr[:,:,0] * 0.299 + img_arr[:,:,1] * 0.587 + img_arr[:,:,2] * 0.114
image = np.ceil(image)   #对数组数据向上取整

plt.title("image_gray")
plt.imshow(image,cmap="gray")
plt.show()

height,width = image.shape


# #生成图像的直方图数据
hist = np.zeros((256,1))
for i in range(height):
    for j in range(width):
        hist[int(image[i,j]),0] += 1

        
#步骤二:类间方差计算
        
#获取灰度级
grayscale = range(256)

#像素总数
num_pixels = height * width
        
#根据直方图数据计算灰度值的总和
total_gray = np.dot(hist[:,0],grayscale)

#计算整个图像的平均灰度值,以作为预设的灰度值阈值初值
m = total_gray / num_pixels  

#创建存储类间方差的数组(两个集合一共是由256种不同的阈值分割的,因此产生的类间方差也就有256种)
sigma_array = np.zeros(256)

#根据阈值处置生成两个集合(当然循环操作)
for T in range(256):
    num_G1 = np.sum(hist[:T,0])  #统计G1的像素数量
    sum_G1 = np.dot(hist[:T,0],range(T))   #统计G1的灰度值总和
    num_G2 = num_pixels - num_G1     #统计G2的像素数量
    sum_G2 = total_gray - sum_G1     #统计G2的灰度值总和
    
    P1 = num_G1 / num_pixels
    P2 = num_G2 / num_pixels
    
    #分别求两个集合的平均灰度(记得一定要取整)
    m1 = (sum_G1 / num_G1) if  num_G1 > 0 else 0
    m2 = (sum_G2 / num_G2) if  num_G2 > 0 else 0
    
    #计算当前迭代所用阈值得到的类间方差
    sigma_array[T] = P1 * (m1 - m) ** 2  + P2 * (m2 - m) ** 2

#步骤三:根据上一步骤得到的类间方差数组,找寻最大类间方差对应的阈值,作为最优阈值。
max = np.max(sigma_array)
max_index = np.argmax(sigma_array)    # numpy.argmax()  Returns the indices of the maximum values along an axis.

T = max_index

print("使用的Otsu后的全局最优阈值:" + str(T))

#步骤四:阈值处理

#创建阈值处理后的新图像
image_threshold = np.zeros((height,width))
for i in range(height):
    for j in range(width):
        if image[i,j] < T:
            image_threshold[i,j] = 0
        else:
            image_threshold[i,j] = 255

plt.title("image_threshold_total_Ostu")
plt.imshow(image_threshold,cmap="gray")
plt.show()

#步骤五:膨化

#滤波运算法进行膨化
def filter_dilate(img,filter_size):
    #获取原图高和宽
    height,width = img.shape
    
    #根据原图大小创建新图
    img_dilate = np.ones((height,width))
    
    #根据参数filter_size,即滤波核大小,创建滤波器
    filter = np.ones((filter_size,filter_size))
    
    #新图像最外围的((filter_size - 1) / 2)圈不赋值,默认都是1就行。
    for i in range(int((filter_size-1)/2),height-int((filter_size-1)/2)):
        for j in range(int((filter_size-1)/2),width-int((filter_size-1)/2)):
            img_dilate[i][j] = np.max(np.dot(img[i-int((filter_size-1)/2):i+int((filter_size-1)/2)+1,j-int((filter_size-1)/2):j+int((filter_size-1)/2)+1],filter))
            
    return img_dilate

#3*3滤波的一次腐蚀
img_dilate = filter_dilate(image_threshold,3)

plt.title("image_dilate(3*3_one_times)")
plt.imshow(img_dilate,cmap="gray")
plt.show()

#3*3滤波的两次腐蚀
img_dilate_2 = filter_dilate(filter_dilate(image_threshold,3),3)

plt.title("image_dilate(3*3_two_times)")
plt.imshow(img_dilate_2,cmap="gray")
plt.show()

#9*9滤波的一次腐蚀
img_dilate_3 = filter_dilate(image_threshold,9)

plt.title("image_dilate(9*9_one_times)")
plt.imshow(img_dilate_3,cmap="gray")
plt.show()

#9*9滤波的两次腐蚀
img_dilate_4 = filter_dilate(filter_dilate(image_threshold,9),9)

plt.title("image_dilate(9*9_two_times)")
plt.imshow(img_dilate_4,cmap="gray")
plt.show()

print(img_dilate_4)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

[[1. 1. 1. ... 1. 1. 1.]
 [1. 1. 1. ... 1. 1. 1.]
 [1. 1. 1. ... 1. 1. 1.]
 ...
 [1. 1. 1. ... 1. 1. 1.]
 [1. 1. 1. ... 1. 1. 1.]
 [1. 1. 1. ... 1. 1. 1.]]

结语

  尤其是 9 × 9 9\times9 9×9的滤波,最为明显,我们会发现腐蚀之后的图像是黑色区域较多,膨胀之后的图像是白色区域较多。

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cherry Yuan

再多的奖励也换不回失去的头发

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值