LCOV - code coverage report
Current view: top level - nntrainer-0.5.0/nntrainer/dataset - dir_data_producers.cpp (source / functions) Hit Total Coverage
Test: nntrainer 0.5.0-0 nnstreamer/nntrainer.git#7135f75d29b46a8913396dc62973559febc0ff1d Lines: 0 77 0.0 %
Date: 2023-06-08 09:54:03 Functions: 0 12 0.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: Apache-2.0
       2             : /**
       3             :  * Copyright (C) 2023 Jijoong Moon <jijoong.moon@samsung.com>
       4             :  *
       5             :  * @file   dir_data_producers.h
       6             :  * @date   24 Feb 2023
       7             :  * @brief  This file contains dir data producers, reading from the files in
       8             :  * directory
       9             :  * @see    https://github.com/nnstreamer/nntrainer
      10             :  * @author Jijoong Moon <jijoong.moon@samsung.com>
      11             :  * @bug    No known bugs except for NYI items
      12             :  *
      13             :  */
      14             : 
      15             : #include <dir_data_producers.h>
      16             : #include <filesystem>
      17             : 
      18             : #include <memory>
      19             : #include <numeric>
      20             : #include <random>
      21             : #include <sys/stat.h>
      22             : #include <vector>
      23             : 
      24             : #include <common_properties.h>
      25             : #include <nntrainer_error.h>
      26             : #include <node_exporter.h>
      27             : #include <util_func.h>
      28             : 
      29             : /**
      30             :  * @brief this function helps to read the image
      31             :  * currently only bmp image is supported and extend the image type will be
      32             :  * remain as TODO. ( BGR --> RGB )
      33             :  * @param     path file path
      34             :  * @param     inputs float data for image pixel
      35             :  * @param     width width
      36             :  * @param     height height
      37             :  */
      38           0 : static void readImage(const std::string path, float *input, uint width,
      39             :                       uint height) {
      40           0 :   FILE *f = fopen(path.c_str(), "rb");
      41             : 
      42           0 :   if (f == nullptr)
      43           0 :     throw std::invalid_argument("Cannot open file: " + path);
      44             : 
      45           0 :   unsigned char info[54];
      46           0 :   size_t result = fread(info, sizeof(unsigned char), 54, f);
      47           0 :   NNTR_THROW_IF(result != 54, std::invalid_argument)
      48           0 :     << "Cannot read bmp header";
      49             : 
      50           0 :   uint w = *(int *)&info[18];
      51           0 :   uint h = *(int *)&info[22];
      52             : 
      53           0 :   size_t row_padded = (width * 3 + 3) & (~3);
      54           0 :   unsigned char *data = new unsigned char[row_padded];
      55             : 
      56           0 :   for (uint i = 0; i < height; i++) {
      57           0 :     result = fread(data, sizeof(unsigned char), row_padded, f);
      58           0 :     NNTR_THROW_IF(result != row_padded, std::invalid_argument)
      59           0 :       << "Cannot read bmp pixel data";
      60             : 
      61           0 :     for (uint j = 0; j < width; j++) {
      62             : 
      63           0 :       input[height * i + j] = (float)data[j * 3 + 2];
      64             : 
      65           0 :       input[(height * width) + height * i + j] = (float)data[j * 3 + 1];
      66             : 
      67           0 :       input[(height * width) * 2 + height * i + j] = (float)data[j * 3];
      68             :     }
      69             :   }
      70             : 
      71           0 :   delete[] data;
      72           0 :   fclose(f);
      73           0 : }
      74             : 
      75             : namespace nntrainer {
      76             : 
      77           0 : DirDataProducer::DirDataProducer() :
      78           0 :   dir_data_props(new Props()),
      79             :   num_class(0),
      80           0 :   num_data_total(0) {}
      81             : 
      82           0 : DirDataProducer::DirDataProducer(const std::string &dir_path) :
      83           0 :   dir_data_props(new Props(props::DirPath(dir_path))),
      84             :   num_class(0),
      85           0 :   num_data_total(0) {}
      86             : 
      87           0 : DirDataProducer::~DirDataProducer() {}
      88             : 
      89           0 : const std::string DirDataProducer::getType() const {
      90           0 :   return DirDataProducer::type;
      91             : }
      92             : 
      93           0 : bool DirDataProducer::isMultiThreadSafe() const {
      94             :   /// @todo make this true, it is needed to test multiple worker scenario
      95           0 :   return false;
      96             : }
      97             : 
      98           0 : void DirDataProducer::setProperty(const std::vector<std::string> &properties) {
      99           0 :   auto left = loadProperties(properties, *dir_data_props);
     100           0 :   NNTR_THROW_IF(!left.empty(), std::invalid_argument)
     101           0 :     << "There are unparsed properties, size: " << left.size();
     102           0 : }
     103             : 
     104             : DataProducer::Generator
     105           0 : DirDataProducer::finalize(const std::vector<TensorDim> &input_dims,
     106             :                           const std::vector<TensorDim> &label_dims,
     107             :                           void *user_data) {
     108             : 
     109           0 :   auto dir_path = std::get<props::DirPath>(*dir_data_props).get();
     110             : 
     111           0 :   for (const auto &entry : std::filesystem::directory_iterator(dir_path))
     112           0 :     class_names.push_back(entry.path());
     113             : 
     114           0 :   num_class = class_names.size();
     115             : 
     116           0 :   size_t id = 0;
     117           0 :   size_t num_data = 0;
     118           0 :   for (auto c_name : class_names) {
     119           0 :     num_data = 0;
     120           0 :     std::filesystem::directory_iterator itr(c_name);
     121           0 :     while (itr != std::filesystem::end(itr)) {
     122           0 :       const std::filesystem::directory_entry &entry = *itr;
     123           0 :       std::string p = std::filesystem::absolute(entry.path()).string();
     124           0 :       if (p.compare(".") && p.compare("..")) {
     125           0 :         num_data++;
     126           0 :         data_list.push_back(std::make_pair(id, p));
     127             :       }
     128           0 :       itr++;
     129             :     }
     130             : 
     131           0 :     id++;
     132           0 :     num_data_total += num_data;
     133             :   }
     134             : 
     135             :   /// @todo expand this to non onehot case
     136           0 :   NNTR_THROW_IF(std::any_of(label_dims.begin(), label_dims.end(),
     137             :                             [](const TensorDim &dim) {
     138             :                               return dim.channel() != 1 || dim.height() != 1;
     139             :                             }),
     140             :                 std::invalid_argument)
     141           0 :     << "Label dimension containing channel or height not allowed";
     142             : 
     143           0 :   auto sz = size(input_dims, label_dims);
     144             : 
     145           0 :   NNTR_THROW_IF(sz == 0, std::invalid_argument)
     146           0 :     << "size is zero, dataproducer does not provide anything";
     147             : 
     148           0 :   return [sz, input_dims, this](unsigned int idx, std::vector<Tensor> &inputs,
     149           0 :                                 std::vector<Tensor> &labels) {
     150           0 :     NNTR_THROW_IF(idx >= sz, std::range_error)
     151           0 :       << "given index is out of bound, index: " << idx << " size: " << sz;
     152             : 
     153           0 :     std::string file_name = data_list[idx].second;
     154             : 
     155           0 :     readImage(file_name, inputs[0].getData(), input_dims[0].width(),
     156           0 :               input_dims[0].height());
     157             : 
     158           0 :     unsigned int c_id = data_list[idx].first;
     159             : 
     160           0 :     std::memset(labels[0].getData(), 0.0, num_class * sizeof(float));
     161             : 
     162           0 :     labels[0].getData()[c_id] = 1.0;
     163             : 
     164           0 :     return idx == sz - 1;
     165           0 :   };
     166             : }
     167             : 
     168             : unsigned int
     169           0 : DirDataProducer::size(const std::vector<TensorDim> &input_dims,
     170             :                       const std::vector<TensorDim> &label_dims) const {
     171             : 
     172           0 :   return num_data_total;
     173             : }
     174             : 
     175             : } // namespace nntrainer

Generated by: LCOV version 1.16