前言
本文所涉是笔者模式识别课的第一次大作业——用朴素贝叶斯来做nemo鱼图像区域分割。它是用贝叶斯来做二元分类的简单实践,适合用来做贝叶斯算法入门,现将简要理论和笔者所写代码放在这里,供大家参考。不知道有没有朋友有疑问,明明是图像区域分割,怎么又和二元分类扯上了关系,其实逐像素的图像分割,就是在做分类。当然,这里的分割不是指复杂的语义分割,只是简单的根据灰度或者颜色分布来做区域分割。
贝叶斯理论:机器学习十大经典算法:深入浅出聊贝叶斯决策
任务与数据
图像fish.bmp
与掩膜mask.mat
,掩膜点乘图像,即可获得待分割区域ROI。小鱼区域主要有两种类型的区域,以下就是要用朴素贝叶斯把这两个部分分出来——用不同的颜色表示不同区域。
训练数据sample.mat
,它是一个二维的matlab数组,第一列为灰度值,第2-4列为RGB值,第五列为当前灰度值或者RGB值对应的类别标签(1,-1)。它蕴含着两种类型区域的灰度值或者RGB值的分布,根据它来估计两种类型区域的类概率密度函数的参数。
任务1:对训练数据用极大似然,估计出两类区域灰度值的概率密度函数,并用最小错误贝叶斯对fish.bmp
ROI灰度图像进行分割。
任务2:对训练数据用极大似然,估计出两类区域RGB值的概率密度函数,并用最小错误贝叶斯对fish.bmp
ROI彩色图像进行分割。
理论与实现
统计模型的训练过程就是类条件概率密度函数参数的估计过程。通过参数估计方法,从训练样本中估计出参数,便完成了训练。测试或者说应用过程就是用估计出的类概率密度函数和代表类别占比的先验概率进行统计决策或者分类的过程。最大似然是常用的参数估计方法,用在高斯混合模型(GMM)中。
假定我们面对的就是一个高斯混合模型(GMM),即每个类别训练样本的灰度值或者RGB值均服从正态分布,正态分布含有两个参数,均值方差或者均值协方差。
我们知道,极大似然的目的是要找到最可能产生该样本序列的概率密度函数的参数。而在某概率密度函数参数下产生该样本序列的概率如式(1),即似然函数。
当每个样本都独立同分布(iid)时,对应的贝叶斯决策即为朴素贝叶斯。则式(1)便可以化为概率连乘的形式,如式(2),
两边同取自然对数后,用导数工具可以求出其极大值点,即极大似然。在高斯混合模型的情况下,某个样本序列似然函数的极值点的解析解为:
一维情况:对应灰度值。
多维情况:三维时对应RGB值
由以上4个式子,我们可以看出。我们习以为然的求均值和方差的公式,其实是在默认中央极限定理的前提下,用最大似然估计的结果。
copyright ©意疏:https://blog.csdn.net/sinat_35907936/article/details/109167111
由机器学习十大经典算法:深入浅出聊贝叶斯决策,我们可以知道,在给类别地位均等时,采用最小错误率或者最大后验概率贝叶斯决策即可。只比较分子,即下式,便可得出决策——选两类中结果较大者为决策结果。
算法流程如下图所示,前半部分时统计模型的训练过程,即用最大似然(MLE)进行参数估计。测试过程,就是用决策的过程,图中为为Nemo鱼逐像素做灰度或者颜色决策或者分割的过程。PDF为scipy包中包含的正态分布PDF函数,只需给其参数和输入即可得到输出值。
数据加载与解析。python可以通过scipy模块读取matlab文件。matlab文件读入后是以字典的形式展现的。
from scipy import io
from scipy.stats import norm
import numpy as np
import PIL.Image as Image
import matplotlib.pyplot as plt
from scipy.stats import multivariate_normal
# 数据加载与解析
mask = io.loadmat('mask.mat')['Mask'] # 数据为一个字典,根据key提取数据
sample = io.loadmat('sample.mat')['array_sample']
src_image = Image.open('fish.bmp')
RGB_img = np.array(src_image)
Gray_img = np.array(src_image.convert('L'))
# 根据Mask,获取ROI区域
Gray_ROI = (Gray_img * mask)/255
RGB_mask = np.array([mask, mask, mask]).transpose(1, 2, 0)
RGB_ROI = (RGB_img * RGB_mask)/255
# 根据标签拆分数据
gray1 = []
gray2 = []
RGB1 = []
RGB2 = []
for i in range(len(sample)):
if(sample[i][4]) == 1.: # 数据第5位为标签
gray1.append(sample[i][0])
RGB1.append(sample[i][1:4])
else:
gray2.append(sample[i][0])
RGB2.append(sample[i][1:4])
RGB1 = np.array(RGB1)
RGB2 = np.array(RGB2)
计算先验概率。先验概率可以通过样本中各类别的占比得来。也可以通过各类别在世界中的占比而来。
# 计算两类在数据中的占比,即先验概率
P_pre1 = len(gray1)/len(sample)
P_pre2 = 1-P_pre1
一维贝叶斯决策,计算一维输入时贝叶斯后验概率。
# 一维时,贝叶斯
# ------------------------------------------------------------------------------------#
# 数据为一维时(灰度图像),用最大似然估计两个类别条件概率pdf的参数——标准差与均值
gray1_m = np.mean(gray1)
gray1_s = np.std(gray1)
gray2_m = np.mean(gray2)
gray2_s = np.std(gray2)
# print(gray1_s, gray2_s)
# 绘制最大似然估计出的类条件pdf
x = np.arange(0, 1, 1/1000)
gray1_pdf = norm.pdf(x, gray1_m, gray1_s)
gray2_pdf = norm.pdf(x, gray2_m, gray2_s)
plt.figure(0)
ax = plt.subplot(2, 1, 1)
ax.set_title('p(x|w)')
ax.plot(x, gray1_pdf, 'r', x, gray2_pdf, 'b')
ax.set_xlabel('x')
ax.set_ylabel('f(x)')
ax1 = plt.subplot(2, 1, 2)
ax1.plot(x, P_pre1*gray1_pdf, 'r', x, P_pre2*gray2_pdf, 'b')
ax1.set_title('p(w)*p(x|w)')
ax1.set_xlabel('x')
ax1.set_ylabel('f(x)')
# 用最大后验贝叶斯对灰度图像进行分割
gray_out = np.zeros_like(Gray_img)
for i in range(len(Gray_ROI)):
for j in range(len(Gray_ROI[0])):
if Gray_ROI[i][j] == 0:
continue
elif P_pre1*norm.pdf(Gray_ROI[i][j], gray1_m, gray1_s) > P_pre2*norm.pdf(Gray_ROI[i][j], gray2_m, gray2_s): # 贝叶斯公式分子比较
gray_out[i][j] = 100
else:
gray_out[i][j] = 255
# plt.imshow(RGB_ROI)
plt.figure(1)
bx = plt.subplot(1, 1, 1)
bx.set_title('gray ROI')
bx.imshow(Gray_ROI, cmap='gray')
plt.figure(2)
bx1 = plt.subplot(1, 1, 1)
bx1.set_title('gray segment result')
bx1.imshow(gray_out, cmap='gray')
分割结果:
copyright ©意疏:https://blog.csdn.net/sinat_35907936/article/details/109167111
三维贝叶斯决策,计算三维输入时的贝叶斯后验概率。
# 三维时,贝叶斯
# ------------------------------------------------------------------------------------#
# 数据为三维时(彩色图像),用最大似然估计两个类别条件概率pdf的参数——协方差与均值
RGB1_m = np.mean(RGB1, axis=0)
RGB2_m = np.mean(RGB2, axis=0)
cov_sum1 = np.zeros((3, 3))
cov_sum2 = np.zeros((3, 3))
for i in range(len(RGB1)):
# print((RGB1[i]-RGB1_m).reshape(3, 1))
cov_sum1 = cov_sum1 + np.dot((RGB1[i]-RGB1_m).reshape(3, 1), (RGB1[i]-RGB1_m).reshape(1, 3))
for i in range(len(RGB2)):
cov_sum2 = cov_sum2 + np.dot((RGB2[i]-RGB2_m).reshape(3, 1), (RGB2[i]-RGB2_m).reshape(1, 3))
RGB1_cov = cov_sum1/(len(RGB1)-1) # 无偏估计除以N-1
RGB2_cov = cov_sum2/(len(RGB2)-1)
xx = np.array([x, x, x])
# print(P_pre1*multivariate_normal.pdf(RGB1, RGB1_m, RGB1_cov))
# 用最大后验贝叶斯对彩色图像进行分割
RGB_out = np.zeros_like(RGB_ROI)
for i in range(len(RGB_ROI)):
for j in range(len(RGB_ROI[0])):
if np.sum(RGB_ROI[i][j]) == 0:
continue
elif P_pre1*multivariate_normal.pdf(RGB_ROI[i][j], RGB1_m, RGB1_cov) > P_pre2*multivariate_normal.pdf(RGB_ROI[i][j], RGB2_m, RGB2_cov): # 贝叶斯公式分子比较
RGB_out[i][j] = [255, 0, 0]
else:
RGB_out[i][j] = [0, 255, 0]
# print(RGB_ROI.shape)
# 显示RGB ROI,与彩色分割结果
plt.figure(3)
cx = plt.subplot(1, 1, 1)
cx.set_title('RGB ROI')
cx.imshow(RGB_ROI)
plt.figure(4)
cx1 = plt.subplot(1, 1, 1)
cx1.set_title('RGB segment result')
cx1.imshow(RGB_out)
plt.show()
分割结果:
copyright ©意疏:https://blog.csdn.net/sinat_35907936/article/details/109167111
参考
张学工.模式识别(第三版).M.清华大学出版社.2010.
来源:oschina
链接:https://my.oschina.net/u/4417917/blog/4683953