#include "capture.h" #include #include #include #include #include #include #include "logc/log.h" #include capture::capture(int camera_index, int zmq_port, int width_set, int height_set, int fps_set, bool _flip) { index = camera_index; port = zmq_port; width = width_set; height = height_set; fps = fps_set; flip = _flip; log_info("trying open camera %d", index); cap = new cv::VideoCapture(index, cv::CAP_V4L2); cap->set(cv::CAP_PROP_FRAME_WIDTH, width); cap->set(cv::CAP_PROP_FRAME_HEIGHT, height); cap->set(cv::CAP_PROP_FPS, fps); if (!cap->isOpened()) { log_error("开启摄像头 %d 失败", index); status = false; } else { log_info("开启摄像头 %d 成功", index); status = true; } context = new zmq::context_t(1); socket = new zmq::socket_t(*context, ZMQ_REP); // int hwm = 10; // socket->setsockopt(ZMQ_SNDHWM, &hwm, sizeof(hwm)); char zmq_bind_port[10] = {0}; sprintf(zmq_bind_port, "%d", port); strcat(zmq_bind_addr, zmq_bind_port); log_info("设置 %d zmq 地址 %s", index, zmq_bind_addr); socket->bind(zmq_bind_addr); } void capture::start(void) { if (this->is_open()) { log_info("开启摄像头 %d 采集和应答线程", index); // FIXME request 启动后若 capture 尚未读取到有效帧,则会断言 thread_capture = new std::thread(&capture::get, this); sleep(1); thread_request = new std::thread(&capture::req, this); } else { log_error("摄像头 %d 未成功初始化,跳过", index); } } void capture::get(void) { cv::Mat dst; while (1) { *cap >> dst; if (dst.empty()) { log_error("摄像头 %d 读取到空帧,尝试销毁后重启", index); cap->release(); // delete cap; cap = new cv::VideoCapture(index, cv::CAP_V4L2); cap->set(cv::CAP_PROP_FRAME_WIDTH, width); cap->set(cv::CAP_PROP_FRAME_HEIGHT, height); cap->set(cv::CAP_PROP_FPS, fps); log_warn("摄像头 %d 重新构造完成\r\n", index); *cap >> dst; } // 确保图像是连续的 if (!dst.isContinuous()) { dst = dst.clone().reshape(1, dst.total()); } // 中心翻转处理 if (flip) { cv::flip(dst, dst, -1); } // 将图像转换为 rgb cv::cvtColor(dst, frame, cv::COLOR_BGR2RGB); // 在这里添加一些延迟,以控制帧率 cv::waitKey(1); } } void capture::req(void) { zmq::message_t msg_temp; while (1) { socket->recv(&msg_temp); // 将帧编码后发送 std::vector buff; cv::imencode(".jpg", frame, buff); zmq::message_t message(buff.size()); memcpy(message.data(), buff.data(), buff.size()); socket->send(message, zmq::send_flags::none); } log_error("capture exit"); } bool capture::is_open(void) { return status; }