一、概述

本篇文章介绍通过YOLO模型进行目标识别的应用,原始代码来源于:https://github.com/dotnet/machinelearning-samples

实现的功能是输入一张图片,对图片中的目标进行识别,输出结果在图片中通过红色框线标记出来。如下:

YOLO简介

YOLO(You Only Look Once)是一种最先进的实时目标检测系统。官方网站:https://pjreddie.com/darknet/yolo/

本文采用的是TinyYolo2模型,可以识别的目标类型包括:"aeroplane", "bicycle", "bird", "boat", "bottle","bus", "car", "cat", "chair", "cow","diningtable", "dog", "horse", "motorbike", "person","pottedplant", "sheep", "sofa", "train", "tvmonitor" 。

ONNX简介

ONNX 即Open Neural Network Exchange(开放神经网络交换格式),是一个用于表示深度学习模型的通用标准,可使模型在不同框架之间进行互相访问,其规范及代码主要由微软,亚马逊 ,Facebook 和 IBM 等公司共同制定与开发。有了ONNX标准,我们就可以在ML.NET代码中使用通过其他机器学习框架训练并保存的模型。

二、代码分析

 1、Main方法

        static void Main(string[] args)
{
TrainAndSave();
LoadAndPredict(); Console.WriteLine("Press any key to exit!");
Console.ReadKey();
}

第一次运行时需要运行TrainAndSave方法,生成本地模型后,可以直接运行生产代码。

2、训练并保存模型

     static readonly string tagsTsv = Path.Combine(trainImagesFolder,  "tags.tsv");       
     private static void TrainAndSave()
{
var mlContext = new MLContext();
var trainData = mlContext.Data.LoadFromTextFile<ImageNetData>(tagsTsv); var pipeline = mlContext.Transforms.LoadImages(outputColumnName: "image", imageFolder: trainImagesFolder, inputColumnName: nameof(ImageNetData.ImagePath))
.Append(mlContext.Transforms.ResizeImages(outputColumnName: "image", imageWidth: ImageNetSettings.imageWidth, imageHeight: ImageNetSettings.imageHeight, inputColumnName: "image"))
.Append(mlContext.Transforms.ExtractPixels(outputColumnName: "image"))
.Append(mlContext.Transforms.ApplyOnnxModel(modelFile: YOLO_ModelFilePath, outputColumnNames: new[] { TinyYoloModelSettings.ModelOutput }, inputColumnNames: new[] { TinyYoloModelSettings.ModelInput })); var model = pipeline.Fit(trainData); using (var file = File.OpenWrite(ObjectDetectionModelFilePath))
mlContext.Model.Save(model, trainData.Schema, file); Console.WriteLine("Save Model success!");
}

ImageNetData类定义如下:

    public class ImageNetData
{
[LoadColumn()]
public string ImagePath; [LoadColumn()]
public string Label;
}

tags.tsv文件中仅包含一条样本数据,因为模型已经训练好,不存在再次训练的意义。这里只要放一张图片样本即可,通过Fit方法建立数据处理通道模型。

ApplyOnnxModel方法加载第三方ONNX模型,

    public struct TinyYoloModelSettings
{
// input tensor name
public const string ModelInput = "image"; // output tensor name
public const string ModelOutput = "grid";
}

其中,输入、输出的列名称是指定的。可以通过安装Netron这样的工具来查询ONNX文件的详细信息,可以看到输入输出的数据列名称。

3、应用
        private static void LoadAndPredict()
{
var mlContext = new MLContext(); ITransformer trainedModel;
using (var stream = File.OpenRead(ObjectDetectionModelFilePath))
{
trainedModel = mlContext.Model.Load(stream, out var modelInputSchema);
}
var predictionEngine = mlContext.Model.CreatePredictionEngine<ImageNetData, ImageNetPrediction>(trainedModel); DirectoryInfo testdir = new DirectoryInfo(testimagesFolder);
foreach (var jpgfile in testdir.GetFiles("*.jpg"))
{
ImageNetData image = new ImageNetData
{
ImagePath = jpgfile.FullName
};
var Predicted = predictionEngine.Predict(image);
PredictImage(image.ImagePath, Predicted);
}
}
代码遍历一个文件夹下面的JPG文件。对每一个文件进行转换,获得预测结果。
ImageNetPrediction类定义如下:
    public class ImageNetPrediction
{
[ColumnName(TinyYoloModelSettings.ModelOutput)]
public float[] PredictedLabels;
}

输出的“grid”列数据是一个float数组,不能直接理解其含义,所以需要通过代码将其数据转换为便于理解的格式。

     YoloWinMlParser _parser = new YoloWinMlParser();
IList<YoloBoundingBox> boundingBoxes = _parser.ParseOutputs(Predicted.PredictedLabels, 0.4f);

YoloWinMlParser.ParseOutputs方法将float数组转为YoloBoundingBox对象的列表,第二个参数是可信度阙值,只输出大于该可信度的数据。

YoloBoundingBox类定义如下:

    class YoloBoundingBox
{
public string Label { get; set; }
public float Confidence { get; set; } public float X { get; set; }
public float Y { get; set; }
public float Height { get; set; }
public float Width { get; set; }
public RectangleF Rect
{
get { return new RectangleF(X, Y, Width, Height); }
}
}

其中:Label为目标类型,Confidence为可行程度。

由于YOLO的特点导致对同一个目标会输出多个同样的检测结果,所以还需要对检测结果进行过滤,去掉那些高度重合的结果。

     YoloWinMlParser _parser = new YoloWinMlParser();
IList<YoloBoundingBox> boundingBoxes = _parser.ParseOutputs(Predicted.PredictedLabels, 0.4f);
var filteredBoxes = _parser.NonMaxSuppress(boundingBoxes, , 0.6F);

YoloWinMlParser.NonMaxSuppress第二个参数表示最多保留多少个结果,第三个参数表示重合率阙值,将去掉重合率大于该值的记录。

四、资源获取 

源码下载地址:https://github.com/seabluescn/Study_ML.NET

工程名称:YOLO_ObjectDetection

资源获取:https://gitee.com/seabluescn/ML_Assets (ObjectDetection)

点击查看机器学习框架ML.NET学习笔记系列文章目录

机器学习框架ML.NET学习笔记【8】目标检测(采用YOLO2模型)的更多相关文章

  1. 机器学习框架ML.NET学习笔记【4】多元分类之手写数字识别

    一.问题与解决方案 通过多元分类算法进行手写数字识别,手写数字的图片分辨率为8*8的灰度图片.已经预先进行过处理,读取了各像素点的灰度值,并进行了标记. 其中第0列是序号(不参与运算).1-64列是像 ...

  2. 机器学习框架ML.NET学习笔记【2】入门之二元分类

    一.准备样本 接上一篇文章提到的问题:根据一个人的身高.体重来判断一个人的身材是否很好.但我手上没有样本数据,只能伪造一批数据了,伪造的数据比较标准,用来学习还是蛮合适的. 下面是我用来伪造数据的代码 ...

  3. 机器学习框架ML.NET学习笔记【1】基本概念与系列文章目录

    一.序言 微软的机器学习框架于2018年5月出了0.1版本,2019年5月发布1.0版本.期间各版本之间差异(包括命名空间.方法等)还是比较大的,随着1.0版发布,应该是趋于稳定了.之前在园子里也看到 ...

  4. 机器学习框架ML.NET学习笔记【3】文本特征分析

    一.要解决的问题 问题:常常一些单位或组织召开会议时需要录入会议记录,我们需要通过机器学习对用户输入的文本内容进行自动评判,合格或不合格.(同样的问题还类似垃圾短信检测.工作日志质量分析等.) 处理思 ...

  5. 机器学习框架ML.NET学习笔记【5】多元分类之手写数字识别(续)

    一.概述 上一篇文章我们利用ML.NET的多元分类算法实现了一个手写数字识别的例子,这个例子存在一个问题,就是输入的数据是预处理过的,很不直观,这次我们要直接通过图片来进行学习和判断.思路很简单,就是 ...

  6. 机器学习框架ML.NET学习笔记【6】TensorFlow图片分类

    一.概述 通过之前两篇文章的学习,我们应该已经了解了多元分类的工作原理,图片的分类其流程和之前完全一致,其中最核心的问题就是特征的提取,只要完成特征提取,分类算法就很好处理了,具体流程如下: 之前介绍 ...

  7. 机器学习框架ML.NET学习笔记【7】人物图片颜值判断

    一.概述 这次要解决的问题是输入一张照片,输出人物的颜值数据. 学习样本来源于华南理工大学发布的SCUT-FBP5500数据集,数据集包括 5500 人,每人按颜值魅力打分,分值在 1 到 5 分之间 ...

  8. 机器学习框架ML.NET学习笔记【9】自动学习

    一.概述 本篇我们首先通过回归算法实现一个葡萄酒品质预测的程序,然后通过AutoML的方法再重新实现,通过对比两种实现方式来学习AutoML的应用. 首先数据集来自于竞赛网站kaggle.com的UC ...

  9. OpenCV 学习笔记 07 目标检测与识别

    目标检测与识别是计算机视觉中最常见的挑战之一.属于高级主题. 本章节将扩展目标检测的概念,首先探讨人脸识别技术,然后将该技术应用到显示生活中的各种目标检测. 1 目标检测与识别技术 为了与OpenCV ...

随机推荐

  1. 「UVA557」 Burger(概率

    本题征求翻译.如果你能提供翻译或者题意简述,请 提交翻译 ,感谢你的贡献. 题目描述 PDF 输入输出格式 输入格式: 输出格式: 输入输出样例 输入样例#1: 复制 3 6 10 256 输出样例# ...

  2. JVM(一)虚拟机内存划分

    Java内存区域 线程私有数据区域:虚拟机栈,本地方法栈,程序计数器 线程共享数据区域:方法区,堆 程序计数器:当前线程所执行的字节码的行号指示器,JVM通过这个字节码解释器改变计数器的值,以选择下一 ...

  3. Idea无法加载主类

    今天重装了下电脑,运行idea发现各种问题. 直接进主题哈, 遇到三种情况 第一种: 首先查看这里是否有多个,只保留当前需要用工程路径.点击P右边的删除即可 删除后 然后运行是否能运行. 如果没有的话 ...

  4. Openstack web 添加和删除按钮

    注:当前已经时候用smaba将openstack环境的源码共享到windows系统上,并使用pycharm进行代码编辑和修改(参见openstack开发环境搭建).如下图:

  5. centos7 install pip

    1. 安装过程 yum -y install epel-release yum install python-pip pip install --upgrade pip

  6. 生成分布式随机ID

    经测试,最快的一种 public class Generator { // should be between 40 (34 years) and 42 (139 years) ; // should ...

  7. CodeForces 1131G. Most Dangerous Shark

    题目简述:从左到右依次有$n \leq 10^7$个Domino骨牌,高度为$h_i$,手动推倒他的花费为$c_i$.每个骨牌之间的距离为$1$.一个骨牌可以被向左或者向右推倒.当第$i$个骨牌被推倒 ...

  8. 《精通Spring4.X企业应用开发实战》读后感第四章(Application中Bean的生命周期)

    package com.smart.beanfactory; import org.springframework.beans.BeansException; import org.springfra ...

  9. Linux下磁盘加密luks使用

    使用luks加密磁盘,磁盘需要映射才可以挂载,映射的时候需要输入密码验证.luks相对于是对硬盘上了一把锁,要想打开就得有相应的钥匙,如果打开了就可以随意操作了,和普通硬盘一样. 使用方法如下: 0. ...

  10. UVaLive 3266 Tian Ji -- The Horse Racing (贪心)

    题意:田忌赛马,每胜一局就得200,负一局少200,问最多得多少钱. 析:贪心,如果最快的马比齐王的还快,就干掉它,如果最慢的马比齐王的马快,就干掉它,否则用最慢的马去和齐王最快的马比. 代码如下: ...