如何构建一个减少迭代的循环

时间:2015-12-11 19:58:26

标签: performance matlab loops image-processing

在MATLAB中,我有一个256x256的RGB图像和一个经过它的3x3内核。 3x3内核计算内核中9个像素的每对组合之间的颜色 - 欧氏距离,并将最大值存储在数组中。然后它移动1个像素并执行相同的计算,依此类推。

我可以轻松编写内核在图像上的移动,以及从内核中的像素中提取RGB值。

但是,我确实无法有效地计算每对像素组合的颜色 - 欧几里德距离操作。

例如,如果我有一个3x3矩阵,其中包含以下值:

[55 12 5; 77 15 99; 124 87 2]

我需要编写一个循环,使第一个元素执行第二个,第三个...第九个元素的操作。然后第二个元素用第3个,第4个...第9个元素执行操作,依此类推,直到最后第8个元素用第9个元素执行操作。优选地,相同的像素组合不应该再次计算(就像你用第7个计算第2个,不用第2个计算第7个)。

提前谢谢。

编辑:我的代码到目前为止

K=3;
s=1; %If S=0, don't reject, If S=1 Reject first max distance pixel pair
OI=imread('onion.png');
Rch = im2col(OI(:,:,1),[K,K],'sliding')
Gch = im2col(OI(:,:,2),[K,K],'sliding')
Bch = im2col(OI(:,:,3),[K,K],'sliding')

indexes = bsxfun(@gt,(1:K^2)',1:K^2)
a=find(indexes);
[idx1,idx2] = find(indexes);

Rsqdiff = (Rch(idx2,:) - Rch(idx1,:)).^2
Gsqdiff = (Gch(idx2,:) - Gch(idx1,:)).^2
Bsqdiff = (Bch(idx2,:) - Bch(idx1,:)).^2

dists = sqrt(double(Rsqdiff + Gsqdiff + Bsqdiff))                           %Distance values for all 36 combinations in 1 column
[maxdist,idx3] = max(dists,[],1)                                            %idx3 is each column's index of max value

if s==0
    y = reshape(maxdist,size(OI,1)-K+1,[])                                  %max value of each column (each column has 36 values)
elseif s==1
    [~,I]=max(maxdist);
    idx3=idx3(I);
    n=size(idx3,2);
    for i=1:1:n
        idx3(i)=a(idx3(i));
    end
    [I,J]=ind2sub([K*K K*K],idx3);
    for j=1:1:a
        [M,N]=ind2sub([K*K K*K],dists(j,:));
        M(I,:)=0;
        N(:,J)=0;
        dists(j,:)=sub2ind; %Incomplete line, don't know what to do here
    end
    [maxdist,idx3] = max(dists,[],1);
    y = reshape(maxdist,size(OI,1)-K+1,[]);
end

2 个答案:

答案 0 :(得分:4)

如果我正确理解了这个问题,那么您希望在滑动3x3窗口内形成唯一的成对组合,执行欧几里德距离计算,考虑所有三个通道,我们称之为 color-euclidean distance < / em>并最终挑选出每个滑动窗口的最大距离。因此,对于具有3x3元素的9窗口,您将拥有36个唯一对。如果图片大小为MxN,由于滑动性质,您会(M-3+1)*(N-3+1) = 64516(对于256x256个案例)这样的滑动窗口,每个都有36对,因此距离数组的大小为36x64516,最大距离的输出数组的大小为254x254。这里建议的实现涉及im2col将滑动窗口元素提取为列,nchoosek以形成对,最后执行这些对的三个通道之间的平方差的平方根,看起来像这样 -

K = 3; %// Kernel size
Rch = im2col(img(:,:,1),[K,K],'sliding')
Gch = im2col(img(:,:,2),[K,K],'sliding')
Bch = im2col(img(:,:,3),[K,K],'sliding')

[idx1,idx2] = find(bsxfun(@gt,(1:K^2)',1:K^2)); %//'

Rsqdiff = (Rch(idx2,:) - Rch(idx1,:)).^2
Gsqdiff = (Gch(idx2,:) - Gch(idx1,:)).^2
Bsqdiff = (Bch(idx2,:) - Bch(idx1,:)).^2

dists = sqrt(Rsqdiff + Gsqdiff + Bsqdiff)
out = reshape(max(dists,[],1),size(img,1)-K+1,[])

答案 1 :(得分:2)

你的问题很有趣,引起了我的注意。据我所知,你需要计算3x3内核中所有单元格的RGB颜色值之间的欧氏距离,并找到最大的一个。我建议使用T(n) = 3*T(n*2/3)函数和4D数组操作来实现此目的:

首先,我们填充输入数组并为每个方向创建8个移位版本:

circshift

接下来,我们创建一个数组,计算所有上述数组之间所有可能组合的差异:

DIM = 256;
A = zeros(DIM,DIM,3,9);
A(:,:,:,1) = round(255*rand(DIM,DIM,3));%// random 256x256 array (suppose it is your image)
A = padarray(A,[1,1]);%// add zeros on each side of image
%// compute shifted versions of the input array
%// and write them as 4th dimension starting from shifted up clockwise:
A(:,:,:,2) = circshift(A(:,:,:,1),[-1, 0]);
A(:,:,:,3) = circshift(A(:,:,:,1),[-1, 1]);
A(:,:,:,4) = circshift(A(:,:,:,1),[ 0, 1]);
A(:,:,:,5) = circshift(A(:,:,:,1),[ 1, 1]);
A(:,:,:,6) = circshift(A(:,:,:,1),[ 1, 0]);
A(:,:,:,7) = circshift(A(:,:,:,1),[ 1,-1]);
A(:,:,:,8) = circshift(A(:,:,:,1),[ 0,-1]);
A(:,:,:,9) = circshift(A(:,:,:,1),[-1,-1]);

最后,我们所拥有的是3x3内核中所有可能对之间的所有欧氏距离。我们所要做的就是提取最大值。据我所知,你不考虑图像边缘,所以:

q = nchoosek(1:9,2);
B = zeros(DIM+2,DIM+2,3,size(q,1));
for i = 1:size(q,1)
    B(:,:,:,i) = (A(:,:,:,q(i,1)) - A(:,:,:,q(i,2))).^2;
end
C = sqrt(sum(B,3));

C = sqrt(sum(B,3)); D = zeros(DIM-2); for i = 3:DIM for j = 3:DIM temp = C(i-1:i+1,j-1:j+1); D(i-2,j-2) = max(temp(:)); end end 是254x254阵列,A(2:255,2:255)的欧几里德距离最大,即我们排除图像边缘。

希望有所帮助。

P.S。我很惊讶@Divakar提供的代码很短。