2012-12-15 12 views
6

to jest nasze ćwiczenie w zadaniach domowych obróbki obrazu. mój kod działa poprawnie. Chciałbym uzyskać pomoc w optymalizacji kodu.Splot 2D w matlab - optymalizacja kodu

function C = convolve_slow(A,B) 
(file name is accordingly convolve_slow.m) 
This routine performs convolution between an image A and a mask B. 
Input:  A - a grayscale image (values in [0,255]) 
      B - a grayscale image (values in [0,255]) serves as a mask in the convolution. 
Output:  C - a grayscale image (values in [0,255]) - the output of the convolution. 
         C is the same size as A. 

Method: Convolve A with mask B using zero padding. Assume the origin of B is at 
    floor(size(B)/2)+1. 
Do NOT use matlab convolution routines (conv,conv2,filter2 etc). 
Make the routine as efficient as possible: Restrict usage of for loops which are expensive (use matrix multiplications and matlab routines such as dot etc). 
To simplify and reduce ifs, you should pad the image with zeros before starting your convolution loop. 
Do not assume the size of A nor B (B might actually be larger than A sometimes). 

Oto nasze rozwiązanie

function [ C ] = convolve_slow(A,B) 
%This routine performs convolution between an image A and a mask B. 
% Input:  A - a grayscale image (values in [0,255]) 
%    B - a grayscale image (values in [0,255]) serves as a mask in the convolution. 
% Output:  C - a grayscale image (values in [0,255]) - the output of the convolution. 
%    C is the same size as A. 
% 
% Method: Convolve A with mask B using zero padding. Assume the origin of B is at floor(size(B)/2)+1. 
% init C to size A with zeros 
C = zeros(size(A)); 
% make b xy-reflection and vector 
vectB = reshape(flipdim(flipdim(B,1),2)' ,[] , 1); 
% padding A with zeros 
paddedA = padarray(A, [floor(size(B,1)/2) floor(size(B,2)/2)]); 
% Loop over A matrix: 
for i = 1:size(A,1) 
    for j = 1:size(A,2) 
     startAi = i; 
     finishAi = i + size(B,1) - 1; 
     startAj = j; 
     finishAj = j + size(B,2) - 1; 
     vectPaddedA = reshape(paddedA(startAi :finishAi,startAj:finishAj)',1,[]); 
     C(i,j) = vectPaddedA* vectB; 
    end 
end 
end 

ponieważ jestem nowy na Przetwarzanie obrazu i Matlab. czy możesz mi pomóc w optymalizacji kodu, szczególnie przy użyciu operacji opartych na macierzy. czy można nie używać pętli?

+1

ty wolno używać fft2 i ifft2 działa w jakikolwiek sposób? Jeśli tak, byłby to sposób na szybkie znalezienie rozwiązania. – MarkV

+0

Nie, przepraszam, no fft, głównym założeniem jest to, że implementujemy splot, aby dowiedzieć się, jak to działa. to działa! teraz chcę zobaczyć, czy istnieje sposób, aby zrobić to lepiej. – Gilad

Odpowiedz

5

Bez wyraźnego zapisania kodu widzę sposób na przeniesienie go do jednej głównej pętli for. Zasadniczo, pomyśl o macierzy A i B jako wektorach kolumnowych, odsławiając każdą kolumnę A i B w wektor (tak to jest przechowywany wewnętrznie w MATLAB). Następnie każda koordynacja (i,j) z A może zostać odwzorowana na liniowy indeks k (stosując na przykład funkcję sub2ind). Następnie, dla każdego indeksu liniowego w ciele A (ignorowanie dopełnienia), oblicz listę indeksów liniowych odpowiadających submatrix wokół tego liniowego indeksu (który jest prawdopodobnie najtrudniejszą częścią tutaj). Następnie obliczyć produkt kropki A(theseIndices) i B(:). Dzięki tej metodzie właśnie przechodzisz do pętli z każdym indeksem liniowym A.

3

nie wiem, czy to jest szybciej, ale przynajmniej nie ma pętli (co nie znaczy, że musi być szybciej już w ostatnich wersjach matlab)

function A = tmpConv(A,B) 

    filterSize = size(B,1); 
    filterSize2 = floor(filterSize/2); 
    inputSize = size(A); 

    A = padarray(A,[filterSize2 filterSize2]); 

    f = repmat(B(:),[1 inputSize(1)*inputSize(2)]); 
    A = im2col(A,[filterSize filterSize]); 
    A = reshape(sum(A.*f),inputSize); 
+0

Oblicza to korelację, a nie splot. Trzeba by obrócić filtr o 180 stopni. Ponadto, budowanie macierzy "f" nie jest konieczne, ponieważ ten sam wynik jest uzyskiwany dzięki mnożeniu macierzowemu 'A'' z (odwróconym) wektorem filtru. – Joost