欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2022-06-03 13:58:44
...

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

关于Cifar-10

CIFAR-10数据集由10个类的60000个32x32彩色图像组成,每个类有6000个图像。 有50000个训练图像和10000个测试图像:
自己制作机器学习训练和测试使用的二进制数据集(C++)

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

<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源文件列表如下:

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

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时读取二进制文件。

相关标签: binary dataset