前言
我们选择对全局二值化后的图像进行腐蚀、膨胀操作。
腐蚀与膨胀类似于滤波算法,只不过腐蚀的滤波运算结果是二值图像某一邻域内的最小值,也可理解为该邻域内像素的相与运算结果。膨胀的滤波运算结果是二值化图像某一邻域内的最大值,即该邻域内像素的或运算结果。
腐蚀
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的滤波,最为明显,我们会发现腐蚀之后的图像是黑色区域较多,膨胀之后的图像是白色区域较多。