#来自学渣的问候~
这个是我在用Python学OpenCV的时候,对一张图片进行边缘检测时,遇到的情况和解决的学习过程。
因为我在思考这个东西的时候,感觉这个学习的过程很有趣,所以在这里叙述一下,和大家分享。如有错误,请指正,感激不尽!
第一次学Python,环境用的是anaconda。
边缘检测目前学了两种方法,一个是直接调用OpenCV的Canny函数,另一个是利用Sobel Lapalce 算子,来实现图像的边缘检测。
使用的图像是这个(仅供学习使用,侵删)
导入图片信息
import cv2
import numpy as np
import random
img = cv2.imread('image0.jpg',1)
imgInfo = img.shape
height,width,_ = imgInfo #下划线是一个占位符,因为imgInfo返回三个数,第三个刚好用不到,也不想耗费变量去接收,就用下划线给空掉
灰度转换
这里用的也是现成的函数cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
,img 是图片信息,后面的是转换成的格式。
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #得到灰度图像
高斯滤波
这里用opencv 自带的函数,来进行滤波。
imgG = cv2.GaussianBlur(gray,(3,3),0) #高斯滤波
cv2.imshow('imgG',imgG)
滤波前后的图像如下(左边是滤波前的灰度图,右边是滤波后的):
我一开始学这个高斯滤波的时候,感觉很奇怪,这和我学信号滤波有点不太一样。一般来说,信号中有噪音而需要滤波。滤波后的信号相比滤波前的信号会更清晰(以音频为例)。我把这个感觉带入到图片滤波,发现这个效果是反着来的,高斯滤波后的图像比原图看起来更糊了。
后来我查了一下,高斯滤波本来就是用来对图片进行模糊处理的,但是很奇怪的是,经过滤波后的图片在边缘检测上的线条更加清晰。
边缘检测
dst = cv2.Canny(imgG,100,90) #边缘检测
cv2.imshow('dst1',dst)
左边未滤波的边缘检测,右边滤波后的边缘检测。(代码里我只给了一种代码,这里图像是分开的,方便讲解)
从这个图里,能够明显的看出,经过了高斯滤波之后的图像,边缘特性更加明显。但是,造成这样的理由是什么呢?我查阅了一下,图像噪声这个概念。
图像噪声是指存在于图像数据中的不必要的或多余的干扰信息。各类图像处理系统在图像的采集、获取、传送和转换(如成像、复制扫描、传输以及显示等)过程中,均处在复杂的环境中,光照、电磁多变,所有的图像均不同程度地被可见或不可见的噪声干扰,导致图像质量的下降,掩盖图片重要细节
图片其实是由很多个像素点组成的,而每个像素点,其实表示的就是图像的二维数组中的地址,灰度值。而在图像的生成过程中,由于不可控因素(可以理解为是数字器件产生的随机误差或者噪音),会造成临近灰度值所形成的函数的导数过大——也就是噪声,让其与真实颜色产生误差,掩盖图片细节,之后的各种后期图像处理便会不断放大这种误差。
而滤波则是对图片预处理时消除噪音的一种重要方式。
简单边缘检测的代码(OpenCV)
#边缘检测 图像的卷积运算
import cv2
import numpy as np
import random
img = cv2.imread('image0.jpg')
imgInfo = img.shape
height,width,_ = imgInfo
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #灰度图
cv2.imshow('gray',gray)
imgG = cv2.GaussianBlur(gray,(3,3),0) #高斯滤波
cv2.imshow('imgG',imgG)
dst = cv2.Canny(imgG,100,90) #边缘检测
cv2.imshow('dst0',dst)
cv2.waitKey(0)
一个简单的图像边缘检测就OK了!
~~ 这是一条没有什么存在感的分割线~~
前期题要:我和我的好姐妹都在学习open CV,所以我俩一脸懵逼的讨论了一下怎么优化这个边缘检测后的图像。由于对去噪原理一知半解,除了滤波之外,想了一个对图像显示的边缘线条进行去毛刺的办法。
图片膨胀
图片膨胀和图像反转写在一份代码里面了,线条黑色更加容易体现图像效果。
dst = cv2.dilate(dst,(400,500),iterations=1) #图片膨胀
cv2.imshow('dst',dst)
dstc = np.zeros((height,width,1),np.uint8) #图像反转
for i in range(0,height):
for j in range(0,width):
gra = dst[i,j]
dstc[i,j] = 255-gra
cv2.imshow('src1',dstc)
这个是图片膨胀前后的对比,可以发现,白色的线条更清晰了。
关于cv2.deliate
这个的用法,参考:
cv2.dilate(src, kernel, iteration)
参数说明: src表示输入的图片, kernel表示方框的大小, iteration表示迭代的次数
膨胀操作原理:存在一个kernel,在图像上进行从左到右,从上到下的平移,如果方框中存在白色,那么这个方框内所有的颜色都是白色
图像反转后的效果是这样的
非常漂亮的线稿图,经过了高斯滤波和图像膨胀。
//