Given a greyscale 8 bit image (2D array with values from 0 - 255 for pixel intensity), I want to implement the Sobel operators (mask) on an image. The Sobel function below basically loops around a given pixel,applies the following weight to the pixels:
And then aplies the given formula:
Im trying to implement the formulas from this link: 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()
Given this greyscale 8 bit image
I get this when applying the function:
but should get this:
I have implemented other gaussian filters with python, I'm not sure where I'm going wrong here?
Sticking close to what your code is doing, one elegant solution is to use the scipy.ndimage.filters.generic_filter()
with the formula provided above.
import numpy as np
from scipy.ndimage.filters import generic_filter
from scipy.ndimage import imread
# Load sample data
with np.DataSource().open("https://i.sstatic.net/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))
Running this on the sample image takes about 400 ms. For comparison, the convolve2d
's performance is about 6.5 ms.