目录
- OpenCV库(二)
- 五、 图像直方图
- 1、 基本概念
- 2、 统计函数
- 3、绘制直方图
- 3.1 matplotlib
- 3.2 OpenCV
- 4、 使用掩膜的直方图
- 六、 视频采集
- 1、 打开视频
- 2、 读取数据
- 3、 视频属性
- 4、 视频录制
- 5、 控制鼠标
- 七、 特征检测
- 1、 基本概念
- 2、 Harris角点检测
- 3、 SIFT 关键点检测
- 4、 Shi-Tomasi角点检测
- 5、 Fast算法
- 5.1 原理
- 5.2 机器学习的角点检测器
- 5.3 非极大值抑制
- 5.4 实现
- 6、 ORB算法
- 6.1 原理
- 6.2 实现
- 五、 图像直方图
OpenCV库(二)
五、 图像直方图
1、 基本概念
在统计学中,直方图是一种对数据分布情况的图形表示,是一种二维统计图表
图像直方图是用一表示数字中亮度分布的直方图,标绘了图像中每个亮度值的像素数,可以借助观察该直方图了需要如何调整亮度分布的直方图。这种直方图中,横坐标的左侧为纯黑、较暗的区域,而右侧为较亮、纯白的区域。因此,一张较暗图片的图像直方图中的数据多集中于左侧和中间部分,而整体明亮,只有少量明显的图像则相反
- 横坐标:图像中各个像素点的灰度级
- 纵坐标:具有该灰度的像素个数
2、 统计函数
语法:
calcHist(imgs, channels, mask, histSize, ranges[, hist[, accumulate]])
参数:
-
:图像集,传入一个图像列表imgs
-
channels
:指定通道
需要用中括号括起来,输入图像是灰度图像的值是[0],彩色图像可以是[0], [1], [2],分别对应B, G, R
-
:掩码图像mask
- 统计整副图像的直方图,设为None
- 统计图像某一部分的直方图时,需要设置掩码图像
-
histSize
:BINS的数量
需要用中括号括起来,例如[256]
-
:像素值范围,例如[0, 255]ranges
-
:累积标识accumulate
- 默认值为False
- 如果被设置为True,则直方图在开始分配时不会被清零
- 该参数允许从多个对象中计算单个直方图,或者用于实时更新直方图
- 多个直方图的累积结果,用于对一组图像计算直方图
# !/usr/bin/python3
# -*- coding: UTF-8 -*-
__author__ = "A.L.Kun"
__file__ = "demo9.py"
__time__ = "2022/7/18 18:09"
import cv2.cv2 as cv2
import numpy as np
# 读取图像
img = cv2.imread("./img/1.jpg")
assert isinstance(img, np.ndarray)
hist = cv2.calcHist([img], [0], None, [256], [0, 255])
print(hist.shape)
# 如何绘制直方图
3、绘制直方图
3.1 matplotlib
# !/usr/bin/python3
# -*- coding: UTF-8 -*-
__author__ = "A.L.Kun"
__file__ = "demo9.py"
__time__ = "2022/7/18 18:09"
import cv2.cv2 as cv2
import numpy as np
import matplotlib.pyplot as plt
# 读取图像
img = cv2.imread("./img/1.jpg", cv2.IMREAD_GRAYSCALE) # 读取黑白效果
assert isinstance(img, np.ndarray)
# print(img.ravel())
# 统计直方图数据
plt.hist(img.ravel(), 256, [0, 255]) # 转换为一维数据,
plt.show() # 绘制直方图数据
3.2 OpenCV
# !/usr/bin/python3
# -*- coding: UTF-8 -*-
__author__ = "A.L.Kun"
__file__ = "demo9.py"
__time__ = "2022/7/18 18:09"
import cv2.cv2 as cv2
import numpy as np
import matplotlib.pyplot as plt
# 读取图像
img = cv2.imread("./img/1.jpg") # 读取黑白效果
assert isinstance(img, np.ndarray)
# 统计直方图数据
histB = cv2.calcHist([img], [0], None, [256], [0, 255]) # 蓝色通道
histG = cv2.calcHist([img], [1], None, [256], [0, 255]) # 绿色通道
histR = cv2.calcHist([img], [2], None, [256], [0, 255]) # 红色通道
# 画图
plt.plot(histB, color="b", label="blue")
plt.plot(histG, color="g", label="green")
plt.plot(histR, color="r", label="red")
plt.legend()
plt.show()
4、 使用掩膜的直方图
如何生成掩膜:
- 先生成一个全黑的图像和原图图像大小一样大的图片,
mask = np.zeros(img.shape, np.uint8)
- 将想要的区域通过索引方式设置为255,
mask[100: 200, 200: 300] = 255
# !/usr/bin/python3
# -*- coding: UTF-8 -*-
__author__ = "A.L.Kun"
__file__ = "demo9.py"
__time__ = "2022/7/18 18:09"
import cv2.cv2 as cv2
import numpy as np
import matplotlib.pyplot as plt
# 读取图像
img = cv2.imread("./img/1.jpg", cv2.IMREAD_GRAYSCALE) # 读取黑白效果
assert isinstance(img, np.ndarray)
# 生成掩膜
mask = np.zeros(img.shape, np.uint8)
mask[100:700, 200: 900] = 255
# # 进行与操作:img和img做与运算,结果再和mask做与运算
# new_img = cv2.bitwise_and(img, img, mask=mask)
# 掩膜直方图,专门对某一个区域
hist_mask = cv2.calcHist([img], [0], mask, [256], [0, 255])
hist_gray = cv2.calcHist([img], [0], None, [256], [0, 255])
# 统计结果
plt.plot(hist_mask, label="mask")
plt.plot(hist_gray, label="gray")
plt.legend()
plt.show()
六、 视频采集
1、 打开视频
- 视频是有图片组成的,视频的每一帧都是一副图片,一般是30fps,表示每秒显示30张图片
-
可以捕获摄像头,用数字来表示不同的设备,比如0,1cv2.VideoCapture
- 如果是视频文件,可以直接指定路径即可
#!/usr/bin/python3
# -*- coding: UTF-8 -*-
__author__ = "A.L.Kun"
__file__ = "demo10.py"
__time__ = "2022/7/29 19:20"
import cv2.cv2 as cv
# 打开视频文件
vc = cv.VideoCapture("./img/1.mp4")
# 打开摄像头
vc_ = cv.VideoCapture(0)
2、 读取数据
#!/usr/bin/python3
# -*- coding: UTF-8 -*-
__author__ = "A.L.Kun"
__file__ = "demo10.py"
__time__ = "2022/7/29 19:20"
import cv2.cv2 as cv
# 打开摄像头,并读取数据
vc = cv.VideoCapture(0) # 如果打开失败,或者是没有读取到数据,不会报错
while vc.isOpened(): # 如果摄像头成功打开
# 读每一帧数据,返回标记,True表示读到了数据,False表示是没有读到数据
flag, frame = vc.read()
if not flag:
break # 如果没有读到数据,直接退出
# 显示数据
cv.imshow("video", frame)
key = cv.waitKey(30) # 注意,不能写0,不然要点退出才能展示下一帧的数据,每隔10毫秒显示数据
if key & 0xFF == ord('q'): # 使用 key 来监控键盘中输入的内容
break
# 别忘了释放资源
vc.release()
cv.destroyAllWindows()
3、 视频属性
参数 | propld | 功能 |
---|---|---|
cv2.CAP_PROP_POS_MSEC | 视频文件的当前位置(以毫秒为单位)或视频捕获时间戳 | |
cv2.CAP_PROP_POS_FRAMES | 1 | 基于0的索引将被解码/捕获下一帧 |
cv2.CAP_PROP_POS_AVI_RATIO | 2 | 视频文件的相对位置:0 - 视频的开始,1 - 视频的结束 |
cv2.CAP_PROP_FRAME_WIDTH | 3 | 帧的宽度 |
cv2.CAP_PROP_FRAME_HEIGHT | 4 | 帧的高度 |
cv2.CAP_PROP_FPS | 5 | 帧速 |
cv2.CAP_PROP_FOURCC | 6 | 4个字符表示的视频编码器格式 |
cv2.CAP_PROP_FRAME_COUNT | 7 | 帧数 |
cv2.CAP_PROP_FORMAT | 8 | byretrieve()返回的Mat对象的格式 |
cv2.CAP_PROP_MODE | 9 | 指示当前捕获模式的后端特定值 |
cv2.CAP_PROP_BRIGHTNESS | 10 | 图像的亮度(仅适用于相机) |
cv2.CAP_PROP_CONTRAST | 11 | 图像对比度(仅适用于相机) |
cv2.CAP_PROP_SATURATION | 12 | 图像的饱和度(仅适用于相机) |
cv2.CAP_PROP_HUE | 13 | 图像的色相(仅适用于相机) |
cv2.CAP_PROP_GAIN | 14 | 图像的增益(仅适用于相机) |
cv2.CAP_PROP_EXPOSURE | 15 | 曝光(仅适用于相机) |
cv2.CAP_PROP_CONVERT_RGB | 16 | 表示图像是否应转换为RGB的布尔标志 |
cv2.CAP_PROP_WHITE_BALANCE | 17 | |
cv2.CAP_PROP_RECTIFICATION | 18 | 立体摄像机的整流标志 |
获取和修改属性值:
vc = cv.VideoCapture(0) # 如果打开失败,或者是没有读取到数据,不会报错
vc.set(propId, value) # 设置视频的属性值
"""
:propId: 上面表格中的id值
:value: 修改后的值
"""
vc.get(propId) # 获取对应功能的值
4、 视频录制
cv2.VideoWriter()
- 参数:
- 输出文件
- 多媒体文件的格式(
)VideoWriter_fourcc
- 帧率
- 分辨率
write编码,并写入缓存
release函数将缓存内容写入磁盘,并释放资源
#!/usr/bin/python3
# -*- coding: UTF-8 -*-
__author__ = "A.L.Kun"
__file__ = "demo10.py"
__time__ = "2022/7/29 19:20"
import cv2.cv2 as cv
# 打开摄像头,并读取数据
cap = cv.VideoCapture(0)
fourcc = cv.VideoWriter_fourcc(*'mp4v') # 文件格式,*表示解包操作
vw = cv.VideoWriter("./img/outer.mp4", fourcc, 30, (640, 480)) # (640, 480) 表示摄像头拍摄视频,这个大小不能搞错
cap.set(cv.CAP_PROP_FPS, 30) # 设置摄像头的帧率
while cap.isOpened(): # 根据flag来判断是否读到了视频数据
# 读每一帧数据,返回标记,True表示读到了数据,False表示是没有读到数据
flag, frame = cap.read()
if not flag:
print("没有捕获到视频数据")
break # 如果没有读到数据,直接退出
# 将数据写入文件中
vw.write(frame)
cv.imshow("frame", frame)
if cv.waitKey(1000 // 30) == ord('q'):
break
vw.release() # 将数据内容写入文件中
cap.release() # 并释放缓存内容
cv.destroyAllWindows() # 摧毁窗口
:
VideoWriter_fourcc
CV_FOURCC('I','4','2','0') :未压缩的YUV编码,4:2:0色度子采样。这种编码广泛兼容,但会产生大文件。文件扩展名应为.avi CV_FOURCC('P','I','M','1') :MPEG-1编码。文件扩展名应为.avi。 CV_FOURCC('X','V','I','D') :相对较旧的MPEG-4编码。如果要限制结果视频的大小,这是一个很好的选择。文件扩展名应为.avi。 CV_FOURCC('M','P','4','V') :另一个相对较旧的MPEG-4编码。如果要限制结果视频的大小,这是一个很好的选择。文件扩展名应为.mp4 CV_FOURCC('X','2','6','4'): 一种比较新的MPEG-4编码方式。如果你想限制结果视频的大小,这可能是最好的选择。文件扩展名应为.mp4 CV_FOURCC('F','L','V','1') :此选项为Flash视频。文件扩展名应为.flv
5、 控制鼠标
OpenCV 允许我们对窗口上的鼠标动作做出响应
-
setMouseCallbask(winname, callback, userdata)
-
:窗口名字winname
-
:回调函数callback
-
:给回调函数传递的参数userdata
-
-
callback(event, x, y, flags, userdata)
-
:鼠标事件event
-
:坐标点x, y
-
:主要用于组合键flags
-
:给回调函数传递的参数userdata
-
鼠标事件:
EVENT_MOUSEMOVE 0 # 滑动
EVENT_LBUTTONDOWN 1 # 左键点击
EVENT_RBUTTONDOWN 2 # 右键点击
EVENT_MBUTTONDOWN 3 # 中键点击
EVENT_LBUTTONUP 4 # 左键放开
EVENT_RBUTTONUP 5 # 右键放开
EVENT_MBUTTONUP 6 # 中键放开
EVENT_LBUTTONDBLCLK 7 # 左键双击
EVENT_RBUTTONDBLCLK 8 # 右键双击
EVENT_MBUTTONDBLCLK 9 # 中键双击
"""组合键"""
EVENT_FLAG_LBUTTON 1 # 左键拖曳
EVENT_FLAG_RBUTTON 2 # 右键拖曳
EVENT_FLAG_MBUTTON 4 # 中键拖曳
EVENT_FLAG_CTRLKEY 8 # (8~15)按Ctrl不放事件
EVENT_FLAG_SHIFTKEY 16 # (16~31)按Shift不放事件
EVENT_FLAG_ALTKEY 32 # (32~39)按Alt不放事件
示例:
#!/usr/bin/python3
# -*- coding: UTF-8 -*-
__author__ = "A.L.Kun"
__file__ = "demo10.py"
__time__ = "2022/7/29 19:20"
import numpy as np
import cv2.cv2 as cv
# 回调函数函数名可以随便取
def callback_mouse(event, x, y, flags, userdata):
"""
用来监听鼠标事件的函数
:param event: 鼠标事件
:param x: x坐标
:param y: y坐标
:param flags: 用于组合键
:param userdata: 传入的数据
:return: None
"""
print(event, x, y, flags, userdata)
# 创建窗口
cv.namedWindow("mouse", cv.WINDOW_NORMAL)
cv.resizeWindow("mouse", 640, 360)
# 设置鼠标回调函数
cv.setMouseCallback("mouse", callback_mouse, "这个为传入的用户数据") # 给mouse窗口添加回调函数
img = np.zeros((360, 640, 3), np.uint8)
while True:
cv.imshow("mouse", img)
if cv.waitKey(1) == ord("q"):
break
cv.destroyAllWindows()
七、 特征检测
1、 基本概念
特征检测是计算机视觉和图像处理中的一种概念,它指的是使用计算机提取图像信息,决定每个图像的点是否属于一个图像特征。特征检测的结果是把图像上的点分为不同的子集,这些子集往往属于孤立的点,连续的曲线或者连续的区域
特征检测包括边缘检测、角检测、区域检测和脊检测
特征检测应用场景:
- 图像搜索,比如以图搜图
- 拼图游戏
- 图像拼接
平坦部分很难找到它在原图中的位置
边缘相对于平坦要好找一些,但是也不能立马确定
角点可以马上找到其在原图中的位置
图像特征就是值有意义的图像区域,具有独特性,易于识别,比较角点,斑点及高密度区
在图像特征中最重要的就是角点,哪些是角点呢?
- 灰度梯度的最大值对应的像素
- 两条线的交点
- 极值点
2、 Harris角点检测
人眼对角点的识别通常是在一个局部的小区域或小窗口完成的。如果在各个方向上移动这个特征的小窗口,窗口内区域的灰度发生了较大的变化,那么就认为在窗口内遇到了角点。如果这个特定的窗口在图像各个方向上移动时,窗口内图像的灰度没有发生变化,那么窗口内就不存在角点;如果窗口在某一个方向移动时,窗口内图像的灰度发生了较大的变化,而在另一些方向上没有发生变化,那么,窗口内的图像可能就是一条直线的线段。
对于图像I(x,y)I(x,y),当在点(x,y)(x,y)处平移(Δx,Δy)(Δx,Δy)后的自相似性,可以通过自相关函数给出:
W(x,y)W(x,y)是以点(x, y)(x, y)为中心的窗口,即加权函数,例如高斯加权函数
基于泰勒展开式,对图像(x, y)I(x, y)在平移(Δx,Δy)(Δx,Δy)后进行一阶近似
其中,lx, lylx, ly 是图像I(x,y)I(x,y)的偏导数
近似可得:
其中M:
化简可得:
二次项函数本质上就是一个椭圆函数,椭圆方程为:
椭圆函数特征值与图像中的角点、直线(边缘)和平面之间的关系如下图所示。共可分为三种情况:
- 图像中的直线。一个特征值大,另一个特征值小,λ1≫λ2λ1≫λ2或λ2≫λ1λ2≫λ1。自相关函数值在某一方向上大,在其他方向上小。
- 图像中的平面。两个特征值都小,且近似相等;自相关函数数值在各个方向上都小。
- 图像中的角点。两个特征值都大,且近似相等,自相关函数在所有方向都增大。
根据二次项函数特征值的计算公式,我们可以求M(x,y)M(x,y)矩阵的特征值。但是Harris给出的角点差别方法并不需要计算具体的特征值,而是计算一个角点响应值RR来判断角点。RR的计算公式为:
\[R=detM−α(traceM)^2\\
detM=\lambda 1λ2=AC−B^2\\
traceM=λ2+λ2=A+C
\]
语法:
cornerHarris(src, blockSize, ksize, k[, dist[, borderType]])
参数:
-
:检测窗口大小blockSize
-
:sobel的卷积核ksize
-
:权重系数,即上面公式中的\(\alpha\),是一个经验值,一般取0.04~0.06之间,一般默认0.04k
#!/usr/bin/python3
# -*- coding: UTF-8 -*-
__author__ = "A.L.Kun"
__file__ = "demo10.py"
__time__ = "2022/7/29 19:20"
import cv2.cv2 as cv2
# 读取图片
img = cv2.imread("./img/1.jpg")
# 转换为灰度图
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 角点检测
# blockSize 没有要求是必须奇数的,返回角点响应,R值
dst = cv2.cornerHarris(img_gray, 2, 3, 0.04)
# 显示角点
# 设定阈值:dst > 0.01 * dst.max()(经验值)
img[dst > (0.01 * dst.max())] = [0, 0, 255] # 找到这些角点,并且将角点的颜色改为红色
cv2.imshow("img", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
3、 SIFT 关键点检测
SIFT,即尺度不变换特征转换,适用于图像处理领域的一种描述,这种描述具有尺度不变性,可在图像中检测出关键点,是一种局部特征描述子
Harris角点具有旋转不变的特性,但是缩放后,原来的角点有可能不就是角点了
算法原理:原理中公式太多,观摩大佬的文章
使用算法的步骤:
- 创建SIFT对象:
sift = cv2.xfeatures2d.SIFT_create()
- 进行检测:
kp = sift.detect(img, ...)
- 绘制关键点:
cv2.drawKeypoints(gray, kp, img)
#!/usr/bin/python3
# -*- coding: UTF-8 -*-
__author__ = "A.L.Kun"
__file__ = "demo10.py"
__time__ = "2022/7/29 19:20"
import cv2.cv2 as cv2
# 读取图片
img = cv2.imread("./img/1.jpg")
# 转换为灰度图
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 注意:xfeatures2d是OpenCV的扩展包,需要安装opencv-contrib-python才有
# 创建sift对象
sift = cv2.xfeatures2d.SIFT_create() # type: cv2.SIFT
# 进行检测
kp = sift.detect(img_gray) # 是一个列表,里面存放的是封装的KeyPoint对象
# 绘制关键点
cv2.drawKeypoints(img_gray, kp, img) # 创建角点的对象 角点列表 输出图像
cv2.imshow("img", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
关键点和描述子:
- 关键点:位置、大小和方向
- 描述子:记录了关键点周围对其有共享的像素点的一组向量值,其不受仿射变换,光照变换等影响。描述子的作用就是特征匹配,在后面进行特征匹配的时候会用上
#!/usr/bin/python3 # -*- coding: UTF-8 -*- __author__ = "A.L.Kun" __file__ = "demo10.py" __time__ = "2022/7/29 19:20" import cv2.cv2 as cv2 # 读取图片 img = cv2.imread("./img/1.jpg") # 转换为灰度图 img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 注意:xfeatures2d是OpenCV的扩展包,需要安装opencv-contrib-python才有 # 创建sift对象 sift = cv2.xfeatures2d.SIFT_create() # type: cv2.SIFT # 进行检测 # kp = sift.detect(img_gray) # 是一个列表,里面存放的是封装的KeyPoint对象 # 检测关键点,并计算描述子 # kp, des = sift.compute(img, kp) # 或者一步到位,把关键点和描述子一起检测出来 kp, des = sift.detectAndCompute(img_gray, None) # 绘制关键点 cv2.drawKeypoints(img_gray, kp, img) # 创建角点的对象 角点列表 输出图像 cv2.imshow("img", img) cv2.waitKey(0) cv2.destroyAllWindows()
4、 Shi-Tomasi角点检测
- Shi-Tomasi是Harris角点检测的改进
- Harris角点检测计算的稳定性和K有关,而K是一个经验值,不太好设定最佳的K值
- Shi-Tomasi发现,角点的稳定性其实和矩阵M的较小特征值有关,于是直接用较小的那个特征值作为分数,这样就不用调整K值了
- Shi-Tomasi将分数公式改为如下形式:\(R=min(\lambda_1\lambda_2)\)
- 和Harris一样,如果该分数大于设定的阈值,我们就认为它是一个角点
语法:
goodFeaturesToTrack(img, maxComers, qualityLevel, minDistance[, corners[, mask[, blockSize[, userHarrisDetect[, k]]]]])
-
:角点的最大数,值为0表示无限制maxCorner
-
:角点质量,小于1.0的整数,一般在0.01~0.1之间qualityLevel
-
:教之间最小欧氏距离,忽略小于此距离的点minDiatance
-
:掩膜mask
-
:检测窗口的大小blockSize
-
:是否使用Harris算法userHarris
-
:默认是0.04k
#!/usr/bin/python3
# -*- coding: UTF-8 -*-
__author__ = "A.L.Kun"
__file__ = "demo10.py"
__time__ = "2022/7/29 19:20"
import numpy as np
import cv2.cv2 as cv2
# 读取图片
img = cv2.imread("./img/1.jpg")
# 转换为灰度图
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
corners = cv2.goodFeaturesToTrack(img_gray, 100, 0.01, 10) # 最大找出100个角点
corners = np.int0(corners) # 这个为坐标
# 画出角点
for i in corners:
# i 相当于corners中的每一行数据
# ravel() 二维数据变为一维数据
x, y = i.ravel()
cv2.circle(img, (x, y), 3, (0, 255, 0), -1) # 实心圆
cv2.imshow("shi-tomasi", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
5、 Fast算法
5.1 原理
- 在图像中选取一个像素点 p,来判断它是不是关键点。 Ip 等于像素点 p的灰度值。
- 选择适当的阈值 t。
- 如下图所示在像素点 p 的周围选择 16 个像素点进行测试。
- 如果在这 16 个像素点中存在 n 个连续像素点的灰度值都高于 Ip + t,或者低于 Ip − t,那么像素点 p 就被认为是一个角点。如上图中的虚线所示,n 选取的值为 12。
- 为了获得更快的效果,还采用了而外的加速办法。首先对候选点的周围每个 90 度的点: 1, 9, 5, 13 进行测试(先测试 1 和 19, 如果它们符合阈值要求再测试 5 和 13)。如果 p 是角点,那么这四个点中至少有 3 个要符合阈值要求。如果不是的话肯定不是角点,就放弃。对通过这步测试的点再继续进行测试(是否有 12 的点符合阈值要求)。
这个检测器的效率很高,但是它有如下几条缺点:
• 当 n<12 时它不会丢弃很多候选点 (获得的候选点比较多)。
• 像素的选取不是最优的,因为它的效果取决与要解决的问题和角点的分布情况。
• 高速测试的结果被抛弃
• 检测到的很多特征点都是连在一起的。
前 3 个问题可以通过机器学习的方法解决,最后一个问题可以使用非最大值抑制的方法解决。
5.2 机器学习的角点检测器
- 选择一组训练图片(最好是跟最后应用相关的图片)
- 使用 FAST 算法找出每幅图像的特征点
- 对每一个特征点,将其周围的 16 个像素存储构成一个向量。对所有图像都这样做构建一个特征向量 P
- 每一个特征点的 16 像素点都属于下列三类中的一种
- 根据这些像素点的分类,特征向量 P 也被分为 3 个子集: Pd, Ps, Pb
- 定义一个新的布尔变量 Kp,如果 p 是角点就设置为 Ture,如果不是就设置为 False。
- 使用 ID3 算法(决策树分类器)使用ID3算法(决策树分类器)使用变量Kp查询每个子集,了解真实类的知识。 它选择产生关于候选像素是否是由Kp的熵测量的角的最多信息的x
- 上述方法递归地应用于所有子集,直到其熵为零。
- 将构建好的决策树运用于其他图像的快速的检测
5.3 非极大值抑制
使用极大值抑制的方法可以解决检测到的特征点相连的问题:
- 对所有检测到到特征点构建一个打分函数 V。 V 就是像素点 p 与周围 16个像素点差值的绝对值之和。
- 计算临近两个特征点的打分函数 V,把V值较小的候选点去除掉
-
忽略 V 值最低的特征点
总结:
- FAST算法比其他角点检测法都快;
- 在噪声很高时不稳定,这是由阈值决定的。
5.4 实现
import cv2.cv2 as cv2
# 实例化对象
fast = cv2.FastFeatureDetector_create(threshold=10, nonmaxSuppression=True) # 实例化一个对象
"""
:threshold: 阈值,默认为10
:nonmaxSuppression: 是否进行非极大值抑制,默认为True
:return 返回创建的对象
"""
# 进行关键点检测
kp = fast.detect(img1) # 可以用传入彩色图像,返回关键点信息
# fast.setNonmaxSuppression(False) # 取消非极大值抑制
cv2.drawKeypoints(img1, kp, img2) # 进行角点的绘制
cv2.imshow("a", img2) # 展示图片
cv2.waitKey(0) # 绘制图片
cv2.destroyAllWindows()
6、 ORB算法
6.1 原理
ORB算法是FAST算法和BRIEF算法的结合,ORB可以用来对图像中的关键点快速创建特征向量,并用这些特征向量来识别图像中的对象。即,提出了构造金字塔,为Fast特征点添加了方向,从而使得关键点具有了尺度不变性。
具体实现原理较为复杂,请到百度自行搜索
6.2 实现
import cv2.cv2 as cv2
# 创建ORB对象
orb = cv2.ORB_create(nfeatures) # 实例化ORB对象
"""
:nfeatrues: 最大特征数量
"""
# 进行关键点检测
kp, des = orb.detectAndCompute(gray)
"""
:gray: 进行关键点检测的图像,注意是灰度图像
:return:
:kp: 关键点信息
:des: 关键点描述符,每个关键点BRIEF特征向量,二进制字符串
"""
# 将关键点检测结果绘制在图像上
cv2.drawKeypoints(img1, kp, img2)
cv2.imshow("a", img2) # 展示图片
cv2.waitKey(0) # 绘制图片
cv2.destroyAllWindows()
本文来自博客园,作者:A-L-Kun,转载请注明原文链接:https://www.cnblogs.com/liuzhongkun/p/16646481.html