opencv-svm之利用hog提取训练样本特征

首先我们需要正负样本两种数据 svm虽然支持少量数据的分类,但原则上数据更多效果更佳
这里面我们采用正样本232张 负样本555张。推荐负样本是正样本的2-3倍。这里我们做的是对老鼠特征的识别,正样本都是包含老鼠的 ,负样本不能包含老鼠。然后所有训练样本的大小尺寸要缩成一致。把winsize,blocksize,blockstride,cell,winstride越小计算的当然越仔细。只是这样会大量冗余的计算,造成计算时间过长,影响实际效率。
在参数方面的选择 可分为线性可分,线性不可分,非线性可分 其中对应不同的核函数
主要是利用交叉正则和穷举求出参数c和g来达到效果的最优,其中本文用的是线性可分方法。svm参数的设置诸君可以自己尝试修改,毕竟不同的样本有不同的方案。

#include <iostream>
#include <fstream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/ml/ml.hpp>

using namespace std;
using namespace cv;
using namespace cv::ml;
#define plus 232
#define minus  555
void hogsvm(HOGDescriptor &hog)
{
	ifstream pluspath("data\\plus-data\\plus-data.txt");//正样本路径
	ifstream minuspath("data\\minus-data\\minus-data.txt");//负样本路径
	string name;//txt中每一行图片的名字 注意一定要是绝对路径
	int descriptordim;//特征向量的维数
	Mat samplefeaturemat;//所以训练样本的特征向量矩阵 行数为样本数,列数为hog特征向量
	Mat samplelabel;//样本标签 1,-1
	cout << "开始计算" << endl;
	for (int num = 0; num < plus&&getline(pluspath, name); num++)//遍历正样本txt 
	{
		Mat temple = imread(name);//用来代表正样本种的每一个图片
		vector<float> descriptor;//样本的特征向量
		hog.compute(temple, descriptor, Size(1, 1));//计算特征向量
		descriptordim = descriptor.size();//向量的维数
		if (num == 0)
		{
			samplefeaturemat = Mat::zeros(plus+minus, descriptordim, CV_32FC1);//初始化所有正样本特征向量组成的矩阵

			samplelabel = Mat::zeros(plus+minus, 1, CV_32SC1);//初始化所有正样本的标签为1
		}
		for (int i = 0; i < descriptordim; i++)
		{
			samplefeaturemat.at<float>(num, i) = descriptor[i];//每个正特征向量都存进去
		}
		samplelabel.at<int>(num, 0) = 1;//正样本矩阵都为1


	}
	cout << "正样本计算完毕" << endl;
	for (int num = 0; num < minus&&getline(minuspath, name); num++)//遍历负样本txt 
	{
		Mat temple = imread(name);//用来代表负样本种的每一个图片
		vector<float> descriptor;//样本的特征向量
		hog.compute(temple, descriptor, Size(1,1));//计算特征向量
		descriptordim = descriptor.size();//向量的维数
		for (int i = 0; i < descriptordim; i++)
		{
			samplefeaturemat.at<float>(num + plus, i) = descriptor[i];//每个负特征向量相加得到总的负特征向量
		}
		samplelabel.at<int>(num + plus, 0) = -1;//负样本矩阵为-1
	}
	cout << "负样本计算完毕" << endl;
	cout << endl << "开始训练分类" << endl;
	Ptr<SVM> svm = SVM::create();//创建一个svm
	svm->setType(SVM::C_SVC);//svm分类器的类型 有5种选择
	svm->setKernel(SVM::RBF); //svm的核函数选择 有4种选择	
	svm->setGamma(0.5);//gamma是rbf核函数的参数,决定支持向量的个数,越小,支持向量越多,反之越少
	svm->train(samplefeaturemat, ROW_SAMPLE, samplelabel);
	svm->save("mouse.xml");
	cout << "训练成功" << endl;
}
int main()
{
	HOGDescriptor hog(Size(64, 128), Size(16, 16), Size(8, 8), Size(8, 8), 9);
	hogsvm(hog);
	return 0;
}

在这里插入图片描述
在这里插入图片描述
我们可以看到其实就是特征向组成的矩阵

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要使用Python-OpenCV训练SVM,您需要遵循以下步骤: 1. 收集并准备数据集:您需要准备正样本和负样本的图像。将它们分别放在两个文件夹中,并确保它们的命名方式相同。 2. 提取图像特征:使用OpenCVHOG描述符提取每个图像的特征。将这些特征存储在一个numpy数组中。 3. 创建SVM训练器:使用OpenCV的ml库创建一个SVM训练器对象。 4. 训练SVM:调用SVM训练器的train方法,并将特征数组和标签数组作为参数传递。标签数组应该是一个大小相同的numpy数组,其中包含正样本和负样本的标签。 5. 测试SVM:使用一些测试数据来测试SVM的性能,可以使用OpenCV的predict方法。预测结果将是一个数字,其中1表示正类,0表示负类。 以下是一个简单的示例代码,用于训练SVM: ```python import cv2 import numpy as np # Step 1: Collect and prepare dataset pos_images = ["pos1.jpg", "pos2.jpg", ...] neg_images = ["neg1.jpg", "neg2.jpg", ...] # Step 2: Extract image features hog = cv2.HOGDescriptor() features = [] labels = [] for img in pos_images: img = cv2.imread(img) features.append(hog.compute(img)) labels.append(1) for img in neg_images: img = cv2.imread(img) features.append(hog.compute(img)) labels.append(0) features = np.squeeze(features) labels = np.array(labels) # Step 3: Create SVM trainer svm = cv2.ml.SVM_create() # Step 4: Train SVM svm.train(features, cv2.ml.ROW_SAMPLE, labels) # Step 5: Test SVM test_img = cv2.imread("test.jpg") test_features = hog.compute(test_img) result = svm.predict(test_features) print(result) ``` 请注意,此代码仅为示例,您可能需要根据自己的数据集和需求进行修改。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值