【问题标题】:Fastest way to find the sign of different square最快找到不同方块符号的方法
【发布时间】:2015-03-01 15:27:27
【问题描述】:

给定一个图像 I 和两个矩阵 m_1 ;m_2(与 I 大小相同)。函数 f 定义为: 因为我的目标设计想要得到 f 的符号。因此,函数 f 可以重写如下:

  • 我认为第二个公式比第一个公式更快,因为:它 可以忽略平方项
  • 它可以直接计算符号,而不是第一个等式中的两个步骤:计算 f 和检查符号。

你同意我的观点吗?你有另一个更快的公式 f

I =[16    23    11    42    10
    11    21    22    24    30
    16    22   154   155   156
    25    28   145   151   156
    11    38   147   144   153];

m1 =[0     0     0     0     0
     0     0    22    11     0
     0    23    34    56     0
     0    56     0     0     0
     0    11     0     0     0];

m2 =[0     0     0     0     0
     0     0    12    11     0
     0    22   111   156     0
     0    32     0     0     0
     0    12     0     0     0];

输出 f 是

 f =[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]

我实现了第一种方式,但是我没有通过matlab完成第二种方式。你能帮我看看第二种方法并比较一下吗

更新:我想添加 chepyle 和 Divakar 的代码以明确提出问题。请注意,它们都给出与上面相同的结果 f

function compare()
I =[16    23    11    42    10
    11    21    22    24    30
    16    22   154   155   156
    25    28   145   151   156
    11    38   147   144   153];

m1 =[0     0     0     0     0
    0     0    22    11     0
    0    23    34    56     0
    0    56     0     0     0
    0    11     0     0     0];

m2 =[0     0     0     0     0
    0     0    12    11     0
    0    22   111   156     0
    0    32     0     0     0
    0    12     0     0     0];

    function f=first_way()
        f=sign((I-m1).^2-(I-m2).^2);
        f(f==0)=1;

    end

    function f= second_way()
        f = double(abs(I-m1) >= abs(I-m2));
        f(f==0) = -1;

    end

    function f= third_way()
        v1=abs(I-m1);
        v2=abs(I-m2);
        f= int8(v1>v2) + -1*int8(v1<v2); % need to convert to int from logical
        f(f==0) = 1;

    end

disp(['First way : '  num2str(timeit(@first_way))])
disp(['Second way: '  num2str(timeit(@second_way))])
disp(['Third way : '  num2str(timeit(@third_way))])

end

First way : 1.2897e-05 Second way: 1.9381e-05 Third way : 2.0077e-05

【问题讨论】:

  • 我不认为你的第二个公式是正确的,因为平方项会改变v_i(x,y) 的符号——除非你知道I &gt;= m_i 什么的。
  • 您到底在寻找什么?第一个等式还是第二个等式与题名一致但与第一个等式不匹配?
  • @Divakar 和 angdaers3:对不起,我弄错了第二个等式。我更新它。让我们再检查一次。我的目标是以最快的方式检查方程 1 中方程 f 的符号。因为,我们只考虑 f 的符号而不考虑它的实际值,因此,我们可以重新公式化以缩短计算时间
  • @john2182 将我编辑的代码最后添加到您的基准测试中,还请增加数据大小?如果内存允许,我会建议这样的东西 - N = 5000; I = randi(1000,N,N); m1 = randi(1000,N,N); m2 = randi(1000,N,N); 。随意更改N,但尽量保持较大的数字。
  • @Divakar:我再检查一次。抱歉,我的预期结果必须将 0 转换为 1。这意味着结果 f 只有 {1;-1}。所以我们需要添加 f(f==0) = -1;你有其他方程式可以更快吗?我提出了一个从等式 1 扩展而来的等式 2

标签: performance matlab image-processing optimization matrix


【解决方案1】:

这似乎是可比的,有时可能比原来的方法快一点 -

f = sign(abs(I-m1) - abs(I-m2)) + sign(abs(m1-m2)) + ...
    sign(abs(2*I-m1-m2)) - 1 -sign(abs(2*I-m1-m2) + abs(m1-m2))

基准代码

%// Create random inputs
N = 5000;
I = randi(1000,N,N);
m1 = randi(1000,N,N);
m2 = randi(1000,N,N);

num_iter = 20;  %// Number of iterations for all approaches

%// Warm up tic/toc.
for k = 1:100000
    tic(); elapsed = toc();
end

disp('------------------------- With Original Approach')
tic
for iter = 1:num_iter
    out1 = sign((I-m1).^2-(I-m2).^2);
    out1(out1==0)=-1;
end
toc, clear out1

disp('------------------------- With Proposed Approach')
tic
for iter = 1:num_iter    
    out2 = sign(abs(I-m1) - abs(I-m2)) + sign(abs(m1-m2)) + ...
           sign(abs(2*I-m1-m2)) - 1 -sign(abs(2*I-m1-m2) + abs(m1-m2));    
end
toc

结果

------------------------- With Original Approach
Elapsed time is 1.751966 seconds.
------------------------- With Proposed Approach
Elapsed time is 1.681263 seconds.

【讨论】:

  • 感谢迪瓦卡。我通过您的实现和 chepyle 比较了第一种方式和第二种方式。但是,最快的方法是第一种方法。为什么它是最快的,尽管它必须计算平方结果。
  • @john2182 如果第一种方式,你的意思是sign((I-m1).^2-(I-m2).^2),那么它给你一个错误的结果,对吧?另外,请确保选择足够大的数据来计时!使用这些小数据量,您将无法正确判断它们的表现!
  • 没有。第一种方式和第二种方式给出相同的结果。第一种方法计算 f 的结果,然后检查其符号。但是,它必须计算矩阵的平方。对于第二种方法,我们可以在没有矩阵平方的情况下计算 f 的符号。根据我的观察,第二种方式一定更快。但 matlab 显示它比第一种方式慢
  • @john2182 sign((I-m1).^2-(I-m2).^2) 没有给我与问题中的f 匹配的输出。你能再回来看看吗?请告诉我们预期的输出必须是什么!
  • 我在我的问题中显示了我的预期输出。我认为第一种方法必须添加一个代码为 f(f==0) = -1;
【解决方案2】:

第二个公式的准确性存在问题,但为了比较,这是我在 matlab 中实现它的方法,以及第三种避免平方的方法和 sign() 函数,符合您的意图。请注意,matlab 的矩阵和符号函数优化得很好,第二种和第三种方法都比较慢。

function compare()
I =[16    23    11    42    10
    11    21    22    24    30
    16    22   154   155   156
    25    28   145   151   156
    11    38   147   144   153];

m1 =[0     0     0     0     0
    0     0    22    11     0
    0    23    34    56     0
    0    56     0     0     0
    0    11     0     0     0];

m2 =[0     0     0     0     0
    0     0    12    11     0
    0    22   111   156     0
    0    32     0     0     0
    0    12     0     0     0];

    function f=first_way()
        f=sign((I-m1).^2-(I-m2).^2);
    end

    function f= second_way()
        v1=(I-m1);
        v2=(I-m2);
        f= int8(v1<=0 & v2>0) + -1* int8(v1>0 & v2<=0);
    end

    function f= third_way()
        v1=abs(I-m1);
        v2=abs(I-m2);
        f= int8(v1>v2) + -1*int8(v1<v2); % need to convert to int from logical
    end

disp(['First way : '  num2str(timeit(@first_way))])
disp(['Second way: '  num2str(timeit(@second_way))])
disp(['Third way : '  num2str(timeit(@third_way))])

end

输出:

First way : 9.4226e-06
Second way: 1.2247e-05
Third way : 1.1546e-05

【讨论】:

  • 您似乎对图像处理感兴趣-您能帮助我们打开这个专门的小组吗:area51.stackexchange.com/proposals/66531/computer-vision/72084 只需对少于 10 人的问题投票票。谢谢。
猜你喜欢
  • 2015-01-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多