forked from zakaria/chicken-counting-sukawarna-det
140 lines
4.3 KiB
C++
140 lines
4.3 KiB
C++
#pragma once
|
|
|
|
#include <chrono>
|
|
#include <filesystem>
|
|
#include <fstream>
|
|
#include <iomanip>
|
|
#include <iostream>
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include <nlohmann/json.hpp>
|
|
|
|
#include "chicken_counter/types.hpp"
|
|
|
|
namespace cc {
|
|
|
|
inline std::string now_iso() {
|
|
auto now = std::chrono::system_clock::now();
|
|
auto t = std::chrono::system_clock::to_time_t(now);
|
|
std::ostringstream oss;
|
|
oss << std::put_time(std::gmtime(&t), "%FT%TZ");
|
|
return oss.str();
|
|
}
|
|
|
|
inline std::string relative_output_path(const std::string& path,
|
|
const std::string& base_dir) {
|
|
if (path.empty()) return "";
|
|
if (base_dir.empty()) return std::filesystem::path(path).filename().string();
|
|
try {
|
|
auto rel = std::filesystem::relative(path, base_dir);
|
|
return rel.string();
|
|
} catch (...) {
|
|
return std::filesystem::path(path).filename().string();
|
|
}
|
|
}
|
|
|
|
inline nlohmann::json build_camera_report_entry(
|
|
const CameraBatchResult& item,
|
|
const std::string& output_dir = "")
|
|
{
|
|
if (item.skipped) {
|
|
return {{"skipped", true},
|
|
{"skip_reason", item.skip_reason},
|
|
{"total_entered", 0}};
|
|
}
|
|
|
|
return {
|
|
{"total_entered", item.pipeline.total_entered_count},
|
|
{"source_video", std::filesystem::path(item.pipeline.source_video).filename().string()},
|
|
{"vis_video", relative_output_path(item.pipeline.vis_video_path, output_dir)},
|
|
{"compressed_video", relative_output_path(item.compressed_video_path, output_dir)},
|
|
{"compressed_size_mb", item.compressed_size_mb},
|
|
{"frames_processed", item.pipeline.frames_processed},
|
|
{"stopped_reason", item.pipeline.stopped_reason},
|
|
{"elapsed_seconds", std::round(item.pipeline.elapsed_seconds * 10.0) / 10.0}
|
|
};
|
|
}
|
|
|
|
struct BatchReport {
|
|
std::string date;
|
|
std::string generated_at;
|
|
nlohmann::json cameras;
|
|
int total_entered_sum;
|
|
};
|
|
|
|
inline BatchReport build_batch_report(
|
|
const std::string& date,
|
|
const std::vector<CameraBatchResult>& results,
|
|
const std::string& output_dir = "")
|
|
{
|
|
BatchReport report;
|
|
report.date = date;
|
|
report.generated_at = now_iso();
|
|
report.total_entered_sum = 0;
|
|
|
|
for (const auto& item : results) {
|
|
auto entry = build_camera_report_entry(item, output_dir);
|
|
if (entry.empty()) continue;
|
|
report.cameras[item.camera_id] = entry;
|
|
if (!item.skipped)
|
|
report.total_entered_sum += entry.value("total_entered", 0);
|
|
}
|
|
|
|
return report;
|
|
}
|
|
|
|
inline std::string write_json_file(const std::string& path, const nlohmann::json& j) {
|
|
namespace fs = std::filesystem;
|
|
fs::create_directories(fs::path(path).parent_path());
|
|
std::ofstream f(path);
|
|
f << j.dump(2);
|
|
std::cerr << "[report] wrote " << path << "\n";
|
|
return path;
|
|
}
|
|
|
|
inline std::string write_batch_report(const BatchReport& report,
|
|
const std::string& output_path) {
|
|
nlohmann::json j = {
|
|
{"date", report.date},
|
|
{"generated_at", report.generated_at},
|
|
{"cameras", report.cameras},
|
|
{"total_entered_sum", report.total_entered_sum}
|
|
};
|
|
return write_json_file(output_path, j);
|
|
}
|
|
|
|
inline std::string write_camera_report(
|
|
const std::string& date,
|
|
const CameraBatchResult& item,
|
|
const std::string& output_dir)
|
|
{
|
|
namespace fs = std::filesystem;
|
|
fs::create_directories(output_dir);
|
|
auto entry = build_camera_report_entry(item, output_dir);
|
|
nlohmann::json payload = {
|
|
{"date", date},
|
|
{"camera_id", item.camera_id},
|
|
{"generated_at", now_iso()}
|
|
};
|
|
for (auto& [k, v] : entry.items()) payload[k] = v;
|
|
std::string path = output_dir + "/" + item.camera_id + "_counts_" + date + ".json";
|
|
return write_json_file(path, payload);
|
|
}
|
|
|
|
inline std::string persist_batch_reports(
|
|
const std::string& date,
|
|
const std::vector<CameraBatchResult>& results,
|
|
const std::string& output_dir)
|
|
{
|
|
const auto& latest = results.back();
|
|
write_camera_report(date, latest, output_dir);
|
|
std::string aggregate_path = output_dir + "/counts_" + date + ".json";
|
|
auto report = build_batch_report(date, results, output_dir);
|
|
write_batch_report(report, aggregate_path);
|
|
return aggregate_path;
|
|
}
|
|
|
|
} // namespace cc
|