https://www.yuque.com/lart/papershtml
本文不是按照以前的论文那样, 考虑显著性目标与背景之间的对比度, 而是经过使用流形排序方法, 来使用前景/背景线索对图像元素(像素或者区域)进行排序. node
在这种方法中, 图像元素的显著性是基于它们与给定种子/查询的相关性来定义的.python
咱们将图像表示为一个以超像素为节点的闭环图。这些节点的排序是基于与背景和前景查询的类似性,基于关联矩阵(affinity matrices)。采用两阶段的显著性检测方法,有效地提取背景区域和前景显著目标。git
同时本文也构建了一个大规模的数据集, 来进行显著性检测的测试评估.github
本篇论文主要专一的是一种由下而上的方法. 算法
主要相关的几个方法结论或者观察.app
这篇文章中, 使用这些线索基于超像素的排序来计算像素的显著性.less
从这个流程中, 能够关注几个点:dom
基于图的流形排序, 被描述为: 给定一个节点做为查询. 剩余节点基于与这个给定节点之间的相关性来进行排序. 目标是学习一个定义了未标记节点与查询之间的相关性的流形函数.函数
也就是说, 文中的基于图的流行排序实际上就是经过一个流行函数定义未标记节点与查询节点之间的相关性. 如果有了这个与前景或者背景查询节点的相关性, 就能够用来排序, 与前景相关性高的就能够用其表示显著性, 与背景相关性高的, 就能够用其表示非显著性(1-f能够用来表示显著性).(具体细节见后).
论文[D. Zhou, J. Weston, A. Gretton, O. Bousquet, and B. Scholkopf. Ranking on data manifolds_. In NIPS, 2004_]提出了一种利用数据(如图像)固有流形结构进行图形标签排序的方法.
为何要建模成流行排序问题?
为了充分捕捉图的内在结构信息,并在图的标注中加入局部分组线索(local grouping),咱们利用流形排序技术(manifold ranking)来学习排序函数,这对于学习最优亲和矩阵是相当重要的.
对于该问题的建模以下:
主要是将映射 表示为一个排序问题. 赋予一个排序值到每一个点数据点
上, 汇总获得的
,做为最终获得的排序值.
将图片表示为一个无向图结构, 节点为超像素, 而边的权重整体表示为关联矩阵 , 对应的图所对应的度矩阵表示为
这里的d对应于W特定行之和.
反映了和特定节点链接的其余全部节点边的权重之和. 这个也在必定程度上能够认为是一种节点之间的相关程度/关联性. 这里计算显著性就是用它.
是否能够表示为有向图, 这样能够表示更为丰富的信息, 好比特征之间的依赖性, 不过感受这个想法不适合与这样的自下而上的传统方法, 由于这种有向的依赖关系, 对应的特征应该是更为高级的语义信息.
这里让我想到了分割的一个结构, DD-RNN和DAG-RNN
为了找到最好的一个排序, 这里将这个优化问题表述为:
从式子1能够了解到
最小解, 利用导数求解, 获得结果以下, 式子2是最终的排序结果对应的函数. 而式子3使用的是未标准化的拉普拉斯矩阵.
具体参数可见前面图片的定义. 实际使用的是式子3. 这里是测试比较:
The figure shows that the ranking results with the unnormalized Laplacian matrix are better, and used in all the experiments.
这里有一点, 文中没有细说, 最终的排序是对f中的元素进行排序, 仍是说f中的元素实际上已经排好序了 (这里划掉的部分, 能够如此理解并推翻: f的索引实际上与y的索引是对应的, 也就是说,** f表示的是特定节点到全部查询点之间的相关性之和**. 因此说, 若是索引固定, 那么这里应该是基于获得的f来计算对应的显著性值.)
实际上这里说是排序, 其实并无进行排序操做, 只是利用这个优化问题获得的相关性解, 来进行显著性值的计算. 虽然这个值在必定程度上反映了显著性的排序状况, 可是并无具体用到排序的操做
关于式子2, 3. 两者的差异, 前者是用的是标准化参数, 后者使用的是更为直接的参数. 而在计算显著性的时候, 是须要进行标准化的, 因此使用3式的时候, 仍是要进行标准化处理的. .
这里的标准化是将数据放缩到了0~1范围, 能够看下面的代码示例:
bsalt=optAff*Yt; bsalt=(bsalt-min(bsalt(:)))/(max(bsalt(:))-min(bsalt(:)));
传统的排序问题, 查询是要手动用真实标记的. 然而提出的算法选择的查询, 一些可能被标错了. 所以须要对每一个查询计算一个置信度(也就是显著性值), 这个用它的排序得分, 这是经过其余查询计算出来的(排除自身).
最后, 设定A中的对角元素为0. 这个看似可有可无的过程对最终结果有很大的影响, 这里 若是没有设置A的对角元素为0来进行计算每个查询的显著性的时候, 结果会包含查询与自身的相关性, 这个一般很大 (是同一行其余项的和的负数), 会严重抑制其余查询对于排序得分的贡献.
由于度矩阵D的对角元素是仿射矩阵W的每行元素的和. 若是D不设定为0, 那么差值以后, 就会减掉自身的影响.
关于权重w, 有以下设定:
节点之间的权重使用颜色空间的距离的钟形函数来进行建模. 方差项用来控制权重的强度. 色彩距离(差别)越大, 赋予的权重也就越小.
这里提到了两点:
因为相邻节点可能具备类似的外观和显著性值,使用_k-regular_图来利用空间关系。
经过对边的约束,能够看出构造图是稀疏链接的。也就是说,关联矩阵 的大部分项都是零。
这里为何是稀疏链接的? 虽然从结果上来看确实是稀疏的. 可见参考连接里的
SLIC算法测试
, 里面有一些测试.
这里能够看python代码计算W和D的部分, 有一段:W = sp.exp(-1*W / self.weight_parameters['delta']) # 归属于不一样超像素的像素之间, 不相邻的赋予0 W[adj.astype(np.bool)] = 0这里是反着取得邻接矩阵, 因此, 不相邻的部分对应的关联矩阵W是要置0的. 而这里的邻接矩阵, 在这里指定的关于邻接的约束, 致使大部分节点之间是不相邻的. 因此这里adj是稀疏的, 致使W也是一个稀疏矩阵.
根据早期关于视觉显著性[17]的注意理论,咱们将图像边界上的节点做为背景种子,即,将标记的数据(查询样本)对全部其余区域的相关性进行排序。具体地说,咱们使用边界先验构造了四个显著性图,而后将它们集成到最终的映射中,这被称为分离/组合(SC)方法.
以图像顶部边界为例,使用这一侧的节点做为查询,其余节点做为未标记的数据。所以, 指示向量y被给定, 全部的节点是基于式子3中的_f∗_排名, 这是一个N维向量(N是图的节点总数)。此向量中的每一个元素表示节点与背景查询节点的相关性, 其关于1的补数是显著性测量.
相似的计算其余三边的状况. 注意, 实际上, 在这个过程当中, 矩阵D, W只须要计算一次, 而y都是能够肯定的.
最后进行集成:
使用相乘的方法来进行集成. 这里有点相似于同一年的Graph-Regularized Saliency Detection
With Convex-Hull-Based Center Prior文章中集成对比度先验与基于凸包的中心先验的方法.
- 这种经过相乘的方式来进行集成的方式来自哪里? * 还有没有其余的集成的方式?
使用SC方法的主要的考虑是四边同时使用的效果很差, 主要体如今两个方面:
对比结果以下图:
进一步基于前景查询排序来优化结果, 主要是为了应对目标出如今靠近图像边缘的状况.
第一阶段的显著性映射是二值分割的(即,突出的前景和背景), 使用一个自适应阈值,这有助于选择节点的前景显著性目标做为查询节点。咱们指望选择的查询尽量地覆盖突出的对象区域(即)。所以,阈值被设置为整个显著性映射的平均显著性。
相似的, 这里则直接可使用与查询节点计算相关性来得到显著性值:
这里就不用互补计算了, 由于这里是算的与前景的相关性.
显著目标区域一般是相对紧凑的(在空间分布方面)和均匀的外观(在特征分布方面),而背景区域正好相反。换句话说,对象内部的相关性(即,显著对象的两个节点)在统计上远大于对象背景和背景内相关性,能够从关联矩阵A中推断。为了进一步显示这个现象, 文章从数据集真值中, 进行了测试:
To show this phenomenon, we compute the average intra-object, intra-background and object-background relevance values in A for each of the 300 images sampled from a dataset with ground truth labels.
从真值标记统计出来, 明显能够看出来, 目标节点到全部真值的显著性查询的相关性之和要大于背景节点到全部查询的相关性之和. 这个是最优状态的A的结果对应的解释.
可是这个可以说明这个方法中的背景是能够被有效抑制的么? 能够的.
由于A是最终的的f的一个仿射变换矩阵, 其中的值对应着f的结果, 也就是对应着最终的显著性结果.
这里用实验解释了目标内部相关性是最大的. 而这个结论在使用前景查询进行优化提高的时候, 在必定程度上能够改善已经预测的显著性区域. 由于_通常显著性目标对象区域更为紧凑, 均匀. 在计算距离的时候, 周围的一致性更强, 鉴于色彩空间加权的做用, 最终与相关性值会更高一些. 而先前错误标记的部分, 相对而言值更小了_.
A是基于原始图像的色彩的. 从一开始就是个定值. 查询的选择, 影响的是y.
主要流程:
https://github.com/huchuanlu/13_4/blob/master/demo.m
https://github.com/ruanxiang/mr_saliency/blob/master/MR/MR.py(主要从这里入手理解), python版本的实现与matlab实现细节有些差别, 主要是在于里面对于第一阶段的计算中, python版本是反着来的, 它把背景(边界)的指示值设定为了1, 最后集成的时候又用1算了个补数. 而matlab的流程设定和论文是一致的.
% Demo for paper "Saliency Detection via Graph-Based Manifold Ranking" % by Chuan Yang, Lihe Zhang, Huchuan Lu, Ming-Hsuan Yang, and Xiang Ruan % To appear in Proceedings of IEEE Conference on Computer Vision and Pattern Recognition (CVPR 2013), Portland, June, 2013. clear all; addpath('./others/'); %%------------------------set parameters---------------------%% theta=10; % control the edge weight alpha=0.99;% control the balance of two items in manifold ranking cost function spnumber=200;% superpixel number imgRoot='./test/';% test image path saldir='./saliencymap/';% the output path of the saliency map supdir='./superpixels/';% the superpixel label file path mkdir(supdir); mkdir(saldir); imnames=dir([imgRoot '*' 'jpg']); % 迭代图片 for ii=1:length(imnames) disp(ii); imname=[imgRoot imnames(ii).name]; [input_im,w]=removeframe(imname);% run a pre-processing to remove the image frame [m,n,k] = size(input_im); %%----------------------generate superpixels使用SLIC方法来生成超像素--------------------%% imname=[imname(1:end-4) '.bmp'];% the slic software support only the '.bmp' image comm=['SLICSuperpixelSegmentation' ' ' imname ' ' int2str(20) ' ' int2str(spnumber) ' ' supdir]; system(comm); spname=[supdir imnames(ii).name(1:end-4) '.dat']; % 得到超像素标记矩阵 superpixels=ReadDAT([m,n],spname); % superpixel label matrix spnum=max(superpixels(:));% the actual superpixel number %%----------------------design the graph model 计算聚拢的像素在lab颜色空间中的平均值--------------------------%% % compute the feature (mean color in lab color space) % for each node (superpixels) input_vals=reshape(input_im, m*n, k); rgb_vals=zeros(spnum,1,3); inds=cell(spnum,1); for i=1:spnum inds{i}=find(superpixels==i); rgb_vals(i,1,:)=mean(input_vals(inds{i},:),1); end lab_vals = colorspace('Lab<-', rgb_vals); seg_vals=reshape(lab_vals,spnum,3);% feature for each superpixel % get edges 获取节点之间的边 adjloop=AdjcProcloop(superpixels,spnum); edges=[]; for i=1:spnum indext=[]; ind=find(adjloop(i,:)==1); for j=1:length(ind) indj=find(adjloop(ind(j),:)==1); indext=[indext,indj]; end indext=[indext,ind]; indext=indext((indext>i)); indext=unique(indext); if(~isempty(indext)) ed=ones(length(indext),2); ed(:,2)=i*ed(:,2); ed(:,1)=indext; edges=[edges;ed]; end end % compute affinity matrix 计算关联矩阵, 表示了各类权重关系 weights = makeweights(edges,seg_vals,theta); W = adjacency(edges,weights,spnum); % learn the optimal affinity matrix (eq. 3 in paper) 学习最优的关联矩阵 % 这里是设定了一个稀疏矩阵. % 使用i=1:spnum和j=1:spnum指定的坐标, 赋予特定的值dd, 也就是D(i(k), j(k))=dd(k) % 获得的结果中, dd = sum(W); D = sparse(1:spnum,1:spnum,dd); clear dd; optAff =(D-alpha*W)\eye(spnum); mz=diag(ones(spnum,1)); mz=~mz; optAff=optAff.*mz; %%-----------------------------stage 1--------------------------%% % compute the saliency value for each superpixel % with the top boundary as the query Yt=zeros(spnum,1); bst=unique(superpixels(1,1:n)); Yt(bst)=1; bsalt=optAff*Yt; bsalt=(bsalt-min(bsalt(:)))/(max(bsalt(:))-min(bsalt(:))); bsalt=1-bsalt; % down Yd=zeros(spnum,1); bsd=unique(superpixels(m,1:n)); Yd(bsd)=1; bsald=optAff*Yd; bsald=(bsald-min(bsald(:)))/(max(bsald(:))-min(bsald(:))); bsald=1-bsald; % right Yr=zeros(spnum,1); bsr=unique(superpixels(1:m,1)); Yr(bsr)=1; bsalr=optAff*Yr; bsalr=(bsalr-min(bsalr(:)))/(max(bsalr(:))-min(bsalr(:))); bsalr=1-bsalr; % left Yl=zeros(spnum,1); bsl=unique(superpixels(1:m,n)); Yl(bsl)=1; bsall=optAff*Yl; bsall=(bsall-min(bsall(:)))/(max(bsall(:))-min(bsall(:))); bsall=1-bsall; % combine bsalc=(bsalt.*bsald.*bsall.*bsalr); bsalc=(bsalc-min(bsalc(:)))/(max(bsalc(:))-min(bsalc(:))); % 这时 ,bsalc是第一阶段最终的显著性标记 % assign the saliency value to each pixel 为每一个像素分配显著性值 tmapstage1=zeros(m,n); for i=1:spnum tmapstage1(inds{i})=bsalc(i); end tmapstage1=(tmapstage1-min(tmapstage1(:)))/(max(tmapstage1(:))-min(tmapstage1(:))); mapstage1=zeros(w(1),w(2)); mapstage1(w(3):w(4),w(5):w(6))=tmapstage1; mapstage1=uint8(mapstage1*255); outname=[saldir imnames(ii).name(1:end-4) '_stage1' '.png']; imwrite(mapstage1,outname); %%----------------------stage2-------------------------%% % binary with an adaptive threhold (i.e. mean of the saliency map) 自适应阈值二值化, 阈值被设置为整个显著图上的平均显著性 th=mean(bsalc); bsalc(bsalc<th)=0; bsalc(bsalc>=th)=1; % compute the saliency value for each superpixel fsal=optAff*bsalc; % assign the saliency value to each pixel tmapstage2=zeros(m,n); for i=1:spnum tmapstage2(inds{i})=fsal(i); end tmapstage2=(tmapstage2-min(tmapstage2(:)))/(max(tmapstage2(:))-min(tmapstage2(:))); mapstage2=zeros(w(1),w(2)); mapstage2(w(3):w(4),w(5):w(6))=tmapstage2; mapstage2=uint8(mapstage2*255); outname=[saldir imnames(ii).name(1:end-4) '_stage2' '.png']; imwrite(mapstage2,outname); end
#################################################################### ## Author: ## Xiang Ruan ## httpr://ruanxiang.net ## ruanxiang@gmail.com ## License: ## GPL 2.0 ## NOTE: the algorithm itself is patented by OMRON, co, Japan ## my previous employer, so please do not use the algorithm in ## any commerical product ## Version: ## 1.0 ## ## ---------------------------------------------------------------- ## A python implementation of manifold ranking saliency ## Usage: ## import MR ## import matplotlib.pyplot as plt ## mr = MR.MR_saliency() ## sal = mr.saliency(img) ## plt.imshow(sal) ## plt.show() ## ## Check paper.pdf for algorithm details ## I leave all th parameters open to maniplating, however, you don't ## have to do it, default values work pretty well, unless you really ## know what you want to do to modify the parameters import scipy as sp import numpy as np import cv2 from skimage.segmentation import slic from skimage.segmentation import mark_boundaries from skimage.data import camera from scipy.linalg import inv import matplotlib.pyplot as plt cv_ver = int(cv2.__version__.split('.')[0]) _cv2_LOAD_IMAGE_COLOR = cv2.IMREAD_COLOR if cv_ver >= 3 else cv2.CV_LOAD_IMAGE_COLOR class MR_saliency(object): """Python implementation of manifold ranking saliency""" weight_parameters = {'alpha':0.99, 'delta':0.1} superpixel_parameters = {'segs':200, 'compactness':10, 'max_iter':10, 'sigma':1, 'spacing':None, 'multichannel':True, 'convert2lab':None, 'enforce_connectivity':False, 'min_size_factor':0.5, 'max_size_factor':3, 'slic_zero':False} binary_thre = None def __init__(self, alpha = 0.99, delta = 0.1, segs = 200, compactness = 10, max_iter = 10, sigma = 1, spacing = None, multichannel = True, convert2lab = None, enforce_connectivity = False, min_size_factor = 0.5, max_size_factor = 3, slic_zero = False): self.weight_parameters['alpha'] = alpha self.weight_parameters['delta'] = delta self.superpixel_parameters['segs'] = segs self.superpixel_parameters['compactness'] = compactness self.superpixel_parameters['max_iter'] = max_iter self.superpixel_parameters['sigma'] = sigma self.superpixel_parameters['spacing'] = spacing self.superpixel_parameters['multichannel'] = multichannel self.superpixel_parameters['convert2lab'] = convert2lab self.superpixel_parameters['enforce_connectivity'] = enforce_connectivity self.superpixel_parameters['min_size_factor'] = min_size_factor self.superpixel_parameters['max_size_factor'] = max_size_factor self.superpixel_parameters['slic_zero'] = slic_zero def saliency(self,img): """ 主要的处理函数, 反映了算法的主要流程 """ # read image img = self.__MR_readimg(img) # superpixel # labels获得的是什么: 对于各个像素的超像素划分的标记 labels = self.__MR_superpixel(img) # affinity matrix aff = self.__MR_affinity_matrix(img,labels) # first round first_sal = self.__MR_first_stage_saliency(aff,labels) # second round fin_sal = self.__MR_final_saliency(first_sal, labels,aff) return self.__MR_fill_superpixel_with_saliency(labels,fin_sal) def __MR_superpixel(self,img): """ 超像素划分 """ return slic(img, self.superpixel_parameters['segs'], self.superpixel_parameters['compactness'], self.superpixel_parameters['max_iter'], self.superpixel_parameters['sigma'], self.superpixel_parameters['spacing'], self.superpixel_parameters['multichannel'], self.superpixel_parameters['convert2lab'], self.superpixel_parameters['enforce_connectivity'], self.superpixel_parameters['min_size_factor'], self.superpixel_parameters['max_size_factor'], self.superpixel_parameters['slic_zero']) def __MR_superpixel_mean_vector(self,img,labels): """ 返回关于关于每一个超像素的三个颜色通道的均值. """ s = sp.amax(labels)+1 vec = sp.zeros((s,3)).astype(float) # 每一个超像素的获得的颜色均值是三个值, 三个通道各自一个均值. for i in range(s): mask = labels == i # img[mask]表示图像上被标记为同一个超像素的像素值 super_v = img[mask].astype(float) mean = sp.mean(super_v,0) vec[i] = mean return vec def __MR_affinity_matrix(self,img,labels): """ 得到关联矩阵A """ W,D = self.__MR_W_D_matrix(img,labels) # 得到矩阵A aff = inv(D-self.weight_parameters['alpha']*W) aff[sp.eye(sp.amax(labels)+1).astype(bool)] = 0.0 # diagonal elements to 0 return aff def __MR_saliency(self,aff,indictor): """ 计算A*y """ return sp.dot(aff,indictor) def __MR_W_D_matrix(self,img,labels): """ 得到矩阵W和D """ s = sp.amax(labels)+1 vect = self.__MR_superpixel_mean_vector(img,labels) # 获取超像素之间的邻接矩阵, 这里邻接关系对应着False adj = self.__MR_get_adj_loop(labels) W = sp.spatial.distance.squareform(sp.spatial.distance.pdist(vect)) W = sp.exp(-1*W / self.weight_parameters['delta']) # 归属于不一样超像素的像素之间, 不相邻的赋予0 W[adj.astype(np.bool)] = 0 D = sp.zeros((s,s)).astype(float) for i in range(s): D[i, i] = sp.sum(W[i]) return W,D def __MR_boundary_indictor(self,labels): """ 这里将四个边界像素所在超像素指示值都设定为0 """ s = sp.amax(labels)+1 up_indictor = (sp.ones((s,1))).astype(float) right_indictor = (sp.ones((s,1))).astype(float) low_indictor = (sp.ones((s,1))).astype(float) left_indictor = (sp.ones((s,1))).astype(float) upper_ids = sp.unique(labels[0,:]).astype(int) right_ids = sp.unique(labels[:,labels.shape[1]-1]).astype(int) low_ids = sp.unique(labels[labels.shape[0]-1,:]).astype(int) left_ids = sp.unique(labels[:,0]).astype(int) up_indictor[upper_ids] = 0.0 right_indictor[right_ids] = 0.0 low_indictor[low_ids] = 0.0 left_indictor[left_ids] = 0.0 return up_indictor,right_indictor,low_indictor,left_indictor def __MR_get_adj_loop(self, labels): """ 获取超像素的邻接矩阵 """ # 总的超像素数量, amax方法会返回最大的类别值 s = sp.amax(labels) + 1 # 超像素邻接矩阵预约义 adj = np.ones((s, s), np.bool) # 对图像的各个像素的超像素标记进行遍历 for i in range(labels.shape[0] - 1): for j in range(labels.shape[1] - 1): # 下面的四个判断, 检查了以(i,j)为左上角的一个2x2像素区域四个像素之间的连通关系 if labels[i, j] != labels[i+1, j]: # (i,j)与(i+1,j)不位于同一个超像素中, 就在超像素邻接矩阵中对应位置置为False # 注意, 有两个位置, 由于邻接矩阵能够表示有向图. adj[labels[i, j] , labels[i+1, j]] = False adj[labels[i+1, j], labels[i, j]] = False if labels[i, j] != labels[i, j + 1]: # (i,j)与(i,j+1) adj[labels[i, j] , labels[i, j+1]] = False adj[labels[i, j+1], labels[i, j]] = False if labels[i, j] != labels[i + 1, j + 1]: # (i,j)与(i+1,j+1) adj[labels[i, j] , labels[i+1, j+1]] = False adj[labels[i+1, j+1], labels[i, j]] = False if labels[i + 1, j] != labels[i, j + 1]: # (i+1,j)与(i,j+1) adj[labels[i+1, j], labels[i, j+1]] = False adj[labels[i, j+1], labels[i+1, j]] = False # 这里循环结束后, 获得的adj中的True表示的是图像像素的超像素标记并非相邻的.(这两个超像素的 # 像素之间并不相邻), 而对应的False表示的是超像素的元素之间是相邻的. # 这里肯定了四个边上的像素对应的超像素标记, 这里会查找特定向量的惟一超像素标记的集合 upper_ids = sp.unique(labels[0,:]).astype(int) right_ids = sp.unique(labels[:,labels.shape[1]-1]).astype(int) low_ids = sp.unique(labels[labels.shape[0]-1,:]).astype(int) left_ids = sp.unique(labels[:,0]).astype(int) # np.append会拼接指定的向量. 四个边拼接起来, 获得的bd表示被认为是背景的超像素标记 bd = np.append(upper_ids, right_ids) bd = np.append(bd, low_ids) bd = sp.unique(np.append(bd, left_ids)) for i in range(len(bd)): for j in range(i + 1, len(bd)): # 任意两个包含边界像素的超像素, 对应的邻接关系也被设置为False adj[bd[i], bd[j]] = False adj[bd[j], bd[i]] = False # 这里的循环结束后, adj表示的是全部包含边界像素的超像素之间都认为是元素相邻的, 这里设定为False return adj def __MR_fill_superpixel_with_saliency(self,labels,saliency_score): """ 为各个超像素区域赋予对应的显著性得分 """ sa_img = labels.copy().astype(float) for i in range(sp.amax(labels)+1): mask = labels == i sa_img[mask] = saliency_score[i] return cv2.normalize(sa_img,None,0,255,cv2.NORM_MINMAX) def __MR_first_stage_saliency(self,aff,labels): """ 获取边界查询(种子)对应的图得分. """ # 边界指示对应为0 up,right,low,left = self.__MR_boundary_indictor(labels) # 计算的是节点到非边界元素的相关性的补数, 也就是非显著性图 up_sal = 1-self.__MR_saliency(aff,up) # sp.dot(aff, up) up_img = self.__MR_fill_superpixel_with_saliency(labels,up_sal) right_sal = 1-self.__MR_saliency(aff,right) right_img = self.__MR_fill_superpixel_with_saliency(labels,right_sal) low_sal = 1-self.__MR_saliency(aff,low) low_img = self.__MR_fill_superpixel_with_saliency(labels,low_sal) left_sal = 1-self.__MR_saliency(aff,left) left_img = self.__MR_fill_superpixel_with_saliency(labels,left_sal) # 使用非显著性图乘积的补数来做为显著性图 return 1-up_img*right_img*low_img*left_img def __MR_second_stage_indictor(self,saliency_img_mask,labels): s = sp.amax(labels)+1 # get ids from labels image ids = sp.unique(labels[saliency_img_mask]).astype(int) # indictor indictor = sp.zeros((s,1)).astype(float) indictor[ids] = 1.0 return indictor def __MR_final_saliency(self,integrated_sal, labels, aff): # get binary image if self.binary_thre == None: thre = sp.median(integrated_sal.astype(float)) mask = integrated_sal > thre # get indicator ind = self.__MR_second_stage_indictor(mask,labels) return self.__MR_saliency(aff,ind) # read image def __MR_readimg(self,img): if isinstance(img,str): # a image path img = cv2.imread(img, _cv2_LOAD_IMAGE_COLOR) img = cv2.cvtColor(img,cv2.COLOR_RGB2LAB).astype(float)/255 h = 100 w = int(float(h)/float(img.shape[0])*float(img.shape[1])) return cv2.resize(img,(w,h))