| 171 | } |
| 172 | |
| 173 | static void build_frame_overlay(vapp_state& app, std::vector<uint8_t>& overlay) { |
| 174 | if (app.frame.data.empty()) return; |
| 175 | int w = app.frame.width; |
| 176 | int h = app.frame.height; |
| 177 | |
| 178 | overlay.resize(w * h * 4); |
| 179 | for (int i = 0; i < w * h; ++i) { |
| 180 | overlay[4*i+0] = app.frame.data[3*i+0]; |
| 181 | overlay[4*i+1] = app.frame.data[3*i+1]; |
| 182 | overlay[4*i+2] = app.frame.data[3*i+2]; |
| 183 | overlay[4*i+3] = 255; |
| 184 | } |
| 185 | |
| 186 | if (app.show_masks) { |
| 187 | for (size_t d = 0; d < app.result.detections.size(); ++d) { |
| 188 | const auto& det = app.result.detections[d]; |
| 189 | if (det.mask.data.empty()) continue; |
| 190 | int ci = det.instance_id > 0 ? (det.instance_id - 1) % N_COLORS : (int)(d % N_COLORS); |
| 191 | const float* c = INSTANCE_COLORS[ci]; |
| 192 | float alpha = 0.4f; |
| 193 | |
| 194 | int mw = det.mask.width; |
| 195 | int mh = det.mask.height; |
| 196 | for (int y = 0; y < std::min(h, mh); ++y) { |
| 197 | for (int x = 0; x < std::min(w, mw); ++x) { |
| 198 | if (det.mask.data[y * mw + x] > 127) { |
| 199 | int idx = (y * w + x) * 4; |
| 200 | overlay[idx+0] = (uint8_t)(overlay[idx+0]*(1-alpha) + c[0]*255*alpha); |
| 201 | overlay[idx+1] = (uint8_t)(overlay[idx+1]*(1-alpha) + c[1]*255*alpha); |
| 202 | overlay[idx+2] = (uint8_t)(overlay[idx+2]*(1-alpha) + c[2]*255*alpha); |
| 203 | } |
| 204 | } |
| 205 | } |
| 206 | } |
| 207 | } |
| 208 | } |
| 209 | |
| 210 | static bool screen_to_image(const vapp_state& app, float sx, float sy, |
| 211 | float& ix, float& iy) { |