图像特征是图像中独特的,易于跟踪和比较的特定模板或特定结构。
特征就是有意义的图像区域,该区域具有独特性
或易于识别性
!
图像特征提取与匹配是计算机视觉中的一个关键问题,在目标检测、 物体识别、三维重建、图像配准、图像理解等具体应用中发挥着重要作用。
图像特征主要有图像的颜色特征
、纹理特征
、形状特征
和空间关系特征
。
全局特征
,描述了图像或图像区域所对应的景物的表面性质
纹理特征也是一种全局特征
,它也描述 了图像或图像区域所对应景物的表面性质
。但由于纹理只是一种物体表面的特性,并不能完全反映出物体的本质属性, 所以仅仅利用纹理特征是无法获得高层次图像内容
的。
形状特征有两类表示方法, 一类是轮廓特征
,另一类是区域特征
。
图像的轮廓特征主要针对物体的外边界
.
图像的区域特征则描述了是图像中的局部形状特征
。
空间关系特征,是指图像中分割出来的多个目标之间的相互的空间位置
或相对方向关系
这些关系也可分为连接/邻接关系
、交叠/重叠关系
和包含/独立关系
等。
方向梯度直方图
(Histogram of Oriented Gradient, HOG)物体检测
的特征描述子
。局部区域
的梯度方向直方图
来构成特征。SVM分类器
已经被广泛应用于图像识别
中,尤其在行人检测
中获得了极大的成功。主要思想
:在一副图像中,目标的形状能够被梯度或边缘
的方向密度分布
很好地描述。hog.detectMultiScale(img, 0.1, (1, 1))
• 灰度化(将图像看做一个x,y,z(灰度)的三维图像);
• 采用Gamma校正法对输入图像进行颜色空间的标准化(归一化);
• 计算图像每个像素的梯度(包括大小和方向);
• 将图像划分成小cells;
• 统计每个cell的梯度直方图(不同梯度的个数),得到cell的描述子
;
• 将每几个cell组成一个block,得到block的描述子;
• 将图像image内的所有block的HOG特征descriptor串联
起来就可以得到HOG特征,该特征向量就是用来目标检测或分类的特征。
hog = cv2.HOGDescriptor() # 启动检测器对象
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector()) # 指定检测器类型为人体
found, w = hog.detectMultiScale(img, 0.1, (1, 1)) # 加载并检测图像
# -------------------------------HOG特征-------------------------------
flag = 0
# flag = 1
if flag:
def is_inside(o, i):
ox, oy, ow, oh = o
ix, iy, iw, ih = i
return ox > ix and oy > iy and ox + ow < ix + iw and oy + oh < iy + ih
def draw_person(image, person):
x, y, w, h = person
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 255), 2)
img = cv2.imread('people.jpg')
hog = cv2.HOGDescriptor() # 启动检测器对象
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector()) # 指定检测器类型为人体
found, w = hog.detectMultiScale(img, 0.1, (1, 1)) # 加载并检测图像
print(found)
print(w)
# 丢弃某些完全被其它矩形包含在内的矩形NMS
found_filtered = []
for ri, r in enumerate(found):
for qi, q in enumerate(found):
if ri != qi and is_inside(r, q):
break
else:
found_filtered.append(r)
# 对不包含在内的有效矩形进行颜色框定
for person in found_filtered:
draw_person(img, person)
cv2.imshow('people detection', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
角点:在现实世界中,角点对应于物体的拐角,道路的十字路口、丁字路口等。
从图像分析的角度来定义角点可以有以下两种定义:
• 角点可以是两个边缘的交点
;
• 角点是邻域内具有两个主方向的特征点
;
角点计算方法:
• 前者通过图像边缘
计算,计算量大,图像局部变化会对结果产生较大的影响;
• 后者基于图像灰度
的方法通过计算点的曲率及梯度
来检测角点;
角点所具有的特征:
• 轮廓之间的交点
;
• 对于同一场景,即使视角发生变化,通常具备稳定性质的特征
;
• 该点附近区域的像素点无论在梯度方向上还是其梯度幅值上有着较大变化
;
性能较好的角点:
• 检测出图像中“真实”的角点
• 准确的定位性能
• 很高的重复检测率
• 噪声的鲁棒性
• 较高的计算效率
• 计算图像在X和Y方向的梯度;
• 计算图像两个方向梯度的乘积;
• 使用高斯函数对三者进行高斯加权,生成矩阵M的A,B,C;
• 计算每个像素的Harris响应值R,并对小于某一阈值t的R置为零;
• 在3×3或5×5的邻域内进行非最大值抑制,局部最大值点即为图像中的角点;
cv2.cornerHarris()
float32
的输入图像领域大小
窗口大小
自由参数
,取值参数为 [0,04,0.06]# -------------------------------Harris角点检测-------------------------------
flag = 0
flag = 1
if flag:
img = cv2.imread('harris2.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = np.float32(gray)
# 输入图像必须是 float32 ,最后一个参数在 0.04 到 0.06 之间
dst = cv2.cornerHarris(gray, 2, 3, 0.06)
# 结果进行膨胀,可有可无
dst = cv2.dilate(dst, None)
# 设定阈值,不同图像阈值不同
img[dst > 0.01 * dst.max()] = [0, 0, 255]
cv2.imshow('dst_img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
尺度不变特征变换算法
SIFT,即尺度不变特征变换算法
(Scale-invariant feature transform, SIFT),是用于图像处理领域的一种算法。SIFT具有尺度不变性,可在图像中检测出关键点
,是一种局部特征描述子
。
其应用范围包含物体辨识、机器人地图感知与导航、影像缝合、3D模型建立、 手势辨识、影像追踪和动作比对。
SIFT特性:
• 独特性,也就是特征点可分辨性高,类似指纹,适合在海量数据中匹配。
• 多量性,提供的特征多。
• 高速性,就是速度快。
• 可扩展,能与其他特征向量联合使用。
SIFT特点:
• 旋转、缩放、平移不变性
• 解决图像仿射变换,投影变换的关键的匹配
• 光照影响小
• 目标遮挡影响小
• 噪声景物影响小
• 尺度空间极值检测点
检测
• 关键点定位
:去除一些不好的特征点,保存下来的特征点能够满足稳定性等条件
• 关键点方向参数
:获取关键点所在尺度空间的邻域,然后计算该区域的梯度和方向,根据计算得到的结果创建方向直方图,直方图的峰值为主方向的参数
•关键点描述符
:每个关键点用一组向量(位置、尺度、方向)将这个关键点描述出来,使其不随着光照、视角等等影响而改变
• 关键点匹配
:分别对模板图和实时图建立关键点描述符集合,通过对比关键点描述符来判断两个关键点是否相同
sift=cv2.xfeatures2d.SIFT_create()
&kp=sift.detect(gray, None)
关键点描述符
kp,des = sift.compute(gray,kp)
sift.detectAndCompute()
直接找到关键点并计算
。
kp,des=sift.compute(gray,kp)
&sift.detectAndCompute()
封装在高版本opencv中,有专利保护,可以更新版本尝试。
sift = cv2.xfeatures2d.SIFT_create()
kp = sift.detect(gray, None) # 找到关键点
img = cv2.drawKeypoints(gray, kp, img) # 绘制关键点
# -------------------------------SIFT-------------------------------
flag = 0
flag = 1
if flag:
img = cv2.imread('harris2.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
sift = cv2.xfeatures2d.SIFT_create()
kp = sift.detect(gray, None) # 找到关键点
img = cv2.drawKeypoints(gray, kp, img) # 绘制关键点
cv2.imshow('res', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
import cv2
import numpy as np
import matplotlib.pyplot as plt
# -------------------------------HOG特征-------------------------------
flag = 0
# flag = 1
if flag:
def is_inside(o, i):
ox, oy, ow, oh = o
ix, iy, iw, ih = i
return ox > ix and oy > iy and ox + ow < ix + iw and oy + oh < iy + ih
def draw_person(image, person):
x, y, w, h = person
cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 255), 2)
img = cv2.imread('people.jpg')
hog = cv2.HOGDescriptor() # 启动检测器对象
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector()) # 指定检测器类型为人体
found, w = hog.detectMultiScale(img, 0.1, (1, 1)) # 加载并检测图像
print(found)
print(w)
# 丢弃某些完全被其它矩形包含在内的矩形NMS
found_filtered = []
for ri, r in enumerate(found):
for qi, q in enumerate(found):
if ri != qi and is_inside(r, q):
break
else:
found_filtered.append(r)
# 对不包含在内的有效矩形进行颜色框定
for person in found_filtered:
draw_person(img, person)
cv2.imshow('people detection', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
# -------------------------------Harris角点检测-------------------------------
flag = 0
# flag = 1
if flag:
img = cv2.imread('harris2.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = np.float32(gray)
# 输入图像必须是 float32 ,最后一个参数在 0.04 到 0.06 之间
dst = cv2.cornerHarris(gray, 2, 3, 0.06)
# 结果进行膨胀,可有可无
dst = cv2.dilate(dst, None)
# 设定阈值,不同图像阈值不同
img[dst > 0.01 * dst.max()] = [0, 0, 255]
cv2.imshow('dst_img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
# -------------------------------SIFT-------------------------------
flag = 0
flag = 1
if flag:
img = cv2.imread('harris2.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
sift = cv2.xfeatures2d.SIFT_create()
kp = sift.detect(gray, None) # 找到关键点
img = cv2.drawKeypoints(gray, kp, img) # 绘制关键点
cv2.imshow('res', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
局部二值模式
LBP(Local Binary Pattern,局部二值模式),是一种用来描述图像局部纹理特征
的算子;
它具有旋转不变性
和灰度不变性
等显著的优点;
LBP算子定义在一个3×33×3的窗口内,以窗口中心像素为阈值
,与相邻的8个像素的灰度值比较,若周围的像素值大于中心像素值,则该位置被标记为1;,否则标记为0
。
如此可以得到一个8位二进制数
(通常还要转换为10进制,即LBP码,共256种),将这个值作为窗口中心像素点的LBP值
,以此来反应这个3×3区域的纹理信息。
import cv2
import numpy as np
import matplotlib.pyplot as plt
def LBP(src):
'''
:param src:灰度图像
:return:
'''
height = src.shape[0]
width = src.shape[1]
dst = src.copy()
lbp_value = np.zeros((1, 8), dtype=np.uint8)
# print(lbp_value)
neighbours = np.zeros((1, 8), dtype=np.uint8)
# print(neighbours)
for x in range(1, width - 1):
for y in range(1, height - 1):
neighbours[0, 0] = src[y - 1, x - 1]
neighbours[0, 1] = src[y - 1, x]
neighbours[0, 2] = src[y - 1, x + 1]
neighbours[0, 3] = src[y, x - 1]
neighbours[0, 4] = src[y, x + 1]
neighbours[0, 5] = src[y + 1, x - 1]
neighbours[0, 6] = src[y + 1, x]
neighbours[0, 7] = src[y + 1, x + 1]
center = src[y, x]
for i in range(8):
if neighbours[0, i] > center:
lbp_value[0, i] = 1
else:
lbp_value[0, i] = 0
lbp = lbp_value[0, 0] * 1 + lbp_value[0, 1] * 2 + lbp_value[0, 2] * 4 + lbp_value[0, 3] * 8 \
+ lbp_value[0, 4] * 16 + lbp_value[0, 5] * 32 + lbp_value[0, 6] * 64 + lbp_value[0, 7] * 128
# print(lbp)
dst[y, x] = lbp
return dst
img = cv2.imread('people.jpg', 0)
LBP_img = LBP(img)
cv2.imshow('LBP', LBP_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.matchTemplate(target,tpl,method)
result = cv2.matchTemplate(target, tpl, md)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
import cv2
import numpy as np
import matplotlib.pyplot as plt
def template_demo(tpl, target):
method = [cv2.TM_SQDIFF_NORMED, cv2.TM_CCORR_NORMED, cv2.TM_CCOEFF_NORMED]
th, tw = tpl.shape[:2]
for md in method:
result = cv2.matchTemplate(target, tpl, md)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
if md == cv2.TM_SQDIFF_NORMED:
tl = min_loc
else:
tl = max_loc
br = (tl[0] + tw, tl[1] + th) # br是矩形右下角的点的坐标
cv2.rectangle(target, tl, br, (0, 0, 255), 2)
cv2.namedWindow("match-" + np.str(md), cv2.WINDOW_NORMAL)
cv2.imshow("match-" + np.str(md), target)
tpl = cv2.imread('sample2.jpg')
target = cv2.imread('target1.jpg')
template_demo(tpl, target)
cv2.waitKey(0)
cv2.destroyAllWindows()
face_cascade.detectMultiScale()
一般人脸识别系统包含四步骤:人脸检测、人脸对齐、人脸特征提取、人脸识别
人脸检测 Face Detection
输入:Image
输出:人脸坐标框
人脸对齐 Face Alignment:
输入:Image+人脸坐标框
输出:五官关键点的坐标序列(5点、69点、90点等等)
人脸特征提取 Face Feature Extraction
用一串字符表示人脸特征。
人脸识别
输入:人脸特征
输出:找到注册库中相似度最高的特征,将最高相似度值和设定的阈值进行比较。超过阈值则是“1”,否则是“0”。
方法一:cv2.CascadeClassifier(r'haarcascade_frontalface_default.xml')
&face_cascade.detectMultiScale()
import cv2
# 读入图像
img = cv2.imread("3.png")
# 加载人脸特征,该文件在 python安装目录\Lib\site-packages\cv2\data 下
face_cascade = cv2.CascadeClassifier(r'haarcascade_frontalface_default.xml')
# 将读取的图像转为COLOR_BGR2GRAY,减少计算强度
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 检测出的人脸个数
faces = face_cascade.detectMultiScale(gray, scaleFactor = 1.15, minNeighbors = 4, minSize = (5, 5))
print("Face : {0}".format(len(faces)))
print(faces)
# 用矩形圈出人脸的位置
for(x, y, w, h) in faces:
cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.namedWindow("Faces")
cv2.imshow("Faces", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
方法二:
# -*- coding:utf-8 -*-
import cv2
import dlib
import numpy as np
predictor_model = 'shape_predictor_68_face_landmarks/shape_predictor_68_face_landmarks.dat'
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor(predictor_model)
# cv2读取图像
test_film_path = "3.png"
img = cv2.imread(test_film_path)
# 取灰度
img_gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
# 人脸数rects
rects = detector(img_gray, 0)
print(rects[0])
for i in range(len(rects)):
landmarks = np.matrix([[p.x, p.y] for p in predictor(img,rects[i]).parts()])
print(landmarks, type(landmarks))
for idx, point in enumerate(landmarks):
# 68点的坐标
pos = (point[0, 0], point[0, 1])
#print(idx+1, pos)
# 利用cv2.circle给每个特征点画一个圈,共68个
cv2.circle(img, pos, 3, color=(0, 255, 0))
# 利用cv2.putText输出1-68
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img, str(idx+1), pos, font, 0.5, (0, 0, 25 5), 1, cv2.LINE_AA)
#cv2.imwrite("result.png", img)
cv2.imshow("img", img)
cv2.waitKey(0)
cv2.destroyAllWindows()