2016-08-19 3 views
2

Étant donné une image en niveaux de gris 8 bits (tableau 2D avec des valeurs de 0 à 255 pour l'intensité des pixels), je souhaite implémenter les opérateurs Sobel (masque) sur une image. La fonction Sobel ci-dessous boucles essentiellement autour d'un pixel donné, applique le poids suivant aux pixels: enter image description herepython - Implémentation d'opérateurs Sobel avec python sans opencv

enter image description here

Et aplies alors la formule donnée:

enter image description here

Im essayant de mettre en œuvre les formules à partir de ce lien: http://homepages.inf.ed.ac.uk/rbf/HIPR2/sobel.htm

import numpy as np 
import matplotlib.pyplot as plt 
import matplotlib.image as mpimg 
import Image 


def Sobel(arr,rstart, cstart,masksize, divisor): 
    sum = 0; 
    x = 0 
    y = 0 

    for i in range(rstart, rstart+masksize, 1): 
    x = 0 
    for j in range(cstart, cstart+masksize, 1): 
     if x == 0 and y == 0: 
      p1 = arr[i][j] 
     if x == 0 and y == 1: 
      p2 = arr[i][j] 
     if x == 0 and y == 2: 
      p3 = arr[i][j] 
     if x == 1 and y == 0: 
      p4 = arr[i][j] 
     if x == 1 and y == 1: 
      p5 = arr[i][j]   
     if x == 1 and y == 2: 
      p6 = arr[i][j] 
     if x == 2 and y == 0: 
      p7 = arr[i][j] 
     if x == 2 and y == 1: 
      p8 = arr[i][j] 
     if x == 2 and y == 2: 
      p9 = arr[i][j] 
     x +=1 
    y +=1 
    return np.abs((p1 + 2*p2 + p3) - (p7 + 2*p8+p9)) + np.abs((p3 + 2*p6 + p9) - (p1 + 2*p4 +p7)) 


def padwithzeros(vector, pad_width, iaxis, kwargs): 
    vector[:pad_width[0]] = 0 
    vector[-pad_width[1]:] = 0 
    return vector 

im = Image.open('charlie.jpg') 
im.show() 
img = np.asarray(im) 
img.flags.writeable = True 
p = 1 
k = 2 
m = img.shape[0] 
n = img.shape[1] 
masksize = 3 
img = np.lib.pad(img, p, padwithzeros) #this function padds image with zeros to cater for pixels on the border. 
x = 0 
y = 0 
for row in img: 
    y = 0 
    for col in row: 
    if not (x < p or y < p or y > (n-k) or x > (m-k)): 
     img[x][y] = Sobel(img, x-p,y-p,masksize,masksize*masksize) 
    y = y + 1 
    x = x + 1 

img2 = Image.fromarray(img) 
img2.show() 

Donné ce niveau de gris 8 bits d'image

enter image description here

Je reçois quand l'application de la fonction:

enter image description here

mais devrait obtenir ceci:

enter image description here

I ont mis en œuvre d'autres gau filtres ssian avec python, je ne sais pas où je vais mal ici?

Répondre

1

Sticking proche de ce que fait votre code, une solution élégante est d'utiliser la scipy.ndimage.filters.generic_filter() avec la formule indiquée ci-dessus.

import numpy as np 
from scipy.ndimage.filters import generic_filter 
from scipy.ndimage import imread 

# Load sample data 
with np.DataSource().open("http://i.stack.imgur.com/8zINU.gif", "rb") as f: 
    img = imread(f, mode="I") 

# Apply the Sobel operator 
def sobel_filter(P): 
    return (np.abs((P[0] + 2 * P[1] + P[2]) - (P[6] + 2 * P[7] + P[8])) + 
      np.abs((P[2] + 2 * P[6] + P[7]) - (P[0] + 2 * P[3] + P[6]))) 
G = generic_filter(img, sobel_filter, (3, 3)) 

Exécution sur l'image échantillon prend environ 400 ms. A titre de comparaison, la performance de convolve2d est d'environ 6,5 ms.

0

Si vous utilisez NumPy et SciPy n'est pas un problème, alors une solution simple est d'utiliser le convolve2d() de SciPy.

import numpy as np 
from scipy.signal import convolve2d 
from scipy.ndimage import imread 

# Load sample data 
with np.DataSource().open("http://i.stack.imgur.com/8zINU.gif", "rb") as f: 
    img = imread(f, mode="I") 

# Prepare the kernels 
a1 = np.matrix([1, 2, 1]) 
a2 = np.matrix([-1, 0, 1]) 
Kx = a1.T * a2 
Ky = a2.T * a1 

# Apply the Sobel operator 
Gx = convolve2d(img, Kx, "same", "symm") 
Gy = convolve2d(img, Ky, "same", "symm") 
G = np.sqrt(Gx**2 + Gy**2) 
# or using the absolute values 
G = np.abs(Gx) + np.abs(Gy)