2013-01-07 21 views
9

Belirli bir kenar algılama durumu için difference of guassians (DoG) gerçekleştirmeye çalışıyorum. algoritmanın Adından da anlaşılacağı gibi, aslında oldukça basittir: AncakOpenCV: Verimli Fark-of Gaussian

Mat g1, g2, result; 
Mat img = imread("test.png", CV_LOAD_IMAGE_COLOR); 
GaussianBlur(img, g1, Size(1,1), 0); 
GaussianBlur(img, g2, Size(3,3), 0); 
result = g1 - g2; 

, bu daha verimli yapılabileceğini duygu var. Veriler üzerinde daha az geçişte yapılabilir mi?

here soruları bana ayrılabilir filtreleri öğretti, ancak bu durumda bunları nasıl uygulayacağımı anlamak için çok fazla görüntü işleme uzmanıyım.

Birisi bunu nasıl optimize edebilecek konusunda bazı işaretçiler verebilir mi?

cevap

8

Ayrı filtreler normal gauss filtreleriyle aynı şekilde çalışır. Ayrılabilir filtreler, görüntü boyutu büyük olduğunda normal Gaussian'dan daha hızlıdır. Filtre çekirdeği analitik olarak oluşturulabilir ve filtre, biri yatay ve bir dikey olmak üzere iki boyutlu vektörlere ayrılabilir. örneğin

..

Şimdi bu yatay vektörü (Y) 1 2 1 ve dikey vektörü (V) 1 2 1. ayrılabilir

1 2 1 
2 4 2 
1 2 1 

bu filtre için bir filtre dikkate görüntüye iki filtre kümesi uygulanır. Vektör H yatay piksellere ve V dikey piksellere uygulanır. Gauss Bulanıklığı elde etmek için sonuçlar daha sonra eklenir. Ayrılabilir Gauss Bulanıklığı'nı yapan bir işlev yapıyorum. Gauss Bulanıklığı hesaplama FFT kullanmaktır geliştirmek için

Mat sepConv(Mat input, int radius) 
{ 


Mat sep; 
Mat dst,dst2; 

int ksize = 2 *radius +1; 
double sigma = radius/2.575; 

Mat gau = getGaussianKernel(ksize, sigma,CV_32FC1); 

Mat newgau = Mat(gau.rows,1,gau.type()); 
gau.col(0).copyTo(newgau.col(0)); 


filter2D(input, dst2, -1, newgau); 


filter2D(dst2.t(), dst, -1, newgau); 


return dst.t(); 


} 

Bir daha yöntemini: (P ben de tembelim, yorumlarla ilgili sorma bana lütfen). Veri boyutu oldukça büyükse, FFT tabanlı dönüşüm, ayrılabilir çekirdek yönteminden çok daha hızlıdır.

Hızlı google arama şu fonksiyonu

Mat Conv2ByFFT(Mat A,Mat B) 
{ 
Mat C; 
// reallocate the output array if needed 
C.create(abs(A.rows - B.rows)+1, abs(A.cols - B.cols)+1, A.type()); 
Size dftSize; 
// compute the size of DFT transform 
dftSize.width = getOptimalDFTSize(A.cols + B.cols - 1); 
dftSize.height = getOptimalDFTSize(A.rows + B.rows - 1); 

// allocate temporary buffers and initialize them with 0's 
Mat tempA(dftSize, A.type(), Scalar::all(0)); 
Mat tempB(dftSize, B.type(), Scalar::all(0)); 

// copy A and B to the top-left corners of tempA and tempB, respectively 
Mat roiA(tempA, Rect(0,0,A.cols,A.rows)); 
A.copyTo(roiA); 
Mat roiB(tempB, Rect(0,0,B.cols,B.rows)); 
B.copyTo(roiB); 

// now transform the padded A & B in-place; 
// use "nonzeroRows" hint for faster processing 
Mat Ax = computeDFT(tempA); 
Mat Bx = computeDFT(tempB); 

// multiply the spectrums; 
// the function handles packed spectrum representations well 
mulSpectrums(Ax, Bx, Ax,0,true); 

// transform the product back from the frequency domain. 
// Even though all the result rows will be non-zero, 
// we need only the first C.rows of them, and thus we 
// pass nonzeroRows == C.rows 
//dft(Ax, Ax, DFT_INVERSE + DFT_SCALE, C.rows); 

updateMag(Ax); 
Mat Cx = updateResult(Ax); 

//idft(tempA, tempA, DFT_SCALE, A.rows + B.rows - 1); 
// now copy the result back to C. 
Cx(Rect(0, 0, C.cols, C.rows)).copyTo(C); 
//C.convertTo(C, CV_8UC1); 
// all the temporary buffers will be deallocated automatically 
return C; 

} 

bu yardımcı olur Umut ile sağlandı.

+0

cv2.sepFilter2D, 2 filter2D aramayı yoğunlaştırabilir mi? –

0

Bu yazının eski olduğunu biliyorum. Fakat soru, içgüdüseldir ve gelecekteki okuyuculara müdahale edebilir. Bildiğim kadarıyla bir DoG filtresi ayrılmaz. Yani iki çözüm kalıyor: 1) GaussianBlur() fonksiyonunu iki kere çağırdıktan sonra iki görüntüyü de iki ekrandan çıkartın. 2) İki gauss çekirdeğinin farkını hesaplayarak bir çekirdek yapın, sonra görüntü ile onu çevirin.

Hangi çözüm daha hızlıdır: Çözüm 2, ilk bakışta daha hızlı görünür çünkü görüntü yalnızca bir kez katlanır. Ancak, bu bir ayrılabilir filtre içermiyor. Aksine, ilk çözüm iki ayrılabilir filtre içerir ve daha hızlı sonuç verebilir. (OpenCV fonksiyonu GaussianBlur() 'un nasıl optimize edildiğini ve ayrılabilir filtreler kullanıp kullanmadığını bilmiyorum. Fakat bu büyük olasılıkla.)

Ancak, eğer biri FFT tekniğini kullanıyorsa ikinci çözüm kesinlikle daha hızlıdır. Herhangi birinin bana tavsiyede bulunacak ya da düzeltmek istediği varsa, lütfen yapın.