2016-08-19 88 views
2

給定一個灰度8位圖像(像素強度爲0到255的二維數組),我想在圖像上實現Sobel運算符(蒙版)。下面基本上索貝爾功能迴路給定的像素周圍,適用以下重量的像素: enter image description herepython - 使用python實現Sobel運算符而不使用opencv

enter image description here

然後aplies給定的公式:

enter image description here

我試着去實現來自此鏈接的公式: 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() 

鑑於這種灰度8位圖像

enter image description here

應用功能時,我得到這個:

enter image description here

,但應該得到這樣的:

enter image description here

我已經實施了其他指標用python過濾ssian過濾器,我不確定我在哪裏出錯了?

回答

1

堅持貼近你的代碼做什麼,一個優雅的解決方案是與上面提供的公式使用scipy.ndimage.filters.generic_filter()

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

在示例圖像上運行此操作大約需要400毫秒。爲了比較,convolve2d的性能約爲6.5毫秒。

0

如果使用NumPy和SciPy不是問題,那麼一個簡單的解決方案是使用SciPy的convolve2d()

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)