2016-08-19 206 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)