2013-01-07 2 views
9

특정 가장자리 감지의 경우 difference of guassians (DoG)을 구현하려고합니다. 알고리즘의 이름에서 알 수 있듯이, 실제로는 매우 간단합니다 : 그러나OpenCV : 효율적인 가우스 차이

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; 

,이보다 효율적으로 수행 할 수 있다는 느낌이 듭니다. 데이터에 대한 패스가 적어 질 수 있습니까?

질문 : here은 분리 가능한 필터에 대해 가르쳐 왔지만,이 경우에 적용하는 방법을 이해하기에는 이미지 처리 초보자가 너무 많습니다.

아무도 나를이 방법을 최적화 할 수있는 방법에 대한 몇 가지 지침을 줄 수 있습니까?

답변

8

분리 가능한 필터는 일반 가우스 필터와 동일한 방식으로 작동합니다. 분리 가능한 필터는 이미지 크기가 클 때 일반 가우스보다 빠릅니다. 필터 커널은 분석적으로 형성 될 수 있고 필터는 수평 및 수직 중 하나의 2 차원 벡터로 분리 될 수 있습니다. 예

은 ..

이제 이러한 수평 벡터 (H) 1 2 1 수직 벡터 (V) (1) (2) (1)로 분리 될 수

1 2 1 
2 4 2 
1 2 1 

이 필터로 필터를 고려 두 개의 필터 세트가 이미지에 적용됩니다. 벡터 H는 수평 픽셀에 적용되고 V는 수직 픽셀에 적용됩니다. 그런 다음 결과를 합쳐 가우시안 흐림 효과를 얻습니다. 분리 가능한 Gaussian Blur를하는 함수를 제공하고 있습니다. 가우시안 블러의 계산은 FFT를 사용하는 것입니다 개선하기 위해

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


} 

또 하나 개의 방법 : (P 내가 너무 게으른 해요, 의견에 대해 물어 해달라고하십시오). FFT 기반의 컨볼 루션은 데이터 크기가 꽤 큰 경우 분리 가능한 커널 방법보다 훨씬 빠릅니다.

빠른 구글 검색은 다음과 같은 기능

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; 

} 

희망이 도움이 나에게 제공했다. :)

+0

cv2.sepFilter2D는 2 filter2D를 응축시킬 수 있습니까? –

0

나는이 지위가 오래되었음을 안다. 그러나 문제는 interresting이며 미래의 독자들을 interrest 수 있습니다. 내가 아는 한, DoG 필터는 분리 할 수 ​​없습니다. 따라서 두 해결책이 남았습니다 : 1) 함수 GaussianBlur()를 두 번 호출하고 두 이미지를 뺍니다. 둘째 이미지를 뺍니다. 2) 두 가우스 커널의 차이를 계산하여 커널을 만든 다음 이미지와 컨벌루션합니다.

어떤 솔루션이 더 빠릅니까? 해결 방법 2는 이미지가 한 번만 뒤 틀리기 때문에 첫눈에 더 빨리 보입니다. 그러나 이것은 분리 가능한 필터를 포함하지 않습니다. 반대로, 첫 번째 솔루션은 두 개의 분리 가능한 필터를 포함하며 최종 속도가 더 빠릅니다. (OpenCV 함수 GaussianBlur()가 최적화되어 있고 분리 가능한 필터를 사용하는지 여부는 알 수 없지만 가능성이 있습니다.)

그러나 FFT 기술을 사용하여 컨볼 루션하는 경우 두 번째 해결 방법은 분명 빠릅니다. 누구든지 나를 추가하고 싶거나 수정하고 싶다면 조언을 구하십시오.