LCOV - code coverage report
Current view: top level - nntrainer/dataset - dir_data_producers.cpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 0.0 % 62 0
Test Date: 2025-12-14 20:38:17 Functions: 0.0 % 12 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, unsigned int width,
      39              :                       unsigned int 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              :   unsigned char info[54];
      46              :   size_t result = fread(info, sizeof(unsigned char), 54, f);
      47            0 :   NNTR_THROW_IF(result != 54, std::invalid_argument)
      48              :     << "Cannot read bmp header";
      49              : 
      50            0 :   size_t row_padded = (width * 3 + 3) & (~3);
      51            0 :   unsigned char *data = new unsigned char[row_padded];
      52              : 
      53            0 :   for (unsigned int i = 0; i < height; i++) {
      54              :     result = fread(data, sizeof(unsigned char), row_padded, f);
      55            0 :     NNTR_THROW_IF(result != row_padded, std::invalid_argument)
      56              :       << "Cannot read bmp pixel data";
      57              : 
      58            0 :     for (unsigned int j = 0; j < width; j++) {
      59              : 
      60            0 :       input[height * i + j] = (float)data[j * 3 + 2];
      61              : 
      62            0 :       input[(height * width) + height * i + j] = (float)data[j * 3 + 1];
      63              : 
      64            0 :       input[(height * width) * 2 + height * i + j] = (float)data[j * 3];
      65              :     }
      66              :   }
      67              : 
      68            0 :   delete[] data;
      69            0 :   fclose(f);
      70            0 : }
      71              : 
      72              : namespace nntrainer {
      73              : 
      74            0 : DirDataProducer::DirDataProducer() :
      75            0 :   dir_data_props(new Props()), num_class(0), num_data_total(0) {}
      76              : 
      77            0 : DirDataProducer::DirDataProducer(const std::string &dir_path) :
      78            0 :   dir_data_props(new Props(props::DirPath(dir_path))),
      79            0 :   num_class(0),
      80            0 :   num_data_total(0) {}
      81              : 
      82            0 : DirDataProducer::~DirDataProducer() {}
      83              : 
      84            0 : const std::string DirDataProducer::getType() const {
      85            0 :   return DirDataProducer::type;
      86              : }
      87              : 
      88            0 : bool DirDataProducer::isMultiThreadSafe() const {
      89              :   /// @todo make this true, it is needed to test multiple worker scenario
      90            0 :   return false;
      91              : }
      92              : 
      93            0 : void DirDataProducer::setProperty(const std::vector<std::string> &properties) {
      94            0 :   auto left = loadProperties(properties, *dir_data_props);
      95            0 :   NNTR_THROW_IF(!left.empty(), std::invalid_argument)
      96              :     << "There are unparsed properties, size: " << left.size();
      97            0 : }
      98              : 
      99              : DataProducer::Generator
     100            0 : DirDataProducer::finalize(const std::vector<TensorDim> &input_dims,
     101              :                           const std::vector<TensorDim> &label_dims,
     102              :                           void *user_data) {
     103              : 
     104            0 :   const auto &dir_path = std::get<props::DirPath>(*dir_data_props).get();
     105              : 
     106            0 :   for (const auto &entry : std::filesystem::directory_iterator(dir_path))
     107            0 :     class_names.push_back(entry.path().string());
     108              : 
     109            0 :   num_class = class_names.size();
     110              : 
     111              :   size_t id = 0;
     112              :   size_t num_data = 0;
     113            0 :   for (auto &c_name : class_names) {
     114              :     num_data = 0;
     115            0 :     std::filesystem::directory_iterator itr(c_name);
     116            0 :     while (itr != std::filesystem::end(itr)) {
     117            0 :       const std::filesystem::directory_entry &entry = *itr;
     118            0 :       std::string p = std::filesystem::absolute(entry.path()).string();
     119            0 :       if (p.compare(".") && p.compare("..")) {
     120            0 :         num_data++;
     121            0 :         data_list.push_back(std::make_pair((unsigned int)id, p));
     122              :       }
     123            0 :       itr++;
     124              :     }
     125              : 
     126            0 :     id++;
     127            0 :     num_data_total += num_data;
     128              :   }
     129              : 
     130              :   /// @todo expand this to non onehot case
     131            0 :   NNTR_THROW_IF(std::any_of(label_dims.begin(), label_dims.end(),
     132              :                             [](const TensorDim &dim) {
     133              :                               return dim.channel() != 1 || dim.height() != 1;
     134              :                             }),
     135              :                 std::invalid_argument)
     136              :     << "Label dimension containing channel or height not allowed";
     137              : 
     138            0 :   auto sz = size(input_dims, label_dims);
     139              : 
     140            0 :   NNTR_THROW_IF(sz == 0, std::invalid_argument)
     141              :     << "size is zero, data producer does not provide anything";
     142              : 
     143            0 :   return [sz, input_dims, this](unsigned int idx, std::vector<Tensor> &inputs,
     144              :                                 std::vector<Tensor> &labels) {
     145            0 :     NNTR_THROW_IF(idx >= sz, std::range_error)
     146              :       << "given index is out of bound, index: " << idx << " size: " << sz;
     147              : 
     148            0 :     std::string file_name = data_list[idx].second;
     149              : 
     150            0 :     readImage(file_name, inputs[0].getData(), input_dims[0].width(),
     151            0 :               input_dims[0].height());
     152              : 
     153            0 :     unsigned int c_id = data_list[idx].first;
     154              : 
     155            0 :     std::memset(labels[0].getData(), 0, num_class * sizeof(float));
     156              : 
     157            0 :     labels[0].getData()[c_id] = 1.0;
     158              : 
     159            0 :     return idx == sz - 1;
     160            0 :   };
     161              : }
     162              : 
     163              : unsigned int
     164            0 : DirDataProducer::size(const std::vector<TensorDim> &input_dims,
     165              :                       const std::vector<TensorDim> &label_dims) const {
     166              : 
     167            0 :   return num_data_total;
     168              : }
     169              : 
     170              : } // namespace nntrainer
        

Generated by: LCOV version 2.0-1