(1)完成图像读取和显示,给图像加上高斯噪声;
(2)利用三种一阶微分算子(Roberts、Sobel、Prewitt算子)和二阶微分算子(拉普拉斯算子、LOG、DOG)实现边缘检测;
话不多说,上代码
import numpy as np
import cv2
import matplotlib.pyplot as plt
from skimage import util,filters
def roberts_operator(block):
kernel1 = np.array([[1,0], [0,-1]])
kernel2 = np.array([[0,-1], [1,0]])
return np.abs(np.sum(block[1:,1:] * kernel1)) + np.abs(np.sum(block[1:,1:] * kernel2))
def sobel_operator(block, orientation):
if orientation == 'horizontal':
kernel = np.array([[-1,-2,-1], [0,0,0], [1,2,1]])
elif orientation == 'vertical':
kernel = np.array([[-1,0,1], [-2,0,2], [-1,0,1]])
else:
raise('Orientation Error')
return np.abs(np.sum(block * kernel))
def prewitt_operator(block):
kernel1 = np.array([[1,0,-1],[1,0,-1],[1,0,-1]])
kernel2 = np.array([[-1,-1,-1],[0,0,0],[1,1,1]])
return np.abs(np.sum(block * kernel1)) + np.abs(np.sum(block * kernel2))
def laplacian_operator(block):
kernel = np.array([[0,-1,0], [-1,4,-1], [0,-1,0]])
return np.abs(np.sum(block * kernel))
def Dog_operator(img, operator_type):
if operator_type == 'dog':
#两次高斯滤波
gimg1 = filters.gaussian(img, sigma=2)
gimg2 = filters.gaussian(img, sigma=1.6 * 2)
#两个高斯运算的差分
dimg = gimg2 - gimg1
#归一化
dimg /= 2
return dimg
def Log_operator(img,operator_type):
if operator_type == 'log':
img = cv2.GaussianBlur(img, (3, 3), sigmaX=0) # 以核大小为3x3,方差为0的高斯函数进行高斯滤波
filter = np.array([[0, 0, 1, 0, 0],
[0, 1, 2, 1, 0],
[1, 2, 16, 2, 1],
[0, 1, 2, 1, 0],
[0, 0, 1, 0, 0]])
img = np.pad(img, ((2, 2), (2, 2)), 'constant') # 填充
# 高斯滤波:平滑
w, h = img.shape
for i in range(w - 4):
for j in range(h - 4):
img[i][j] = np.sum(img[i:i + 5, j:j + 5] * filter)
#laplace算子
lap4_filter = np.array([[0, 1, 0], [1, -4, 1], [0, 1, 0]])
img = np.pad(img, ((1, 1), (1, 1)), 'constant')
edge4_img = np.zeros((w, h))
for i in range(w - 2):
for j in range(h - 2):
edge4_img[i, j] = np.sum(img[i:i + 3, j:j + 3] * lap4_filter)
if edge4_img[i, j] < 0:
edge4_img[i, j] = 0 # 把所有负值修剪为0
elif edge4_img[i,j] > 0:
edge4_img[i,j] = 152 # 增强一些正值的像素值
return edge4_img
def operator_process(img, operator_type, orientation=None):
n, m = img.shape
res = np.zeros((n, m))
for i in range(1, n-1):
for j in range(1, m-1):
if operator_type == 'roberts':
res[i][j] = roberts_operator(img[i-1:i+2, j-1:j+2])
elif operator_type == 'sobel':
res[i][j] = sobel_operator(img[i-1:i+2, j-1:j+2], orientation)
elif operator_type == 'prewitt':
res[i][j] = prewitt_operator(img[i-1:i+2, j-1:j+2])
elif operator_type == 'laplacian':
res[i][j] = laplacian_operator(img[i-1:i+2, j-1:j+2])
else:
raise('Operator Type Error')
return res
# 图像转化成灰度图像
rose = cv2.imread('2.png', cv2.IMREAD_GRAYSCALE)
#添加高斯噪声
rose_Gaussian = util.random_noise(rose,mode = 'Gaussian')
rose_Gaussian = rose_Gaussian*255
#Roberts算子
Roberts = operator_process(rose_Gaussian,'roberts')
#Sobel算子
Sobel = operator_process(rose_Gaussian,'sobel','horizontal')
#Prewitt算子
Prewitt = operator_process(rose_Gaussian,'prewitt')
#拉普拉斯算子
Laplacian = operator_process(rose_Gaussian,'laplacian')
#Dog算子
Dog = Dog_operator(rose_Gaussian,'dog')
#Log算子:图像去噪+拉普拉斯算子
Log = Log_operator(rose_Gaussian,'log')
#绘图
#设置画布标题字体为中文,不设置的话,可能会出现乱码结果
plt.rcParams["font.sans-serif"]=["SimHei"]
plt.rcParams["axes.unicode_minus"]=False
plt.subplot(331),plt.imshow(rose,cmap='gray'),plt.title('原图')
plt.subplot(332),plt.imshow(rose_Gaussian,cmap='gray'),plt.title('After-Gaussian')
plt.subplot(334),plt.imshow(Roberts,cmap='gray'),plt.title('Roberts')
plt.subplot(335),plt.imshow(Sobel,cmap='gray'),plt.title('Sobel')
plt.subplot(335),plt.imshow(Sobel,cmap='gray'),plt.title('Sobel')
plt.subplot(336),plt.imshow(Prewitt,cmap='gray'),plt.title('Prewitt')
plt.subplot(337),plt.imshow(Laplacian,cmap='gray'),plt.title('Laplacian')
plt.subplot(338),plt.imshow(Log,cmap='gray'),plt.title('Log')
plt.subplot(339),plt.imshow(Dog,cmap='gray'),plt.title('Dog')
plt.suptitle('边缘检测',fontsize = 20)
plt.tight_layout(rect=(0, 0, 1, 0.9))
plt.show()
结果分析:如上图所示,很容易看出三种一阶微分算子的表现力还是很好的。Roberts算子定位较精确,对具有陡峭的低噪声的图像处理效果较好,但是对于噪声还是比较敏感。Sobel 算子、Prewitt算子对灰度渐变和噪声较多的图像处理效果较好,上图结果可以看出边界还是比较清晰的。
但是,二阶微分算子Laplacian算子对噪声非常敏感,丢失大量边缘方向的信息,效果不是太好。LoG:通过图像平滑,然后在进行Laplacian算子的操作,提高了定位精度,边缘连续性好,也可以提取较弱的边缘点。最后,DoG算子高斯差分计算简单,但表现力是上述六种算子中最强的一种,很好的实现了边缘检测。
小白初学!