wip: C++ demo 支持批量清单
This commit is contained in:
+60
-26
@@ -1,9 +1,12 @@
|
|||||||
// 演示与对拍工具:读一张原始像素转储,推理并打印框。
|
// 演示与对拍工具:读一张原始像素转储,推理并打印框。
|
||||||
//
|
//
|
||||||
// ./film_predict <model.xml> <image.bin> <宽> <高> <通道> [conf] [tile]
|
// 单张: ./film_predict <model.xml> <image.bin> <宽> <高> <通道> [conf] [overlap]
|
||||||
|
// 批量: ./film_predict <model.xml> --manifest <清单> [conf] [overlap]
|
||||||
//
|
//
|
||||||
// 输入是连续的 HWC uint8 缓冲(用 scripts/dump_raw.py 从图片生成)。产线里通常直接
|
// 输入是连续的 HWC uint8 缓冲(用 scripts/dump_raw.py 从图片生成)。产线里通常直接
|
||||||
// 拿相机帧的指针,不需要这一步。tile 传 0 表示图本身就是网络输入尺寸。
|
// 拿相机帧的指针,不需要这一步。
|
||||||
|
//
|
||||||
|
// 清单每行 `路径 宽 高 通道`,模型只加载一次——逐张起进程的话加载耗时会盖过推理。
|
||||||
#include "film_detector.hpp"
|
#include "film_detector.hpp"
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
@@ -11,39 +14,70 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
namespace {
|
||||||
if (argc < 6) {
|
|
||||||
std::cerr << "用法: " << argv[0]
|
|
||||||
<< " <model.xml> <image.bin> <宽> <高> <通道> [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;
|
|
||||||
|
|
||||||
std::ifstream file(image_path, std::ios::binary);
|
bool read_pixels(const std::string& path, size_t expected, std::vector<unsigned char>& out) {
|
||||||
if (!file) { std::cerr << "打不开 " << image_path << "\n"; return 1; }
|
std::ifstream file(path, std::ios::binary);
|
||||||
std::vector<unsigned char> pixels((std::istreambuf_iterator<char>(file)),
|
if (!file) { std::cerr << "打不开 " << path << "\n"; return false; }
|
||||||
std::istreambuf_iterator<char>());
|
out.assign(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>());
|
||||||
const size_t expected = static_cast<size_t>(width) * height * channels;
|
if (out.size() != expected) {
|
||||||
if (pixels.size() != expected) {
|
std::cerr << path << " 的缓冲是 " << out.size() << " 字节,应为 " << expected << "\n";
|
||||||
std::cerr << "缓冲大小 " << pixels.size() << " 与 " << width << "x" << height
|
return false;
|
||||||
<< "x" << channels << " 不符(应为 " << expected << ")\n";
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
film::Detector detector(model_path);
|
void run_one(const film::Detector& detector, const film::ImageView& image, float conf,
|
||||||
film::ImageView image{pixels.data(), width, height, channels};
|
int overlap) {
|
||||||
const auto boxes = (width == detector.input_size() && height == detector.input_size())
|
const auto boxes = (image.width == detector.input_size() &&
|
||||||
|
image.height == detector.input_size())
|
||||||
? detector.infer_tile(image, conf)
|
? detector.infer_tile(image, conf)
|
||||||
: detector.infer(image, conf, 0.5f, overlap);
|
: detector.infer(image, conf, 0.5f, overlap);
|
||||||
|
|
||||||
std::printf("%zu\n", boxes.size());
|
std::printf("%zu\n", boxes.size());
|
||||||
for (const auto& b : boxes) {
|
for (const auto& b : boxes) {
|
||||||
std::printf("%d %.6f %.6f %.6f %.6f %.4f\n",
|
std::printf("%d %.6f %.6f %.6f %.6f %.4f\n",
|
||||||
b.class_id, b.x1, b.y1, b.x2, b.y2, b.score);
|
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] << " <model.xml> <image.bin> <宽> <高> <通道>"
|
||||||
|
<< " [conf] [overlap]\n " << argv[0]
|
||||||
|
<< " <model.xml> --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<unsigned char> 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<size_t>(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<size_t>(width) * height * channels, pixels)) return 1;
|
||||||
|
run_one(detector, film::ImageView{pixels.data(), width, height, channels}, conf, overlap);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user