赞
踩
训练数据的时候,首先需要做下面几步:
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)
-
-
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。