首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >转置矩阵/理解bsxfun的工作原理

转置矩阵/理解bsxfun的工作原理
EN

Stack Overflow用户
提问于 2015-05-01 06:59:58
回答 3查看 251关注 0票数 2

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

但是,换位对我来说不是个问题。我提出了我自己的问题,并试图使用特定的函数来解决,这样我就可以了解这个函数是如何工作的。我试着用bsxfun解决一些例子,并成功地获得了预期的结果。但是当我尝试这个例子时,我的想法,我已经理解了这个函数的工作原理,改变了。

我所拍摄的示例图像是一个正方形的2D图像,因此我不会试图访问不可用的索引。

这里是我的代码:

代码语言:javascript
复制
im = imread('cameraman.tif');
imshow(im);
[rows,cols] = size(im);

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

我得到的错误:

使用bsxfun时出错 输出维数无效。 测试中的错误(第9行) imout = bsxfun(@(r,c) im(c,r),(1:row).‘,1:cols);

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

我还尝试了使用循环和简单的转置使用.'操作符,这是非常完美的。

,这是我的代码:

代码语言:javascript
复制
imout(size(im)) = 0;

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

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

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-05-01 10:00:00

这里的问题是,您的函数返回的输出形状与给定输入的形状不同。尽管对bsxfun的要求是函数按元素进行操作,但它不是用标量元素调用的。所以,你需要这样做:

代码语言:javascript
复制
x = randi(5, 4, 5)
[m, n] = size(x);
bsxfun(@(r, c) transpose(x(c, r)), (1:n)', 1:m)
票数 1
EN

Stack Overflow用户

发布于 2015-05-01 07:32:02

你可以和anonymous function一起使用bsxfun就像这样-

代码语言:javascript
复制
%// 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)
票数 2
EN

Stack Overflow用户

发布于 2015-05-01 13:40:15

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

bsxfun 测试函数:

代码语言:javascript
复制
function out = bsxfuntest(r,c)
    disp([size(r) , size(c)]);
    out = r + c;  // just normal addition so that it works fine.
end

我的脚本:

代码语言:javascript
复制
im = magic(5);

[rows,cols] = size(im);

bsxfun(@bsxfuntest ,(1:rows).',1:cols);

输出:(不是函数输出的值)。这些都是在bsxfuntest.m函数中使用disp打印的)

代码语言:javascript
复制
 5     1     1     1

 5     1     1     1

 5     1     1     1

 5     1     1     1

 5     1     1     1

结论:

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

尝试如下:

代码语言:javascript
复制
bsxfun(@bsxfuntest , repmat(5,[5 5 5]) ,1);

另外,如果两个输入都具有相同的维数,那么函数也只能被调用一次。

尝试如下:

代码语言:javascript
复制
bsxfun(@bsxfuntest , repmat(5,[5 5 2]) , repmat(2,[5 5 2]))  

如果它们都不是标量,且两种输入都有不同的维数,则输入作为列向量传递。

尝试如下:

代码语言:javascript
复制
bsxfun(@bsxfuntest , repmat(5,[5 5 1]) ,permute(1:3,[1 3 2]));

和这个:

代码语言:javascript
复制
bsxfun(@bsxfuntest , repmat(5,[5 5 2]) ,permute(1:2,[1 3 2]));    

来解决问题

代码语言:javascript
复制
>> 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

接受问题中的代码:

代码语言:javascript
复制
imout = bsxfun(@(r,c) im(c,r),(1:rows).',1:cols);

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

代码语言:javascript
复制
>> im(1,(1:5).')

ans =

17    24     1     8    15   

在这里,bsxfun需要一个列向量,而输出是行向量。我猜这就是为什么MatLab产生错误的原因

输出维数无效。

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

因此,我试图将结果转到如下所示的列向量:

代码语言:javascript
复制
>> 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完全相同,并给出了预期的结果。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29982866

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档