人眼怎么识别图像边缘?

比如有一幅图,图里面有一条线,左边很亮,右边很暗,那人眼就很容易识别这条线作为边缘.也就是像素的灰度值快速变化的地方.

sobel算子



对于f(t),其导数f'(t)反映了每一处的变化趋势.在变化最快的位置其导数最大. sobel算子的思路就是模拟求一阶导数.

sobel算子是一个离散差分算子.它计算图像像素点亮度值的近似梯度.

图像是二维的,即沿着宽度/高度两个方向.

我们使用两个卷积核对原图像进行处理:

  • 水平方向



    很好理解,原始像素灰度值-->(右边像素值-左边像素值),反映了水平方向的变化情况.

  • 垂直方向

这样的话,我们就得到了两个新的矩阵,分别反映了每一点像素在水平方向上的亮度变化情况和在垂直方向上的亮度变换情况.

综合考虑这两个方向的变化,我们使用



反映某个像素的梯度变化情况.

有时候为了简单起见,也直接用绝对值相加替代.

opencv里可以使用了如下的卷积核,可以"放大像素的变化情况".



可以参考这个函数Scharr

opencv实现

import cv2 as cv
def test():
src = cv.imread("/home/sc/disk/keepgoing/opencv_test/sidetest.jpeg")
src = cv.GaussianBlur(src, (3, 3), 0)
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
grad_x = cv.Sobel(gray, -1, 1, 0, ksize=3)
grad_y = cv.Sobel(gray, -1, 0, 1, ksize=3) grad = cv.addWeighted(grad_x, 0.5, grad_y, 0.5, 0) cv.imshow("origin",src)
cv.imshow("grad",grad)
cv.waitKey() test()

首先是高斯模糊去噪.某种意义上说高斯模糊是和sobel相反的过程.高斯模糊平滑了某点像素与周边像素的差异.那为什么还要先高斯去噪呢?

噪声就是像素的强度相对于真值有个突变。从时域上讲,通过高斯滤波能让一个像素的强度与周围的点相关,就减小了突变的影响;从频域上讲,突变引入了高频分量,而高斯滤波器可以滤除高频分量。

高斯去噪是为了防止把噪点也检测为边缘.

然后计算grad_x,grad_y.即对原图做水平方向/垂直方向的sobel卷积核卷积

    grad_x = cv.Sobel(gray, -1, 1, 0, ksize=3)
grad_y = cv.Sobel(gray, -1, 0, 1, ksize=3)

sobel api



注意区分c++版本和python版本api. 在上述代码中,第二个参数-1代表我们希望输出的图像矩阵和原图有同样的depth,第3/4个参数分别代表在x/y方向做一阶差分.取值0或1.

ksize必须为奇数.

tips:通常我们使用( xorder = 1, yorder = 0, ksize = 3) or ( xorder = 0, yorder = 1, ksize = 3)来计算水平/垂直方向的一阶差分矩阵.ksize=3用的是标准sobel卷积核.如果ksize传入FILTER_SCHARR,则使用的是如下卷积核:

最后将两个矩阵叠加,综合考虑水平和垂直方向的像素灰度值变化强度.得到边缘.

 grad  = cv.addWeighted(grad_x, 0.5, grad_y, 0.5, 0)

完整代码处理效果如下

ksize采用cv.FILTER_SCHARR效果如下:

    grad_x = cv.Sobel(gray, -1, 1, 0, ksize=cv.FILTER_SCHARR)
grad_y = cv.Sobel(gray, -1, 0, 1, ksize=cv.FILTER_SCHARR)

opencv边缘检测的更多相关文章

  1. [OpenCV入门教程之十二】OpenCV边缘检测:Canny算子,Sobel算子,Laplace算子,Scharr滤波器合辑

    http://blog.csdn.net/poem_qianmo/article/details/25560901 本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog ...

  2. OpenCV——边缘检测入门、Canny边缘检测

    边缘检测的一般步骤: 最优边缘检测的三个评价标准: 低错误率:表示出尽可能多的实际边缘,同时尽可能地减少噪声产生的误报: 高定位性:标识出的边缘要与图像实际边缘尽可能接近: 最小响应:图像中的边缘只能 ...

  3. opencv边缘检测的入门剖析(第七天)

    ---边缘检测概念理解--- 边缘检测的理解可以结合前面的内核,说到内核在图像中的应用还真是多,到现在为止学的对图像的操作都是核的操作,下面还有更神奇的! 想把边缘检测出来,从图像像素的角度去想,那就 ...

  4. OpenCV边缘检测的详细参数调节

    1. findCountours 转载于http://blog.sina.com.cn/s/blog_7155fb1a0101a90h.html findContours函数,这个函数的原型为: &l ...

  5. opencv边缘检测-拉普拉斯算子

    sobel算子一文说了,索贝尔算子是模拟一阶求导,导数越大的地方说明变换越剧烈,越有可能是边缘. 那如果继续对f'(t)求导呢? 可以发现"边缘处"的二阶导数=0. 我们可以利用这 ...

  6. opencv 边缘检测原理

    只是实现一下,暂不考虑效率 import cv2 as cv import numpy as np import math # 从源码层面实现边缘检测 img = cv.imread('../imag ...

  7. OpenCV——边缘检测(sobel算子、Laplacian算子、scharr滤波器)

    #include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namespace st ...

  8. opencv边缘检测报错

    cnts = cv2.findContours(edged_image.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)cnts = cnts[0] if ...

  9. 【资料分享】 OpenCV精华收藏

    OpenCV精华收藏 SkySeraph Dec.29th 2010  HQU Email:zgzhaobo@gmail.com    QQ:452728574 Latest Modified Dat ...

随机推荐

  1. Egret白鹭开发微信小游戏手机震动功能

    最近一直在修改调整项目,没有接触新功能,今天终于有机会,去翻了微信API,发现手机震动的API,今天分享出来大家一起学习学习 对于震动,微信提供了两个API,分别是: wx.vibrateShort: ...

  2. switch语句(下)(转载)

    之前我们介绍了在switch语句中使用整数类型和枚举类型的情况.这一部分继续介绍使用string类型的情况.string类型是switch语句接受的唯一一种引用类型参数. 下面来看一段C#代码. 代码 ...

  3. angular8 + redux 管理状态

    1. angular8.1.1 ----- package.json { "name": "angular-demo", "version" ...

  4. LeetCode刷题 - (01)两数之和

    题目描述 给定一个整数数组nums和一个目标值target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是,你不能重复利用这个数组中同样的元 ...

  5. Delphi - Indy TIdMessage和TIdSMTP实现邮件的发送

    idMessage / idSMTP 首先对idMessage类的各种属性进行赋值(邮件的基本信息,如收件人.邮件主题.邮件正文等),其次通过idSMTP连接邮箱服务器,最后通过idSMTP的Send ...

  6. SpringCloud(二)- 服务注册与发现Eureka

    离上一篇微服务的基本概念已经过去了几个月,在写那篇博客之前,自己还并未真正的使用微服务架构,很多理解还存在概念上.后面换了公司,新公司既用了SpringCloud也用了Dubbo+Zookeeper, ...

  7. JMeter使用代理进行录制

    参考: http://www.cnblogs.com/zhuque/archive/2012/11/13/2767747.html JMeter支持第三方(Badboy)录制和代理录制,Badboy录 ...

  8. codeforce303C-Minimum Modular-剪枝,暴力

    Minimum Modular 题意:就是在一堆数字中,每一个数字对m取模不能等于这堆数字中的其他数字,同时给了K个机会可以删除一些数字.求最小的m: 思路:我一开始完全没思路,队长说的并查集什么的不 ...

  9. HDU4289Control 无向图拆点最大流

    /* ** 无向图拆点,求最大流,最大流即为割点个数. */ #include <iostream> #include <cstdio> #include <cstrin ...

  10. CF - 1110 C Meaningless Operations

    题目传送门 题解: 首先根据观察,很容易发的是: x != (1<<k) - 1 时候 答案就是, 将x二进制下再最高位后的0都变成1. 然后就是考虑 x == (1<<k) ...