sobel算子_用sobel算子提取图片内容的轮廓

c091fede431fc3f93bbae0a797c1bb99.png

个人学习笔记:用sobel算子将RGB图片的轮廓提取出来

分成两个步骤:

1、将RGB转为灰度图:

分别对三个通道进行计算,RGB代表红绿蓝三种颜色,这个公式的含义就是对三种颜色进行加权处理,获得最后的灰度图(opencv提供了RGB2GRAY的功能,可以作为对比)

aa884fb273d9d753ab7599c68217bc5f.png
import numpy as np
import imageio
def rgb2gray(rgb):
    """
    convert rgb image into gray
    Args:
        rgb: grb image with numpy type
    Returns:
        gray: gray image
    """
    gray = rgb[:, :, 0] * 0.299 + rgb[:, :, 1] * 0.587 + rgb[:, :, 2] * 0.114
    return gray
image_in = imageio.imread("desk.jpg")
gray = rgb2gray(image_in)
imageio.imsave(im=gray.astype(np.uint8), uri="gray_image.jpg")

下面首先来看一下原始的RGB图(上自习的时候拍的,水平和垂直边缘都很多啊):

60f92aeee1157950c4aff846c45e72f7.png

然后就是转换以后的灰度图,现在只能感受到亮度差,看不出来颜色是什么了:

03f825585eaaf3bbaf4175504c4517fd.png

2、将灰度图用sobel算子处理

sobel算子可以用来提取图片的边缘,那么什么是图片的边缘呢?我的认为,就是比如颜色图片或者是物体的轮廓(纯粹个人理解)。据说啊,sobel算子并没有发表在论文中,仅仅是在一次博士生讨论会中提出来的,这么厉害的东西居然没有发论文,要是引用的时候参考文献怎么写?有点跑题。。。

sobel模板就是3x3的矩阵,分为水平检测和垂直检测。之前看数字图像处理就感觉很玄幻,不知道为什么下面这种卷积核就能把图像的边缘找到:

86e7fdc5a88a9409cd3386ea6f7b5f0b.png

把这个3x3的卷积核与灰度图进行卷积计算,就能得到边缘了。

现在想想,还是不太懂。感觉上看,就是右边的像素减去左边的像素:如果左边和右边的像素值越接近(同一物体或者同一颜色或者没有任何断层),那么差值就越小,也就是没有边缘;反之,如果右边和左边不是连续的,那么减法获得的结果就会很大,也就出现了轮廓。

def sobel(image):
    """
    implement sobel compute on a single gray image 
    Args:
        image:  a gray image

    Returns:
        the image that have been processd by sobel
    Raises:
        ValueError: the input's shape image must bigger than sobel(3x3)
    """
    # change the data type of input image into np.uint8(cheaper compute cost)
    image = image.astype(np.uint8)
    assert len(image.shape) == 2
    if image.shape[0] < 3 or image.shape[1] < 3:
        raise ValueError("The width and height of input image must bigger than 3")
    # create temp image container
    sobel_image_x = np.zeros(shape=image.shape)
    sobel_image_y = np.zeros(shape=image.shape)
    # create sobel
    sobel_x = np.array([[-1, 0, 1], [-2, 0, 2], [-1, 0, 1]])
    sobel_y = np.array([[-1, -2, -1], [0, 0, 0], [1, 2, 1]])

    for i in range(image.shape[0]-2):
        for j in range(image.shape[1]-2):
            # have to use np.abs() to make sure the value is positive
            sobel_image_x[i, j] = np.abs(np.sum(image[i:i+3, j:j+3] * sobel_x))
            sobel_image_y[i, j] = np.abs(np.sum(image[i:i+3, j:j+3] * sobel_y))
    sobel_image = np.sqrt(sobel_image_x*sobel_image_x + sobel_image_y*sobel_image_y).astype(np.uint8)

    return sobel_image

上面的代码流程如下:

(1)数据类型转换与输入数据尺寸检测

(2)创建X和Y方向的边缘图像容器,定义sobel算子

(3)卷积(求abs,也就是绝对值,是因为差值可能是负数)

image_in = imageio.imread("desk.jpg")
rgb = rgb2gray(image_in)
sobel_image = sobel(rgb)
imageio.imsave(im=sobel_image, uri="sobel_image.jpg")

处理前后 对比 :

1d73755b60cdff4f10aa8a36312e348f.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值