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)#这个输出的值就是检测过的标签,然后通过判断这个标签是什么,就可以执行下面的操作了。
  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值