马尔可夫随机场的python实现

       前几天看图网络的时候,不知怎么从贝叶斯网络突然跳到了马尔科夫随机场,感觉还有点意思,不过还是没有完全理清其中的逻辑,网上讲的比较乱,参考博主on2way这篇博文《从贝叶斯理论到图像马尔科夫随机场》我梳理了一下思路,找时间总结一下,先挖一个坑吧,由于博主给出的是matlab实现,我本身不怎么使用matlab,于是就简单的用python复现了一下思路,由于没有使用kmeans算法初始化,结果差距比较明显,但是还算不错,其中应该是有一些问题,包括最后多分类的接口没有调好,还有四分类显示结果貌似不太对,由于后天要考英语今天看来是没法调完了,依旧是放着这个坑,有时间的时候代码改一下,以下是python3的代码,直接用jupyter notebook写的:

import numpy as np
import cv2
import copy
from scipy.stats import norm
import matplotlib as plot

img = cv2.imread('Lena.jpeg',0)
cluster_num = 4
maxiter = 50
#随机初始化标签
label = np.random.randint(0,cluster_num,img.shape)

def cal_pp(label):
    result = np.zeros((cluster_num, 8, label.shape[0], label.shape[1]))
    statis_result = np.zeros((cluster_num, label.shape[0], label.shape[1]))
    for i in range(cluster_num):
        label_temp = copy.deepcopy(label)
        #先设置为4再设置为0,防止处理0时出错
        label_temp[label_temp!=i] = 4
        label_temp[label_temp==i] = 1
        label_temp[label_temp==4] = 0
        #根据label_temp可以计算出8个方向的标签
        #从左上角起顺时针方向,依次为0-8
        result[i][0][:,0] = 0
        result[i][0][0,:] = 0
        result[i][0][1:,1:] = label_temp[:-1,:-1]
        result[i][1][:,0] = 0
        result[i][1][1:,:] = label_temp[:-1,:]
        result[i][2][:,0] = 0
        result[i][2][0,:] = 0
        result[i][2][1:,1:] = label_temp[1:,:-1]
        result[i][3][:,0] = 0
        result[i][3][:,1:] = label_temp[:,:-1]
        result[i][4][:,-1] = 0
        result[i][4][:,:-1] = label_temp[:,1:]
        result[i][5][:,0] = 0
        result[i][5][-1,:] = 0
        result[i][5][1:,:-1] = label_temp[1:,:-1]
        result[i][6][-1,:] = 0
        result[i][6][:-1,:] = label_temp[1:,:]
        result[i][7][:,-1] = 0
        result[i][7][-1,:] = 0
        result[i][7][:-1,:-1] = label_temp[1:,1:]
        statis_result[i] = result[i][0]+result[i][1]+result[i][2]+result[i][3]+result[i][4]+result[i][5]+result[i][6]+result[i][7]
    statis_result = np.array(statis_result,dtype=np.float) / 8
    #防止出现0,原因不清楚
    statis_result[statis_result==0] = 0.001
    return statis_result

def cal_lf(img, label):
    result = np.zeros((cluster_num, 8, label.shape[0], label.shape[1]))
    distribution_parameter = np.zeros((cluster_num,2),np.float)
    for i in range(cluster_num):
        img_temp = copy.deepcopy(img)
        img_temp[label!=i] = 0
        #根据原图灰度统计每一个标签的分布和方差
        img_list = img_temp.tolist()
        img_list = [item for sublist in img_list for item in sublist if item!= 0]
        #再根据原图的灰度数值算出似然函数值
        distribution_parameter[i][0] = np.mean(img_list)
        distribution_parameter[i][1] = np.std(img_list)
    #计算每一点属于不同类型的概率
    result_lf = np.zeros((cluster_num,label.shape[0],label.shape[1]),np.float)
    for i in range(cluster_num):
        result_lf[i] = norm(distribution_parameter[i][0],distribution_parameter[i][1]).pdf(img)
    return result_lf

def update_label(img, init_label, maxiter):
    label = init_label
    for i in range(maxiter):
        prior_probability = cal_pp(label)
        likelihood = cal_lf(img,label)
        probability = np.zeros((cluster_num,label.shape[0],label.shape[1]))
        for j in range(cluster_num):
            probability[j] = prior_probability[j]*likelihood[j]
        #根据概率值更新label
        max_probability = probability.max(0)
        #label_one不需要,这一部分代码需要做一下调整,时间紧迫先演示一下
        label_two = probability[1]-max_probability
        label_two[label_two!=0] = 4
        label_two[label_two==0] = 1
        label_two[label_two==4] = 0
        label_three = probability[2]-max_probability
        label_three[label_three!=0] = 4
        label_three[label_three==0] = 2
        label_three[label_three==4] = 0
        label_four = probability[3]-max_probability
        label_four[label_four!=0] = 4
        label_four[label_four==0] = 3
        label_four[label_four==4] = 0
        label= label_two + label_three + label_four
        #每次绘制一张图片
        cv2.imshow("test",label)
        cv2.waitKey(500)
        cv2.destroyAllWindows()
    return label

#main函数中运行,博主使用jupyter notebook就没有改了,请需要的自行改一下
final = update_label(img,label,maxiter)

原图放这里供大家下载使用:

贴一下大致效果:
其中前两排是第1-8次迭代结果,最后一排是第12、16、20、24次迭代结果,效果还行

  • 1
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
马尔机场(Markov Random Field,MRF)是一种表示联合分布的概率图模型,其基本原理是基于概率分布的马尔性质,即当前状态只与其相邻的状态有关。它广泛应用于自然语言处理、计算机视觉、运筹学、图像处理和生物医学等领域。 在Python中,我们可以使用许多开源工具来建立和分析马尔机场模型。其中,最为经典的是PyMC3库和图形模型工具箱(Python Graphical Model Toolbox,pyGM)。PyMC3是一个建立贝叶斯统计模型的Python库,支持误差分布、后验分布、概率分布和随机变量等相关操作。它可以用来建立MRF模型,并使用蒙特卡罗马尔链(Monte Carlo Markov Chain,MCMC)采样方法对模型进行参数估计和推断。PyGM是一个专门用于图形模型编程的Python库,支持多种概率图模型,包括贝叶斯网络、马尔网络、隐马尔模型和因子图等。用户可以用PyGM建立和分析MRF模型,并通过LBP、VMP、MP、Gibbs Sampling、Structural EM等算法进行推断。 除了这些库之外,我们还可以使用Gibbs采样或Metropolis-Hastings算法等其它蒙特卡罗方法直接从MRF概率分布中抽样。这些算法可以用于发现概率分布的样式、特征、相关项和相关性等信息,从而提高模型精度和预测准确率。 总之,Python是一个功能强大的MRF模型建立和分析的工具,具有广泛的应用领域和丰富的编程库和算法支持。通过选择适当的库和算法,用户可以在Python上建立高效的MRF模型,并进行鲁棒性测试、参数估计和预测分析等操作。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值