【深度之眼opencv-6】:图像特征与目标检测

目录

  • 一、图像特征理解
    • 1、颜色特征
    • 2、纹理特征
    • 3、形状特征
    • 4、空间关系特征
  • 二、形状特征
    • 1、HOG-`方向梯度直方图`(Histogram of Oriented Gradient, HOG)
      • HOG特征提取
      • HOG实现过程-`hog.detectMultiScale(img, 0.1, (1, 1))`
    • 2、Harris
      • 角点概念
      • Harris角点检测
      • Harris实现过程
      • Harris代码-`cv2.cornerHarris()`
    • 3、SIFT-`尺度不变特征变换算法`
      • SIFT算法
      • SIFT特点
      • SIFT算法步骤
      • 函数封装-` sift=cv2.xfeatures2d.SIFT_create()`&`kp=sift.detect(gray, None)`
    • 4、代码汇总
  • 三、LBP纹理特征
    • LBP介绍-`局部二值模式`
    • LBP原理
    • LBP 实现(opencv封装不好,自己实现)
  • 四、模版匹配-`cv2.matchTemplate(target,tpl,method)`
  • 五、人脸检测-`face_cascade.detectMultiScale()`
  • 六、行人检测

一、图像特征理解

图像特征是图像中独特的,易于跟踪和比较的特定模板或特定结构。
特征就是有意义的图像区域,该区域具有独特性易于识别性!

图像特征提取与匹配是计算机视觉中的一个关键问题,在目标检测、 物体识别、三维重建、图像配准、图像理解等具体应用中发挥着重要作用。
图像特征主要有图像的颜色特征纹理特征形状特征空间关系特征

1、颜色特征

  • 颜色特征是一种全局特征,描述了图像或图像区域所对应的景物的表面性质
  • 颜色特征描述方法:
    • 颜色直方图
    • 颜色空间
    • 颜色分布

2、纹理特征

纹理特征也是一种全局特征,它也描述 了图像或图像区域所对应景物的表面性质。但由于纹理只是一种物体表面的特性,并不能完全反映出物体的本质属性, 所以仅仅利用纹理特征是无法获得高层次图像内容的。

3、形状特征

形状特征有两类表示方法, 一类是轮廓特征,另一类是区域特征
图像的轮廓特征主要针对物体的外边界.
图像的区域特征则描述了是图像中的局部形状特征

4、空间关系特征

空间关系特征,是指图像中分割出来的多个目标之间的相互的空间位置或相对方向关系
这些关系也可分为连接/邻接关系交叠/重叠关系包含/独立关系等。

二、形状特征

1、HOG-方向梯度直方图(Histogram of Oriented Gradient, HOG)

HOG特征提取

  • 方向梯度直方图(Histogram of Oriented Gradient, HOG)特征是一种在计算机视觉和图像处理中用来进行物体检测特征描述子
  • 它通过计算和统计图像局部区域梯度方向直方图来构成特征。
  • Hog特征结合SVM分类器已经被广泛应用于图像识别中,尤其在行人检测中获得了极大的成功。
  • 主要思想:在一副图像中,目标的形状能够被梯度或边缘方向密度分布很好地描述。

HOG实现过程-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()
【深度之眼opencv-6】:图像特征与目标检测_第1张图片 【深度之眼opencv-6】:图像特征与目标检测_第2张图片

2、Harris

角点概念

  • 角点:在现实世界中,角点对应于物体的拐角,道路的十字路口、丁字路口等。

  • 从图像分析的角度来定义角点可以有以下两种定义:
    • 角点可以是两个边缘的交点;
    • 角点是邻域内具有两个主方向的特征点;

  • 角点计算方法:
    • 前者通过图像边缘计算,计算量大,图像局部变化会对结果产生较大的影响;
    • 后者基于图像灰度的方法通过计算点的曲率及梯度来检测角点;

Harris角点检测

  • 角点所具有的特征:
    轮廓之间的交点;
    • 对于同一场景,即使视角发生变化,通常具备稳定性质的特征;
    • 该点附近区域的像素点无论在梯度方向上还是其梯度幅值上有着较大变化;

  • 性能较好的角点:
    • 检测出图像中“真实”的角点
    • 准确的定位性能
    • 很高的重复检测率
    • 噪声的鲁棒性
    • 较高的计算效率

Harris实现过程

• 计算图像在X和Y方向的梯度;
• 计算图像两个方向梯度的乘积;
• 使用高斯函数对三者进行高斯加权,生成矩阵M的A,B,C;
• 计算每个像素的Harris响应值R,并对小于某一阈值t的R置为零;
• 在3×3或5×5的邻域内进行非最大值抑制,局部最大值点即为图像中的角点;

【深度之眼opencv-6】:图像特征与目标检测_第3张图片

Harris代码-cv2.cornerHarris()

  • 函数:cv2.cornerHarris() 进行角点检测。
  • 参数如下:
    img :数据类型为float32 的输入图像
    blockSize :角点检测中要考虑的领域大小
    ksize - Sobel :求导中使用的窗口大小
    k - Harris :角点检测方程中的自由参数,取值参数为 [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.040.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()

【深度之眼opencv-6】:图像特征与目标检测_第4张图片

3、SIFT-尺度不变特征变换算法

SIFT算法

SIFT,即尺度不变特征变换算法(Scale-invariant feature transform, SIFT),是用于图像处理领域的一种算法。SIFT具有尺度不变性,可在图像中检测出关键点,是一种局部特征描述子

其应用范围包含物体辨识、机器人地图感知与导航、影像缝合、3D模型建立、 手势辨识、影像追踪和动作比对。

SIFT特点

  • SIFT特性:
    • 独特性,也就是特征点可分辨性高,类似指纹,适合在海量数据中匹配。
    • 多量性,提供的特征多。
    • 高速性,就是速度快。
    • 可扩展,能与其他特征向量联合使用。

  • SIFT特点:
    旋转、缩放、平移不变性
    • 解决图像仿射变换,投影变换的关键的匹配
    光照影响小
    • 目标遮挡影响小
    噪声景物影响小

SIFT算法步骤

• 尺度空间极值检测点检测
关键点定位:去除一些不好的特征点,保存下来的特征点能够满足稳定性等条件
关键点方向参数:获取关键点所在尺度空间的邻域,然后计算该区域的梯度和方向,根据计算得到的结果创建方向直方图,直方图的峰值为主方向的参数
关键点描述符:每个关键点用一组向量(位置、尺度、方向)将这个关键点描述出来,使其不随着光照、视角等等影响而改变
关键点匹配:分别对模板图和实时图建立关键点描述符集合,通过对比关键点描述符来判断两个关键点是否相同

函数封装-sift=cv2.xfeatures2d.SIFT_create()&kp=sift.detect(gray, None)

  • 返回的关键点是一个带有很多不用属性的特殊 结构体,属性当中有坐标,方向、角度等。
  • 使用sift.compute()函数来进行计算关键点描述符
    kp,des = sift.compute(gray,kp)
  • 如果未找到关键点,可使用函数sift.detectAndCompute()直接找到关键点并计算
  • 在第二个函数中,kp为关键点列表,des为numpy的数组,为关键点数目×128

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()
【深度之眼opencv-6】:图像特征与目标检测_第5张图片

4、代码汇总

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.040.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纹理特征

LBP介绍-局部二值模式

LBP(Local Binary Pattern,局部二值模式),是一种用来描述图像局部纹理特征的算子;
它具有旋转不变性灰度不变性等显著的优点;

LBP原理

LBP算子定义在一个3×33×3的窗口内,以窗口中心像素为阈值,与相邻的8个像素的灰度值比较,若周围的像素值大于中心像素值,则该位置被标记为1;,否则标记为0
如此可以得到一个8位二进制数(通常还要转换为10进制,即LBP码,共256种),将这个值作为窗口中心像素点的LBP值,以此来反应这个3×3区域的纹理信息。
【深度之眼opencv-6】:图像特征与目标检测_第6张图片

【深度之眼opencv-6】:图像特征与目标检测_第7张图片
  • 特点
    LBP记录的是中心像素点与领域像素点之间的差值
    当光照变化引起像素灰度值同增同减时,LBP变化并不明显
    LBP对与光照变化不敏感,LBP检测的仅仅是图像的纹理信息;

LBP 实现(opencv封装不好,自己实现)

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()


【深度之眼opencv-6】:图像特征与目标检测_第8张图片

四、模版匹配-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()

【深度之眼opencv-6】:图像特征与目标检测_第9张图片

五、人脸检测-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()

【深度之眼opencv-6】:图像特征与目标检测_第10张图片

方法二:

# -*- 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() 

六、行人检测

你可能感兴趣的:(opencv,opencv)