文章目录
一. 阈值
代码
from matplotlib import image
import cv2
import matplotlib.pyplot as plt
img=cv2.imread('./material/image/e.jpg',cv2.IMREAD_GRAYSCALE)
# img 只能是单通道的
# 127 是阈值
# maxval 即255 是最大值
# type 二值法的类型
# ret 是阈值,thresh1是阈值处理后的图像
ret,thresh1=cv2.threshold(img,127,255,cv2.THRESH_BINARY) #超过阈值取最大值,否则取0
ret,thresh2=cv2.threshold(img,127,255,cv2.THRESH_BINARY_INV) #和上边反过来
ret,thresh3=cv2.threshold(img,127,255,cv2.THRESH_TRUNC) #超出阈值设为阈值,否则不变
ret,thresh4=cv2.threshold(img,127,255,cv2.THRESH_TOZERO) #超过阈值不变,否则取0
ret,thresh5=cv2.threshold(img,127,255,cv2.THRESH_TOZERO_INV) #和上边的反过来
# 搞到一个数组里
images=[img,thresh1,thresh2,thresh3,thresh4,thresh5]
# 画出看看
for i in range(6):
plt.subplot(2,3,i+1),plt.imshow(images[i],'gray')
plt.xticks([]),plt.yticks([])
plt.show()
效果图:
二. 平滑处理
平缓处理,就是有用来去除噪音点的,可以通俗的理解为磨光
均值滤波,就是用九个数的平均数,代替中间的,中值滤波就是用 中位数 的代替两边的,所以一般来讲,应该是中值滤波器效果比较好。
代码:
from matplotlib import image
import cv2
import matplotlib.pyplot as plt
img=cv2.imread('./material/image/g.jpg')
# 均值滤波
# 使用 3*3 的滤波器
blur=cv2.blur(img,(3,3))
# 方框滤波和均值滤波其实是一样的
# 高斯滤波 离中间点越近,影响越大,权重越大
aussian=cv2.GaussianBlur(img,(5,5),1)
#中值滤波
median=cv2.medianBlur(img,5)
# 画出看看
images=[img,blur,aussian,median]
for i in range(4):
plt.subplot(2,2,i+1),plt.imshow(images[i],'gray')
plt.xticks([]),plt.yticks([])
plt.show()
效果图:
三.梯度处理
3.1梯度的概念
就以上边的图为例,可以看出来,红点的地方,左边和右边的像素点的值,差距是非常大的(一个是255,一个0),那么就可以说,这个区域是存在 梯度 的
在一般的实际应用中,梯度就是用来做边缘检测的。相当于把边界线标出来(边界线就是 中间的那个数)
3.2图像梯度 - Sobel 算子
Gx这样相当于始终是右边减左边,所以有些时候可以取绝对值
以 Gx 为例,梯度运算和上边平滑处理是一样,这个也是用来算 P5 值的,所以 P4和P6 会对P5 的影响比较大,权重为2,而P1和P3 的权重为1 。
3.3代码:
import cv2
from _00_pubulic import cv_show
from matplotlib import image
import matplotlib.pyplot as plt
#读进来一张照片
img=cv2.imread('./material/image/a.jpg',cv2.IMREAD_GRAYSCALE)
cv_show(img,'img')
#进行x轴方向的检测 即(1,0)表示的是x 轴的检测
sobelx=cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
cv_show(sobelx,"sobelx")
#转成绝对值在看x轴的检测
sobelx=cv2.convertScaleAbs(sobelx)
cv_show(sobelx,"sobelx")
#进行y方向的检测
sobely=cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
cv_show(sobely,"sobelx")
#竖着的和横着的相加
sobelxy=cv2.addWeighted(sobelx,0.5,sobely,0.5,0)
cv_show(sobelxy,"sobelxy")
原图:
竖直方向进行梯度处理(x轴放下的处理)
Y轴方向上的梯度处理
x轴的处理结果和y方向的处理结果相加
x轴方向,转换成绝对值后的结果:
建议先后求出 x ,y,的梯度,然后相加,不建议直接求梯度
3.其他算子
注意:
- Scharr 算子相当于比 Sobel 算子更细了,可以查出更细小的变化
- laplacian 算子一般不会单独使用,因为对噪音点比较敏感
四.边缘检测
只看一个经典的边缘检测算法:Canny 边缘检测
(一) Canny边缘检测的步骤:
- 使用高斯滤波器,以平滑图像,滤掉噪音
- 计算每个像素点的梯度强度和梯度方向
- 应用极大值抑制。来消除边缘检测带来的杂散响应
- 应用双阈值,来检测真正和潜在的边缘
- 采用抑制孤立的弱边缘最终完成边缘检测
(二)具体过程
1.高斯滤波器
计算梯度和方向
非极大值抑制:判断不是最大值的梯度,不是最大的就抑制:
canny中非最大抑制(Non-maximum suppression)其实就是回答这样一个问题: “当前的梯度值在梯度方向上是一个局部最大值吗?” 所以,要把当前位置的梯度值与梯度方向上两侧的梯度值进行比较.
双阈值检测
(三) 代码
import cv2
from _00_pubulic import cv_show
from matplotlib import image
import matplotlib.pyplot as plt
import numpy as np
#读进来一张照片
img=cv2.imread('./material/image/a.jpg',cv2.IMREAD_GRAYSCALE)
cv_show(img,'img')
#使用Canny边缘检测算法 80,150 是两个阈值
v1=cv2.Canny(img,80,150)
v2=cv2.Canny(img,50,100)
res=np.hstack((v1,v2))
cv_show(res,'res')
原图和效果图
可以看出来,右边的边缘检测更细腻
五. 图像金字塔与边缘检测
(一)图像金字塔
主要分为两种
- 高斯金字塔
- 拉普拉斯金字塔
上下采样的代码
#读进来一张照片
img=cv2.imread('./material/image/a.jpg',cv2.IMREAD_GRAYSCALE)
print(img.shape)
# (300,530)
# 上采样
up=cv2.pyrUp(img)
cv_show(up,'up')
print(up.shape)
# 下采样
down=cv2.pyrDown(img)
cv_show(down,'down')
(二)轮廓检测
轮廓检测和边缘检测的区别:虽然边缘检测把边界找出来,然后零零散散的拼成一个轮廓,但是他毕竟不是一个整体,轮廓检测是一个整体性的。
轮廓构建的方法
轮廓都是用边缘检测得到的点来勾画出来的,轮廓逼近法,主要有两种
- CHAIN_APPROX_NONE:
- CHAIN_APPROX_SIMPLE:
代码:
import cv2
from _00_pubulic import cv_show
import matplotlib.pyplot as plt
import numpy as np
#读进来一张图
img=cv2.imread('./material/image/e.jpg')
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#转换成灰度图
# thresh_binary 是非黑即白的分类方式
ret,threshimg=cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
cv_show(threshimg,'thresh')
# 执行边缘检测
# 参数的含义:cv2.retr_tree 是检测所有的轮廓
# chain——approx——none 是把所有点都画出来,
# contours 是返回的轮廓信息
# herarchy 是层级
contours,hierarchy=cv2.findContours(threshimg,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
# 绘制轮廓(在原图上把轮廓画出来)
# 注意不要是使用 copy ,要不原图会变
draw_img=img.copy()
res=cv2.drawContours(draw_img,contours,-1,(0,0,255),2)
cv_show(res,'res')
效果图:
(三)轮廓特征
轮廓特征,就是比如轮廓的面积或者边长等等特征。
#轮廓特征 (先找到一个轮廓)
cnt=contours[139]
#面积
a=cv2.contourArea(cnt)
print(a)
#周长 。true 表示闭合
a=cv2.arcLength(cnt,True)
print(a)
六.直方图
(一)直方图
直方图的均衡化:
直方图均衡化是通过拉伸像素强度分布范围来增强图像对比度的一种方法
(二)将图片转换成直方图的代码
#读进来一张图,0表示是灰度图
img=cv2.imread('./material/image/e.jpg',0)
# channels:表示的是通道数,如果是会对就是[0], 彩色图就是 [0][1][2]分别对应着BGR
# mask 就是表示其中的一部分
# [0,256]表示的取值范围
# hist
hist=cv2.calcHist([img],[0],None,[256],[0,256])
print(hist.shape)
# 把图画出来
plt.hist(img.ravel(),256)
plt.show()
# 进行均衡化操作
equ=cv2.equalizeHist(img)
plt.hist(equ.ravel(),256)
plt.show()
运行结果:
均衡化之后的结果:
(三)自适应直方图
直接进行全局适应,会出现上边的问题,会把人脸变模糊,所以,可以把上面的图片进行画区域进行均衡化处理
代码:
# 自适应均衡化
clahe=cv2.createCLAHE(clipLimit=2.0,tileGridSize=(8,8)) # 声明一个方法
res_clahe=clahe.apply(img) # 把方法应用到图片上
# 把三张图摞在一起画出来
res=np.hstack((img,equ,res_clahe))
cv_show(res,'res')
效果图如下:
七.傅里叶变换
傅里叶变换的作用:
- 高频:变化剧烈的灰度分量,例如边界
- 低频:变化缓慢的灰度图分量,例如一片大海
滤波:
- 低通滤波器:只保留低频,会让图片变得模糊
- 高通滤波器:只保留高频,会让图像的细节增强
八.图像特征
(一)图像特征 -harris 角点检测
B是平面,C是边界,A是角点,从图中可以看出,只有A在沿 x ,y 轴移动的时候,会发生剧烈变化,所以可以认定为焦点 (当然,真正的推算的数学公式是比较复杂的,用到再看)
- 边界可以大致找到位置
- 角点可以迅速定位到位置
(二)图像特征-sift
1.图像的尺寸空间:
在一定的范围内,无论物体是大是小,人眼都可以分辨出来,然而计算机要有相同的功能却很难,所以要让机器对物体不同尺度下有一个统一的认知,就需要考虑一下图像在不同的尺度下都存在的特点。
尺寸空间的获取通常通过高斯模糊来实现:
权重模糊的程度,是通过 ??来显示的
也就是说,无论是清楚或者模糊,你都得能认出来才行
2.多分辨率金字塔
通过上采样和下采样,把图分成大小不同的几张,且每张都要做高斯滤波。
高斯差分金字塔:
就是通过做差,看哪个差距大,就说明哪个更容易区分。
具体查看参考文献: https://blog.csdn.net/dcrmg/article/details/52561656