python+opencv实现hog+svm的训练

    python实现hog+svm训练的网上很多,但是资源svm训练这一块都是通过skimage这个库来实现的,本文从hog特征提取到svm的训练,以及后面的测试都是通过调用opencv来实现的,这样对于基于opencv来做开发的话较为方便,python+opencv通常是在建模的时候会用到,这主要是python脚本语言的高效性。话不多少,下面直接上代码:
"""
Created on Tue Apr  3 10:16:07 2018

@author: kuangyongjian

get_data.py
"""
import cv2 as cv
import random
import glob
import os

#加载负样本
def get_neg_samples(foldername,savePath):
    count = 0
    imgs = []
    labels = []
    f = open('neg.txt')
    filenames = glob.iglob(os.path.join(foldername,'*'))
    for filename in filenames:
        print('filename = ',filename)
        src = cv.imread(filename,1)
        
        if((src.cols >= 64) & (src.rows >= 128)):
            x = random.uniform(0,src.cols - 64)
            y = random.uniform(0,src.rows - 128)
            
            imgRoi = src(cv.Rect(x,y,64,128))
            imgs.append(imgRoi)
            saveName = savePath + 'neg' + str(count) + '.jpg'
            cv.imwrite(saveName,imgRoi)
            
            label = 'neg' + str(count) + '.jpg'
            labels.append(label)
            label = label + '\n'
            f.write(label)
            count += 1
    return imgs,labels


#读取负样本
def read_neg_samples(foldername):
    imgs = []
    labels = []
    neg_count = 0;
    filenames = glob.iglob(os.path.join(foldername,'*'))
    for filename in filenames:
       # print('filename = ',filename)
        src = cv.imread(filename,1)
       # cv.imshow("src",src)
       # cv.waitKey(5)
        imgs.append(src)
        labels.append(-1)
        neg_count += 1
   
    #print ('neg_count = ',neg_count)     
    return imgs,labels
        
        

#加载正样本
def get_pos_samples(foldername,savePath):
    count = 0
    imgs = []
    labels = []
    f = open('pos.txt')
    filenames = glob.iglob(os.path.join(foldername,'*'))
    for filename in filenames:
        print('filename = ',filename)
        src = cv.imread(filename)
        imgRoi = src(cv.Rect(16,16,64,128))
        imgs.append(imgRoi)
        saveName = savePath + 'neg' + str(count) + '.jpg'
        cv.imwrite(saveName,imgRoi)
        
        label = 'neg' + str(count) + '.jpg'
        labels.append(label)
        f.write(label)
        count += 1
        
    return imgs,labels


#读取正样本
def read_pos_samples(foldername):
    imgs = []
    labels = []
    pos_count = 0
    filenames = glob.iglob(os.path.join(foldername,'*'))
    
    for filename in filenames:
        src = cv.imread(filename)
        imgs.append(src)
        labels.append(1)
        pos_count += 1
     
    return imgs,labels
# -*- coding: utf-8 -*-
"""
Created on Tue Apr  3 11:47:53 2018

@author: kuangyongjian

svm_train.py
"""
import numpy as np
import cv2 as cv

#svm参数配置
def svm_config():
    svm = cv.ml.SVM_create()
    svm.setCoef0(0)
    svm.setCoef0(0.0)
    svm.setDegree(3)
    criteria = (cv.TERM_CRITERIA_MAX_ITER + cv.TERM_CRITERIA_EPS, 1000, 1e-3)
    svm.setTermCriteria(criteria)
    svm.setGamma(0)
    svm.setKernel(cv.ml.SVM_LINEAR)
    svm.setNu(0.5)
    svm.setP(0.1)
    svm.setC(0.01)
    svm.setType(cv.ml.SVM_EPS_SVR)

    return svm

#svm训练
def svm_train(svm,features,labels):
    svm.train(np.array(features),cv.ml.ROW_SAMPLE,np.array(labels))
    
#svm参数保存
def svm_save(svm,name):
    svm.save(name)
        
#svm加载参数 
def svm_load(name):
    svm = cv.ml.SVM_load(name)
    
    return svm
# -*- coding: utf-8 -*-
"""
Created on Tue Apr  3 14:06:43 2018

@author: kuangyongjian

hog_feature.py
"""
import numpy as np
import cv2 as cv

from get_data import get_pos_samples,get_neg_samples,read_pos_samples,read_neg_samples
from svm_train import svm_config,svm_train,svm_save,svm_load

#计算hog特征
def computeHog(imgs,features,wsize = (128,64)):
    hog = cv.HOGDescriptor()
    count = 0
    
    for i in range(len(imgs)):
        if imgs[i].shape[1] >= wsize[1] and imgs[i].shape[0] >= wsize[0]:
            y = imgs[i].shape[0] - wsize[0]
            x = imgs[i].shape[1] - wsize[1]
            h = imgs[i].shape[0]
            w = imgs[i].shape[1]
            roi = imgs[i][y : y + h, x : x + w]
            features.append(hog.compute(roi))
            count += 1
    
    print ('count = ',count)
    return features

#获取svm参数
def get_svm_detector(svm):
    sv = svm.getSupportVectors()
    rho, _, _ = svm.getDecisionFunction(0)
    sv = np.transpose(sv)
    return np.append(sv,[[-rho]],0)        

#加载hardexample
def get_hard_samples(svm,hog_features,labels):
    hog = cv.HOGDescriptor()
    hard_examples = []
    hog.setSVMDetector(get_svm_detector(svm))
    negs,hardlabel= read_neg_samples('F:/za/Model/pedestrain/INRIAPerson/Train/neg')
    
    for i in range(len(negs)):
        rects,wei = hog.detectMultiScale(negs[i],0,winStride = (8,8),padding = (0,0),scale = 1.05)
        for (x,y,w,h) in rects:
            hardexample = negs[i][y : y + h, x : x + w]
            hard_examples.append(cv.resize(hardexample,(64,128)))
            
    computeHog(hard_examples,hog_features)
    [labels.append(-1) for _ in range(len(hard_examples))]
    svm_train(svm,hog_features,labels)
    hog.setSVMDetector(get_svm_detector(svm))
    hog.save('myHogDector1.bin')
    #svm.train(np.array(hog_features),cv.ml.ROW_SAMPLE,np.array(labels))
 
#获取所有的hog特征
def get_features(features,labels):
    pos_imgs,pos_labels = read_pos_samples('F:/za/Model/pedestrain/INRIAPerson/pos_64x128')
    computeHog(pos_imgs,features)
    
    [labels.append(1) for _ in range(len(pos_imgs))]
    
    neg_imgs,neg_labels = read_neg_samples('F:/za/Model/pedestrain/INRIAPerson/neg_64x128')
    computeHog(neg_imgs,features)
    
    [labels.append(-1) for _ in range(len(neg_imgs))]

    #print('feature_shape = ',np.shape(features))

    return features,labels

#hog训练
def hog_train(svm):
    features = []
    labels = []
    
    hog = cv.HOGDescriptor()
    
    #get hog features
    get_features(features,labels)
    
    #svm training
    print ('svm training...')
    svm_train(svm,features,labels)
    print ('svm training complete...')
    
    hog.setSVMDetector(get_svm_detector(svm))
    hog.save('myHogDector.bin')
    
    print('hard samples training...')
    get_hard_samples(svm,features,labels)
    print('hard samples complete...')
    
    
if __name__ == '__main__':
    #svm config
    svm = svm_config()
    
    #hog training
    hog_train(svm)
    
# -*- coding: utf-8 -*-
"""
Created on Tue Apr  3 19:26:28 2018

@author: kuangyongjian

nms.py
"""
import numpy as np


def py_cpu_nms(dets,scores,thresh):    
    """Pure Python NMS baseline."""    
    x1 = dets[:, 0]    
    y1 = dets[:, 1]    
    x2 = dets[:, 2]    
    y2 = dets[:, 3]    
    #scores = dets[:, 4]  #bbox打分  
    
    areas = (x2 - x1 + 1) * (y2 - y1 + 1)    
#打分从大到小排列,取index    
    order = scores.argsort()[::-1]    
#keep为最后保留的边框    
    keep = []  
    boxs = []
    while order.size > 0:    
#order[0]是当前分数最大的窗口,肯定保留    
        i = order[0]    
        keep.append(i)    
#计算窗口i与其他所有窗口的交叠部分的面积  
        xx1 = np.maximum(x1[i], x1[order[1:]])    
        yy1 = np.maximum(y1[i], y1[order[1:]])    
        xx2 = np.minimum(x2[i], x2[order[1:]])    
        yy2 = np.minimum(y2[i], y2[order[1:]])    
    
        w = np.maximum(0.0, xx2 - xx1 + 1)    
        h = np.maximum(0.0, yy2 - yy1 + 1)    
        inter = w * h    
#交/并得到iou值    
        ovr = inter / (areas[i] + areas[order[1:]] - inter)    
#inds为所有与窗口i的iou值小于threshold值的窗口的index,其他窗口此次都被窗口i吸收    
        inds = np.where(ovr <= thresh)[0]    
#order里面只保留与窗口i交叠面积小于threshold的那些窗口,由于ovr长度比order长度少1(不包含i),所以inds+1对应到保留的窗口  
        order = order[inds + 1]    
    
    [boxs.append(dets[i]) for i in keep]
    
    return boxs
# -*- coding: utf-8 -*-
"""
Created on Tue Apr  3 14:47:20 2018

@author: kuangyongjian

test.py
"""
import numpy as np
import cv2 as cv
from nms import py_cpu_nms 
from imutils.object_detection import non_max_suppression


hog = cv.HOGDescriptor()
hog.load('myHogDector1.bin')


img = cv.imread('person_236.png')

cv.imshow('src',img)
cv.waitKey(10)

rects,scores = hog.detectMultiScale(img,winStride = (8,8),padding = (0,0),scale = 1.05)

sc = [score[0] for score in scores]
sc = np.array(sc)

#转换下输出格式(x,y,w,h) -> (x1,y1,x2,y2)
for i in range(len(rects)):
    r = rects[i]
    rects[i][2] = r[0] + r[2]
    rects[i][3] = r[1] + r[3]


pick = []
#非极大值移植  
print('rects_len',len(rects))
pick = non_max_suppression(rects, probs = sc, overlapThresh = 0.3)
print('pick_len = ',len(pick))

#画出矩形框
for (x,y,xx,yy) in pick:
    cv.rectangle(img, (x, y), (xx, yy), (0, 0, 255), 2)    

cv.imshow('a', img)  
cv.waitKey(10)

python+opencv实现hog+svm的训练_第1张图片

python+opencv实现hog+svm的训练_第2张图片

由于python语言平时用的不多,而且自己python应该也还算是刚刚入门吧,若有不当之处,请指教!

代码下载:点击打开链接

你可能感兴趣的:(python,机器视觉,图像处理基础算法,机器学习)