2016-04-20 7 views
1

Ich implementiere derzeit die filter2 MATLAB-Funktion in R, die eine Methode für 2D-Faltung ist. Ich habe mich für die 2D-Faltungsarbeit entschieden, aber wie die "gültige" Option in filter2 funktioniert, ist mir nicht ganz klar.Implementierung der MATLAB-Filter2-Funktion in R

Die MATLAB-Funktion ist hier beschrieben: http://se.mathworks.com/help/matlab/ref/filter2.html

Meine Implementierung:

filter2D <- function(img, window) { 
    # Algoritm for 2D Convolution 
    filter_center_index_y <- median(1:dim(window)[1]) 
    filter_max_index_y <- dim(window)[1] 
    filter_center_index_x <- median(1:dim(window)[2]) 
    filter_max_index_x <- dim(window)[2] 

    # For each position in the picture, 2D convolution is done by 
    # calculating a score for all overlapping values within the two matrices 
    x_min <- 1 
    x_max <- dim(img)[2] 
    y_min <- 1 
    y_max <- dim(img)[1] 

    df <- NULL 
    for (x_val in c(x_min:x_max)){ 
    for (y_val in c(y_min:y_max)){ 
     # Distanced from cell 
     img_dist_left <- x_val-1 
     img_dist_right <- x_max-x_val 
     img_dist_up <- y_val-1 
     img_dist_down <- y_max-y_val 

     # Overlapping filter cells 
     filter_x_start <- filter_center_index_x-img_dist_left 
     if (filter_x_start < 1) { 
     filter_x_start <- 1 
     } 
     filter_x_end <- filter_center_index_x+img_dist_right 
     if (filter_x_end > filter_max_index_x) { 
     filter_x_end <- filter_max_index_x 
     } 
     filter_y_start <- filter_center_index_y-img_dist_up 
     if (filter_y_start < 1) { 
     filter_y_start <- 1 
     } 
     filter_y_end <- filter_center_index_y+img_dist_down 
     if (filter_y_end > filter_max_index_y) { 
     filter_y_end <- filter_max_index_y 
     } 

     # Part of filter that overlaps 
     filter_overlap_matrix <- filter[filter_y_start:filter_y_end, filter_x_start:filter_x_end] 

     # Overlapped image cells 
     image_x_start <- x_val-filter_center_index_x+1 
     if (image_x_start < 1) { 
     image_x_start <- 1 
     } 
     image_x_end <- x_val+filter_max_index_x-filter_center_index_x 
     if (image_x_end > x_max) { 
     image_x_end <- x_max 
     } 
     image_y_start <- y_val-filter_center_index_y+1 
     if (image_y_start < 1) { 
     image_y_start <- 1 
     } 
     image_y_end <- y_val+filter_max_index_y-filter_center_index_y 
     if (image_y_end > y_max) { 
     image_y_end <- y_max 
     } 

     # Part of image that is overlapped 
     image_overlap_matrix <- img[image_y_start:image_y_end, image_x_start:image_x_end] 

     # Calculating the cell value 
     cell_value <- sum(filter_overlap_matrix*image_overlap_matrix) 
     df = rbind(df,data.frame(x_val,y_val, cell_value)) 
    } 
    } 

    # Axis labels 
    x_axis <- c(x_min:x_max) 
    y_axis <- c(y_min:y_max) 

    # Populating matrix 
    filter_matrix <- matrix(df[,3], nrow = x_max, ncol = y_max, dimnames = list(x_axis, y_axis)) 

    return(filter_matrix) 
} 

Ausführen des Verfahrens:

> image 
    [,1] [,2] [,3] [,4] [,5] [,6] 
[1,] 1 2 3 4 5 6 
[2,] 7 8 9 10 11 12 
[3,] 13 14 15 16 17 18 
[4,] 19 20 21 22 23 24 
[5,] 25 26 27 28 29 30 
[6,] 31 32 33 34 35 36 

> filter 
    [,1] [,2] [,3] 
[1,] 1 2 1 
[2,] 0 0 0 
[3,] -1 -2 -1 

> filter2D(image, filter) 
    1 2 3 4 5 6 
1 -22 -32 -36 -40 -44 -35 
2 -36 -48 -48 -48 -48 -36 
3 -36 -48 -48 -48 -48 -36 
4 -36 -48 -48 -48 -48 -36 
5 -36 -48 -48 -48 -48 -36 
6 76 104 108 112 116 89 

Dies ist die gleiche Ausgabe, die FILTER2 (Bild, Filter) erzeugt in Matlab jedoch, wenn die Option 'gültig' hinzugefügt wird, wird die folgende Ausgabe generiert:

-48 -48 -48 -48                                                 
-48 -48 -48 -48                                                 
-48 -48 -48 -48                                                 
-48 -48 -48 -48 

Es ist nicht ganz offensichtlich, wie filter2 mit der Option 'valid' das erzeugt. Benutzt es nur die Mittelwerte? Oder macht es etwas anspruchsvoller?

+0

Minor note: Ihr ursprünglicher Code verwendete 'input' innerhalb der Faltungssumme, wenn Ihre Funktionsdefinition 'img' verwendet wurde. Ich habe im Code "input" in "img" umbenannt und es funktioniert jetzt. – rayryeng

Antwort

2

Bevor ich beginne, macht Ihr Code tatsächlich 2D Korrelation. 2D-Faltung erfordert, dass Sie eine 180-Grad-Drehung auf dem Kernel ausführen, bevor Sie die gewichtete Summe ausführen. Korrelation und Faltung sind in der Tat die gleiche Operation , wenn der Kernel symmetrisch ist (d. H. Die Transponierung des Kerns ist gleich zu sich selbst). Ich wollte das erst klarstellen, bevor ich anfange. Auch die Dokumentation für filter2 besagt, dass die Korrelation durchgeführt wird.


Die 'valid' Option in MATLAB bedeutet einfach, dass es nur die Ausgänge zurückkehren sollte, wenn der Kern vollständig das 2D-Signal überlappt beim Filtern. Da Sie einen 3 x 3-Kernel haben, bedeutet dies, dass der Kernel beispielsweise im 2D-Signal an der Stelle (2,2) nicht über die Signalgrenzen hinausgeht. Daher wird das Ausmaß des gefilterten 2D-Signals zurückgegeben, bei dem der Kern vollständig innerhalb des ursprünglichen 2D-Signals war. Um Ihnen ein Beispiel zu geben: Wenn Sie den Kernel an der Position (1,1) platzieren, würde ein Teil des Kernels außer Kraft gesetzt werden. Das Behandeln von Bedingungen außerhalb der Grenzen beim Filtern kann auf viele Arten erfolgen, was sich auf die Ergebnisse und die Interpretation dieser Ergebnisse auswirken kann, wenn es darauf ankommt. Daher ist die Option 'valid' erwünscht, da Sie echte Informationen verwenden, die das Endergebnis bilden. Sie interpolieren oder führen keine Schätzungen für Daten durch, die über die Grenzen des 2D-Signals hinausgehen.

Einfach ausgedrückt, geben Sie eine reduzierte Matrix zurück, die die Randelemente entfernt. Der Filter ist so seltsam geformt, dass dies einfach ist. Sie entfernen einfach die ersten und letzten floor(M/2) Zeilen und die ersten und letzten floor(N/2) Spalten, wobei M x N die Größe Ihres Kernels ist. Da dein Kernel also 3 x 3 ist, bedeutet das, dass wir 1 Zeile von oben und 1 Zeile von unten entfernen müssen, sowie 1 Spalte von links und 1 Spalte von rechts. Dies ergibt die -48 in einem 4 x 4 Raster, wie Sie von der Ausgabe von MATLAB sehen können.

Daher, wenn Sie die Option 'valid 'in Ihrem Code verwenden möchten, stellen Sie sicher, dass Sie die Rahmenelemente in Ihrem Ergebnis entfernen.Sie können vor Ihrer Rückkehr am Ende dieses Recht tun, um die Matrix:

# Place your code here... 
# ... 
# ... 
# Now we're at the end of your code 

# Populating matrix 
filter_matrix <- matrix(df[,3], nrow = x_max, ncol = y_max, dimnames = list(x_axis, y_axis)) 

# New - Determine rows and columns of matrix as well as the filter kernel 
nrow_window <- nrow(window) 
ncol_window <- ncol(window) 
nrows <- nrow(filter_matrix) 
ncols <- ncol(filter_matrix) 

# New - Figure out where to cut off 
row_cutoff <- floor(nrow_window/2) 
col_cutoff <- floor(ncol_window/2) 

# New - Remove out borders 
filter_matrix <- filter_matrix[((1+row_cutoff):(nrows-row_cutoff)), ((1+col_cutoff):(ncols-col_cutoff))] 

# Finally return matrix 
return(filter_matrix)  

Beispiel Run

Ihre Daten verwenden:

> image <- t(matrix(c(1:36), nrow=6, ncol=6)) 
> image 
    [,1] [,2] [,3] [,4] [,5] [,6] 
[1,] 1 2 3 4 5 6 
[2,] 7 8 9 10 11 12 
[3,] 13 14 15 16 17 18 
[4,] 19 20 21 22 23 24 
[5,] 25 26 27 28 29 30 
[6,] 31 32 33 34 35 36 
> filter <- matrix(c(1,0,-1,2,0,-2,1,0,-1), nrow=3, ncol=3) 
> filter 
    [,1] [,2] [,3] 
[1,] 1 2 1 
[2,] 0 0 0 
[3,] -1 -2 -1 

ich die Funktion lief und jetzt erhalte ich:

> filter2D(image,filter) 
    2 3 4 5 
2 -48 -48 -48 -48 
3 -48 -48 -48 -48 
4 -48 -48 -48 -48 
5 -48 -48 -48 -48 

Ich denke, es ist wichtig, die horizontalen und vertikalen Etiketten so zu lassen, wie sie sind Sie können explizit sehen, dass nicht das gesamte Signal zurückgesendet wird, was der Code gerade tut. Das liegt aber an Ihnen. Ich überlasse das Ihnen, um zu entscheiden.

+1

Danke, dass Sie sowohl 2D-Korrelation als auch 2D-Faltung angeben - das war sehr hilfreich. Jetzt macht die gültige Option auch viel mehr Sinn! Oft ist die Dokumentation für Methoden ein wenig implizit in ihren Erklärungen und Ihre ist viel klarer. –

+0

Sie sind herzlich willkommen :) Was ich erwähnt habe kommt aus Erfahrung und diese Information ist etwas, das die Dokumentation kurz beschönigt. Froh, dass ich helfen konnte. Viel Glück! – rayryeng