将 "keep top N values" 蒙版应用于图像,以块为单位

Applying a "keep top N values" mask to image, in blocks

我很难理解如何在数据块/矩阵的子矩阵上应用函数。

我的任务是拍摄一张图像,将其分成 8x8 块,然后从每个块中选择 8 个最大值并将其余值设置为零。我知道方法可以通过 for 循环,但我想学习如何在数据块上应用函数。

目前,我正在将一个函数应用到整个 256x256 矩阵,但我需要找到一种方法如何将它应用到每个 8x8 块上。这是我的注释代码:

%% DCT transformation
I = imread('cameraman.tif');
I = im2double(I);
T = dctmtx(8); %returns the 8-by-8 DCT transform matrix
dct = @(block_struct) T * block_struct.data * T';
B = blockproc(I,[8 8],dct);
% Here I want to apply my function applyMask to blocks of 8x8 individualy
%this function will take a block 8x8, sort it, pick 8 biggest ones, save
%them and set rest to zero
f = @applyMask;
b = f(B)
function y = applyMask(x)
vector = x(:); %retransform matrix to be sorted
y=zeros(8,8)   %prepare matrix where 8 biggest values will be stored (rest is zero)
sorted = transpose(sort(vector,'descend')) %sort vecotr in descending order
pick = sorted(1:1, 1:8) %takes just first 8 biggest values 
for k=1 : 8
for i=1 : 8
    for j=1 : 8
        if ((x(i,j)==pick(1,k)) && nnz(y)<8 ) %if there is one of the 8 biggest - keep
           y(i,j)= pick(1,k) %put 8 biggest values to matrix
        end
    end
end

end
end

您的代码可以从矢量化中获益(即移除 for 循环)。

function C = q52688681
%% DCT transformation
I = imread('cameraman.tif');
I = im2double(I);
T = dctmtx(8); %returns the 8-by-8 DCT transform matrix
B = blockproc(I,[8 8], @(block_struct) T * block_struct.data * T.');
C = blockproc(I,[8 8], @applyMask);

function out = applyMask(img)
NMAX = 8;
out = zeros(size(img.data));
[~,idx] = maxk(img.data(:), NMAX);
out(idx) = img.data(idx);

如果你的MATLAB版本是>= R2017b,你可以使用maxk,否则:

function out = applyMask(img)
NMAX = 8;
out = zeros(size(img.data));
[~,idx] = sort(img.data(:), 'descend');
out( idx(1:NMAX) ) = img.data( idx(1:NMAX) );

并且您可以通过这样做进一步减少代码量和计算量:

function B = q52688681
NMAX = 8;
I = im2double(imread('cameraman.tif'));
B = blockproc(I, [NMAX NMAX], @(x)applyMask(x, NMAX, dctmtx(NMAX)) );

function out = applyMask(blk, nmax, T)
img = T * blk.data * T.';
out = zeros(size(img));
[~,idx] = sort(img(:), 'descend');
out( idx(1:nmax) ) = img( idx(1:nmax) );

如果这段代码有任何不清楚的地方,请在评论中告诉我,我会尽力解释。