首页 文章

转置矩阵/麻烦了解bsxfun的工作原理

提问于
浏览
2

这可能是一个奇怪的问题,因为许多人会想知道为什么要使用像 bsxfun 这样复杂的函数进行转置,而你有 .' 运算符 .

但是,转置对我来说不是问题 . 我构建自己的问题并尝试使用特定函数来解决,以便我了解函数的实际工作方式 . 我尝试使用 bsxfun 解决一些例子并成功获得了预期的结果 . 但是我的想法,我已经理解了这个功能如何工作,当我尝试这个例子时,它已经改变了 .

我拍摄的示例图像是方形2D图像,因此我不会尝试访问不可用的索引 .

Here is my code:

im = imread('cameraman.tif');
imshow(im);
[rows,cols] = size(im);

imout = bsxfun(@(r,c) im(c,r),(1:rows).',1:cols);

Error i got:

使用bsxfun时出错输出尺寸无效 . 测试错误(第9行)imout = bsxfun(@(r,c)im(c,r),(1:行) . ',1:cols);

PS: 我尝试在 im( , ) (如下: bsxfun(@(r,c) im(r,c),(1:rows).',1:cols) )内交换 rc ,它没有造成任何错误,我得到了与输入完全相同的图像 .


我也尝试使用循环和简单的转置使用 .' 运算符,它完美地工作 .

Here is my loopy code:

imout(size(im)) = 0;

for i = 1:rows
    for j = 1:cols
        imout(i,j) = im(j,i);
    end
end

答案我期待的是,我的代码有什么问题,错误意味着什么以及如何修改代码以使其工作 .

3 回答

  • 1

    这里的问题是你的函数没有返回与给定输入相同形状的输出 . 虽然 bsxfun 的要求是函数按元素操作,但不会使用标量元素调用它 . 所以,你需要这样做:

    x = randi(5, 4, 5)
    [m, n] = size(x);
    bsxfun(@(r, c) transpose(x(c, r)), (1:n)', 1:m)
    
  • 2

    您可以像这样使用anonymous functionbsxfun -

    %// Create the tranposed indices with BSXFUN
    idx = bsxfun(@(r,c) (c-1)*size(im,1)+r,1:rows,(1:cols).') %//'
    
    %// Index into input array with those indices for the final transposed output
    imout = im(idx)
    
  • 1

    我想知道 bsxfun 是如何工作的,所以我创建了一个这样的函数:

    bsxfun test function:

    function out = bsxfuntest(r,c)
        disp([size(r) , size(c)]);
        out = r + c;  // just normal addition so that it works fine.
    end
    

    My script:

    im = magic(5);
    
    [rows,cols] = size(im);
    
    bsxfun(@bsxfuntest ,(1:rows).',1:cols);
    

    Output: (不是函数输出的值 . 这些是使用 dispbsxfuntest.m 函数中打印的值)

    5     1     1     1
    
     5     1     1     1
    
     5     1     1     1
    
     5     1     1     1
    
     5     1     1     1
    

    Conclusion:

    bsxfun将每列传递给函数而不是每个元素 . 如果输入中的任何一个是标量,则该函数仅被调用一次,即矩阵无论是2D还是3D还是nD,都是一次性传递的 .

    Try this:

    bsxfun(@bsxfuntest , repmat(5,[5 5 5]) ,1);
    

    此外,如果两个输入都具有相同的尺寸,那么该函数也只被调用一次 .

    Try this:

    bsxfun(@bsxfuntest , repmat(5,[5 5 2]) , repmat(2,[5 5 2]))
    

    如果它们都不是标量,并且两个输入都具有不同的维度,那么输入将作为列向量传递 .

    Try this:

    bsxfun(@bsxfuntest , repmat(5,[5 5 1]) ,permute(1:3,[1 3 2]));
    

    and this:

    bsxfun(@bsxfuntest , repmat(5,[5 5 2]) ,permute(1:2,[1 3 2]));
    

    Coming to the problem

    >> im
    
    im =
    
    17    24     1     8    15
    23     5     7    14    16
     4     6    13    20    22
    10    12    19    21     3
    11    18    25     2     9
    

    Taking the code in the question:

    imout = bsxfun(@(r,c) im(c,r),(1:rows).',1:cols);
    

    当我尝试 im(c,r) ,即 im(1,(1:5).')

    >> im(1,(1:5).')
    
    ans =
    
    17    24     1     8    15
    

    这里, bsxfun 期望 column vector ,而输出是 row vector . 我猜这就是MatLab产生错误的原因

    无效的输出尺寸 .

    当我在上面的代码中替换 rc 时,这也是我没有得到任何错误的原因 bsxfun(@(r,c) im(r,c),(1:rows).',1:cols) . 因为在这里,输出本身就是列向量 .

    所以我试图转置结果以获得像这样的列向量:

    >> imout = bsxfun(@(r,c) (im(c,r)).',(1:rows).',1:cols)
    
    imout =
    
    17    23     4    10    11
    24     5     6    12    18
     1     7    13    19    25
     8    14    20    21     2
    15    16    22     3     9
    

    代码与Edrics's solution完全相同,它给出了预期的结果 .

相关问题