To move to main

This commit is contained in:
proitlab committed 2026-07-22 11:58:27 +07:00
1 parent f34eaa3af4
commit be204b91cc
11 files changed
+187 -63

No files matched your search

+16 -4
View File
@@ -284,6 +284,7 @@ struct OverlayConfig {
bool show_track_ring = false;
cv::Point2i count_anchor = {900, 120};
bool inside_box_only = true;
bool validated_only = false;
bool pending_blink = true;
std::vector<cv::Scalar> pending_colors = {cv::Scalar(255, 255, 0), cv::Scalar(0, 255, 255)};
};
@@ -291,7 +292,8 @@ inline void to_json(nlohmann::json& j, const OverlayConfig& c) {
j = {{"show_boxes", c.show_boxes}, {"show_track_trails", c.show_track_trails},
{"trail_length", c.trail_length}, {"show_center_marker", c.show_center_marker},
{"show_track_ring", c.show_track_ring}, {"count_anchor", c.count_anchor},
{"inside_box_only", c.inside_box_only}, {"pending_blink", c.pending_blink},
{"inside_box_only", c.inside_box_only}, {"validated_only", c.validated_only},
{"pending_blink", c.pending_blink},
{"pending_colors", c.pending_colors}};
}
inline void from_json(const nlohmann::json& j, OverlayConfig& c) {
@@ -302,6 +304,7 @@ inline void from_json(const nlohmann::json& j, OverlayConfig& c) {
c.show_track_ring = j.value("show_track_ring", false);
c.count_anchor = j.value("count_anchor", cv::Point2i{900, 120});
c.inside_box_only = j.value("inside_box_only", true);
c.validated_only = j.value("validated_only", false);
c.pending_blink = j.value("pending_blink", true);
c.pending_colors = j.value("pending_colors",
std::vector<cv::Scalar>{cv::Scalar(255, 255, 0), cv::Scalar(0, 255, 255)});
@@ -328,7 +331,8 @@ inline void to_json(nlohmann::json& j, const DisplayConfig& c) {
inline void from_json(const nlohmann::json& j, DisplayConfig& c) {
c.window_name = j.value("window_name", "Chicken Counter");
c.show_window = j.value("show_window", true);
c.output_path = j.value("output_path", "");
if (j.contains("output_path") && !j["output_path"].is_null())
c.output_path = j["output_path"].get<std::string>();
c.write_fps = j.value("write_fps", -1.0f);
c.max_frames = j.value("max_frames", -1);
c.encoder = j.value("encoder", "auto");
@@ -455,9 +459,10 @@ struct CameraPreset {
std::string camera_id;
int camera_num;
RoiConfig roi;
cv::Point2i count_anchor = {-1, -1}; // (-1,-1) = not set
cv::Point2i count_anchor = {-1, -1};
GateConfig gate;
MotionConfig motion;
nlohmann::json detection_overrides;
bool has_gate = false;
bool has_motion = false;
};
@@ -536,6 +541,9 @@ inline BatchSettings load_batch_config(const std::string& path) {
preset.motion = cam["motion"].get<MotionConfig>();
preset.has_motion = true;
}
if (cam.contains("detection")) {
preset.detection_overrides = cam["detection"];
}
settings.cameras[id] = std::move(preset);
}
@@ -561,6 +569,10 @@ inline CameraConfig build_camera_config_from_batch(
if (!raw.contains("overlay")) raw["overlay"] = nlohmann::json::object();
raw["overlay"]["count_anchor"] = preset.count_anchor;
}
if (!preset.detection_overrides.empty()) {
if (!raw.contains("detection")) raw["detection"] = nlohmann::json::object();
raw["detection"].update(preset.detection_overrides);
}
if (!raw.contains("roi")) raw["roi"] = nlohmann::json::object();
raw["roi"]["points"] = preset.roi.points;
@@ -589,7 +601,7 @@ inline CameraConfig build_camera_config_from_batch(
}
if (!raw.contains("display")) raw["display"] = nlohmann::json::object();
raw["display"]["output_path"] = output_path.empty() ? nlohmann::json(nullptr) : nlohmann::json(output_path);
if (!output_path.empty()) raw["display"]["output_path"] = output_path;
raw["display"]["show_window"] = false;
if (!raw.contains("feedback")) raw["feedback"] = nlohmann::json::object();
+1
View File
@@ -108,6 +108,7 @@ inline cv::Mat draw_overlay(
if (config.overlay.inside_box_only && !inside_box) continue;
bool validated = counting_zone.is_validated(track.track_id);
if (config.overlay.validated_only && !validated) continue;
int x1 = track.bbox_x1, y1 = track.bbox_y1, x2 = track.bbox_x2, y2 = track.bbox_y2;
int cx = track.centroid_x, cy = track.centroid_y;
int seq = static_cast<int>(counting_zone.sequence_number_for(track.track_id));
+23 -53
View File
@@ -119,8 +119,6 @@ public:
std::string input_name, output_name;
size_t input_bytes = 0, output_bytes = 0;
int output_num_classes = 1, output_num_cells = 8400;
bool output_layout_packed = true; // true = [1,N,8400], false = [1,8400,N]
private:
struct Logger : nvinfer1::ILogger {
@@ -158,25 +156,12 @@ private:
input_name = name; input_bytes = bytes;
} else {
output_name = name; output_bytes = bytes;
// cache output layout once
int d1 = (shape.nbDims >= 2) ? shape.d[1] : 1;
int d2 = (shape.nbDims >= 3) ? shape.d[2] : 1;
if (d2 > d1) {
output_layout_packed = true; // [1, N, cells]
output_num_classes = std::max(1, d1 - 4);
output_num_cells = d2;
} else {
output_layout_packed = false; // [1, cells, N]
output_num_classes = std::max(1, d2 - 4);
output_num_cells = d1;
}
}
}
stream.reset(new cudaStream_t{});
trt_check(cudaStreamCreate(stream.get()));
std::cerr << "[trt] ready: in=" << input_name << " (" << input_bytes
<< "B) out=" << output_name << " (" << output_bytes
<< "B) cls=" << output_num_classes << " cells=" << output_num_cells << "\n";
<< "B) out=" << output_name << " (" << output_bytes << "B)\n";
}
};
@@ -311,52 +296,37 @@ private:
return cv::dnn::blobFromImage(p, 1.0/255.0, {imgsz, imgsz}, cv::Scalar(), true, false);
}
// --- decode (uses cache layout) ---
// --- decode: model outputs (1, 300, 6) = [x1,y1,x2,y2,conf,cls] in letterbox space ---
std::vector<cv::Rect2f> decode(float scale, int pad_x, int pad_y, int ow, int oh) {
std::vector<cv::Rect> iboxes; iboxes.reserve(32);
std::vector<float> scores; scores.reserve(32);
int nc = trt->output_num_classes;
int cells = trt->output_num_cells;
int stride = nc + 4; // total channels per cell
const float* d = output_buf;
int stride = 6; // (x1,y1,x2,y2,conf,cls) per detection
if (trt->output_layout_packed) {
// layout [1, N, cells] — each channel is contiguous stride apart
for (int i = 0; i < cells; ++i) {
float maxc = 0;
for (int c = 0; c < nc; ++c) {
float v = d[(4 + c) * cells + i];
if (v > maxc) maxc = v;
}
if (maxc < conf_thresh) continue;
float cx = d[i], cy = d[cells + i], w = d[2*cells + i], h = d[3*cells + i];
float x = (cx - pad_x) / scale, y = (cy - pad_y) / scale;
float bw = w / scale, bh = h / scale;
int x1 = std::max(0, std::min(static_cast<int>(x - bw/2), ow));
int y1 = std::max(0, std::min(static_cast<int>(y - bh/2), oh));
int x2 = std::max(0, std::min(static_cast<int>(x + bw/2), ow));
int y2 = std::max(0, std::min(static_cast<int>(y + bh/2), oh));
if (x2 > x1 && y2 > y1) { iboxes.push_back({x1, y1, x2 - x1, y2 - y1}); scores.push_back(maxc); }
}
} else {
// layout [1, cells, N] — contiguous per row
for (int i = 0; i < cells; ++i) {
const float* row = d + i * stride;
float maxc = 0;
for (int c = 0; c < nc; ++c) { float v = row[4 + c]; if (v > maxc) maxc = v; }
if (maxc < conf_thresh) continue;
float cx = row[0], cy = row[1], w = row[2], h = row[3];
float x = (cx - pad_x) / scale, y = (cy - pad_y) / scale;
int x1 = std::max(0, std::min(static_cast<int>(x - w/scale/2), ow));
int y1 = std::max(0, std::min(static_cast<int>(y - h/scale/2), oh));
int x2 = std::max(0, std::min(static_cast<int>(x + w/scale/2), ow));
int y2 = std::max(0, std::min(static_cast<int>(y + h/scale/2), oh));
if (x2 > x1 && y2 > y1) { iboxes.push_back({x1, y1, x2 - x1, y2 - y1}); scores.push_back(maxc); }
for (int i = 0; i < output_buf_size / stride; ++i) {
const float* row = d + i * stride;
float conf = row[4];
if (conf < conf_thresh) continue;
// boxes are in letterbox coordinates, scale back
float x1 = (row[0] - pad_x) / scale;
float y1 = (row[1] - pad_y) / scale;
float x2 = (row[2] - pad_x) / scale;
float y2 = (row[3] - pad_y) / scale;
int ix1 = std::max(0, std::min(static_cast<int>(x1), ow));
int iy1 = std::max(0, std::min(static_cast<int>(y1), oh));
int ix2 = std::max(0, std::min(static_cast<int>(x2), ow));
int iy2 = std::max(0, std::min(static_cast<int>(y2), oh));
if (ix2 > ix1 && iy2 > iy1) {
iboxes.push_back({ix1, iy1, ix2 - ix1, iy2 - iy1});
scores.push_back(conf);
}
}
std::vector<int> idx; cv::dnn::NMSBoxes(iboxes, scores, conf_thresh, iou_thresh, idx);
std::vector<int> idx;
cv::dnn::NMSBoxes(iboxes, scores, conf_thresh, iou_thresh, idx);
std::vector<cv::Rect2f> out; out.reserve(idx.size());
for (int i : idx) out.push_back(iboxes[i]);
return out;