[学习笔记] MRF 入门
MRF马尔可夫随机场入门
Intro
MRF是一种广泛应用于图像分割的模型,当然我看到MRF的时候并不是因为分割,而是在图像生成领域,有的paper利用MRF模型来生成图像,因此入门一下MRF,并以分割模型为例记一下代码。
Model
Target
在图像分割中,我们的任务是给定一张图像,输出每个像素的标签。因此我们就是要得到在给定图片特征之下,标签概率最大化时所对应的标签。
因此可以这么建模:
\]
其中w表示标签,f表示图像特征,求最大后验概率。
根据贝叶斯理论,上式右边可以写成:
\]
其中,P(f)是常量,因为当一张图片确定之后,P(f)便确定了。因此,上式只取决于分子部分。分子又可以表达为\(P(f,\omega)\),所以我们直接建模的其实是这个部分,计算的也是这个部分,这是与CRF不同的一点(MRF是直接对左边建模,不分解为右边,所以没个样本都要算一遍后验概率,然后乘起来最大化,MRF其实是通过对等式右边分子建模"曲线救国")。
因此,我们的任务中只需要对分子的两个部分进行定义即可。
Neighbors
像素Neighbors的定义很简单,就是这个像素周围的其他像素。
举例而言,下图分别是中心点像素的四邻域和八邻域。
Hammersley-Clifford Theorem
定理的内容为:
如果一个分布\(P(x)>0\)满足无向图\(G\)中的局部马尔可夫性质,当且仅当\(P(x)\)可以表示为一系列定义在最大团上的非负函数的乘积形式,即:
\]
其中\(C\)为\(G\)中最大团集合,也就是所有的最大团组成的集合,\(\phi(x_c) \ge 0\)是定义在团\(c\)上的势能函数,Z是配分函数,用来将乘积归一化为概率的形式。
\]
无向图模型与有向图模型的一个重要区别就是配分函数Z。
Hammersley-Clifford Theorem表明,无向图模型和吉布斯分布是一致的,所以将\(P(\omega)\)定义下式:
\]
其中,Z作为normalization项,\(Z = \sum exp(-U(\omega))\),U定义为势能,而等号最右边将U变成了V的求和,在后面我们会说到,这里其实是每个原子团的势能的求和。
Clique
Clique就是我们上面提到的“团”的概念。集合\(c\)是\(S\)的原子团当且仅当c中的每个元素都与该集合中的其他元素相邻。那么Clique就是所有\(c\)的并集。
\]
举例而言:
一个像素的四邻域及他自己组成的集合的原子团可以分为singleton和doubleton如图所示。
Clique Potential
翻译过来就是势能,用\(V(w)\)表示,描述的是一个Clique的能量。
那么,一个像素的领域的势能就是每个团的能量的和。
\]
其中c表示原子团,c表示Clique,V是如何定义的呢?
在图像分割中,可以以一阶团为例,
\]
到这里,\(P(\omega)\)的所有变量解释完了,下一步是计算\(P(f|\omega)\)
\(P(f|\omega)\)的计算
\(P(f|\omega)\)被认为是服从高斯分布的,也就是说,如果我们知道了这个像素的标签是什么,那么他的像素值应该服从这个标签下的条件概率的高斯分布。其实他服从高斯分布还是很好理解的,我们已知这个像素点的label比如说是A,那么我们去统计一下所有标签是A的点的像素值的均值和方差,显然以这个均值和方差为参数的高斯分布更加契合这里的条件分布。
\]
计算每个类别的像素均值和方差,带入公式,即得条件概率。
最后,就是最大化\(P(\omega)P(f|\omega)\),以对数形式转化为求和的形式去优化,最大化\(log(P(\omega)) + log(P(f|\omega))\).
Coding
import numpy as np
import cv2 as cv
import copy
class MRF():
def __init__(self,img,max_iter = 100,num_clusters = 5,init_func = None,beta = 8e-4):
self.max_iter = max_iter
self.kernels = np.zeros(shape = (8,3,3))
self.beta = beta
self.num_clusters = num_clusters
for i in range(9):
if i < 4:
self.kernels[i,i//3,i%3] = 1
elif i > 4:
self.kernels[i-1,i//3,i%3] = 1
self.img = img
if init_func is None:
self.labels = np.random.randint(low = 1,high = num_clusters + 1,size = img.shape,dtype = np.uint8)
def __call__(self):
img = self.img.reshape((-1,))
for iter in range(self.max_iter):
p1 = np.zeros(shape = (self.num_clusters,self.img.shape[0] * self.img.shape[1]))
for cluster_idx in range(self.num_clusters):
temp = np.zeros(shape = (self.img.shape))
for i in range(8):
res = cv.filter2D(self.labels,-1,self.kernels[i,:,:])
temp[(res == (cluster_idx + 1))] -= self.beta
temp[(res != (cluster_idx + 1))] += self.beta
temp = np.exp(-temp)
p1[cluster_idx,:] = temp.reshape((-1,))
p1 = p1 / np.sum(p1)
p1[p1 == 0] = 1e-3
mu = np.zeros(shape = (self.num_clusters,))
sigma = np.zeros(shape = (self.num_clusters,))
for i in range(self.num_clusters):
#mu[i] = np.mean(self.img[self.labels == (i+1)])
data = self.img[self.labels == (i+1)]
if np.sum(data) > 0:
mu[i] = np.mean(data)
sigma[i] = np.var(data)
else:
mu[i]= 0
sigma[i] = 1
#print(sigma[i])
#sigma[sigma == 0] = 1e-3
p2 = np.zeros(shape = (self.num_clusters,self.img.shape[0] * self.img.shape[1]))
for i in range(self.img.shape[0] * self.img.shape[1]):
for j in range(self.num_clusters):
#print(sigma[j])
p2[j,i] = -np.log(np.sqrt(2*np.pi)*sigma[j]) -(img[i]-mu[j])**2/2/sigma[j];
self.labels = np.argmax(np.log(p1) + p2,axis = 0) + 1
self.labels = np.reshape(self.labels,self.img.shape).astype(np.uint8)
print("-----------start-----------")
print(p1)
print("-" * 20)
print(p2)
print("----------end------------")
#print("iter {} over!".format(iter))
#self.show()
#print(self.labels)
def show(self):
h,w = self.img.shape
show_img = np.zeros(shape = (h,w,3),dtype = np.uint8)
show_img[self.labels == 1,:] = (0,255,255)
show_img[self.labels == 2,:] = (220,20,60)
show_img[self.labels == 3,:] = (65,105,225)
show_img[self.labels == 4,:] = (50,205,50)
#img = self.labels / (self.num_clusters) * 255
cv.imshow("res",show_img)
cv.waitKey(0)
if __name__ == "__main__":
img = cv.imread("/home/xueaoru/图片/0.jpg")
img = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
img = img/255.
#img = np.random.rand(64,64)
#img = cv.resize(img,(256,256))
mrf = MRF(img = img,max_iter = 20,num_clusters = 2)
mrf()
mrf.show()
#print(mrf.kernels)
Input:
Output(num_clusters = 4):
Output(num_clusters = 2):
[学习笔记] MRF 入门的更多相关文章
- python学习笔记--Django入门四 管理站点--二
接上一节 python学习笔记--Django入门四 管理站点 设置字段可选 编辑Book模块在email字段上加上blank=True,指定email字段为可选,代码如下: class Autho ...
- WebSocket学习笔记——无痛入门
WebSocket学习笔记——无痛入门 标签: websocket 2014-04-09 22:05 4987人阅读 评论(1) 收藏 举报 分类: 物联网学习笔记(37) 版权声明:本文为博主原 ...
- Java学习笔记之---入门
Java学习笔记之---入门 一. 为什么要在众多的编程语言中选择Java? java是一种纯面向对象的编程语言 java学习起来比较简单,适合初学者使用 java可以跨平台,即在Windows操作系 ...
- DBFlow框架的学习笔记之入门
什么是DBFlow? dbflow是一款android高性的ORM数据库.可以使用在进行项目中有关数据库的操作.github下载源码 1.环境配置 先导入 apt plugin库到你的classpat ...
- MongoDB学习笔记:快速入门
MongoDB学习笔记:快速入门 一.MongoDB 简介 MongoDB 是由C++语言编写的,是一个基于分布式文件存储的开源数据库系统.在高负载的情况下,添加更多的节点,可以保证服务器性能.M ...
- 学习笔记_J2EE_SpringMVC_01_入门
1. 概述 笔者作为一个不太正经的不专业佛教信仰者,习惯了解事物的因果关系,所以概述就有点BBB...了.如果不喜欢这些的,请自行跳过概述章节,直接进入第二章的操作实践:2 入门示例. 1.1. ...
- dubbo入门学习笔记之入门demo(基于普通maven项目)
注:本笔记接dubbo入门学习笔记之环境准备继续记录; (四)开发服务提供者和消费者并让他们在启动时分别向注册中心注册和订阅服务 需求:订单服务中初始化订单功能需要调用用户服务的获取用户信息的接口(订 ...
- SpringBoot学习笔记<一>入门与基本配置
毕业实习项目技术学习笔记 参考文献 学习视频 2小时学会Spring Boot:https://www.imooc.com/learn/767 学习资料 SpringBoot入门:https://bl ...
- [学习笔记]SiftGPU入门
当有读者看到我这篇SiftGPU入门的学习笔记时,相信你已经读过了高博那篇<SLAM拾萃:SiftGPU>,那篇文章写于16年,已经过去两年的时间.在我尝试配置SiftGPU的环境时,遇到 ...
随机推荐
- ActiveMQ基础简介
1. 什么是ActiveMQ ActiveMQ 是Apache出品,最流行的,能力强劲的开源消息总线.ActiveMQ 是一个完全支持JMS1.1和J2EE 1.4规范的 JMS Provider实现 ...
- C++虚函数和纯虚函数的用法和区别
C++虚函数与纯虚函数用法与区别(转) 1. 虚函数和纯虚函数可以定义在同一个类(class)中,含有纯虚函数的类被称为抽象类(abstract class),而只含有虚函数的类(class)不能 ...
- -sh: ./a.out: not found
感觉程序没有问题,编译生成a.out后,拷贝到开发板执行,提示 -sh: ./a.out: not found. 上网查找问题,大概原因有2个 一就是有可能/lib下面没有C库 就是没有glibc或者 ...
- cpp编码规范要求
1.所有头文件使用#ifndef #define #endif来防止文件被多重包含,命名格式当是: <PROJECT>_<PATH>_<FILE>_H_ 2.只有当 ...
- java-接口—策略模式
策略模式,就是不同类继承相同的接口,实现不同的策略.
- 腾讯数据安全专家谈联邦学习开源项目FATE:通往隐私保护理想未来的桥梁
数据孤岛.数据隐私以及数据安全,是目前人工智能和云计算在大规模产业化应用过程中绕不开的“三座大山”. “联邦学习”作为新一代的人工智能算法,能在数据不出本地的情况下,实现共同建模,提升AI模型的效果, ...
- MyBatis中<![CDATA[ ]]>的使用
原文地址:https://www.cnblogs.com/catgatp/p/6403382.html <![CDATA[]]>和转义字符 被<![CDATA[]]>这个标记所 ...
- 第二章 Vue快速入门--8 v-bind指令的学习
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8&quo ...
- VUE-文本-事件-属性指令
一.Vue文本指令 文本指令: 1.{{ }} 2.v-text:不能解析html语法的文本,会原样输出 3.v-html:能解析html语法的文本 4.v-once:处理的标签的内容只能被解析一次 ...
- Codeforces Round #427 (Div. 2) [ C. Star sky ] [ D. Palindromic characteristics ] [ E. The penguin's game ]
本来准备好好打一场的,然而无奈腹痛只能带星号参加 (我才不是怕被打爆呢!) PROBLEM C - Star sky 题 OvO http://codeforces.com/contest/835/p ...