HOG+SVM分类器实践

news2024/11/16 23:32:14

文章目录

    • HOG+SVM分类器实践
      • 制作SVM分类器
        • 导入所需的库
        • 提取HOG特征
        • 读取正样本和负样本
        • 训练分类器
        • 定义主函数
        • 小结
      • 测试SVM分类器
      • 相关疑问
        • 1. 提取HOG特征为什么不能彩色图像呢?
        • 2. 出现如下错误
        • 3. 测试代码中,当我传入100*100的图片时候,为什么img_feature.shape是4356呢?
        • 4. 减去的2和//8是什么意思?
        • 5. 当输入图片是16*16时,print(img_feature.shape)是36,这个36是怎么获得的

HOG+SVM分类器实践

目标检测是计算机视觉领域的一个重要任务,目的是从给定的图像中找出感兴趣的目标,并标出它们的位置和类别。传统机器学习方法在目标检测中应用广泛,其中一种常见的方法是基于HOG特征和SVM分类器的方法。在下面的示例中,我们将使用Python编写代码来实现一个SVM分类器。

这个程序是用来训练一个基于HOG特征的SVM分类器,以区分正样本和负样本。具体来说,它从指定目录中读取正负样本图像,提取它们的HOG特征并将其作为训练数据,然后利用线性支持向量机(LinearSVC)算法来训练分类器,最后将分类器保存到文件中。可以调用分类器来检测其他图片。

这个代码是为了训练SVM分类器,以将正样本和负样本进行分类。它使用了一种基于HOG特征的方法来提取图像的特征,从而训练SVM分类器进行分类。它可以用于检测样本是否属于某一类别,但不能直接用于目标检测任务。要进行目标检测,通常需要使用滑动窗口和其他技巧来在图像中搜索可能包含目标的区域,然后对这些区域进行分类。

制作SVM分类器

导入所需的库

首先,我们需要导入所需的库,包括NumPy、OpenCV和Scikit-learn:

import numpy as np
import cv2
from sklearn.svm import LinearSVC
from skimage.feature import hog

提取HOG特征

接下来,我们定义一个函数来提取图像的HOG特征。这个函数使用Scikit-learn库中的hog函数来计算HOG特征。它的输入是一个图像,它的输出是一个向量,表示该图像的HOG特征:

def get_hog_features(img, orient, pix_per_cell, cell_per_block, vis=False, feature_vec=True):
    """
    获取图像的HOG特征向量
    :param img: 输入图像
    :param orient: HOG特征的方向数
    :param pix_per_cell: 细胞的像素数
    :param cell_per_block: 每个块的细胞数
    :param vis: 是否返回可视化HOG图像
    :param feature_vec: 是否返回HOG特征向量
    :return: HOG特征向量或可视化HOG图像
    """
    # 检查vis参数是否为True,如果是,则返回特征向量和可视化HOG图像
    if vis == True:
        features, hog_image = hog(img, orientations=orient,
                                  pixels_per_cell=(pix_per_cell, pix_per_cell),
                                  cells_per_block=(cell_per_block, cell_per_block),
                                  block_norm='L2-Hys', visualize=vis, transform_sqrt=True,
                                  feature_vector=feature_vec)
        return features, hog_image
    # 如果vis参数不是True,只返回特征向量
    else:
        features = hog(img, orientations=orient,
                       pixels_per_cell=(pix_per_cell, pix_per_cell),
                       cells_per_block=(cell_per_block, cell_per_block),
                       block_norm='L2-Hys', visualize=vis, transform_sqrt=True,
                       feature_vector=feature_vec)
        return features

另外,由于在函数注释部分使用了冒号和空格来分隔不同部分,这些注释会被识别为函数的 docstring,可以通过函数名后面的 .__doc__ 来调用该注释。例如,可以通过 print(get_hog_features.__doc__) 来输出函数的注释信息。

读取正样本和负样本

接下来,我们定义一个函数来从给定的目录中读取图像,提取它们的HOG特征,并将它们存储为训练数据。这个函数使用OpenCV库来读取图像,然后使用之前定义的get_hog_features函数来提取图像的HOG特征。它还将标注的对象的类别存储为训练数据的标签:

数据集文件夹如下配置

image-20230425222643158

我就用了两个图片,一个正样本,一个负样本。正样本我采用的是鸣人,负样本我用的是佩恩。

切忌:你的数据集图片大小尺寸要是一致的,否则可能会出问题。

pei

naruto

def get_data():
    """
    从指定目录中读取图像,提取HOG特征,存储为训练数据
    :return: 训练数据和标签
    """
    # 定义正样本图像目录和负样本图像目录
    pos_dir = 'dataset/positives'  # 正样本图像目录
    neg_dir = 'dataset/negatives'  # 负样本图像目录
    
    # 通过列表推导式获取正负样本图像的文件路径
    pos_imgs = [os.path.join(pos_dir, f) for f in os.listdir(pos_dir) if os.path.isfile(os.path.join(pos_dir, f))]
    neg_imgs = [os.path.join(neg_dir, f) for f in os.listdir(neg_dir) if os.path.isfile(os.path.join(neg_dir, f))]
    
    # 提取正样本图像的HOG特征和HOG图像
    pos_features = []  # 存放正样本图像的HOG特征
    pos_hog_img = []  # 存放正样本图像的HOG图像
    for img_path in pos_imgs:
        img = cv2.imread(img_path, 0)  # 以灰度图像读入图像文件
        features, hog_img = get_hog_features(img, orient=9, pix_per_cell=8, cell_per_block=2, vis=True)
        # 调用函数获取HOG特征和HOG图像
        pos_features.append(features)
        pos_hog_img.append(hog_img)  # 存放可视化HOG图像
        #------通过下面这行代码可以查看你训练集的可视化HOG图像,你图像比较少可以用
        #------你图像比较多,建议注释下面两行,因为你需要一张一张的关闭掉图像,挺费劲的
        plt.imshow(pos_hog_img[0], cmap='gray')  # 可视化HOG图像
        plt.show()
    pos_labels = np.ones(len(pos_features))  # 正样本的标签为1(表示含有目标)
    
    # 提取负样本图像的HOG特征和HOG图像
    neg_features = []  # 存放负样本图像的HOG特征
    neg_hog_img = []  # 存放负样本图像的HOG图像
    for img_path in neg_imgs:
        img = cv2.imread(img_path, 0)  # 以灰度图像读入图像文件
        features, neg_hog = get_hog_features(img, orient=9, pix_per_cell=8, cell_per_block=2, vis=True)
        # 调用函数获取HOG特征和HOG图像
        neg_features.append(features)
        neg_hog_img.append(neg_hog)  # 存放可视化HOG图像
        plt.imshow(neg_hog_img[0])  # 可视化HOG图像
        plt.show()
    neg_labels = np.zeros(len(neg_features))  # 负样本的标签为0(表示不含目标)
    
    # 将正样本和负样本的特征和标签组合成训练数据
    features = np.vstack((pos_features, neg_features))  # 将正负样本的HOG特征按行堆叠
    labels = np.hstack((pos_labels, neg_labels))  # 将正负样本的标签按行堆叠
    
    print(labels.shape)  # 输出标签数组的形状
    return features, labels  # 返回训练数据的特征和标签

训练分类器

现在,我们有了训练数据,我们可以使用Scikit-learn库中的LinearSVC来训练SVM分类器。我们定义一个函数来训练分类器,并将其保存到文件中以备后续使用:

def train_classifier(features, labels):
    """
    训练SVM分类器并将其保存到文件中
    :param features: 训练数据
    :param labels: 训练标签
    :return: None
    """
    clf = LinearSVC()
    clf.fit(features, labels)
    #------保存为svm_classifier.pkl分类器,你可以通过调用这个分类器检测其他图片--------------#
    joblib.dump(clf, 'svm_classifier.pkl')

定义主函数

现在,我们可以将这些函数组合起来并使用它们来训练我们的目标检测器。我们定义一个main函数来执行所有这些步骤:

import os
import joblib

def main():
    # 获取训练数据
    features, labels = get_data()

    # 训练分类器
    train_classifier(features, labels)

if __name__ == '__main__':
    main()

小结

在这个示例中,我们展示了如何使用HOG特征和SVM分类器来训练一个简单的目标分类器,可以分辨鸣人和佩恩。它提供了一个基本的框架,可以用来训练一个自己的目标分类器。

---------------------------------------备注------------------------------------------------

精度很低,玩一玩是可以的。

测试SVM分类器

import cv2
import numpy as np
import joblib
from skimage.feature import hog

def predict(img_path, clf_path='svm_classifier.pkl'):
    # 加载分类器
    clf = joblib.load(clf_path)

    # 提取测试图片的HOG特征
    img = cv2.imread(img_path, 0) # 读取灰度图像
    img_feature = hog(img, orientations=9, pixels_per_cell=(8, 8), cells_per_block=(2, 2),
                       block_norm='L2-Hys', transform_sqrt=True, feature_vector=True)

    print(img_feature.shape)
    # 进行预测
    pred = clf.predict(np.array([img_feature]))

    # 展示图片
    cv2.imshow('image', img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

    return pred[0]

def main():
    # img_path = 'dataset/negatives/pei.jpg'
    #-------------------------这里修改图片的路径名称---------------
    img_path = 'test.jpg'
    result = predict(img_path, 'svm_classifier.pkl')

    if result == 0:
        print('This is a negative image.')
    else:
        print('This is a positive image.')

if __name__ == '__main__':
    main()

运行上述测试代码,可以看到输出测试的鸣人图片,并且在终端输出了 This is a positive image 。

image-20230425224227793

用一个火车的图片,可以看到输出是 This is a negative image

image-20230426090110479

但是啊,误检测很严重,因为就用了一个正样本和负样本学习,分类器能力肯定不行的。你即使选择佩恩的图片,或者其他人物图片,他也会认为是真图片的。

这个不能称为目标检测。因为现在大家认为的目标检测,都会在原图片上把目标用矩形框框起来,而这个只能称作简单的分类器,它把待检测的图片预测成1或0,分辨物体是不是真图片或假图片。

相关疑问

训练的时候是灰度图像,因此测试的时候需要用灰度图像测试,如果直接用彩色图像测试会导致通道错误。

1. 提取HOG特征为什么不能彩色图像呢?

对于HOG算法来说,其最初目的是用于在灰度图像上检测边缘和方向,为了保留图像在块和细胞级别上的更丰富的边缘方向特征,输入图像需要是灰度图像。在彩色图像上直接使用HOG算法可能会导致HOG特征提取的结果不理想,因为彩色图像中的RGB或其他色彩通道的变化可能会干扰算法的表现,从而降低分类器的准确性。另外,彩色图像的通道数是3,如果直接使用彩色图像,则提取的特征向量维数将大于灰度图像的特征向量维数,这可能会增加算法的复杂性,导致需要更高的计算成本。因此,在实际中通常将输入图像转换为灰度图像进行HOG特征提取。

2. 出现如下错误

image-20230426091036152

如果出现该错误,表明图像大小不一样。比如你用 256 ∗ 256 256*256 256256的图片训练,那么你测试的图片也需要 256 ∗ 256 256*256 256256

3. 测试代码中,当我传入100*100的图片时候,为什么img_feature.shape是4356呢?

image-20230426093357447

在该代码中,通过使用HOG算法对输入的灰度图像进行特征提取。在这个特定的函数中,通过使用hog()函数,并给定了以下参数来计算HOG特征:

  • orientations=9 # 方向直方图数量
  • pixels_per_cell=(8, 8) # 每个细胞的像素大小
  • cells_per_block=(2, 2) # 每个块包含的细胞数
  • block_norm=‘L2-Hys’ # 块规范化方法
  • transform_sqrt=True # 对数据缩放开方,以获得更好的动态范围
  • feature_vector=True # HOG特征向量

这些参数决定了hog()函数如何对图像进行处理,并获得特征向量。根据这些参数,将图像划分为多个大小为(8,8)的单元格(每个单元格具有64个像素),形成所谓的“cell”。 对每个单元格,计算直方图梯度,每个直方图包含了所涉及单元格中每个像素的幅值,方向,之后将它们放入“block”,这里每个块包含4个细胞。最终,使用块规范化来协调每个块的输出,确保输出的特征向量有更好的动态范围。

根据上述参数,图像的尺寸为100 x 100,划分为8 x 8的单元格时,每个细胞包含8 x 8个像素,每个块包含2 x 2个细胞,其中每个细胞对应一个方向梯度直方图,共9个bins。因此,每个单元格的方向梯度直方图包含9个定向的bin,一个块包含4个单元格,因此一个块的方向梯度直方图特征向量的长度为 9×4=36。 对于该代码给出的图像,形成的特征向量为大小为 (9-2) * ((100 // 8)-2) * 4 * 9 = 4356,减去的2和//8是因为目标图像的尺寸不足以提供块周围的两个单元格的信息。因此,包含4356个元素的一维特征向量被用作SVM分类器的输入。

4. 减去的2和//8是什么意思?

因为该代码中设置的cells_per_block2 x 2,这意味着一个块由2 x 2个单元格组成。然而,在对图像进行“块”提取时,HOG算法需要在图像周围保留至少一个单元格以计算外部梯度。因此,在计算特征向量时,HOG算法需要丢弃图像周围的两个(上下、左右)单元格。 对于这个具体的函数,图像的尺寸为100 x 100,因此在使用8 x 8的单元格大小的情况下,可以形成12 x 12的单元格。然而,对于形状为12 x 12的单元格块,不能在图像的边缘提取其他块,因为图像的尺寸不足以在边缘形成2 x 2的单元格块。因此,需要在图像周围排除两个单元格边缘,即在高度和宽度上的2 x (8 // 8) =2 x 1 = 2个单元格。这就是代码中减去2的原因,并使用整除运算符//用于除以单元格的大小来计算需要从图像边缘删除的单元格数量。

在HOG算法中,图像被划分为多个单元格,每个单元格包含一组像素。而在这个特定的函数中,每个单元格的大小被设置为8 x 8像素。因此,如果输入图像的尺寸为100 x 100,那么图像可以被划分为12 x 12个单元格,其中每个单元格的大小为8 x 8像素。每个单元格的HOG特征向量都是通过计算其方向梯度直方图获得的,然后将这些特征拼接成一个特征向量。因此,在这个特定的函数中,通过这种方式处理图像,呈现的特征向量的长度是定的,即生成了由4356个元素组成的一维特征向量。

5. 当输入图片是16*16时,print(img_feature.shape)是36,这个36是怎么获得的

如果输入图像大小为 16 x 16,则该函数提取HOG特征向量的过程如下:

  1. 定义单元格大小 pixels_per_cell=(8, 8),每个单元格的大小为 8 x 8

2.定义块的大小 cells_per_block=(2, 2),每个块包含 2 x 2 个单元格;

  1. 因为该图像中只有 2 x 2 个单元格,所以只有一个块,因此生成的 HOG 特征向量只有一个块的特征,即一个长度为 36 的一维向量。

对于每个单元格:

4.计算每个单元格内像素的梯度大小和梯度方向,并将其分配到其最接近的方向bin中;

  1. 构建每个单元格的梯度方向直方图,该直方图中包含9个方向bin,分别表示0°至180°之间的均匀间隔;

对于每个块:

cell=(8, 8),每个单元格的大小为 8 x 8`;

2.定义块的大小 cells_per_block=(2, 2),每个块包含 2 x 2 个单元格;

  1. 因为该图像中只有 2 x 2 个单元格,所以只有一个块,因此生成的 HOG 特征向量只有一个块的特征,即一个长度为 36 的一维向量。

对于每个单元格:

4.计算每个单元格内像素的梯度大小和梯度方向,并将其分配到其最接近的方向bin中;

  1. 构建每个单元格的梯度方向直方图,该直方图中包含9个方向bin,分别表示0°至180°之间的均匀间隔;

对于每个块:

  1. 将每个块内包含的4个单元格的HOG特征向量拼接起来,形成一个块的HOG特征向量。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/463847.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux下安装Java8环境

查看主机是否已经安装Java环境 java -version 如下图所示,未找到java命令,则需要安装Java环境 JDK官网下载: https://www.oracle.com/java/technologies/javase/javase8u211-later-archive-downloads.html 根据自己系统的位数下载相应版本…

基于Dokcer安装RabbitMQ

基于Dokcer安装RabbitMQ 一、RabbitMQ介绍 1.1 现存问题 服务调用:两个服务调用时,我们可以通过传统的HTTP方式,让服务A直接去调用服务B的接口,但是这种方式是同步的方式,虽然可以采用SpringBoot提供的Async注解实现…

第6章:集合

集合简介 一种无序且唯一的数据结构。不关心顺序,集合里面的元素都是唯一的。 栈,队列,链表他们里面都有可能出现重复的数据,但是集合里面的元素是唯一的。 栈,队列,链表它们都有自己的顺序,但是…

使用媒体查询实现移动端适配,媒体查询meta标签配置(@media screen and,min-width和max-width)

简述:我们在写网站的时候,难免会遇到需要做移动端适配的需求,今天来记录下使用媒体查询实现移动端的适配。媒体查询是一种CSS技术,可以根据设备屏幕的属性(如宽度、高度、方向和分辨率)选择应用特定样式&am…

火爆全网,JMeter接口自动化测试详细实战(超详细)吐血整理...

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 JMeter接口自动化测…

深度学习 - 44.Gate 与 MMOE 实现多目标学习

目录 一.引言 二.摘要 Abstract 三.介绍 Introduction 四.相关工作 RELATED WORK 1.DNN 中的多任务学习 2.SubNet 集成与 Expert 混合 3.多任务学习应用 五.建模方法 MODELING APPROACHES 1.Shared-bottom Multi-task Model 2.Mixture-of-Experts 3.Multi-gate Mixt…

NOPI用法之自定义单元格背景色(3)

NPOI针对office2003使用HSSFWorkbook,对于offce2007及以上使用XSSFWorkbook;今天我以HSSFWorkbook自定义颜色为例说明,Office2007的未研究呢 在NPOI中默认的颜色类是HSSFColor,它内置的颜色有几十种供我们选择,如果不…

模态分解算法 EMD、EEMD、CEEMD

一、模态分解算法EMD算法介绍 (一)模态分解相关的算法有以下几类 IMF 固有模态函数\EMD经验模态分解\EEMD集合经验模态分解\CEEMD 互补集合经验\(EEMD的标准形式)CEEMDAN自适应噪声完备集合经验模态分解\VMD 变分模态分解 &…

Crypko.ai:动漫角色生成和设计平台

【产品介绍】 Crypko.ai是一个基于GAN(生成对抗网络)的高质量动漫角色生成和设计平台,可以让用户通过简单的操作,创造出各种风格和特征的动漫角色,并且可以对角色的头发、脸部、衣服、风格等进行编辑和调整。 Crypko.a…

【GNN】谱域图卷积

谱域图卷积 1. 谱域卷积的背景知识 1.1 谱域图卷积实现思路 f 1 ( t ) ⋆ f 2 ( t ) F − 1 [ F 1 ( w ) F 2 ( w ) ] f_1(t) \star f_2(t) F^{-1}[F_1(w)F_2(w) ] f1​(t)⋆f2​(t)F−1[F1​(w)F2​(w)] 1.2 如何定义图上的傅里叶变换 经典傅里叶变换: x ( …

人工智能+自助餐:一种有效减少食物浪费的创新方案

一、案例背景: 自助餐是一种受欢迎的餐饮形式,可以满足不同顾客的口味和需求。但是,自助餐也存在着浪费食物的问题,有的顾客拿得多吃得少,有的顾客只吃部分食物,剩下的扔掉。据统计,2022年中国…

【算法竞赛】实现约瑟夫问题的四种方法(附手绘图详解)

💌 博客内容:实现约瑟夫问题的四种方法 😀 作  者:陈大大陈 🚀 个人简介:一个正在努力学技术的准前端,专注基础和实战分享 ,欢迎私信! 💖 欢迎大家&…

视频剪辑配乐技巧 视频剪辑配音推荐

视频是视觉加听觉的艺术,视频的背景音乐不同,所呈现的效果也不同。接下来为大家带来大家视频剪辑配乐技巧,视频剪辑配音推荐的相关内容。 一、视频剪辑配乐技巧 视频剪辑时选好了配乐,视频就成功了一半。那如何找到合适的配乐呢…

yapi一键安装 文档开源系统

访问 GitHub - Ryan-Miao/docker-yapi: Docker build and run yapi as serviceDocker build and run yapi as service. Contribute to Ryan-Miao/docker-yapi development by creating an account on GitHub.https://github.com/Ryan-Miao/docker-yapi git clone https://githu…

Class类

package com.hspedu.reflection.class_;import com.hspedu.Cat;import java.util.ArrayList;/*** author 韩顺平* version 1.0* 对Class类特点的梳理*/ public class Class01 {public static void main(String[] args) throws ClassNotFoundException {//看看Class类图//1. Cla…

python版电报API接入从零到一(有彩蛋)

文章链接 编号分类文章及链接介绍作者来源分类撰写日期收录日期F1框架python版telegram接入开源botpython-telegram-botGithub2023-04-24 申明:本文仅作试验研究用,不对参考本文操作产生的各种结果承担任何责任。 Q&A 使用Telegram的API需要交费吗…

三顾茅庐,七面阿里,成功上岸25k16薪,我行你也行~

写在片头:声明,勿杠 首先简单说一下,这三次面试阿里并不是一次性去面的,实际上第一次面试时候还在大四,找的实习岗,不太清楚是什么部门,别问我为什么还记得面试题,有记录和复盘的习惯…

什么是OADM光分插复用器

文章导读: 什么是OADM光分插复用器 光分插复用器的功能 光分插复用器的类型(FOADM, TOADM) OADM的应用 1、什么是OADM光分插复用器 由不同的光通道进出单模光纤。 它的主要功能是在不影响其他波长信道传输的情况下,选择性地下载或…

Vue(监测数据改变、收集表单数据、过滤器)

一、监测数据改变原理 1. 监测对象数据改变原理 当数据发生改变之后:直接会显示数据改变(一种强硬写法) let data { name: "北京大学", address: "北京" };// 以下通过temp进行监视:还得还原temp值&#xf…

k8s 部署 ldap 服务

1、创建挂载卷,将数据和配置进行持久化存储 1.1、使用nfs作为共享存储 [rootlocalhost openldap_yaml]# cat /etc/exports /dump_file/openldap_db 172.21.53.0/24(rw,sync,no_root_squash,no_all_squash) /dump_file/openldap_conf 172.21.53.0/24(rw,sync,no_roo…