前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >OpenCV 入门之图像模糊与边缘检测

OpenCV 入门之图像模糊与边缘检测

作者头像
用户6021899
发布2019-08-21 18:13:56
2K0
发布2019-08-21 18:13:56
举报

OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux、Windows、Android和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。官方下载链接如下:https://opencv.org/releases/

安装完毕后,在python中导入cv2库就可以使用OpenCV的API。

  • 读取图像 不同系统支持的图像格式不一样,但都支持BMP格式,通常还支持PNG、JPEG和TIFF格式。
代码语言:javascript
复制
img = cv2.imread("sf.jpg")
>>> type(img)
<class 'numpy.ndarray'>
>>> img.shape
(333, 500, 3)
>>> img[0,0]
array([16, 16, 16], dtype=uint8)
>>> img[0,0,1]
16

一个OpenCV图像是 numpy 二维(灰度图)或者三维数组(彩图)。

img[y,x] 表示二维图 y行 x列处像素点的亮度值。

img[y,x,c]表示三维图 y行x列出像素点通道c的亮度值。

像素的亮度值用一个无符号的8位整数表示,所以范围在0到255。

可以只加载灰度图:

代码语言:javascript
复制
img3 = cv2.imread("sf.jpg", cv2.IMREAD_GRAYSCALE)
#因为cv2.IMREAD_GRAYSCALE=0
#可以简写为 img3 = cv2.imread("sf.jpg", 0)
  • 显示图像:
代码语言:javascript
复制
img = cv2.imread("sf.jpg")
cv2.imshow("Sophie Marceau", img) #第一个参数为窗口标题
代码语言:javascript
复制
#创建一个合法的随机数组并显示
img2 = np.random.randint(256,size =(200,400,3),dtype =np.uint8)
cv2.imshow("random pix", img2)
  • 保存图像
代码语言:javascript
复制
img = cv2.imread("hua.jpg")
img_reverse = 255- img #明暗颠倒
cv2.imwrite("jiangshan_r.PNG", img_reverse)
  • 分离和合并RBG通道
代码语言:javascript
复制
B,G,R = cv2.split(img) #分离通道,注意顺序:蓝,绿,红
G[:,:]=0 #绿色通道清零
R[:,:]=0 #红色通道清零
img_blue = cv2.merge((B,G,R)) #合并三通道
cv2.imshow("blue chanel", img_blue)

#其实也可以只用numpy操作
img_blue = img.copy()
img_blue[:,:,1:3]=0
cv2.imshow("blue chanel _", img_blue)
  • 高通滤波器(HPF) 高通滤波器根据像素与邻近像素的亮度差值来提示改像素的亮度。 如: blurred = cv2.GaussianBlur(img, (13,13),sigmaX =1.2) g_HPF = img-blurred cv2.imshow("g_hpf", g_HPF) cv2.waitKey() cv2.destroyAllWindows()

又如使用如下之类的核(后面会介绍),中间元素为正,周围元素为负,核中所有的值之和为0: kernel = np.array([[-1, -1, -1], [-1, 8, 1], [-1, -1, -1]])

  • 低通滤波器(LPF) 在像素与周围像素的亮度差值小于一个特定值时,平滑该像素的亮度。它主要用于去噪和模糊化。比如,高斯模糊是最常用的模糊滤波器之一,它是一个削弱高频信号的低通滤波器。例子见图像模糊中的例子。
  • 核(卷积矩阵) OpenCV许多预定义的滤波器都会使用核。核是一组权重,它决定了如何通过邻近的像素点来计算中心的像素点。核也称为卷积矩阵,它对一个区域的像素做卷积运算。卷积矩阵是一个二维数组,它有奇数行和奇数列。中心的元素对应于感兴趣的像素,其它的元素对应于这个像素周围的邻近像素。每个元素都对应一个整数或者浮点数的值,这些值代表了应用在该像素上的权重。 filter2D()函数 运用用户指定的任意卷积矩阵进行滤波。
代码语言:javascript
复制
#下面的核会使图像锐化
kernel = np.array([[-1, -1, -1],
                  [-1,  9,   1],
                  [-1, -1, -1]])
img_new = cv2.filter2D(img, -1, kernel)
cv2.imshow("sharpening", img)
代码语言:javascript
复制
##下面的核会使图像产生浮雕效果
kernel2 = np.array([[-2, -1, 0],
                    [-1,  0,   1],
                    [0, 1, 2]])
img_embossed = cv2.filter2D(img, -1, kernel2)
cv2.imshow("embossed", img_embossed)

嗯,黑了点...

  • 图像模糊 除了高斯模糊外,还可以自定义模糊滤波器。为了达到模糊效果,通常权重的和应该为1,而且零件像素的权重全为正。下面实现了一个简单的平均滤波器。
代码语言:javascript
复制
#k=3, 5, 7, 9 共四级模糊效果,k越大越模糊
for k in range(3,10,2):
    knrnel3 = np.array([[1.0/k**2]*k for i in range(k)])
    img_edges = cv2.filter2D(img, -1 ,knrnel3)
    cv2.imwrite("blurring k=%d.jpg"%k,img_edges)#保存图像
    cv2.imshow("blurring k=%d"%k,img_edges)
  • 图像边缘检测 1. 使用自定义核 img_old= cv2.imread(r"hua.jpg") cv2.imshow("old", img_old) knrnel = np.array([[-1, -1, -1], [-1, 8, -1], [-1,-1,-1]]) img_edges = cv2.filter2D(img_old, -1 ,knrnel) img_edges_gray = cv2.cvtColor(img_edges, cv2.COLOR_BGR2GRAY) cv2.imshow("img_edges", img_edges_gray) cv2.waitKey() cv2.destroyAllWindows()

原图:

边缘:

2.也可以使用Laplacian()函数:

代码语言:javascript
复制
def strokeEdges(src, blurKsize=7, edgeKsize=5): #两个ksize须为奇数
    if blurKsize >3:
        blurredSrc =cv2.medianBlur(src, blurKsize) #模糊函数,用于降噪
        graySrc = cv2.cvtColor(blurredSrc,cv2.COLOR_BGR2GRAY)#转灰度图
    else:#关闭模糊
        graySrc = cv2.cvtColor(src,cv2.COLOR_BGR2GRAY)#转灰度图
    #边缘检测 edgeKsize越大越灵敏,但可能越多noise
    graySrc=cv2.Laplacian(graySrc, cv2.CV_8U, ksize=edgeKsize)#得到白色边缘,黑色背景
    #cv2.imshow("edges0", graySrc)
    normlizedInverseAlpha = graySrc/255.0
    channels = cv2.split(src)# 通道分离,注意顺序BGR不是RGB
    for channel in channels:
        channel[:] = channel * normlizedInverseAlpha # 边缘映射到原图(会保留色彩)
    return cv2.merge(channels)

img_old = cv2.imread(r"hua.jpg")
cv2.imshow("old", img_old)
edges = strokeEdges(img_old,blurKsize=7, edgeKsize=5) #两个ksize须为奇数
grayEdges = cv2.cvtColor(edges,cv2.COLOR_BGR2GRAY)#转灰度图
cv2.imshow("edges", edges)
#cv2.imshow("edges_GRAY", grayEdges)
cv2.waitKey()
cv2.destroyAllWindows()

3. 还可以考虑非常方便的Canny()函数:

代码语言:javascript
复制
'''
Canny(...)
    Canny(image, threshold1, threshold2[,
    edges[, apertureSize[, L2gradient]]]) -> edges
'''
#image:源图像
#threshold1:阈值1
#threshold2:阈值2
#apertureSize:可选参数,Sobel算子的大小
#其中,较大的阈值2用于检测图像中明显的边缘,但一般情况下检测的效果不会那么完美,
#边缘检测出来是断断续续的。所以这时候用较小的第一个阈值用于将这些间断的边缘连接起来。
#函数返回的是二值图,包含检测出的边缘
img = cv2.imread("hua.jpg")
edges = cv2.Canny(img,20,120)
cv2.imshow("original", img)
cv2.imshow("canny",edges)
cv2.waitKey()
cv2.destroyAllWindows()
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-08-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python可视化编程机器学习OpenCV 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
图像处理
图像处理基于腾讯云深度学习等人工智能技术,提供综合性的图像优化处理服务,包括图像质量评估、图像清晰度增强、图像智能裁剪等。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档