转置矩阵/无法理解 bsxfun 的工作原理
Transposing matrix / Trouble understanding how bsxfun works
这可能是一个奇怪的问题,因为许多人会想知道为什么在拥有 .'
运算符的情况下使用像 bsxfun
这样复杂的函数进行转置。
但是,移调对我来说不是问题。我提出自己的问题并尝试使用特定函数来解决,以便我了解该函数的实际工作原理。我尝试使用 bsxfun
解决一些示例,并成功获得了预期的结果。但是我的想法,我已经理解这个函数是如何工作的,当我尝试这个例子时改变了。
我拍摄的示例图像是方形 2D 图像,因此我不会尝试访问不可用的索引。
这是我的代码:
im = imread('cameraman.tif');
imshow(im);
[rows,cols] = size(im);
imout = bsxfun(@(r,c) im(c,r),(1:rows).',1:cols);
我得到的错误:
Error using bsxfun
Invalid output dimensions.
Error in test (line 9)
imout = bsxfun(@(r,c) im(c,r),(1:rows).',1:cols);
PS: 我尝试在 im( , )
中交换 r
和 c
(像这样:bsxfun(@(r,c) im(r,c),(1:rows).',1:cols)
) 没有造成任何错误,我得到了与输入完全相同的图像。
我也尝试过使用循环和使用 .'
运算符的简单转置,效果很好。
这是我的循环代码:
imout(size(im)) = 0;
for i = 1:rows
for j = 1:cols
imout(i,j) = im(j,i);
end
end
我期待的答案是,我的代码有什么问题,错误意味着什么以及如何修改代码以使其工作。
你可以像这样使用anonymous function
with bsxfun
-
%// 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)
这里的问题是您的函数 return 输出的形状与给定的输入的形状不同。尽管 bsxfun
的要求是该函数按元素运行,但不使用标量元素调用它。所以,你需要这样做:
x = randi(5, 4, 5)
[m, n] = size(x);
bsxfun(@(r, c) transpose(x(c, r)), (1:n)', 1:m)
我想知道 bsxfun
是如何工作的,所以我创建了一个这样的函数:
bsxfun
测试函数:
function out = bsxfuntest(r,c)
disp([size(r) , size(c)]);
out = r + c; // just normal addition so that it works fine.
end
我的脚本:
im = magic(5);
[rows,cols] = size(im);
bsxfun(@bsxfuntest ,(1:rows).',1:cols);
输出:(不是函数的输出值。这些是使用 disp
在 bsxfuntest.m
函数中打印的值)
5 1 1 1
5 1 1 1
5 1 1 1
5 1 1 1
5 1 1 1
结论:
bsxfun
passes each column into the function instead of each element.
If either one of the input is a scalar, then the function is called only one time i.e the matrix whether it is 2D or 3D or nD, is passed in one go.
试试这个:
bsxfun(@bsxfuntest , repmat(5,[5 5 5]) ,1);
Also if both the inputs are of same dimensions, then also the function is called only one time.
试试这个:
bsxfun(@bsxfuntest , repmat(5,[5 5 2]) , repmat(2,[5 5 2]))
If none of them is a scalar, and both the inputs are of different dimensions, then The inputs are passed as column vectors.
试试这个:
bsxfun(@bsxfuntest , repmat(5,[5 5 1]) ,permute(1:3,[1 3 2]));
和这个:
bsxfun(@bsxfuntest , repmat(5,[5 5 2]) ,permute(1:2,[1 3 2]));
问题来了
>> 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
取题中代码:
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
需要一个 列向量 ,而输出是一个 行向量 。我想这就是 MatLab 产生错误
的原因
Invalid output dimensions.
这也是为什么当我像这样 bsxfun(@(r,c) im(r,c),(1:rows).',1:cols)
替换上面代码中的 r
和 c
时没有出现任何错误的原因。因为在这里,输出本身就是一个列向量。
所以我尝试转置结果以获得这样的列向量:
>> 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
代码与 完全相同,并且给出了预期的结果。
这可能是一个奇怪的问题,因为许多人会想知道为什么在拥有 .'
运算符的情况下使用像 bsxfun
这样复杂的函数进行转置。
但是,移调对我来说不是问题。我提出自己的问题并尝试使用特定函数来解决,以便我了解该函数的实际工作原理。我尝试使用 bsxfun
解决一些示例,并成功获得了预期的结果。但是我的想法,我已经理解这个函数是如何工作的,当我尝试这个例子时改变了。
我拍摄的示例图像是方形 2D 图像,因此我不会尝试访问不可用的索引。
这是我的代码:
im = imread('cameraman.tif');
imshow(im);
[rows,cols] = size(im);
imout = bsxfun(@(r,c) im(c,r),(1:rows).',1:cols);
我得到的错误:
Error using bsxfun
Invalid output dimensions.Error in test (line 9)
imout = bsxfun(@(r,c) im(c,r),(1:rows).',1:cols);
PS: 我尝试在 im( , )
中交换 r
和 c
(像这样:bsxfun(@(r,c) im(r,c),(1:rows).',1:cols)
) 没有造成任何错误,我得到了与输入完全相同的图像。
我也尝试过使用循环和使用 .'
运算符的简单转置,效果很好。
这是我的循环代码:
imout(size(im)) = 0;
for i = 1:rows
for j = 1:cols
imout(i,j) = im(j,i);
end
end
我期待的答案是,我的代码有什么问题,错误意味着什么以及如何修改代码以使其工作。
你可以像这样使用anonymous function
with bsxfun
-
%// 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)
这里的问题是您的函数 return 输出的形状与给定的输入的形状不同。尽管 bsxfun
的要求是该函数按元素运行,但不使用标量元素调用它。所以,你需要这样做:
x = randi(5, 4, 5)
[m, n] = size(x);
bsxfun(@(r, c) transpose(x(c, r)), (1:n)', 1:m)
我想知道 bsxfun
是如何工作的,所以我创建了一个这样的函数:
bsxfun
测试函数:
function out = bsxfuntest(r,c)
disp([size(r) , size(c)]);
out = r + c; // just normal addition so that it works fine.
end
我的脚本:
im = magic(5);
[rows,cols] = size(im);
bsxfun(@bsxfuntest ,(1:rows).',1:cols);
输出:(不是函数的输出值。这些是使用 disp
在 bsxfuntest.m
函数中打印的值)
5 1 1 1
5 1 1 1
5 1 1 1
5 1 1 1
5 1 1 1
结论:
bsxfun
passes each column into the function instead of each element.If either one of the input is a scalar, then the function is called only one time i.e the matrix whether it is 2D or 3D or nD, is passed in one go.
试试这个:
bsxfun(@bsxfuntest , repmat(5,[5 5 5]) ,1);
Also if both the inputs are of same dimensions, then also the function is called only one time.
试试这个:
bsxfun(@bsxfuntest , repmat(5,[5 5 2]) , repmat(2,[5 5 2]))
If none of them is a scalar, and both the inputs are of different dimensions, then The inputs are passed as column vectors.
试试这个:
bsxfun(@bsxfuntest , repmat(5,[5 5 1]) ,permute(1:3,[1 3 2]));
和这个:
bsxfun(@bsxfuntest , repmat(5,[5 5 2]) ,permute(1:2,[1 3 2]));
问题来了
>> 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
取题中代码:
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
需要一个 列向量 ,而输出是一个 行向量 。我想这就是 MatLab 产生错误
Invalid output dimensions.
这也是为什么当我像这样 bsxfun(@(r,c) im(r,c),(1:rows).',1:cols)
替换上面代码中的 r
和 c
时没有出现任何错误的原因。因为在这里,输出本身就是一个列向量。
所以我尝试转置结果以获得这样的列向量:
>> 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
代码与