From bbd5fa167e35985414fb6146adb9fc4a478508d1 Mon Sep 17 00:00:00 2001 From: Shaun Zhou Date: Tue, 29 Sep 2026 15:07:48 +0800 Subject: [PATCH] =?UTF-8?q?wip:=20C++=20demo=20=E6=94=AF=E6=8C=81=E6=89=B9?= =?UTF-8?q?=E9=87=8F=E6=B8=85=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deploy/cpp/main.cpp | 86 +++++++++++++++++++++++++++++++-------------- 1 file changed, 60 insertions(+), 26 deletions(-) diff --git a/deploy/cpp/main.cpp b/deploy/cpp/main.cpp index 56ebc63..e72f63e 100644 --- a/deploy/cpp/main.cpp +++ b/deploy/cpp/main.cpp @@ -1,9 +1,12 @@ // 演示与对拍工具:读一张原始像素转储,推理并打印框。 // -// ./film_predict <宽> <高> <通道> [conf] [tile] +// 单张: ./film_predict <宽> <高> <通道> [conf] [overlap] +// 批量: ./film_predict --manifest <清单> [conf] [overlap] // // 输入是连续的 HWC uint8 缓冲(用 scripts/dump_raw.py 从图片生成)。产线里通常直接 -// 拿相机帧的指针,不需要这一步。tile 传 0 表示图本身就是网络输入尺寸。 +// 拿相机帧的指针,不需要这一步。 +// +// 清单每行 `路径 宽 高 通道`,模型只加载一次——逐张起进程的话加载耗时会盖过推理。 #include "film_detector.hpp" #include @@ -11,39 +14,70 @@ #include #include -int main(int argc, char** argv) { - if (argc < 6) { - std::cerr << "用法: " << argv[0] - << " <宽> <高> <通道> [conf] [tile-overlap]\n"; - return 1; - } - const std::string model_path = argv[1], image_path = argv[2]; - const int width = std::stoi(argv[3]), height = std::stoi(argv[4]); - const int channels = std::stoi(argv[5]); - const float conf = argc > 6 ? std::stof(argv[6]) : 0.25f; - const int overlap = argc > 7 ? std::stoi(argv[7]) : 32; +namespace { - std::ifstream file(image_path, std::ios::binary); - if (!file) { std::cerr << "打不开 " << image_path << "\n"; return 1; } - std::vector pixels((std::istreambuf_iterator(file)), - std::istreambuf_iterator()); - const size_t expected = static_cast(width) * height * channels; - if (pixels.size() != expected) { - std::cerr << "缓冲大小 " << pixels.size() << " 与 " << width << "x" << height - << "x" << channels << " 不符(应为 " << expected << ")\n"; - return 1; +bool read_pixels(const std::string& path, size_t expected, std::vector& out) { + std::ifstream file(path, std::ios::binary); + if (!file) { std::cerr << "打不开 " << path << "\n"; return false; } + out.assign(std::istreambuf_iterator(file), std::istreambuf_iterator()); + if (out.size() != expected) { + std::cerr << path << " 的缓冲是 " << out.size() << " 字节,应为 " << expected << "\n"; + return false; } + return true; +} - film::Detector detector(model_path); - film::ImageView image{pixels.data(), width, height, channels}; - const auto boxes = (width == detector.input_size() && height == detector.input_size()) +void run_one(const film::Detector& detector, const film::ImageView& image, float conf, + int overlap) { + const auto boxes = (image.width == detector.input_size() && + image.height == detector.input_size()) ? detector.infer_tile(image, conf) : detector.infer(image, conf, 0.5f, overlap); - std::printf("%zu\n", boxes.size()); for (const auto& b : boxes) { std::printf("%d %.6f %.6f %.6f %.6f %.4f\n", b.class_id, b.x1, b.y1, b.x2, b.y2, b.score); } +} + +} // namespace + +int main(int argc, char** argv) { + if (argc < 4) { + std::cerr << "用法:\n " << argv[0] << " <宽> <高> <通道>" + << " [conf] [overlap]\n " << argv[0] + << " --manifest <清单> [conf] [overlap]\n"; + return 1; + } + const std::string model_path = argv[1]; + const bool batch = std::string(argv[2]) == "--manifest"; + const float conf = batch ? (argc > 4 ? std::stof(argv[4]) : 0.25f) + : (argc > 6 ? std::stof(argv[6]) : 0.25f); + const int overlap = batch ? (argc > 5 ? std::stoi(argv[5]) : 32) + : (argc > 7 ? std::stoi(argv[7]) : 32); + + film::Detector detector(model_path); + std::vector pixels; + + if (batch) { + std::ifstream manifest(argv[3]); + if (!manifest) { std::cerr << "打不开清单 " << argv[3] << "\n"; return 1; } + std::string path; + int width = 0, height = 0, channels = 0; + while (manifest >> path >> width >> height >> channels) { + if (!read_pixels(path, static_cast(width) * height * channels, pixels)) { + return 1; + } + run_one(detector, film::ImageView{pixels.data(), width, height, channels}, + conf, overlap); + } + return 0; + } + + if (argc < 6) { std::cerr << "单张模式需要 宽 高 通道\n"; return 1; } + const int width = std::stoi(argv[3]), height = std::stoi(argv[4]); + const int channels = std::stoi(argv[5]); + if (!read_pixels(argv[2], static_cast(width) * height * channels, pixels)) return 1; + run_one(detector, film::ImageView{pixels.data(), width, height, channels}, conf, overlap); return 0; }