#pragma once #include #include #include #include #include #include #include namespace wust_vision { template class LogsStream { public: LogsStream(const std::string& n) { name = n; } void handleOnce(const T& t, nlohmann::json& j) { log_data.push_back(t); trim(); insertData(j); } void push_back(const T& t) { log_data.push_back(t); } void trim() { while (log_data.size() > MAX_N) { log_data.erase(log_data.begin()); } } void insertData(nlohmann::json& j) { j[name] = log_data; } void clear() { log_data.clear(); } private: std::string name; std::vector log_data; }; template void drawDebugOverlayImpl( const DebugT& dbg, std::pair camera_info, bool auto_fps, DrawFn&& draw_fn, OutputFn&& output_fn ) { static auto last_show_time = std::chrono::steady_clock::now(); if (dbg.img_frame.src_img.empty()) return; constexpr double min_interval_ms = 1000.0 / 30.0; const auto now = std::chrono::steady_clock::now(); if (auto_fps && std::chrono::duration(now - last_show_time).count() < min_interval_ms) return; last_show_time = now; cv::Mat debug_img; if (dbg.img_frame.pixel_format == wust_vl::video::PixelFormat::GRAY) { cv::cvtColor(dbg.img_frame.src_img, debug_img, cv::COLOR_GRAY2RGB); } else if (dbg.img_frame.pixel_format == wust_vl::video::PixelFormat::BGR) { cv::cvtColor(dbg.img_frame.src_img, debug_img, cv::COLOR_BGR2RGB); } else { debug_img = dbg.img_frame.src_img; } if (debug_img.empty()) return; draw_fn(debug_img, dbg, camera_info); output_fn(debug_img); } inline auto writeToFile = [](const cv::Mat& img) { cv::Mat bgr; cv::cvtColor(img, bgr, cv::COLOR_RGB2BGR); std::vector buf; cv::imencode(".jpg", bgr, buf); std::ofstream ofs("/dev/shm/debug_frame.jpg.tmp", std::ios::binary); ofs.write(reinterpret_cast(buf.data()), buf.size()); ofs.close(); std::rename("/dev/shm/debug_frame.jpg.tmp", "/dev/shm/debug_frame.jpg"); }; class ShmWriter { public: static constexpr size_t shm_max_size = 2 * 1024 * 1024; explicit ShmWriter(const char* name, mode_t mode = 0666) { fd_ = shm_open(name, O_CREAT | O_RDWR, mode); if (fd_ == -1) { std::cerr << "[SHM] shm_open failed\n"; return; } if (ftruncate(fd_, shm_max_size) == -1) { std::cerr << "[SHM] ftruncate failed\n"; close(fd_); fd_ = -1; return; } ptr_ = mmap(nullptr, shm_max_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_, 0); if (ptr_ == MAP_FAILED) { std::cerr << "[SHM] mmap failed\n"; close(fd_); fd_ = -1; ptr_ = nullptr; } } ~ShmWriter() { if (ptr_) munmap(ptr_, shm_max_size); if (fd_ != -1) close(fd_); } void operator()(const cv::Mat& img) const { if (!ptr_) return; static const std::vector jpeg_params = { cv::IMWRITE_JPEG_QUALITY, 75 }; std::vector buf; cv::imencode(".jpg", img, buf, jpeg_params); if (buf.size() + 4 > shm_max_size) return; uint32_t size = static_cast(buf.size()); std::memcpy(ptr_, &size, 4); std::memcpy(static_cast(ptr_) + 4, buf.data(), size); } private: int fd_ { -1 }; void* ptr_ { nullptr }; }; inline auto showWindow(const char* win_name) { return [win_name](const cv::Mat& img) { cv::imshow(win_name, img); cv::waitKey(1); }; } } // namespace wust_vision