一、图像滤波
平滑与模糊即失去焦点,致使看不到图像的细节,也就是说像素点与周围像素点混合了,在边缘检测方面很有用处,常用的平滑方法有均值、高斯、中值和双边。实例如下所示:
import cv2 as cv
import numpy as np
test_image = cv.imread(r'E:\kaggleData\computer_version_Data\4.jpg')
cv.imshow('test_image', test_image)
"""
cv2.blur(img,ksize) 均值滤波
img:原图像
ksize:核大小
原理:它只取内核区域下所有像素的平均值并替换中心元素。
特征:核中区域贡献率相同。
作用:对于椒盐噪声的滤除效果比较好
"""
blurred = np.hstack([
cv.blur(test_image, (3, 3)),
cv.blur(test_image, (5, 5)),
cv.blur(test_image, (7, 7))
])
cv.imshow("Averaged", blurred)
"""
cv2.GuassianBlur(img, ksize,sigmaX,sigmaY) 高斯滤波
说明:sigmaX,sigmaY分别表示X,Y方向的标准偏差。如果仅指定了sigmaX,则sigmaY与sigmaX相同.如果两者都为零,
则根据内核大小计算它们。
特征:核中区域贡献率与距离区域中心成正比,权重与高斯分布相关。
作用:高斯模糊在从图像中去除高斯噪声方面非常有。
第三个参数0表示自动计算核大小
"""
blurred = np.hstack([
cv.GaussianBlur(test_image, (3, 3), 0),
cv.GaussianBlur(test_image, (5, 5), 0),
cv.GaussianBlur(test_image, (7, 7), 0)
])
cv.imshow("Gaussian", blurred)
"""
cv2.medianBlur(img, k) 中值滤波
说明:imgs为原图像,k为方框的尺寸,相当于将方框内的个值进行排序,取中值作为当前值。
特征:中心点的像素被核中中位数的像素值代替。
作用:对于椒盐噪声有效。
"""
blurred = np.hstack([
cv.medianBlur(test_image, 3),
cv.medianBlur(test_image, 5),
cv.medianBlur(test_image, 7)
])
cv.imshow("Median", blurred)
"""
双边滤波:
cv2.bilateralFilter(img,d, sigmaColor, sigmaSpace)双边滤波
说明:d为邻域直径,sigmaColor为空间高斯函数标准差,参数越大,临近像素将会在越远的地方越小。
sigmaSpace灰度值相似性高斯函数标准差,参数越大,那些颜色足够相近的的颜色的影响越大。
双边滤波是一种非线性的滤波方法,是结合图像的空间邻近度和像素值相似度的一种折衷处理,
同时考虑空间与信息和灰度相似性,达到保边去噪的目的,具有简单、非迭代、局部处理的特点。
之所以能够达到保边去噪的滤波效果是因为滤波器由两个函数构成:一个函数是由几何空间距离决定滤波器系数,
另一个是由像素差值决定滤波器系数。
特征:处理耗时。
作用:在滤波的同时能保证一定的边缘信息。
"""
blurred = np.hstack([
cv.bilateralFilter(test_image, 5, 21, 21),
cv.bilateralFilter(test_image, 7, 31, 31),
cv.bilateralFilter(test_image, 9, 41, 41)
])
cv.imshow("BilateralFilter", blurred)
cv.waitKey(0)
原始图像
均值滤波图像效果
高斯滤波
‘中值滤波
双边滤波
二、边缘检测
"""
边缘检测方法有Canny,主要包括平滑降噪、求梯度、非极大值抑制与滞后阈值。
"""
import cv2 as cv
test_image = cv.imread(r'E:\kaggleData\computer_version_Data\test.jpg')
cv.imshow("test_image", test_image)
# 颜色空间转换
gray_image = cv.cvtColor(test_image, cv.COLOR_BGR2GRAY)
# 高斯降噪
blured = cv.GaussianBlur(gray_image, (5, 5), 0)
cv.imshow("blured", blured)
# 边缘检测
"""
void cvCanny( const CvArr* image,CvArr*edges,double threshold1,double threshold2, int aperture_size=3 );
参数列表:
image 输入单通道图像(可以是彩色图像)对于多通道的图像可以用cvCvtColor(将图像从一个颜色空间转换到另一个颜色空间的转换)修改。
edges 输出的边缘图像,也是单通道的,但是是黑白的
threshold1 第一个阈值(低阈值)
threshold2 第二个阈值(高阈值)
aperture_size Sobel 算子内核大小(滤波计算矩阵的大小默认为3)可以是1、3、5、7
函数 cvCanny 采用 Canny 算法发现输入图像的边缘而且在输出图像中标识这些边缘。
注释:threshold1和threshold2 当中的小阈值用来控制边缘连接,大的阈值用来控制强边缘的初始分割。
高阈值比较严格,求的边缘很少,认为高阈值的边缘都是有效。低阈值宽松,求的边缘很多(一般包括了高阈值求到的边缘),其中不少是无效的边缘(反正不想要的)。
先用高阈值求边缘。canny求得的边缘希望是连在一起的(通常是封闭的),但高阈值求的边缘一般断断续续。断开的地方如果低阈值求的边缘存在,就用低阈值的边缘接上去,目的让边缘尽量都连在一起。其它情况下低阈值的边缘是不用的。
两个阈值是有区别的,高的那个阈值是将要提取轮廓的物体与背景区分开来,就像阈值分割的那个参数一样,是决定目标与背景对比度的,低的那个阈值是用来平滑边缘的轮廓,有时高的阈值设置太大了,可能边缘轮廓不连续或者不够平滑,通过低阈值来平滑轮廓线,或者使不连续的部分连接起来
"""
canny = cv.Canny(blured, 30, 150)
cv.imshow("Canny", canny)
cv.waitKey(0)
三、人脸和眼睛检测实例
1.OpenCV人脸检测的xml文件下载
人脸检测和眼睛检测要用到haarcascade_eye.xml和haarcascade_frontalface_default.xml这两个文件,文件下载地址:
2.人脸识别
import cv2 as cv
image = cv.imread(r'E:\kaggleData\computer_version_Data\5.jpg')
gray_image = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
cv.imshow('gray_image', gray_image)
# 进行人脸识别必须导入XML文件,然后就可以使用detectMultiScale进行目标(人脸)检测
face_xml = cv.CascadeClassifier('E:\kaggleData\computer_version_Data\OpenCV_xml\haarcascade_frontalface_default.xml')
eye_xml = cv.CascadeClassifier('E:\kaggleData\computer_version_Data\OpenCV_xml\haarcascade_eye.xml')
# 利用face_xml.detectMultiScale()方法识别出人脸的位置,并利用cv2.rectangle()绘制方框
faces = face_xml.detectMultiScale(gray_image,
scaleFactor=1.05,
minNeighbors=5,
minSize=(30, 30),
flags=cv.CASCADE_SCALE_IMAGE)
print("这张图中有%d个人脸" % len(faces))
# 绘制出识别到的人脸
for (x, y, w, h) in faces:
cv.rectangle(image, (x, y), (x+w, y+h), (255, 0, 0), 2)
cv.imshow('dst', image)
3.眼睛识别
在做眼睛识别的过程中遇到了问题,就是把鼻子也识别成了眼睛,大家知不知道什么原因,可以给我留言,感谢。
# 眼睛识别和人脸识别类似,不过眼睛识别是在人脸识别的基础上再进行识别的,所以将人脸的图片进行灰度化处理,再识别
# 眼睛识别并用方框圈出眼睛的位置
face_gray = gray_image[y:y+h, x:x+w]
face_color = image[y:y+h, x:x+w]
# 眼睛识别
eyes = eye_xml.detectMultiScale(face_gray)
print("在这张脸上有%d个眼睛" % len(eyes))
# 绘制出识别到的眼睛
for (e_x, e_y, e_w, e_h) in eyes:
cv.rectangle(face_color, (e_x, e_y), (e_x+e_w, e_y+e_h), (0, 255, 0), 2) # 绘制眼睛方框
cv.imshow('dst', image)
cv.waitKey(0)