python - 在没有 opencv 的情况下使用 python 实现 Sobel 运算符
python - Implementing Sobel operators with python without opencv
给定一个灰度 8 位图像(像素强度值为 0 - 255 的二维数组),我想在图像上实现 Sobel 运算符(掩码)。下面的 Sobel 函数基本上围绕给定像素循环,对像素应用以下权重:
然后应用给定的公式:
我正在尝试实现此 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()
给定这张灰度 8 位图像
我在应用函数时得到这个:
但应该得到这个:
我已经用 python 实现了其他高斯滤波器,我不确定我哪里出错了?
如果使用 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)
贴近您的代码正在执行的操作,一种优雅的解决方案是将 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 毫秒。
我遇到了和你一样的问题。我通过阅读格式 'gray' 的图像来修复它,你可以在下面看到
import PIL.Image
img = PIL.Image.open('image.gif').convert('L')
给定一个灰度 8 位图像(像素强度值为 0 - 255 的二维数组),我想在图像上实现 Sobel 运算符(掩码)。下面的 Sobel 函数基本上围绕给定像素循环,对像素应用以下权重:
然后应用给定的公式:
我正在尝试实现此 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()
给定这张灰度 8 位图像
我在应用函数时得到这个:
但应该得到这个:
我已经用 python 实现了其他高斯滤波器,我不确定我哪里出错了?
如果使用 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)
贴近您的代码正在执行的操作,一种优雅的解决方案是将 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 毫秒。
我遇到了和你一样的问题。我通过阅读格式 'gray' 的图像来修复它,你可以在下面看到
import PIL.Image
img = PIL.Image.open('image.gif').convert('L')