2017-04-09 4 views
2

I essayé de mettre en oeuvre le filtrage de l'image dans le spectre basé sur this OpenCV example de la documentation et copiées par commodité ici:convolution à base de DFT OpenCV est décalée

void convolveDFT(InputArray A, InputArray B, OutputArray C) 
{ 
    C.create(abs(A.rows - B.rows)+1, abs(A.cols - B.cols)+1, A.type()); 
    Size dftSize; 
    // calculate 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 
    dft(tempA, tempA, 0, A.rows); 
    dft(tempB, tempB, 0, B.rows); 

    // multiply the spectrums; 
    // the function handles packed spectrum representations well 
    mulSpectrums(tempA, tempB, tempA); 

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

    // now copy the result back to C. 
    tempA(Rect(0, 0, C.cols, C.rows)).copyTo(C); 
} 

je l'image Lena comme A (512x512) et un filtre d'identité (toutes les entrées mises à 0 sauf la centrale) comme B (41x41).


Originalfiltered

Il semble que le fond et la partie droite de l'image a été recadrée. De plus, bien qu'il ne soit pas visible ici en raison du formatage SO, l'image filtrée est plus petite que l'original (à cause de la première ligne de la fonction).

Comment puis-je modifier le code afin qu'il filtre l'image comme la fonction filter2D le ferait? Alors que dans ce cas le résultat serait l'image originale.

Répondre

1

La taille du résultat de la convolution doit être A.cols + B.cols - 1 par A.rows + B.rows - 1 (tout comme les arguments des appels getOptimalDFTSize). Donc, pour obtenir le plein résultat de convolution, la première ligne de l'exemple doit être changé: tout autour qui

C.create(A.rows + B.rows - 1, A.cols + B.cols - 1, A.type()); 

Cela devrait vous donner une image résultante qui est légèrement plus grande que celle d'origine, y compris une frontière correspondent à la queue de la convolution (où le filtrage monte et descend). D'autre part ne renvoie pas une convolution complète comme la sortie est limitée à une image qui est la même taille que celle d'origine, en supprimant les queues de convolution. Pour ce faire, filter2D suppose un noyau linéaire qui introduit un décalage de (B.cols - 1)/2 le long des colonnes et (B.rows - 1)/2 le long des lignes. L'image filtrée peut ainsi être extraite avec ce qui suit:

C.create(A.rows, A.cols, A.type()); 
... 
tempA(Rect((B.cols-1)/2, (B.rows-1)/2, A.cols, A.rows).copyTo(C);