#include "capture.h" #include #include #include #include #include #include #include "logc/log.h" #include void adjustImageTemperature(cv::Mat &img, float scale) { // 分离通道 std::vector channels; split(img, channels); // 增加蓝色通道和绿色通道的值,减少红色通道的值 channels[0] = channels[0] * scale; // 蓝色通道 channels[1] = channels[1] * scale; // 绿色通道 channels[2] = channels[2] / scale; // 红色通道 // 合并通道 merge(channels, img); } 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("尝试开启摄像头 %d", index); cap = new cv::VideoCapture(index, cv::CAP_V4L2); sleep(2); // 等待两秒进行构造 cap->set(cv::CAP_PROP_FRAME_WIDTH, width); cap->set(cv::CAP_PROP_FRAME_HEIGHT, height); cap->set(cv::CAP_PROP_FPS, fps); // if (10 == camera_index) // { // int fourcc = cv::VideoWriter::fourcc('M', 'J', 'P', 'G'); // 例如,使用 MJPG 编码 // // 设置输出视频的分辨率和帧率,与输入视频一致或根据需要调整 // cv::Size frameSize = cv::Size((int)cap->get(cv::CAP_PROP_FRAME_WIDTH), // (int)cap->get(cv::CAP_PROP_FRAME_HEIGHT)); // int fps = (int)cap->get(cv::CAP_PROP_FPS); // writer = new cv::VideoWriter("/home/evan/Workplace/project_capture/capture.avi", fourcc, fps, frameSize, true); // } int cnt = 1; for (int i = 20; i > 0; i--) { if (cap->isOpened()) { status = true; break; } log_error("开启摄像头 %d 失败,重试中", index); cap->open(index, cv::CAP_V4L2); usleep(100000); status = false; } if (status) { log_info("开启摄像头 %d 成功", index); } else { log_fatal("开启摄像头 %d 十次重试后失败", index); } 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(nullptr != writer){ // writer->write(dst); // } // 确保图像是连续的 if (!dst.isContinuous()) { dst = dst.clone().reshape(1, dst.total()); } // 中心翻转处理 if (flip) { cv::flip(dst, dst, -1); } // adjustImageTemperature(dst, 1.2); // 将图像转换为 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; }