自己制作机器学习训练和测试使用的二进制数据集(C++)

Posted 阳光玻璃杯

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自己制作机器学习训练和测试使用的二进制数据集(C++)相关的知识,希望对你有一定的参考价值。

本文主要分享笔者仿照Cifar-10二进制数据库的格式,自己制作机器学习使用的二进制数据库。经过封装后,非常方便使用。代码可用Github下载:BinaryDataset

关于Cifar-10

CIFAR-10数据集由10个类的60000个32x32彩色图像组成,每个类有6000个图像。 有50000个训练图像和10000个测试图像:

其数据在文件中的存贮格式如下:

<1 x label><3072 x pixel>
...
<1 x label><3072 x pixel>

正是根据这种格式,实现了BinaryDataset对二进制文件的读写。
首先是1个字节来存储label,然后存放image的数据。image大小没有限制,代码中会根据图像的大小自动调整(但是要求所有的图像尺寸一致,比如说,所有的图像的尺寸都为100*100,或者1000*1000或者其他)。如果图像为多个通道,则格式为label R G B。

BinaryDataset详解

BinaryDataset源文件列表如下:

main.cpp 提供了一个制作人脸检测二进制数据库的例子。
BinaryDatasetWriter.h和BinaryDatasetWriter.cpp 用于生成二进制文件。
BinaryDatasetReader.hBinaryDatasetReader.cpp 用于从二进制文件中读取labels和images。

用法

生成二进制文件

把不同的种类的图片放置到不同的文件夹下面,然后在代码中分别指定类别和对应的文件夹,实例如下:

    std::vector<std::pair<int, std::string>> all(2);
    all.at(0).first = 1;
    all.at(0).second = "E:\\\\dataset\\\\TrainingImages\\\\FACES";
    all.at(1).first = 0;
    all.at(1).second = "E:\\\\dataset\\\\TrainingImages\\\\NFACES";

然后调用BinaryDatasetWriter实例的genBinaryDataset方法生成二进制文件。生成二进制文件之前会随机的打乱顺序。

    BinaryDatasetWriter bdw;
    bdw.genBinaryDataset(all);

读取二进制文件

调用 BinaryDatasetReader::readBina 方法会得到std::shared_ptr

    std::string binfile = "E:\\\\dataset\\\\face_detection.bin";
    auto labelAndImages = BinaryDatasetReader::readBina(binfile,19,19,1);

完整的示例

#include "BinaryDatasetWriter.h"
#include "BinaryDatasetReader.h"
#include <random>
#define WITER 0



void main()

#if WITER
    //首先,把不同类别的图片放到不同的文件夹下,比如,人脸图片放到一个文件夹下,非人脸放到一个文件夹下
    //在Vector中的pair下添加所有的类别文件夹和其标签,比如人脸为1,非人脸为0
    //生成二进制文件的过程不需要知道图片的大小,通过opencv读入图片后,就可以知道图片的大小了
    //这种方式目前只适合打包大小相同的图片

    std::vector<std::pair<int, std::string>> all(2);
    all.at(0).first = 1;
    all.at(0).second = "E:\\\\dataset\\\\TrainingImages\\\\FACES";
    all.at(1).first = 0;
    all.at(1).second = "E:\\\\dataset\\\\TrainingImages\\\\NFACES";
    BinaryDatasetWriter bdw;
    bdw.genBinaryDataset(all);

#else
    //测试的时候,我们必须事前知道图像的大小和通道数目
    std::string binfile = "E:\\\\dataset\\\\face_detection.bin";
    auto labelAndImages = BinaryDatasetReader::readBina(binfile,19,19,1);

    std::random_device rd;//来产生一个随机数当作种子  
    std::uniform_int_distribution<int> uni_dist(0, labelAndImages.get()->size()-10); //指定范围的随机数发生器  
    int startIndex = uni_dist(rd);
    for (int i = startIndex;i < startIndex + 10;i++) 
    
        std::pair<int, std::vector<uint8_t>> oneLabelAndData = labelAndImages.get()->at(i);
        std::cout << "label is " << oneLabelAndData.first << std::endl;
        cv::Mat img(19, 19, CV_8UC1, oneLabelAndData.second.data(), 19);
        cv::imshow("test", img);
        cv::waitKey(0);
    

#endif
    cv::waitKey(0);

WITER为1是生成二进制文件,WITER为0时读取二进制文件。

以上是关于自己制作机器学习训练和测试使用的二进制数据集(C++)的主要内容,如果未能解决你的问题,请参考以下文章

深度学习:使用UNet做图像语义分割,训练自己制作的数据集,详细教程

R语言使用caret包中的createDataPartition函数进行机器学习数据集划分划分训练集和测试集并指定训练测试比例

R语言使用caret包中的createDataPartition函数进行机器学习数据集划分划分训练集和测试集并指定训练测试比例

机器学习基础:(Python)训练集测试集分割与交叉验证

机器学习100天:005 数据预处理之划分训练集

机器学习100天:005 数据预处理之划分训练集