计算机视觉基础系列(python与opencv的操作与运用/tensorflow的基础介绍)(二十四)---Hog+SVM的识别

训练数据的时候,首先需要做下面几步:

1.准备训练样本;2.对样本进行Hog+Svm的训练;3.运用test图片进行预测

一、准备样本

样本分为正样本和负样本,样本的准备可以运用视频的分帧截取图片存储。这里pos文件夹下包含正样本,包含所检测的目标;neg不包含检测的目标为负样本。样本的准备的时候,图片的尺寸需要注意,这里的尺寸是64x128。

样本的获取的手段:1.来源于网络;2.自己收集。一个好的样本远胜过一个复杂的神经网络,容量大。通常我们是自己收集样本的,会通过视频截取帧来得到的,比如说一秒28帧,有100秒,则可以得到2800张图片。

正样本的特点:尽可能多样性,这里的多样性一般是指的环境的多样性,干扰性因素多,这样检测的效果较好。这里有截取本数据集的部分代码。如下,代码有部分解释,也较为简单,可以看懂:

# 视频分解成图片
# 1 load加载视频 2 读取info 3 解码 单帧视频parse 4 展示 imshow
import cv2
# 获取一个视频打开cap
cap = cv2.VideoCapture('1.mp4')
# 判断是否打开
isOpened = cap.isOpened
print(isOpened)
#帧率
fps = cap.get(cv2.CAP_PROP_FPS)
#宽度
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
#高度
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
print(fps,width,height)

i = 0
while(isOpened):
	if i == 100:
		break
	else:
		i = i+1
	(flag,frame) = cap.read() # 读取每一张 flag读取是否成功 frame内容
	fileName = 'imgs\\'+str(i) + '.jpg'
	print(fileName)
	if flag == True:
		#写入图片
		cv2.imwrite(fileName,frame,[cv2.IMWRITE_JPEG_QUALITY,100])
print('end!')

图片分解完后,我们这里其实准备的数据集的尺寸是64x128,所以这里我们需要裁剪和截取。下面是裁剪和截取的代码,这里的代码前面有所介绍,这里可以看到具体介绍

# 540 * 960 ==>64*128
import cv2

for i in range(0,100):
	fileName = 'imgs\\'+str(i+1)+'.jpg'
	print(fileName)
	img = cv2.imread(fileName)
	imgInfo = img.shape
	height = imgInfo[0]
	width = imgInfo[1]
	mode = imgInfo[2]
	dstHeight = 128
	dstWidth = 64
	dst = cv2.resize(img,(dstWidth,dstHeight))
	cv2.imwrite(fileName,dst)

这里准备的正样本的数量是820个,负样本是1931个,一般来说,正负样本的比例是1:2或者1:3。

二、训练样本

在训练样本的时候,要注意一些问题,在代码注释中会有详细说明,如下,代码很多地方都有,可以看一下说明注释:

可以结合上一篇博客来看,就会较快的理解。

第七步(检测)的重点介绍:
没有直接运用svm.predict来进行预测。

resultArray是3780维的,rho是一个一行一列一维的,而最终的的数组myDetect是3781维度的,所以3780的维是来自resultArray的,最后一个维度是来自rho的。

检测需要创建myhog,需要用myhog进行检测,用detectMultiScale进行检测,没有用predict方法,得到宽高等信息返回,才能把目标绘制出来。代码如下:

# 1.参数的设置   2.hog的创建(实例对象)  3.获取SVM的参数
# 4.计算hog   5.label标签    6.完成train训练    7.完成predicr     8.绘图draw
import cv2
import numpy as np
import matplotlib.pyplot as plt

# 1 参数的设置:设置全局变量 在一个windows窗体中有105个block,每个block下有4个cell,每个cell下有9个bin,总共3780维
PosNum = 820      # 正样本的个数
NegNum = 1931     # 负样本的个数
winSize = (64, 128)       # 窗体大小
blockSize = (16, 16)      # 105个block
blockStride = (8, 8)      # block的步长
cellSize = (8, 8)
nBin = 9

# 2 hog对象的创建,HOGDescriptor创建的方法,参数设置:1.窗体的大小,2.block的大小,3.步长,4.cell的大小,5.Bin的数量
hog = cv2.HOGDescriptor(winSize, blockSize, blockStride, cellSize, nBin)

# 3 SVM分类器的创建,定义一个SVM的对象,来自机器学习的SVM创建的模块
svm = cv2.ml.SVM_create()

# 4 计算当前的hog,需要准备各种参数,并且我们需要把参数计算完后保存在某个地方,所以我们需要新设置一定的数组,或者是当前hog特征的维度
featureNum = int(((128-16)/8+1)*((64-16)/8+1)*4*9)
# 3780,特征的维度,是一个int类型;((128-16)/8+1)是block的数量,((64-16)/8+1)为windows的宽度,4就是指的一个block里面有4个cell,9是一个cell里面有9个Bin,这样计算可以的恶道3780维
# 还需要创建一个feature数组和一个label数组用于装载当前的特征,为接下来的第五步和第六步作准备,将标签和特征准备好
featureArray = np.zeros(((PosNum+NegNum), featureNum), np.float32)
# featureArray是一个二维的数组,第一个(PosNum+NegNum)是正负样本的个数,featureNum特征的维度
labelArray = np.zeros(((PosNum+NegNum), 1), np.int32)       # 定义一个标签,也是一个二维的,参数和上面的一样
# SVM 是监督学习,所以需要样本和标签 SVM进行学习,而学习的是图片中的的hog特征,所以我们可以说hog特征可以说做是SVM真正的样本,标签是我们在进行SVM训练的时候,进行监督学习使用的
# 遍历所有的图片:正负样本都需要遍历
for i in range(0, PosNum):
	fileName = 'pos\\'+str(i+1)+'.jpg'
	img = cv2.imread(fileName)             # 图片的读取
	hist = hog.compute(img, (8, 8))        # 当前hog的计算 3780维的数据,用hist装载特征,计算HOG描述子,检测窗口移动步长(8,8)
	# 当前的问题是:我们需要将hog特征装载到featureArray中,而featureArray是一个二维的,而计算出来的只是一个hist,那么这一步怎么完成呢?
	# 其实我们这里的hist是一个3780维的,而featureArray是一个二维的,且第一个参数是正负样本的个数,第二个参数是featureNum,我们可以这么操作:
	for j in range(0,featureNum):
		# featureArray装载的是hog的特征,比如说i=1的时候,第一个hog表示为hog1,i=2的时候为hog2,第二个特征,每一个特征是3780维的,所以hist[j]要放到i行,第j列中
		featureArray[i,j] = hist[j]        # hog特征的装载
	labelArray[i,0] = 1          # 正样本标签为1,labelArray也是一个二维的,n行1列的,所以纵坐标放置的是0,正样本处理完毕,接下来的负样本的设置是一样的

for i in range(0, NegNum):
	fileName = 'neg\\'+str(i+1)+'.jpg'
	img = cv2.imread(fileName)
	hist = hog.compute(img,(8,8))
	for j in range(0,featureNum):
		featureArray[i+PosNum,j] = hist[j]         # 同样要把特征放在featureArray中,所以i+PosNum是要记录负样本的时候必须装载在正样本的后面
	labelArray[i+PosNum,0] = -1 # 负样本标签为-1

# 设置SVM的属性,setType设置属性,添加当前类型,再来设置setKernel为SVM的线性内核,再来设置setC
svm.setType(cv2.ml.SVM_C_SVC)
svm.setKernel(cv2.ml.SVM_LINEAR)
svm.setC(0.01)

# 6 train,调用train进行训练,参数:1.特征数组;2.机器学习ROW_SAMPLE;3.标签数组。返回值为ret
ret = svm.train(featureArray, cv2.ml.ROW_SAMPLE, labelArray)

# 预测可以运用svm.predict来进行预测,这里我们不用,使用其他方法来进行检测
# 7 预测(创建myHog--->myDect参数得到-->来源于resultArray(公式得到) rho(训练得到))
# rho是svm得到的一个hog的描述信息,这个在最后的阈值判决的时候起作用,在累加的时候起作用
# 深入到hog以及svm最后的判决中看
alpha = np.zeros((1), np.float32)
# getDecisionFunction方法最核心的还是svm的计算,svm来源于训练方法,样本准备好后训练可以得到svm,然后得到rho
rho = svm.getDecisionFunction(0, alpha)
print(rho)
print(alpha)

# resultArray,定义alphaArray,我们需要用alphaArray和支持向量机数组进行相乘
alphaArray = np.zeros((1, 1), np.float32)
# 设置支持向量机数组
supportVArray = np.zeros((1, featureNum), np.float32)
resultArray = np.zeros((1, featureNum), np.float32)
alphaArray[0, 0] = alpha     # 一行一列的,所以第一个元素是[0, 0]
resultArray = -1*alphaArray*supportVArray       # 计算公式;resultArray 计算,支持向量的个数,只需要当成参数就行

# mydect参数,构建detect
myDetect = np.zeros(3781, np.float32)
for i in range(0, 3780):
	# 是一个一维的,myDetect
	myDetect[i] = resultArray[0,i]
myDetect[3780] = rho[0]
# myHog的创建很重要
# 构建好Hog,用HOGDescriptor方法构建
myHog = cv2.HOGDescriptor()
# 返回的myHog,用setSVMDetector设置属性
myHog.setSVMDetector(myDetect)

# 待检测图片的加载
imageSrc = cv2.imread('test2.jpg', 1)
# 检测小狮子 (8,8)winds的滑动步长 1.05 缩放系数 (32,32)窗口大小
# 完成检测,返回的目标包含哪些信息,myHog有个方法detectMultiScale,和人脸识别比较类似,缩放。
# 它可以检测出图片中所有的目标,并将目标用vector保存各个目标的坐标、大小(用矩形表示),函数由分类器对象调用;1.05是缩放,(8, 8)windows的滑动步长,(32, 32)窗体大小
# myHog的创建很重要
objs = myHog.detectMultiScale(imageSrc, 0, (8, 8), (32, 32), 1.05, 2)
# 起始位置、宽和高 objs三维信息,获取目标的坐标,是三维的,所以我们需要定义一个三维的坐标,这些信息放在三维中的最后一维
x = int(objs[0][0][0])       # 坐标,w和h是宽高
y = int(objs[0][0][1])
w = int(objs[0][0][2])
h = int(objs[0][0][3])

# 目标的绘制 图片 起始位置 终止位置 颜色,绘制矩形框
cv2.rectangle(imageSrc, (x, y), (x+w, y+h), (255, 0, 0))
# 目标的展示
cv2.imshow('dst', imageSrc)
cv2.waitKey(0)


实验相关数据集点击此处下载

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Python OpenCV HOG SVM 行人检测是使用Python编程语言和OpenCV库来实现行人检测的一种方法。该方法主要利用了HOG(Histogram of Oriented Gradients)特征和SVM(Support Vector Machine)分类器来检测行人。 以下是 Python OpenCV HOG SVM 行人检测的步骤: 1. 收集行人图像数据集并标注。 2. 提取图像中的HOG特征。 3. 利用提取的特征训练SVM分类器。 4. 在测试图像中使用训练好的SVM分类器来检测行人。 具体实现细节如下: 1. 数据集收集和标注 要进行行人检测,首先需要收集行人图像数据集并进行标注。可以使用现有的数据集,例如INRIA行人数据集,或者自己创建数据集。 对于数据集的标注,可以使用图像标注工具来手动标注,例如LabelImg或VGG Image Annotator(VIA)。对于每个行人图像,需要标注行人的位置和大小。 2. 提取HOG特征 OpenCV提供了HOGDescriptor函数来提取图像中的HOG特征。HOG特征是由图像中不同方向的梯度组成的向量,可以有效地表示图像的纹理和形状特征。 代码示例: ``` import cv2 # 创建HOG描述符对象 hog = cv2.HOGDescriptor() # 提取HOG特征 features = hog.compute(image) ``` 其中,image是输入图像,features是提取的HOG特征向量。 3. 训练SVM分类器 在提取HOG特征后,需要使用训练数据集训练SVM分类器。可以使用OpenCV提供的SVM函数来实现训练。 代码示例: ``` import cv2 # 加载训练数据集和标签 train_data = cv2.imread('train_data.png') train_labels = cv2.imread('train_labels.png') # 创建SVM分类器对象 svm = cv2.ml.SVM_create() # 设置SVM参数 svm.setType(cv2.ml.SVM_C_SVC) svm.setKernel(cv2.ml.SVM_LINEAR) svm.setTermCriteria((cv2.TERM_CRITERIA_MAX_ITER, 100, 1e-6)) # 训练SVM分类器 svm.train(train_data, cv2.ml.ROW_SAMPLE, train_labels) ``` 其中,train_data是训练数据集,train_labels是对应的标签。SVM参数可以根据实际情况进行调整。 4. 行人检测 在训练SVM分类器后,可以在测试图像中使用它来检测行人。可以使用OpenCV提供的detectMultiScale函数来实现检测。 代码示例: ``` import cv2 # 加载测试图像 test_image = cv2.imread('test_image.png') # 创建HOG描述符对象 hog = cv2.HOGDescriptor() # 设置SVM分类器 hog.setSVMDetector(svm.getSupportVectors()) # 行人检测 rects, weights = hog.detectMultiScale(test_image, winStride=(8, 8)) # 绘制检测结果 for (x, y, w, h) in rects: cv2.rectangle(test_image, (x, y), (x + w, y + h), (0, 255, 0), 2) # 显示检测结果 cv2.imshow('result', test_image) cv2.waitKey(0) ``` 其中,test_image是要检测的测试图像。通过设置SVM分类器,可以使用HOG描述符对象的detectMultiScale函数来检测行人。检测结果是一组矩形框,可以使用OpenCV提供的rectangle函数来绘制。最后使用imshow函数显示检测结果。 总结: Python OpenCV HOG SVM 行人检测是一种简单有效的行人检测方法。通过收集数据集,提取HOG特征,训练SVM分类器,可以实现高效的行人检测。可以应用于视频监控、自动驾驶等领域。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值