创意编程——图像的边缘向量场

基于Python实现

边缘模型

图像的一阶导数和二阶导数

图中(a)显示了从图中(b)中的一段中提取出来的一幅图像。图中(b)显示了一条水平灰度剖面线。该图形还显示了灰度剖面的一阶导数和二阶导数。当沿着灰度剖面从左到右移动时,我们注意到,在斜坡的开始处和在斜坡上的各个点处,一阶导数为正。而在恒定灰度区域的一阶导数为零。在斜坡的开始处,二阶导数为正;在斜坡的结束处,二阶导数为负;在斜坡上的各点处,二阶导数为零;在恒定灰度区域的各点处,二阶导数为零。对于从亮到暗过渡的边缘,刚刚讨论的导数的符号则正好相反。零灰度轴和二姐导数极值间的连线的交点称为该二阶导数的零交叉点。
在这里插入图片描述

典型边缘模型

在这里插入图片描述

实际中,数字图像都存在被模糊且带有噪声的边缘,模糊的程度主要取决于聚焦机理(如光学成像中的镜头)中的限制,而噪声水平主要取决于成像系统的电子元件。

Sobel算子

Soble边缘检测算法比较简,实际应用中效率比canny边缘检测效率要高,但是边缘不如Canny检测的准确,但是很多实际应用的场合,sobel边缘却是首选,尤其是对效率要求较高,而对细纹理不太关心的时候。Soble边缘检测通常带有方向性,可以只检测竖直边缘或垂直边缘或都检测。
算子使用两个33的矩阵(图1)算子使用两个33的矩阵(图1)去和原始图片作卷积,分别得到横向G(x)和纵向G(y)的梯度值,如果梯度值大于某一个阈值,则认为该点为边缘点。

sobel算子在x方向上的卷积核:
sbel_X
sobel算子在y方向上的卷积核:
sobel_Y

def sobel_x(img):
    fil = np.array([[-1, 0, 1],
                    [-2, 0, 2],
                    [-1, 0, 1]])

    return abs(signal.convolve(img, fil, mode='same'))

def sobel_y(img):
    fil = np.array([[1, 2, 1],
                    [0, 0, 0],
                    [-1, -2, -1]])

    return abs(signal.convolve(img, fil, mode='same'))

def sobel(img, orthogonal=True):
    x = sobel_x(img)
    y = sobel_y(img)
    out = np.where(x > y, x, y)
    return out

效果:
在这里插入图片描述

方向梯度法

但上述方法仅仅包含两个方方向的正交梯度,无法体现出八个方向的梯度,因此在此定义8个方向的模板 W i W_i Wi进行计算:

W 1 = [ 1 2 1 0 0 0 − 1 − 2 − 1 ] W_1= \left[ \begin{matrix} 1 & 2 & 1\\ 0 & 0 & 0 \\ -1 & -2 & -1 \\ \end{matrix} \right] W1=101202101

W 2 = [ − 1 − 2 − 1 0 0 0 1 2 1 ] W_2= \left[ \begin{matrix} -1 & -2 & -1\\ 0 & 0 & 0 \\ 1 & 2 & 1 \\ \end{matrix} \right] W2=101202101

W 3 = [ 1 0 − 1 2 0 − 2 1 0 − 1 ] W_3= \left[ \begin{matrix} 1 & 0 & -1\\ 2 & 0 & -2 \\ 1 & 0 & -1 \\ \end{matrix} \right] W3=121000121

W 4 = [ − 1 0 1 − 2 0 2 − 1 0 1 ] W_4= \left[ \begin{matrix} -1 & 0 & 1\\ -2 & 0 & 2 \\ -1 & 0 & 1 \\ \end{matrix} \right] W4=121000121

W 5 = [ 0 1 2 − 1 0 1 − 2 − 1 0 ] W_5= \left[ \begin{matrix} 0 & 1 & 2\\ -1 & 0 & 1 \\ -2 & -1 & 0 \\ \end{matrix} \right] W5=012101210

W 6 = [ 0 − 1 − 2 1 0 − 1 2 1 0 ] W_6= \left[ \begin{matrix} 0 & -1 & -2\\ 1 & 0 & -1 \\ 2 & 1 & 0 \\ \end{matrix} \right] W6=012101210

W 7 = [ 2 1 0 1 0 − 1 0 − 1 − 2 ] W_7= \left[ \begin{matrix} 2 & 1 & 0\\ 1 & 0 & -1 \\ 0 & -1 & -2 \\ \end{matrix} \right] W7=210101012

W 8 = [ − 2 − 1 0 − 1 0 1 0 1 2 ] W_8= \left[ \begin{matrix} -2 & -1 & 0\\ -1 & 0 & 1 \\ 0 & 1 & 2 \\ \end{matrix} \right] W8=210101012

边缘梯度的定义式为:
在这里插入图片描述
其中, G i ( m , n ) = f ( m , n ) ∗ W i G_i(m,n)=f(m,n)*W_i Gi(m,n)=f(m,n)Wi,下标 i i i 代表方向模板的序号, W i W_i Wi代表第 i i i 方向的模板。 ∣ G i ( m , n ) ∣ |G_i(m,n)| Gi(m,n)表示第 i i i 方向的梯度模值, N N N 代表模板的个数。
方向梯度法检测边缘点的过程如图所示,其中的*表示卷积。
在这里插入图片描述
代码:
计算边缘点和方向编码

def sobel_up_x(img):
    fil = np.array([[-1, 0, 1],
                    [-2, 0, 2],
                    [-1, 0, 1]])

    return abs(signal.convolve(img, fil, mode='same'))


def sobel_down_x(img):
    fil = np.array([[1, 0, -1],
                    [2, 0, -2],
                    [1, 0, -1]])

    return abs(signal.convolve(img, fil, mode='same'))


def sobel_up_y(img):
    fil = np.array([[1, 2, 1],
                    [0, 0, 0],
                    [-1, -2, -1]])

    return abs(signal.convolve(img, fil, mode='same'))


def sobel_down_y(img):
    fil = np.array([[-1, -2, -1],
                    [0, 0, 0],
                    [1, 2, 1]])

    return abs(signal.convolve(img, fil, mode='same'))


def sobel_up_diagonal_x(img):
    fil = np.array([[0, 1, 2],
                    [-1, 0, 1],
                    [-2, -1, 0]])

    return abs(signal.convolve(img, fil, mode='same'))


def sobel_down_diagonal_y(img):
    fil = np.array([[-2, -1, 0],
                    [-1, 0, 1],
                    [0, 1, 2]])

    return abs(signal.convolve(img, fil, mode='same'))


def sobel_down_diagonal_x(img):
    fil = np.array([[0, -1, -2],
                    [1, 0, -1],
                    [2, 1, 0]])

    return abs(signal.convolve(img, fil, mode='same'))


def sobel_up_diagonal_y(img):
    fil = np.array([[2, 1, 0],
                    [1, 0, -1],
                    [0, -1, -2]])

    return abs(signal.convolve(img, fil, mode='same'))


def sobel(img, orthogonal=True):
    if orthogonal:
        x = sobel_up_x(img)
        y = sobel_down_y(img)
        out = np.where(x > y, x, y)
        return out
    else:
        up_x = sobel_up_x(img)
        down_dy = sobel_down_diagonal_y(img)
        down_y = sobel_down_y(img)
        down_dx = sobel_down_diagonal_x(img)
        down_x = sobel_down_x(img)
        up_dy = sobel_up_diagonal_y(img)
        up_y = sobel_up_y(img)
        up_dx = sobel_up_diagonal_x(img)

        # 计算边缘点与方向编码
        direct_matrix = -np.ones(img.shape)
        direct_matrix[up_x > down_dy] = 0
        direct_matrix[down_dy > up_x] = 1
        out = np.where(down_dy > up_x, down_dy, up_x)
        direct_matrix[down_y > out] = 2
        out = np.where(down_y > out, down_y, out)
        direct_matrix[down_dx > out] = 3
        out = np.where(down_dx > out, down_dx, out)
        direct_matrix[down_x > out] = 4
        out = np.where(down_x > out, down_x, out)
        direct_matrix[up_dy > out] = 5
        out = np.where(up_dy > out, up_dy, out)
        direct_matrix[up_y > out] = 6
        out = np.where(up_y > out, up_y, out)
        direct_matrix[up_dx > out] = 7
        out = np.where(up_dx > out, up_dx, out)

        return out, direct_matrix

在得到方向梯度法的方向编码后,通过灰度值方式显示不能够直观的表现出方向性,因此再次借助了“场”这种表现形式,通过箭头绘制出方向,并赋予边缘点的权重参数以更加直观的表现出方向编码的“场”。

代码:
绘制场

def draw_direct(direct_matrix,weight):
    y,x = np.mgrid[direct_matrix.shape[0]:0:-1, 0:direct_matrix.shape[1]:1]
    u = np.zeros(direct_matrix.shape)
    v = np.zeros(direct_matrix.shape)

    max_weight = np.max(weight)

    len = 1.0

    u[direct_matrix==0] = len

    u[direct_matrix == 1] = len/2
    v[direct_matrix == 1] = -len/2

    v[direct_matrix == 2] = -len

    u[direct_matrix == 3] = -len/2
    v[direct_matrix == 3] = -len/2

    u[direct_matrix == 4] = -len

    u[direct_matrix == 5] = -len/2
    v[direct_matrix == 5] = len/2

    v[direct_matrix == 6] = len

    u[direct_matrix == 7] = len/2
    v[direct_matrix == 7] = len/2

    u = u * weight / max_weight
    v = v * weight / max_weight

    plt.quiver(x, y, u, v,width=0.001, scale=20,headwidth=6,headlength=6)

效果

图例1

原图像
在这里插入图片描述

边缘
在这里插入图片描述

边缘向量场

在这里插入图片描述

图例2

原图像

在这里插入图片描述

边缘

在这里插入图片描述

边缘向量场

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值