Python-OpenCV —— Machine Learning

前几天有同学问我关于物体识别的问题,问我是否能写一篇相关的教程,其实最近有在做这方面的事情,我做的是一个检测指定物体,画出框框出制定物体,并进行测距,具体的应用场景是检测红绿灯,自动通过路口,其中就用到了物体识别,当然还涉及到单目测距之类的知识,这些暂且不表,下次再说。

之前就知道OpenCV有一个专门的Machine Learning库,一直没有机会学习,想着通过这次机会,正好学习一下,没成想,进了一个巨大的坑,因为大家都知道,Python是胶水语言,所以Python-OpenCV的底层也都是C语言写的,而我C语言又比较差,网上的教程有比较少,所以看官方文档的时候真的是一番煎熬,下次有时间还是试一试主流的一下机器学习框架吧,正好做一个对比,看哪一个比较好。

CV.ml介绍

集成了许多优秀的机器学习算法,主要有:

  • cv2.ml.svm---------------------支持向量机
  • cv2.ml.knn---------------------K.近邻
  • cv2.ml.bayesian----------------正态贝叶斯分类器
  • cv2.ml.em----------------------期望最大化
  • cv2.ml.boost.tree--------------boost分类器
  • cv2.ml.tree--------------------决策树分类器
  • cv2.ml.ann.mlp-----------------感知器神经网络分类器
  • cv2.ml.cnn---------------------卷积神经网络
  • cv2.ml.random.trees-----------------随机树分类器
  • cv2.ml.extremely.randomized.trees---随机森林分类器
  • cv2.ml.gradient.boosting.trees------梯度boost分类器
    具体的功能我就不一一介绍了,大家有兴趣的可以参看上面的官方文档,具体说说我用到的cv2.ml.ANN_MLP

cv2.ml.ANN_MLP

最好的学习一个新功能的方式就是去使用它,话不多说,直接上程序

1. 创建训练模型

这个模型是训练通过摄像头获取到的照片,来判断应该前进的方向,算是智能驾驶的一部分。

import cv2
model = cv2.ml.ANN_MLP_create()#建立模型
model.setActivationFunction(cv2.ml.ANN_MLP_SIGMOID_SYM)#设置激活函数为SIGMOID,其实就这一个可以选
model.setLayerSizes(np.int32([38400,32,4]))#设置层数,输入38400层(像素320*240),输出层4(上下左右四个方向),以及中间层32
model.setTermCriteria(( cv2.TERM_CRITERIA_COUNT | cv2.TERM_CRITERIA_EPS, 500, 0.0001 ))#设置终止条件
model.setTrainMethod(cv2.ml.ANN_MLP_BACKPROP)#设置训练方式为反向传播
model.setBackpropWeightScale(0.001)  #设置反向传播中的一些参数
model.setBackpropMomentumScale(0.0) #设置反向传播中的一些参数

2.开始训练模型

载入数据

训练要有数据,数据是我之前拍好的,拍的时候获取两个参数,一是拍到的照片,二是拍照片的时候的前进方向,以此来进行训练,将拍好的照片以npz格式保存,然后进行读取。

import numpy as np
import glob
# load training data
image_array = np.zeros((1, 38400))
label_array = np.zeros((1, 4), 'float')
training_data = glob.glob('training_data/*.npz')
#开始一个个读取
for single_npz in training_data:
    with np.load(single_npz) as data:
        train_temp = data['train']#拍到的照片
        train_labels_temp = data['train_labels']#照片对应的标签
    image_array = np.vstack((image_array, train_temp))
    label_array = np.vstack((label_array, train_labels_temp))
X = image_array[1:, :]
Y = label_array[1:, :]

数据分类

将数据按照一定的比例分为测试集和训练集,比例大概为2:8

from sklearn.model_selection import train_test_split
train, test, train_labels, test_labels = train_test_split(X, y, test_size=0.2)

开始训练

records = []
#建立一个列表,进行照片和标签的一一对应
for x in range(0, len(train)):
    records.append(record(train[x], train_labels[x]))
#训练两个epoch
EPOCHS = 2
for e in range(0, EPOCHS):
  print("Epoch %d:" % e)
  for t, c in records:
    #开始训练,cv2.ml.ROW_SAMPLE代表每一行是一个样本
    num_iter = model.train(t, cv2.ml.ROW_SAMPLE, c)

3. 保存训练结果

# train data
ret_0, resp_0 = model.predict(train)
prediction_0 = resp_0.argmax(-1)
true_labels_0 = train_labels.argmax(-1)

train_rate = np.mean(prediction_0 == true_labels_0)
print('Train accuracy: ', "{0:.2f}%".format(train_rate * 100))

# test data
ret_1, resp_1 = model.predict(test)
prediction_1 = resp_1.argmax(-1)
true_labels_1 = test_labels.argmax(-1)

test_rate = np.mean(prediction_1 == true_labels_1)
print('Test accuracy: ', "{0:.2f}%".format(test_rate * 100))

# save model
model.save('mlp_xml/mlp.xml')

4. 模型的识别应用

#构建模型网络,一会进行调用
class NeuralNetwork(object):
    def __init__(self, file_path):
        self.model = cv2.ml.ANN_MLP_load(file_path)#载入训练好的模型
    #预测拍的照片给出标签值
    def predict(self, samples):
        ret, resp = self.model.predict(samples)
        return resp.argmax(-1)

下面进行调用,因为调用需要照片,因此我把它放在了另一个接收照片的类里面,照片的传递也可以写一篇教程,这次先不说

class VideoStream(object):
    def __init__(self):
        self.ct_socket = socket.socket()
        self.ct_socket.bind(('0.0.0.0',collect_id))  
        self.ct_socket.listen(5)
        self.connection = self.ct_socket.accept()[0].makefile('rb')
        # 模型实例化,载入训练好的文件
        self.model = NeuralNetwork('mlp_xml/mlp.xml')
    def handle(self):
        global prediction
        stream_bytes = b' '
        try:
            while True:
                stream_bytes += self.connection.read(1024)
                first = stream_bytes.find(b'\xff\xd8')
                last = stream_bytes.find(b'\xff\xd9')
                if first != -1 and last != -1:
                    jpg = stream_bytes[first:last+2]
                    stream_bytes = stream_bytes[last+2:]
                    image = cv2.imdecode(np.fromstring(jpg, dtype=np.uint8), cv2.IMREAD_UNCHANGED)
                    print('接受照片中')
                    prediction = self.model.predict(image)
                    print(prediction)#这个输出的值就是检测过的标签,然后通过判断这个标签是什么,就可以执行下面的操作了。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342