参考:https://github.com/lucasb-eyer/pydensecrf

1.使用

对于图像来说,最简单的使用该库的方法是使用DenseCRF2D类:

  1. import numpy as np
  2. import pydensecrf.densecrf as dcrf
  3.  
  4. d = dcrf.DenseCRF2D(, , ) # width, height, nlabels

2.一元势 Unary potential

你可以使用下面的方法设置固定的一元势

一元势即网络预测得到的结果,进行-np.log(py)等操作

  1. U = np.array(...) # Get the unary in some way.
  2. print(U.shape) # -> (, , )
  3. print(U.dtype) # -> dtype('float32')
  4. U = U.reshape((,-)) # Needs to be flat.
  5. d.setUnaryEnergy(U)
  6.  
  7. # Or alternatively: d.setUnary(ConstUnary(U))

记住U应该是负的log概率,所以如果你用概率py,别忘了执行U = -np.log(py)

需要在一元势上进行reshape是我想要修复的API缺陷,但是如果不引入对numpy的显式依赖,我不知道如何解决这个问题。

注意,nlabel维度是这里reshape之前的第一个维度;如果不是这样的话,你可能需要在reshape之前把nlabel移到前面,即U.shape的结果应该为(5, 480, 640),就像这样:

  1. print(U.shape) # -> (, , )
  2. U = U.transpose(, , ).reshape((,-))

1)Getting a Unary

得到 unary potentials有两种常见的方法:
1)由人类或其他过程产生的硬标签。该方法由from pydensecrf.utils import unary_from_labels实现
2)由概率分布计算得到,例如深度网络的softmax输出。即我们之前先对图片使用训练好的网络预测得到最终经过softmax函数得到的分类结果,这里需要将这个结果转成一元势

对此,请参阅from pydensecrf.utils import unary_from_softmax

1)unary_from_labels(labels, n_labels, gt_prob, zero_unsure=True)函数的使用

简单分类器,该分类器50%确定注释(即从训练好的网络预测img后得到的结果)是正确的。(与推理示例中相同)。

参数:

  • labels: numpy.array;标签label映射,即数据的形状的数组,其中每个唯一值对应于一个标签,一种像素值对应一种标签。
  • n_labels: int;标签的总数。如果' zero_unsure'参数为True(默认值),这个数字不应该包括' 0 '标签,因为' 0 '不是一个标签!
  • gt_prob: float;基本事实的确定性(必须在(0,1)之内)。
  • zero_unsure: bool;如果“True”,则将标签值“0”视为“可能是任何东西”,即具有此值的项将得到一致的一元概率,不将其当作标签。如果“False”,不要特别对待值“0”,而是像对待任何其他类一样对待它。

2)unary_from_softmax(sm, scale=None, clip=1e-5)函数的使用

将softmax类概率转换为一元势(每个节点的NLL)。

即我们之前先对图片使用训练好的网络预测得到最终经过softmax函数得到的分类结果,这里需要将这个结果转成一元势
参数

  • sm: numpy.array ,第一个维度是类的softmax的输出,其他所有维度都是flattend。这意味着“sm.shape[0] == n_classes”。
  • scale: float,softmax输出的确定性(默认为None),需要值在(0,1]。如果不为None,则softmax输出被缩放到从[0,scale]概率的范围。
  • clip: float,将概率裁剪到的最小值。这是因为一元函数是概率的负对数,而log(0) = inf,所以我们需要把0概率裁剪成正的值。

在这里因为scale=None,clip=None,所以这个函数的作用其实只进行了下面的操作:

  1. -np.log(sm).reshape([num_cls, -1]).astype(np.float32)

构建好一元势后需要调用:

  1. d.setUnaryEnergy(U)

将该一元势添加到CRF中

3.Pairwise potentials(二元势)

二维情况下,增加最常见的二元势有两种实用方法:

二元势即用于描述像素点和像素点之间的关系,鼓励相似像素分配相同的标签,而相差较大的像素分配不同的标签。这个相似的定义与颜色值srgb和实际相对距离sxy相关,所以CRF能够使图片尽量在边界处分割。

  • d.addPairwiseGaussian这个函数创建的是颜色无关特征,这里只有位置特征(只有参数实际相对距离sxy),并添加到CRF中
  • d.addPairwiseBilateral这个函数根据原始图像img创建颜色相关和位置相关特征并添加到CRF中,特征为(x,y,r,g,b)
  1. # This adds the color-independent term, features are the locations only.
  2. d.addPairwiseGaussian(sxy=(,), compat=, kernel=dcrf.DIAG_KERNEL, normalization=dcrf.NORMALIZE_SYMMETRIC)
  3.  
  4. # This adds the color-dependent term, i.e. features are (x,y,r,g,b).
  5. # im is an image-array, e.g. im.dtype == np.uint8 and im.shape == (,,)
  6. d.addPairwiseBilateral(sxy=(,), srgb=(,,), rgbim=im, compat=, kernel=dcrf.DIAG_KERNEL, normalization=dcrf.NORMALIZE_SYMMETRIC)

这两种方法都有快捷方式和默认参数,因此最常见的用例可以简化为:

  1. d.addPairwiseGaussian(sxy=, compat=)
  2. d.addPairwiseBilateral(sxy=, srgb=, rgbim=im, compat=)

im即image

参数映射到本文中的参数如下:高斯情况下的sxy为$\theta_{\gamma}$(即Θγ),双边情况下,sxy和srgb分别映射到$\theta_{\alpha}$(即Θα)和$\theta_{\beta}$(即ΘΒ)。names是“x/y标准偏差”(x/y standard-deviation,sxy)和“rgb标准偏差”(rgb standard-deviation,srgb)的简写,公式为:

 1)Non-RGB bilateral

一个重要的警告是,addPairwiseBilateral只适用于RGB图像,即三个通道。如果您的数据与这个简单但常见的情况不同,则需要使用util .create_pairwise_bilateral函数计算你自己的二元能源;有关详细信息,请参阅 generic non-2D case案例。

在examples文件夹中以笔记本的形式提供了一个example of working with Non-RGB data例子。

可见Example of DenseCRF with non-RGB data

2)Compatibilities

compat参数可以是以下任何一种:

  • 一个数字,然后使用PottsCompatibility。
  • 一个一维数组,然后使用对角兼容性。
  • 一个二维数组,然后使用矩阵兼容性。

这些是label-compatibilites µ(xi, xj)的参数可能学到的东西。例如,他们可以指出把鸟的像素误认为天空并不像把猫误认为天空那么糟糕。数组应该有nlabel或(nlabel,nlabel)作为shape和一个float32数据类型。

3)Kernels

kenel参数的可能值有:

  • CONST_KERNEL
  • DIAG_KERNEL (the default)
  • FULL_KERNEL
该参数指定内核的precision-matrixΛ(m),这可能是习得的。这些表示特征类型之间的相关性,默认值表示没有相关性。同样,这也是可以学习 learned的。
 

4)Normalizations

normalization参数可能的值为:
  • NO_NORMALIZATION
  • NORMALIZE_BEFORE
  • NORMALIZE_AFTER
  • NORMALIZE_SYMMETRIC (the default)

5)Kernel weight权重

到目前为止,我还没有找到设置内核权值w(m)的方法。根据本文,w(2)被设置为1,w(1)被交叉验证,但从未指定。
通过查看Philip的代码(包括在 pydensecrf/densecrf中),我没有找到这样显式的权重,我猜它们因此被硬编码为1。
 

4.Inference推理

所以将一元势和二元势结合起来就能够比较全面地去考量像素之间的关系,并得出优化后的结果
用5次迭代进行推理最简单的方法是:
  1. Q = d.inference()

然后MAP预测是:

  1. map = np.argmax(Q, axis=).reshape((,))

如果你对类概率Q感兴趣,你会注意到Q是一个包装好的特征矩阵。本项目的特征包装器实现缓冲接口,可以简单地转换为numpy数组,如下:

  1. proba = np.array(Q)

5.Step-by-step inference一步步推理

如果出于某种原因,你想手动运行推理循环,你可以这样做:

  1. Q, tmp1, tmp2 = d.startInference()
  2. for i in range():
  3. print("KL-divergence at {}: {}".format(i, d.klDivergence(Q)))
  4. d.stepInference(Q, tmp1, tmp2)

6.Generic non-2D

DenseCRF类可用于一般(非2d)denseCRFs。它的用法与上面完全一样,只是缺少了特定于2d的二元势addPairwiseGaussian和addPairwiseBilateral。

相反,您需要使用通用的addPairwiseEnergy方法,如下所示:

  1. d = dcrf.DenseCRF(, ) # npoints, nlabels
  2.  
  3. feats = np.array(...) # Get the pairwise features from somewhere.
  4. print(feats.shape) # -> (, ) = (feature dimensionality, npoints)
  5. print(feats.dtype) # -> dtype('float32')
  6.  
  7. dcrf.addPairwiseEnergy(feats)

此外,你还可以传递兼容性、内核参数和标准化参数,就像在二维高斯和双边情况下一样。

势函数计算为w*exp(-0.5 * |f_i - f_j|^2)。

当然,首先你要先使用create_pairwise_gaussian和create_pairwise_bilateral,然后才能使用addPairwiseEnergy

1.create_pairwise_gaussian(sdims, shape)函数的使用

创建二元高斯势的Util函数。这适用于所有的图像尺寸。对于2D例子,他等价于DenseCRF2D.addPairwiseGaussian的操作

参数:

  • sdims: list or tuple;每个维度的比例因子,等价于DenseCRF2D.addPairwiseGaussian中的sxy参数
  • shape: list or tuple;CRF的形状

2.create_pairwise_bilateral(sdims, schan, img, chdim=-1)

创造二元双边势的Util函数。这适用于所有的图像尺寸。对于2D例子,等价于DenseCRF2D.addPairwiseBilateral。

参数:

  • sdims: list or tuple;每个维度的比例因子。即DenseCRF2D.addPairwiseBilateral中的“sxy”
  • schan: list or tuple;图像中每个通道的比例因子。即DenseCRF2D.addPairwiseBilateral中的“srgb”参数
  • img: numpy.array;输入的图片
  • chdim: int, optional;这指定了通道维度在图像中的位置。例如,' chdim=2 '用于大小为(240,300,3)的RGB图像,指定维度值3放在索引2的位置处。如果图像没有通道尺寸(例如只有一个通道),则使用' chdim=-1 '
举例
inference.py中的non-2d的写法:
  1. d = dcrf.DenseCRF(img.shape[] * img.shape[], n_labels)
  2.  
  3. # get unary potentials (neg log probability)
  4. # 得到一元势(即去负对数),labels为对所有像素值标注label后的数组,label类型n_labels=,
  5. U = unary_from_labels(labels, n_labels, gt_prob=0.7, zero_unsure=HAS_UNK) #U.shape为(, ),即(n_labels,len(labels))
  6. d.setUnaryEnergy(U)
  7.  
  8. # This creates the color-independent features and then add them to the CRF
  9. feats = create_pairwise_gaussian(sdims=(, ), shape=img.shape[:])
  10. d.addPairwiseEnergy(feats, compat=,
  11. kernel=dcrf.DIAG_KERNEL,
  12. normalization=dcrf.NORMALIZE_SYMMETRIC)
  13.  
  14. # This creates the color-dependent features and then add them to the CRF
  15. feats = create_pairwise_bilateral(sdims=(, ), schan=(, , ),
  16. img=img, chdim=)
  17. d.addPairwiseEnergy(feats, compat=,
  18. kernel=dcrf.DIAG_KERNEL,
  19. normalization=dcrf.NORMALIZE_SYMMETRIC)

1)Pairwise potentials for N-D

用户@markusnagel编写了几个numpy函数,将两个经典的二维图像二元势(高斯和双边)推广到任意维数:create_pairwise_gaussian和create_pairwise_bilateral。

你可以从from pydensecrf.utils import create_pairwise_gaussian访问它们,然后查看它们的文档去了解如何使用它们。

 

7.Learning

 学习还没有完全结束。如果你需要它,联系或或者更好是去包装它并提交一个拉请求!

这里有一个供初学者参考的指针:第24期。我们需要包装梯度和获取/设置参数。但是,我们还需要对这些做一些事情,最有可能的是从optimization.cpp调用minimizeLBFGS。遵循原始代码中包含的学习示例应该相对简单。

 
 
8.代码说明如何使用

pydensecrf的使用的更多相关文章

  1. pydensecrf的inference.py代码的学习

    https://github.com/lucasb-eyer/pydensecrf/blob/master/examples/inference.py 1.运行 先运行看看实现的结果: (deeple ...

  2. pydensecrf安装报错1、UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb6 in position 29: invalid start byte2、 LINK : fatal error LNK1158: 无法运行“rc.exe” error: command 'D:\\software\\vs2015\\VC\\BIN

    pydensecrf安装报错 1.UnicodeDecodeError: 'utf-8' codec can't decode byte 0xb6 in position 29: invalid st ...

  3. (转)Image Segmentation with Tensorflow using CNNs and Conditional Random Fields

    Daniil's blog Machine Learning and Computer Vision artisan. About/ Blog/ Image Segmentation with Ten ...

  4. Pytorch实现UNet例子学习

    参考:https://github.com/milesial/Pytorch-UNet 实现的是二值汽车图像语义分割,包括 dense CRF 后处理. 使用python3,我的环境是python3. ...

  5. Example of DenseCRF with non-RGB data

    本笔记本通过一个示例说明如何在非rgb数据上使用DenseCRFs.同时,它将解释基本概念并通过一个示例进行演示,因此即使您正在处理RGB数据,它也可能是有用的,不过也请查看PyDenseCRF's ...

  6. CRF 条件随机场工具包

    CRF - 条件随机场 工具包(python/c++) 项目案例 ConvCRF+FullCRF https://github.com/MarvinTeichmann/ConvCRF 需要的包Opti ...

随机推荐

  1. 精读《Serverless 给前端带来了什么》

    1. 引言 Serverless 是一种 "无服务器架构",让用户无需关心程序运行环境.资源及数量,只要将精力 Focus 到业务逻辑上的技术. 现在公司已经实现 DevOps 化 ...

  2. 【MongoDB】MongoDB环境配置

    软件下载与安装 1.mongDB下载,可到官网下载,我用的是3.4.6版本.可以放到任意目录下,我的MongDB安装目录为 D:\software\small_softeware\MongoDB 2. ...

  3. Python使用WMI模块获取Windows系统的硬件信息,并使用pyinstaller库编译打包成exe的可执行文件

    由于公司现阶段大多数应用软件都是基于Windows系统开发和部署,很多软件安装部署都是在windows server 2012.windows server 2008之类的服务器上,部门同事每次测试一 ...

  4. Golang垃圾回收机制(一)

    原文: http://legendtkl.com/2017/04/28/golang-gc/ 1. Golang GC 发展 Golang 从第一个版本以来,GC 一直是大家诟病最多的.但是每一个版本 ...

  5. 服务器配置用户信息、ssh免密码登录和防火墙等安全配置

    一.登录服务器      1.回到根目录 cd ~      2.ssh + 用户名@服务器公网地址 ssh root@47.94.208.76      3.输入密码:注意输入法大小写 二.查看服务 ...

  6. C#把动态创建的多个控件中指定控件显示在最上层

    在创建多个控件后,有些控件会发生重叠,那么就需要在鼠标按下它时能显示在最上层,下面通过先将按下操作的控件删除然后再重建,就达到让它显示在最上层了 //控件按下 private void picture ...

  7. Java开发笔记(十三)利用关系运算符比较大小

    前面在<Java开发笔记(九)赋值运算符及其演化>中提到,Java编程中的等号“=”表示赋值操作,并非数学上的等式涵义.Java通过等式符号“==”表示左右两边相等,对应数学的等号“=”: ...

  8. 【转】Android播放音频MediaPlayer的几种方式介绍

    接下来笔者介绍一下Android中播放音频的几种方式,android.media包下面包含了Android开发中媒体类,当然笔者不会依次去介绍,下面介绍几个音频播放中常用的类: 1.使用MediaPl ...

  9. vue生成二维码插件qrcodejs2

    1.页面 <div id="qrCode" ref="qrCodeDiv"></div> 2.导入插件 import QRCode fr ...

  10. 文件类型解析漏洞防御与攻击(PHP)

    简介: 解析漏洞主要是一些特殊文件被iis.Apache.Nginx等服务在某种情况下解释成脚本文件格式并得以执行而产生的漏洞,一般的思路都是用图片木马来欺骗服务器,上传webshell,达到提权的目 ...