• 【opencv】传统图像识别:hog+svm行人识别实战



    实战工具:python3.7+pycharm+opencv4.6
    算法知识:HOG特征提取、SVM模型构建
    实战目的:本次实战的目的是熟悉HOG+SVM工作流算法,初步掌握图像分类的传统算法。
    实战记录:本以为在学习原理、算法应用、动手实操后会很顺利的完全自主实现行人检测项目,但实战过程却差强人意,所以结果嘛就马马虎虎了。实战过程中所爆露出的不足有以下几点:

    • 对opencv、numpy、python的基础知识掌握的不够全面、牢固;
    • 对HOG算法的输出数据形式理解不深刻;
    • 对SVM模型的相关参数、函数方法一知半解,特别是数据在svm中的作用、输出。

    实战评价:虽然坎坎坷坷,但还过得去。

    1. 准备工作

    本次实战使用的数据是MIT行人数据库(有现成的资料,懒得收集啦),该数据库为较早公开的行人数据库,共924张行人图片(ppm格式,宽高为64x128),肩到脚的距离约80象素。该数据库只含正面和背面两个视角,无负样本,未区分训练集和测试集。Dalal等采用“HOG+SVM”,在该数据库上的检测准确率接近100%。该数据库的下载链接见这里

    2. 实战代码

    """
    加载并整理数据集-->图像的预处理-->图像的特征提取
    -->设计分类器-->输出分类器准确率-->测试图像
    """
    import cv2
    import random
    import glob
    import numpy as np
    
    
    # 加载本地图像数据集,并将数据集全部添加到列表中,然后打乱数据顺序
    def load_image(filename):
        paths = glob.glob(filename)
        persons, labels = [], []
        for i in paths:
            persons.append(cv2.imread(i))
            labels.append(1)
        random.seed(1)
        random.shuffle(persons)
        persons = np.array(persons)
        return persons, labels
    
    
    # 图像预处理,将输入图像灰度化、高斯模糊
    def image_preprocessing(image):
        cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
        # image = cv2.resize(image, dsize=(32, 64))
        image_preprocess = cv2.GaussianBlur(image, (3, 3), sigmaX=1, sigmaY=1)
        return image_preprocess
    
    
    # 构建HOG检测器
    def get_hog():
        winSize = (64, 128)
        cellSize = (8, 8)
        blockSize = (16, 16)
        blockStride = (16, 16)
        nbins = 9
        signedGradient = True
        derivAperture = 1  # 默认参数
        winSigma = -1.  # 默认参数
        histogramNormType = 0  # 默认参数
        L2HysThreshold = 0.2  # 默认参数
        gammaCorrection = 1  # 默认参数
        nlevels = 64  # 默认参数
        hog = cv2.HOGDescriptor(winSize, blockSize, blockStride, cellSize, nbins, derivAperture, winSigma,
                                histogramNormType, L2HysThreshold, gammaCorrection, nlevels, signedGradient)
        return hog
    
    
    # 创建SVM模型并配置参数
    def SVM_model():
        model = cv2.ml.SVM_create()
        model.setType(cv2.ml.SVM_ONE_CLASS)
        model.setKernel(cv2.ml.SVM_POLY)
        model.setC(1)
        model.setNu(0.01)
        model.setDegree(0.1)
        model.setCoef0(0.5)
        model.setGamma(0.6)
        model.setTermCriteria((cv2.TERM_CRITERIA_MAX_ITER, int(1e2), 1e-5))
        return model
    
    
    # 训练模型
    def SVM_train(model, samples, responses):
        model.train(samples, cv2.ml.ROW_SAMPLE, responses)
        return model
    
    
    # 计算分类器准确率
    def accuracy(model, data_train, labels_train):
        retval, result = model.predict(data_train)
        temp = (np.array(labels_train) == result).mean()
        print(f'该模型的准确率是:{temp * 100}')
    
    
    # 测试分类器
    def image_predict(model, data_test, samples, labels_test):
        retval, result = model.predict(samples)
        counter = 0
        for i in (labels_test == result.ravel()):
            # 测试结果与实际结果不符合仅呈现红色通道
            if not i:
                data_test[counter][..., :2] = 0
                counter += 1
        h1 = data_test[0]
        for i in data_test[1:12, ...]:
            h1 = np.hstack((h1, i))
        h2 = data_test[12]
        for i in data_test[13:, ...]:
            h2 = np.hstack((h2, i))
        return np.vstack((h1, h2))
    
    
    if __name__ == "__main__":
        print('加载图片...')
        datas, labels = load_image('image\\Pedestrian detection\\per*.ppm')
        temp, data_test = np.split(datas, [900])
    
        print('数据预处理...')
        datas = list(map(image_preprocessing, datas))
    
        print('提取训练数据的HOG特征向量...')
        hog = get_hog()
        hog_vector = list(map(hog.compute, datas))
    
        print('将数据集分为两部分,900张用于训练,24张用于测试...')
        data_train, temp = np.split(datas, [900])
        labels_train, labels_test = np.split(np.array(labels), [900])
        hog_vector_train, hog_vector_test = np.split(hog_vector, [900])
    
        print('训练SVM模型...')
        model = SVM_model()
        model_svm = SVM_train(model, hog_vector_train, labels_train)
    
        print('输出分类模型的准确率...')
        accuracy(model_svm, hog_vector_train, labels_train)
    
        print('测试分类模型...')
        result = image_predict(model_svm, data_test, hog_vector_test, labels_test)
    
        cv2.imshow('result, press the q key to exit', result)
        while 1:
            if cv2.waitKey() == ord('q'):
                break
    
        print('测试其他图像...')
        class_name = {0: "不包含行人", 1: "包含行人"}
        img = cv2.imread('image\\persontrain.png')
        img = cv2.resize(img, dsize=(64, 128))
        img2 = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
        img_preprocess = cv2.GaussianBlur(img2, (3, 3), sigmaX=1, sigmaY=1)
        # vector = np.array([hog.compute(img_preprocess)])
        vector = np.expand_dims(hog.compute(img_preprocess), 0)
        ret = model_svm.predict(vector)[1].ravel()
        print(f"图片img{class_name[int(ret)]}")
    
        cv2.imshow('img', img)
        cv2.waitKey()
        cv2.destroyAllWindows()
    
    
    '''
    加载图片...
    数据预处理...
    提取训练数据的HOG特征向量...
    将数据集分为两部分,900张用于训练,24张用于测试...
    训练SVM模型...
    输出分类模型的准确率...
    该模型的准确率是:99.0
    测试分类模型...
    测试其他图像...
    图片img包含行人
    '''
    

    测试图片集的结果:
    result_screenshot_16.07.2023.png
    测试的其他图片:
    woman.png

    3. 项目总结

    • HOG的特征提取的是图像的特征向量,该向量用于作为svm模型train()的"samples"输入变量。当然,在测试图像使用predict()函数时输入的也是图像的特征向量---"samples"。
    • 不同的SVMType有不同的作用,主要分为分类和回归两类。其中分类可分为单分类ONE_CLASS和非单分类SVM_C_SVCNU_SVC。本项目用的是单分类类型。
    • hog.conpute(img)model.train(samples, layout, responses)model.predict(samples)的关系:
      • hog.conpute(img)提取的是单张图像的一维特征向量,如果要提取图像集的特征向量可以使用map()或者for循环。hog.conpute(img)处理后的结果一般被用于训练、测试模型。
      • model.train(samples, layout, responses),该函数的三个参数分别是训练样本集的特征向量矩阵、每个样本特征向量在矩阵的形式、标签矩阵。layout---cv2.ml.ROW_SAMPLE,表示每个训练样本是行向量;cv2.ml.COL_SAMPLE,表示每个训练样本是列向量。layout的值决定了输入的samples中每个样本特征向量在矩阵中的形式。
      • model.predict(samples)中的samples矩阵形式取决于model.train(samples, layout, responses)中layout的值。该函数的返回值有两个retvalresult,测试样本的标签值存储在result.ravel()中。

    __EOF__

  • 本文作者: wpx123
  • 本文链接: https://www.cnblogs.com/wpx123/p/17630934.html
  • 关于博主: 评论和私信会在第一时间回复。或者直接私信我。
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。
  • 相关阅读:
    Nginx配置高可用集群
    图形推理 | 判断推理
    DiFi A Go-as-You-Pay Wi-Fi Access System 精读笔记(三)
    深入URP之Shader篇4: Depth Only Pass
    23种设计模式--简单工厂模式、工厂方法模式、抽象工厂模式
    进销存软件与ERP有哪些差异?
    Qt QPair
    计算机网络(持续更新…)
    如何制作自己的数字人
    【图论】图的遍历 - 构建领接表(无向图)
  • 原文地址:https://www.cnblogs.com/wpx123/p/17630934.html