如何构建一个迭代次数逐步减少的循环。

3
在MATLAB中,我有一个256x256的RGB图像和一个3x3的核,可以对其进行操作。 3x3的核计算核内9个像素之间的颜色欧几里得距离,并将最大值存储在数组中。然后,它移动1个像素并执行相同的计算,以此类推。
我可以很容易地编写移动核心到图像上的代码,以及从核心像素中提取RGB值的代码。但是,我确实遇到了计算每对像素之间的颜色欧几里得距离的效率问题。
例如,如果我有一个以下值的3x3矩阵:
[55 12 5; 77 15 99; 124 87 2]
我需要编写一个循环,使第一个元素与第二个、第三个...第九个元素执行操作。然后第二个元素与第三个、第四个...第九个元素执行操作,以此类推,直到最后一个元素与第九个元素执行操作。最好不要重复计算相同的像素组合(例如,如果您已经计算了第2个和第7个,则不要再计算第7个和第2个)。
提前感谢你。
编辑:到目前为止我的代码如下:
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

关于双遍滤波怎么样?先进行一次操作来计算每个像素的距离,然后再进行一次操作来取最大值。 - Daniel
我该如何做呢?我是一名初学者。感谢您的建议。 - teeniv
请将您已经获得的代码添加到您的问题中。 - Daniel
请注意,代码很基础,您可以自由重构它。 - teeniv
“256x256”图像的输出数组大小将是多少? - Divakar
2个回答

4

如果我正确理解了问题,您希望在滑动的3x3窗口内形成唯一的成对组合,执行欧几里得距离计算并考虑所有三个通道,我们称之为颜色欧几里得距离,最后挑选出每个滑动窗口中所有距离中最大的。因此,对于一个具有9个元素的3x3窗口,您将拥有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,[])

你本可以在 max 操作之后再进行 sqrt 操作的! - user4085386
@smlq 是的,那是一个小的优化,谢谢! - Divakar
这正是我在寻找的。如果我没有恰当地表达我的问题,那么很抱歉,但你似乎已经理解了! - teeniv
@user3749634 不用担心,但我猜以后你可以在提问方面有所改进 :) - Divakar
我的下一步是拒绝每列距离最大的dist中的距离(同时也拒绝创建最大值的像素对),然后找到每列中的下一个最大值,这是由两个不同的像素造成的。我已经输入了主帖中我拥有的代码。 - teeniv

2
您的问题很有趣,吸引了我的注意。据我所理解,您需要计算3x3内核中所有单元格的RGB颜色值之间的欧几里得距离,并找到其中最大的距离。我建议使用circshift函数和4D数组操作来实现这一点:

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

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]);

接下来,我们创建一个数组来计算所有上述数组之间可能组合的差值:
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));

最后,我们得到的是3x3内核中所有可能对之间的欧几里得距离。我们所要做的就是提取最大值。据我了解,您不考虑图像边缘,因此:

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

D是254x254的数组,用于计算A(2:255,2:255)之间的最大欧几里得距离,即我们排除图像边缘。

希望这有所帮助。

P.S. 我对@Divakar提供的代码的简洁感到惊讶。


谢谢您的回复!我很感激您解释了您所做的每一步,这有助于消除我对逻辑方面的一些疑虑。 - teeniv

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接