- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我对矩阵有一个有趣的问题。在吉布斯分布中,吉布斯能量U(x)可计算为
这是所有可能的团C上团势Vc(x)的总和(右图)。集团c定义为S中站点的子集(左图中x-蓝色像素的邻居是黄色像素的邻居),其中每对不同的站点都是邻居,除了单站点集团
其中V(x)的计算如下:
我的目标是如何计算U(x)。在我上面的示例中,x = {1,2}。但是,我有一些卡在图像角上的像素中,该像素只有少于8个邻居(正常情况下一个像素通常有8个邻居像素)。为了解决这个问题,我在带遮罩的卷积图像的边缘角处添加了零。但我认为这可能会影响U(x)。根据上面的定义,当我考虑图像角点(灰色)时的像素时,可以帮我找到U(x = 1)和U(x = 2)吗?我试图通过下面的解决方案来解决它,但是我认为我的解决方案太长了,我不确定是否正确。
这就是我所做的
Imlabel =[ 1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 2 1 1;
1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 1 1;
1 1 2 2 2 1 1 1 1 1;
1 1 2 2 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 2 1;
1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 1 1];
mask=[ 0 0 0;0 1 0;0 0 0];
Imlabel=conv2(Imlabel,mask); % To solve pixel in corner
num_class=2; % x={1,2}
beta=1;
for label=1:num_class
for i=2:size(Imlabel,1)-1
for j=2:size(Imlabel,2)-1
sum_V=0;
%North, south, east and west neighbors
if(label==Imlabel(i-1,j)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i,j+1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i+1,j)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i,j-1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
%% Diagonal pixels
if(label==Imlabel(i-1,j-1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i-1,j+1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i+1,j+1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i+1,j-1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
%% Save
U(i-1,j-1,label)=sum_V; %% Because Index is extended before
end
end
end
P=zeros(size(U));
Z=sum(exp(-U),3);
for i=1:num_class
P(:,:,i)=exp(-U(:,:,i))./Z;
end
最佳答案
您的解释和代码一样有意义。但是,通过精通要使用的功能种类,可以完全实现矢量化。
对于感兴趣的读者,给定您的源代码,您想要做的是以下操作(使用伪代码):
创建一个U
大的矩阵size(Imlabel,1) x size(Imlabel,2) x num_class
。该矩阵的每个切片将确定该切片中每个坐标(i,j)
处的8个相邻像素的吉布斯能量成本。
对于每个类别标签x
...
一个。对于图像中的每个像素(i,j)
...
查找在(i,j)
的8像素邻域中定义的等于x
的那些位置,并将它们设置为beta
查找在(i,j)
的8像素邻域中定义的不等于x
的那些位置,并将它们设置为-beta
计算此8像素邻域内所有这些beta
和-beta
值的总和,并将其设置在位置U(i,j,x)
因此,我要做的是创建一个3D成本矩阵...让我们称之为C
,其中每个切片y
具有与size(Imlabel,1) x size(Imlabel,2)
相同的尺寸,但是切片中的每个位置(i,j)
将是
beta
,否则为
Imlabel(i,j) == y
。完成此操作后,您可以对该矩阵执行N-D卷积,但是要使用2D内核,以便可以分别计算每个切片的8像素邻域之和。
当今的魔术菜单由
-beta
,
bsxfun
和
convn
的副食组成,以使锅变甜。
要获取成本矩阵
permute
,您可以执行此操作。假设
C
的边界没有填充零:
Imlabel =[ 1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 2 1 1;
1 1 1 1 1 1 1 1 1 1;
1 1 2 2 2 1 1 1 1 1;
1 1 2 2 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 2 1;
1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 1 1];
C = double(bsxfun(@eq, Imlabel, permute(1:num_class, [1 3 2])));
C(C == 0) = -beta;
C(C == 1) = beta;
Imlabel
函数用于创建单个3D向量,其范围从1到您定义的多个类。之所以需要这样做,是因为
permute
做所谓的广播。在给定矩阵
bsxfun
的情况下会发生这种情况,使用3D向量将与
Imlabel
或equals函数一起创建3D成本矩阵。此成本矩阵的每个部分都会为您提供与所讨论标签相等或不相等的位置。
eq
输出的locations矩阵的正确性:
>> C = double(bsxfun(@eq, Imlabel, permute(1:num_class, [1 3 2])))
C(:,:,1) =
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 0 1 1
1 1 1 1 1 1 1 1 1 1
1 1 0 0 0 1 1 1 1 1
1 1 0 0 1 1 1 1 1 1
1 1 1 1 1 1 1 1 0 1
1 1 1 1 1 1 1 1 1 1
1 1 1 1 1 1 1 1 1 1
C(:,:,2) =
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 1 0 0
0 0 0 0 0 0 0 0 0 0
0 0 1 1 1 0 0 0 0 0
0 0 1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
bsxfun
,以便可以将其修改为成本矩阵,其中
double
是不等于特定切片标签的位置,而
-beta
是。这是通过
beta
调用后的两个赋值语句完成的。
bsxfun
:
mask = zeros(3,3); mask(2,2) = 1;
Cpad = convn(C, mask);
Cpad(Cpad == 0) = -beta;
-beta
掩码。现在要独立填充每个切片以使其边界为零,我们可以使用
[0 0 0; 0 1 0; 0 0 0]
来帮助我们做到这一点。
mask2 = ones(3,3); mask2(2,2) = 0;
out = convn(Cpad, mask2, 'valid');
convn
循环逻辑中的
if/else
语句。实际上,您正在做的是一个卷积,其中将除中间中间之外的所有8个邻居相加。这可以通过使用除中心像素以外的全1的掩码并将其设置为0来实现。
for
独立地计算每个切片的吉布斯能量,但是使用
convn
标志,以便我们可以删除开头包含的零填充边界。
'valid'
,它将与您使用
out
的情况进行比较,但是由于索引到
U
的方式略有变化。不过,使用
U
的上述输出,您可以验证我们所拥有的是否正确,并且可以很好地处理边界情况:
>> out
out(:,:,1) =
-2 2 2 2 2 2 2 2 2 -2
2 8 8 8 8 8 6 6 6 2
2 8 8 8 8 8 6 8 6 2
2 6 4 2 4 6 6 6 6 2
2 4 2 0 4 6 8 8 8 2
2 4 2 0 2 6 8 6 6 0
2 6 4 4 6 8 8 6 8 0
2 8 8 8 8 8 8 6 6 0
-2 2 2 2 2 2 2 2 2 -2
out(:,:,2) =
-8 -8 -8 -8 -8 -8 -8 -8 -8 -8
-8 -8 -8 -8 -8 -8 -6 -6 -6 -8
-8 -8 -8 -8 -8 -8 -6 -8 -6 -8
-8 -6 -4 -2 -4 -6 -6 -6 -6 -8
-8 -4 -2 0 -4 -6 -8 -8 -8 -8
-8 -4 -2 0 -2 -6 -8 -6 -6 -6
-8 -6 -4 -4 -6 -8 -8 -6 -8 -6
-8 -8 -8 -8 -8 -8 -8 -6 -6 -6
-8 -8 -8 -8 -8 -8 -8 -8 -8 -8
out
以来,我们的总和为3,但是然后还有其他5个我们未考虑的方向,在您的代码中,将这些方向设置为
beta = 1
,因此将其设置为
-beta
。
3 - 5 = -2
相加,而与标签2不相等的任何基本方向均应为
beta / 1
。如您所见,正好有4个标签为1,4个标签为2,因此这些标签应抵消并给我们0。
Imlabel =[ 1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 2 1 1;
1 1 1 1 1 1 1 1 1 1;
1 1 2 2 2 1 1 1 1 1;
1 1 2 2 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 2 1;
1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 1 1];
C = double(bsxfun(@eq, Imlabel, permute(1:num_class, [1 3 2])));
C(C == 0) = -beta;
C(C == 1) = beta;
mask = zeros(3,3); mask(2,2) = 1;
Cpad = convn(C, mask);
Cpad(Cpad == 0) = -beta;
mask2 = ones(3,3); mask2(2,2) = 0;
out = convn(Cpad, mask2, 'valid');
-beta / -1
来帮助实现这一点。
function test_clique_timing
% Setup
Imlabel_orig =[ 1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 2 1 1;
1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 1 1;
1 1 2 2 2 1 1 1 1 1;
1 1 2 2 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 2 1;
1 1 1 1 1 1 1 1 1 1;
1 1 1 1 1 1 1 1 1 1];
num_class=2; % x={1,2}
beta = 1;
function test_orig
mask=[ 0 0 0;0 1 0;0 0 0];
Imlabel=conv2(Imlabel_orig,mask); % To solve pixel in corner
beta=1;
for label=1:num_class
for i=2:size(Imlabel,1)-1
for j=2:size(Imlabel,2)-1
sum_V=0;
%North, south, east and west neighbors
if(label==Imlabel(i-1,j)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i,j+1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i+1,j)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i,j-1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
%% Diagonal pixels
if(label==Imlabel(i-1,j-1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i-1,j+1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i+1,j+1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
if(label==Imlabel(i+1,j-1)) sum_V=sum_V+beta;
else sum_V=sum_V-beta;end
%% Save
U(i-1,j-1,label)=sum_V; %% Because Index is extended before
end
end
end
end
function test_conv
C = double(bsxfun(@eq, Imlabel_orig, permute(1:num_class, [1 3 2])));
C(C == 0) = -beta;
C(C == 1) = beta;
mask = zeros(3,3); mask(2,2) = 1;
Cpad = convn(C, mask);
Cpad(Cpad == 0) = -beta;
mask2 = ones(3,3); mask2(2,2) = 0;
out = convn(Cpad, mask2, 'valid');
end
time1 = timeit(@test_orig);
time2 = timeit(@test_conv);
fprintf('Loop code time: %f seconds\n', time1);
fprintf('Vectorized code time: %f seconds\n', time2);
fprintf('Speedup factor: %f', time1/time2);
end
Loop code time: 0.000049 seconds
Vectorized code time: 0.000060 seconds
Speedup factor: 0.816667
timeit
矩阵:
rng(123); %// Set seed for reproducibility
num_class = 10;
Imlabel_orig = randi(10,2500,2500);
Loop code time: 17.553669 seconds
Vectorized code time: 3.321950 seconds
Speedup factor: 5.284146
Imlabel
的矢量化代码的性能要比原始循环代码高出近5.2倍。
P=zeros(size(U));
Z=sum(exp(-U),3);
for i=1:num_class
P(:,:,i)=exp(-U(:,:,i))./Z;
end
bsxfun / convn / permute
的优势,则只需执行以下操作:
Z = sum(exp(-out),3)); %// out is U in my code
P = bsxfun(@rdivide, exp(-out), Z);
bsxfun
中的每个切片,我们找到
P
并将该切片取反作为输入,然后将每个术语除以
exp
。对于
Z
,将复制
bsxfun
矩阵的切片数与
Z
中的切片数相同,并且按元素进行除法非常类似于循环代码。
关于matlab - 如何从一个清晰的例子中计算2D图像中的吉布斯能量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32056577/
很简单的问题,可能很难回答: 例如,将 SSE 指令用于并行 sum/min/max/average 运算是否比执行任何其他指令(例如单个和)消耗更多的功率? 例如,在 Wikipedia我找不到这方
我想使用流体库的模型。谁能解释一下(我是建模/模拟的新手):质量/能量/动量平衡的公式:稳态、动态和初始猜测初始固定-->之间有什么区别以及对初始化时间/计算的影响是什么时间;我什么时候需要哪一个。
我是一名优秀的程序员,十分优秀!