数字图像处理--边缘检测

数字图像处理–边缘检测

主要内容

(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算子高斯差分计算简单,但表现力是上述六种算子中最强的一种,很好的实现了边缘检测。

小白初学!

猜你喜欢

转载自blog.csdn.net/MZYYZT/article/details/128114623