import cv2
import numpy as np
import matplotlib.pyplot as plt
# 什么是特征?
# 当你看到芒果图像时,如何识别它是芒果?
# 通过分析颜色、形状和质地,你可以说它是芒果。
# 用于识别图像的线索称为图像的特征。同样,计算机视觉的功能是检测图像中的各种特征。
# 1:特征的定义:
# 我们将图像中的某个特别的区域作为一个特征。特征是图像中有意义的图像区域,该区域具有独特特性或易于识别性。
# 角点和高密度区域是很好的特征,而大量重复的区域或低密度区域则不是很好的特征。边缘可将图像分为两个区域,因此也可作为好的特征。
# 斑点也是有意义的特征。
# 2:特征的提取:
# 将原始特征转换为一组具有明显物理意义、几何特征(角点,不变量)、纹理(LBP HOG)、统计意义或核的特征;
# 3:特征的选择:
# 从特征几何中挑选一组最具统计意义的特征,达到降维的目的。
# 通过合适的特征选择可以减少数据存储和输入数据带宽,减少冗余,发现更有意义的潜在变量。
# 由于某些算法在识别和提取某种类型特征的时候有较好的效果,所以输入图像是何种类型特征很重要,有利于选择最合适的特征检测算法。
# 展示图像,封装成函数
def cv_show_image(name, img):
cv2.imshow(name, img)
cv2.waitKey(0) # 等待时间,单位是毫秒,0代表任意键终止
cv2.destroyAllWindows()
# 使用opencv的一些内置的算法来实现对图像特征的检测, 从图像中提取的到的特征可以用来进行图像的匹配和检索
# 常用的图像特征检测算法
# Harris: 检测角点
# SIFT: 检测斑点
# SURF: 检测斑点
# FAST: 检测角点
# BRIEF: 检测斑点
#
# 图像特征就是图像中最具有独特性和具有区别性的图像区域.
# 在图像中特征区域主要分布在角点,高密度区域,边缘(边缘可以将图像分成多个区域),斑点(与周围像素差别很大的区域)
# ==========================================================
# 第一部分:cornerHarrir()角点的检测
img1 = cv2.imread('images/build.jpeg')
gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
# 参数说明:
# src:是数据类型为float32的输入图像,表示输入的灰度图,
# blocksize:我们检测过程中需要一个窗口,这个就是窗口的大小,W(x,y)
# kszie:运用Sobel算子求解每个像素的梯度。有Ix和Iy方向的。
# k:是角点响应值运算中的α数值,一般推荐是[0.06, 0.06]
dst = cv2.cornerHarris(src=gray1, blockSize=3, ksize=3, k=0.04)
# 特征点标记为红色
img1[dst > 0.025 * dst.max()] = (0, 0, 255)
cv_show_image('harris', img1)
# ==========================================================
# 第二部分:DOG和SIFT进行特征提取
# 在某些情况下对图像进行缩放后,角点信息可能会丢失,这时候Harri便不能检测到所有的角点,
# SIFT(scale-invariant feature transform)刚好克服了这个问题,对图像特征的检测,
# 尽量不受图像尺寸变化的影响.SIFT并不直接检测关键点,
# 关键点的检测是由DOG(Difference of Gaussians)检测的.SIFT仅通过特征向量来描述特征点周围的像素情况.
# DOG是通过不同的高斯滤波器对同一张图像进行处理,来得到关键点的.
img2 = cv2.imread('images/build.jpeg')
gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
sift = cv2.xfeatures2d.SIFT_create()
keypoints, descriptor = sift.detectAndCompute(gray2, None)
# 打印特征点的信息
for index, kpoint in enumerate(keypoints):
print("DOG和SIFT进行特征提取: pt[0]:{}\tpt[1]:{}\toctave:{}\tresponse:{}\t]size:{}\tangle:{}\t".format(
kpoint.pt[0], kpoint.pt[1], kpoint.octave, kpoint.response, kpoint.size,
kpoint.angle))
# 将关键点标记的图片上
img2 = cv2.drawKeypoints(image=img2, outImage=img2, keypoints=keypoints,
flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS,
color=(255, 0, 0))
cv_show_image('DOG and SIFT', img2)
# ==========================================================
# 第三部分:基于ORB的特征检测
# ORB是基于FAST关键点检测技术和BRIEF描述符结合的特征检测技术.
# FAST(Features from Accelerated Segment Test)算法会在像素周围绘制一个圆,
# 圆内包含16个像素,FAST算法是将圆内的像素分别与加上一个阈值的圆心像素作比较,
# 若圈内出现连续的几个像素比加上一个阈值的像素还亮或是暗,则可认为圆心是角点.
# FAST是一个很有效率的检测算法,但是需要确定阈值参数来检测角点.
# BRIEF(Binary Robust Independent Elementary Features)在OpenCV中主要是通过detectAndCompute()来实现,
# 这个函数包含两个部分,检测和计算,同时也返回两个结果.一个是检测到的关键点,一个是描述符.
# SIFT和SURF也是这样.关键点的描述符包含了图像的关键信息,可看作是图像的另一种表现形式,
# 在比较两个图像的时候可以通过比较两个图像的特征描述来实现.也可以用来做图像特征的匹配.
img3 = cv2.imread('images/build.jpeg')
gray3 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
orb = cv2.ORB_create()
keypoints, descriptor = orb.detectAndCompute(gray3, None)
# 打印特征点的信息
for index, kpoint in enumerate(keypoints):
print("ORB的特征检测: pt[0]:{}\tpt[1]:{}\toctave:{}\tresponse:{}\t]size:{}\tangle:{}\t".format(
kpoint.pt[0], kpoint.pt[1], kpoint.octave, kpoint.response, kpoint.size,
kpoint.angle))
img3 = cv2.drawKeypoints(image=img3, outImage=img3, keypoints=keypoints,
flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS,
color=(255, 0, 0))
cv_show_image('ORB', img3)
# ==========================================================
# 第四部分:Shi-Tomasi 角点检测器
img4 = cv2.imread('images/build.jpeg')
gray4 = cv2.cvtColor(img4, cv2.COLOR_BGR2GRAY)
corners = cv2.goodFeaturesToTrack(gray4, 20, 0.01, 10)
corners = np.int0(corners)
for i in corners:
x, y = i.ravel()
cv2.circle(img4, (x, y), 3, (255, 0, 0), 3)
cv_show_image('Shi-Tomasi', img4)
# ==========================================================
# 第五部分:斑点检测
img5 = cv2.imread('images/build.jpeg')
gray5 = cv2.cvtColor(img5, cv2.COLOR_BGR2GRAY)
detector = cv2.SimpleBlobDetector_create()
keypoints = detector.detect(gray5)
im_with_keypoints = cv2.drawKeypoints(img5, keypoints, np.array([]), (255, 0, 0),
cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
# 打印特征点的信息
for index, kpoint in enumerate(keypoints):
print("ORB的特征检测: pt[0]:{}\tpt[1]:{}\toctave:{}\tresponse:{}\t]size:{}\tangle:{}\t".format(
kpoint.pt[0], kpoint.pt[1], kpoint.octave, kpoint.response, kpoint.size,
kpoint.angle))
cv_show_image('SimpleBlobDetector_create', im_with_keypoints)
# ==========================================================
# 第六部分:二元鲁棒独立基本特征(BRIEF)
img6 = cv2.imread('images/build.jpeg')
gray6 = cv2.cvtColor(img6, cv2.COLOR_BGR2GRAY)
star = cv2.xfeatures2d.StarDetector_create()
brief = cv2.xfeatures2d.BriefDescriptorExtractor_create()
keypoints = star.detect(gray6, None)
keypoints, descriptor = brief.compute(gray6, keypoints)
print(brief.descriptorSize())
print(descriptor.shape)
im_with_keypoints = cv2.drawKeypoints(img6, keypoints, None, color=(255, 0, 0),
flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
cv_show_image('BRIEF', im_with_keypoints)
# # ==========================================================
# # 第七部分:特征匹配
#
# img1 = cv2.imread('images/saoge.jpg')
# img2 = cv2.imread('images/template.jpg')
# gray1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
# gray2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
#
# # 分别进行特征检测
# sift = cv2.xfeatures2d.SIFT_create()
# kp1, des1 = sift.detectAndCompute(gray1, None)
# kp2, des2 = sift.detectAndCompute(gray2, None)
# print(des2.shape)
# # 整一个匹配器
# bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
# matches = bf.match(des1, des2) # 进行匹配
# matches = sorted(matches, key=lambda x: x.distance)
#
# # 在图上画出来
# match_img = cv2.drawMatches(img1, kp1, img2, kp2, matches[:50], None)
#
# cv2.imshow('original image', img1)
# cv2.imshow('test image', img2)
# cv2.imshow('Matches', match_img)
# cv2.waitKey()
# 第四部分:特征点包括的信息
# 特征点的数量和描述符的数量是相等的,他们是一一对应的,他们都存放在一个列表对象当中,每个关键点包含6个属性,分别是:
# pt : 关键点在图像中的坐标信息
# size : 关键点所在区域的直径信息
# angle : 关键点的方向信息
# response : 关键点的强度信息
# octave : 是关于该特征来自图像金字塔的层级信息
# calss_id : 特征id
效果如下:
cornerHarrir()角点的检测
DOG和SIFT进行特征提取
基于ORB的特征检测
Shi-Tomasi 角点检测器
斑点检测
二元鲁棒独立基本特征(BRIEF)