在matlab中的循环中平均矩阵的一个子集
Average a subset of a matrix in a loop in matlab
我使用我认为是矩阵的图像。
我想将 800 x 800 矩阵 (A) 转换为 400 x 400 矩阵 (B),其中 A 矩阵的 4 个单元格的平均值 = B 矩阵的 1 个单元格(我知道这不正确代码行):
B[1,1] =mean2(A[1,1 + 1,2 + 2,1 + 2,2])
整个矩阵依此类推...
B [1,2]=mean2(A[1,3 + 1,4 + 2,3 + 2,4 ])
我想:
1) 将 A 矩阵重塑为 2 x 320 000 矩阵,这样我就得到了我需要相邻平均的四个单元格,之后处理行号更容易。
Im4bis=reshape(permute(reshape(Im4,size(Im4,2),2,[]),[2,3,1]),2,[]);
2) 用我需要平均(子集化)的 4 个单元格创建一个单元格数组并计算它的平均值。这就是它不起作用的地方
I{1,160000}=ones,
for k=drange(1:2:319999)
for n=1:160000
I{n}=mean2(Im4bis(1:2,k:k+1));
end
end
我创建了一个 400 x 400 个单元格的空矩阵(实际上是一个 1 x 160000 的向量),我想用平均值填充它,但我得到一个 1 x 319 999 个单元格的矩阵,其中一个单元格是 2 个单元格空.
寻找光线
我的输入图像:
让 A
表示您的矩阵,
m = 2; %// block size: rows
n = 2; %// block size: columns
方法一
使用blockproc
:
B = blockproc(A, [m n], @(x) mean(x.data(:)));
示例:
>> A = magic(6)
A =
35 1 6 26 19 24
3 32 7 21 23 25
31 9 2 22 27 20
8 28 33 17 10 15
30 5 34 12 14 16
4 36 29 13 18 11
>> B = blockproc(A, [m n], @(x) mean(x.data(:)))
B =
17.7500 15.0000 22.7500
19.0000 18.5000 18.0000
18.7500 22.0000 14.7500
方法二
如果您更喜欢重塑方式(这可能更快),请使用 this great answer 将矩阵组织成沿第三维平铺的 2x2 块,沿前两个维度取平均值,然后重塑结果:
T = permute(reshape(permute(reshape(A, size(A, 1), n, []), [2 1 3]), n, m, []), [2 1 3]);
B = reshape(mean(mean(T,1),2), size(A,1)/m, size(A,2)/n);
方法三
应用二维卷积(conv2
) and then downsample. The convolution computes more entries than are really necessary (hence the downsampling), but on the other hand it can be done separably,这有助于加快速度:
B = conv2(ones(m,1)/m, ones(1,n)/n ,A,'same');
B = B(m-1:m:end ,n-1:n:end);
方法一
AC = mat2cell(A, repmat(2,size(A,1)/2,1), repmat(2,size(A,2)/2,1));
out = cellfun(@(x) mean(x(:)), AC);
方法二
使用im2col
out = reshape(mean(im2col(A,[2 2],'distinct')),size(A)./2);
方法三
使用简单for
循环
out(size(A,1)/2,size(A,2)/2) = 0;
k = 1;
for i = 1:2:size(A,1)
l = 1;
for j = 1:2:size(A,2)
out(k,l) = mean(mean(A(i:i+1,j:j+1)));
l = l+1;
end
k = k+1;
end
输入图像测试:
A = rgb2gray(imread('inputImage.png'));
%// Here, You could use any of the method from any answers
%// or you could use the best method from the bench-marking tests done by Divakar
out = reshape(mean(im2col(A,[2 2],'distinct')),size(A)./2);
imshow(uint8(out));
imwrite(uint8(out),'outputImage.bmp');
输出图像:
通过读取已写入的图像进行最终检查
B = imread('outputImage.bmp');
>> whos B
Name Size Bytes Class Attributes
B 400x400 160000 uint8
基于 this solution
的一种方法,使用 reshape
、sum
和 squeeze
-
sublen = 2; %// subset length
part1 = reshape(sum(reshape(A,sublen,[])),size(A,1)/sublen,sublen,[]);
out = squeeze(sum(part1,2))/sublen^2;
基准测试
设置#1
以下是目前所列方法针对 800x 800
-
输入数据大小的运行时比较
%// Input
A = rand(800,800);
%// Warm up tic/toc.
for k = 1:50000
tic(); elapsed = toc();
end
disp('----------------------- With RESHAPE + SUM + SQUEEZE')
tic
sublen = 2; %// subset length
part1 = reshape(sum(reshape(A,sublen,[])),size(A,1)/sublen,sublen,[]);
out = squeeze(sum(part1,2))/sublen^2;
toc, clear sublen part1 out
disp('----------------------- With BLOCKPROC')
tic
B = blockproc(A, [2 2], @(x) mean(x.data(:))); %// [m n]
toc, clear B
disp('----------------------- With PERMUTE + MEAN + RESHAPE')
tic
m = 2;n = 2;
T = permute(reshape(permute(reshape(A, size(A, 1), n, []),...
[2 1 3]), n, m, []), [2 1 3]);
B = reshape(mean(mean(T,1),2), size(A,1)/m, size(A,2)/m);
toc, clear B T m n
disp('----------------------- With CONVOLUTION')
tic
m = 2;n = 2;
B = conv2(ones(m,1)/m, ones(1,n)/n ,A,'same');
B = B(m-1:m:end ,n-1:n:end);
toc, clear m n B
disp('----------------------- With MAT2CELL')
tic
AC = mat2cell(A, repmat(2,size(A,1)/2,1), repmat(2,size(A,2)/2,1));
out = cellfun(@(x) mean(x(:)), AC);
toc
disp('----------------------- With IM2COL')
tic
out = reshape(mean(im2col(A,[2 2],'distinct')),size(A)./2);
toc
运行时结果 -
----------------------- With RESHAPE + SUM + SQUEEZE
Elapsed time is 0.004702 seconds.
----------------------- With BLOCKPROC
Elapsed time is 6.039851 seconds.
----------------------- With PERMUTE + MEAN + RESHAPE
Elapsed time is 0.006015 seconds.
----------------------- With CONVOLUTION
Elapsed time is 0.002174 seconds.
----------------------- With MAT2CELL
Elapsed time is 2.362291 seconds.
----------------------- With IM2COL
Elapsed time is 0.239218 seconds.
为了使运行时间更公平,我们可以在最快的三种方法之上使用 1000
的多次试验,以获得相同的输入数据大小 800 x 800
,从而得到 -
----------------------- With RESHAPE + SUM + SQUEEZE
Elapsed time is 1.264722 seconds.
----------------------- With PERMUTE + MEAN + RESHAPE
Elapsed time is 3.986038 seconds.
----------------------- With CONVOLUTION
Elapsed time is 1.992030 seconds.
设置#2
以下是针对 10000x 10000
的较大输入数据大小的三种最快方法的运行时比较 -
----------------------- With RESHAPE + SUM + SQUEEZE
Elapsed time is 0.158483 seconds.
----------------------- With PERMUTE + MEAN + RESHAPE
Elapsed time is 0.589322 seconds.
----------------------- With CONVOLUTION
Elapsed time is 0.307836 seconds.
我使用我认为是矩阵的图像。
我想将 800 x 800 矩阵 (A) 转换为 400 x 400 矩阵 (B),其中 A 矩阵的 4 个单元格的平均值 = B 矩阵的 1 个单元格(我知道这不正确代码行):
B[1,1] =mean2(A[1,1 + 1,2 + 2,1 + 2,2])
整个矩阵依此类推...
B [1,2]=mean2(A[1,3 + 1,4 + 2,3 + 2,4 ])
我想:
1) 将 A 矩阵重塑为 2 x 320 000 矩阵,这样我就得到了我需要相邻平均的四个单元格,之后处理行号更容易。
Im4bis=reshape(permute(reshape(Im4,size(Im4,2),2,[]),[2,3,1]),2,[]);
2) 用我需要平均(子集化)的 4 个单元格创建一个单元格数组并计算它的平均值。这就是它不起作用的地方
I{1,160000}=ones,
for k=drange(1:2:319999)
for n=1:160000
I{n}=mean2(Im4bis(1:2,k:k+1));
end
end
我创建了一个 400 x 400 个单元格的空矩阵(实际上是一个 1 x 160000 的向量),我想用平均值填充它,但我得到一个 1 x 319 999 个单元格的矩阵,其中一个单元格是 2 个单元格空.
寻找光线
我的输入图像:
让 A
表示您的矩阵,
m = 2; %// block size: rows
n = 2; %// block size: columns
方法一
使用blockproc
:
B = blockproc(A, [m n], @(x) mean(x.data(:)));
示例:
>> A = magic(6)
A =
35 1 6 26 19 24
3 32 7 21 23 25
31 9 2 22 27 20
8 28 33 17 10 15
30 5 34 12 14 16
4 36 29 13 18 11
>> B = blockproc(A, [m n], @(x) mean(x.data(:)))
B =
17.7500 15.0000 22.7500
19.0000 18.5000 18.0000
18.7500 22.0000 14.7500
方法二
如果您更喜欢重塑方式(这可能更快),请使用 this great answer 将矩阵组织成沿第三维平铺的 2x2 块,沿前两个维度取平均值,然后重塑结果:
T = permute(reshape(permute(reshape(A, size(A, 1), n, []), [2 1 3]), n, m, []), [2 1 3]);
B = reshape(mean(mean(T,1),2), size(A,1)/m, size(A,2)/n);
方法三
应用二维卷积(conv2
) and then downsample. The convolution computes more entries than are really necessary (hence the downsampling), but on the other hand it can be done separably,这有助于加快速度:
B = conv2(ones(m,1)/m, ones(1,n)/n ,A,'same');
B = B(m-1:m:end ,n-1:n:end);
方法一
AC = mat2cell(A, repmat(2,size(A,1)/2,1), repmat(2,size(A,2)/2,1));
out = cellfun(@(x) mean(x(:)), AC);
方法二
使用im2col
out = reshape(mean(im2col(A,[2 2],'distinct')),size(A)./2);
方法三
使用简单for
循环
out(size(A,1)/2,size(A,2)/2) = 0;
k = 1;
for i = 1:2:size(A,1)
l = 1;
for j = 1:2:size(A,2)
out(k,l) = mean(mean(A(i:i+1,j:j+1)));
l = l+1;
end
k = k+1;
end
输入图像测试:
A = rgb2gray(imread('inputImage.png'));
%// Here, You could use any of the method from any answers
%// or you could use the best method from the bench-marking tests done by Divakar
out = reshape(mean(im2col(A,[2 2],'distinct')),size(A)./2);
imshow(uint8(out));
imwrite(uint8(out),'outputImage.bmp');
输出图像:
通过读取已写入的图像进行最终检查
B = imread('outputImage.bmp');
>> whos B
Name Size Bytes Class Attributes
B 400x400 160000 uint8
基于 this solution
的一种方法,使用 reshape
、sum
和 squeeze
-
sublen = 2; %// subset length
part1 = reshape(sum(reshape(A,sublen,[])),size(A,1)/sublen,sublen,[]);
out = squeeze(sum(part1,2))/sublen^2;
基准测试
设置#1
以下是目前所列方法针对 800x 800
-
%// Input
A = rand(800,800);
%// Warm up tic/toc.
for k = 1:50000
tic(); elapsed = toc();
end
disp('----------------------- With RESHAPE + SUM + SQUEEZE')
tic
sublen = 2; %// subset length
part1 = reshape(sum(reshape(A,sublen,[])),size(A,1)/sublen,sublen,[]);
out = squeeze(sum(part1,2))/sublen^2;
toc, clear sublen part1 out
disp('----------------------- With BLOCKPROC')
tic
B = blockproc(A, [2 2], @(x) mean(x.data(:))); %// [m n]
toc, clear B
disp('----------------------- With PERMUTE + MEAN + RESHAPE')
tic
m = 2;n = 2;
T = permute(reshape(permute(reshape(A, size(A, 1), n, []),...
[2 1 3]), n, m, []), [2 1 3]);
B = reshape(mean(mean(T,1),2), size(A,1)/m, size(A,2)/m);
toc, clear B T m n
disp('----------------------- With CONVOLUTION')
tic
m = 2;n = 2;
B = conv2(ones(m,1)/m, ones(1,n)/n ,A,'same');
B = B(m-1:m:end ,n-1:n:end);
toc, clear m n B
disp('----------------------- With MAT2CELL')
tic
AC = mat2cell(A, repmat(2,size(A,1)/2,1), repmat(2,size(A,2)/2,1));
out = cellfun(@(x) mean(x(:)), AC);
toc
disp('----------------------- With IM2COL')
tic
out = reshape(mean(im2col(A,[2 2],'distinct')),size(A)./2);
toc
运行时结果 -
----------------------- With RESHAPE + SUM + SQUEEZE
Elapsed time is 0.004702 seconds.
----------------------- With BLOCKPROC
Elapsed time is 6.039851 seconds.
----------------------- With PERMUTE + MEAN + RESHAPE
Elapsed time is 0.006015 seconds.
----------------------- With CONVOLUTION
Elapsed time is 0.002174 seconds.
----------------------- With MAT2CELL
Elapsed time is 2.362291 seconds.
----------------------- With IM2COL
Elapsed time is 0.239218 seconds.
为了使运行时间更公平,我们可以在最快的三种方法之上使用 1000
的多次试验,以获得相同的输入数据大小 800 x 800
,从而得到 -
----------------------- With RESHAPE + SUM + SQUEEZE
Elapsed time is 1.264722 seconds.
----------------------- With PERMUTE + MEAN + RESHAPE
Elapsed time is 3.986038 seconds.
----------------------- With CONVOLUTION
Elapsed time is 1.992030 seconds.
设置#2
以下是针对 10000x 10000
的较大输入数据大小的三种最快方法的运行时比较 -
----------------------- With RESHAPE + SUM + SQUEEZE
Elapsed time is 0.158483 seconds.
----------------------- With PERMUTE + MEAN + RESHAPE
Elapsed time is 0.589322 seconds.
----------------------- With CONVOLUTION
Elapsed time is 0.307836 seconds.