C++ 使用OpenCV写入/dev/fb0

C++ 使用OpenCV写入/dev/fb0,c++,opencv,v4l2,C++,Opencv,V4l2,因此,我对使用OpenCV将memcopy复制到映射的帧缓冲设备(ex./dev/fb0)hwne有点困惑 例如,查看C和C++的一个OpenCV捕获函数: C: IplImage* cvQueryFrame(CvCapture* capture) C++: bool VideoCapture::read(Mat& image) P>图像数据存储在C++的矩阵结构(Matrix)和CVClinux黑箱结构中。 但是,我还没有找到任何好的(一致的)代码片段来说明如何获取存储在这些结构中

因此,我对使用OpenCV将memcopy复制到映射的帧缓冲设备(ex./dev/fb0)hwne有点困惑

例如,查看C和C++的一个OpenCV捕获函数:

C: IplImage* cvQueryFrame(CvCapture* capture) 
C++: bool VideoCapture::read(Mat& image)
P>图像数据存储在C++的矩阵结构(Matrix)和CVClinux黑箱结构中。 但是,我还没有找到任何好的(一致的)代码片段来说明如何获取存储在这些结构中的图像数据并将其复制到帧缓冲区

有没有人知道或有这样做所需的转换的例子


(Linux和OpenCV都不支持)

不要试图直接访问原始帧缓冲区设备


相反,使用一些抽象掉实际输出设备的中间库,例如(我不完全确定SDL2是否支持帧缓冲区(很可能是这样),但SDL1肯定支持。

无论这种方法是否被认为是好的,您都可以这样做(只支持某些像素格式的组合):

/**
*@file fbwrite_video.cpp
*在帧缓冲区上显示OpenCV视频。
*编译
*g++-o fbwrite_video-lopencv_core-lopencv_highgui-lopencv_imgproc fbwrite_video.cpp
*
*包含来自的代码https://stackoverflow.com/questions/4722301/writing-to-frame-buffer
*/
#包含//用于std::cerr
#包含//用于cv::cvtColor
#包含//用于cv::VideoCapture
#包含//用于流的std::of
#包括//用于boost::timer::cpu\u timer
//这是C:/
#包括//用于uint32\u t
#包含//用于ioctl
#包括//fb_
#包括//用于O_RDWR
结构帧缓冲区信息{
每像素uint32位;uint32虚拟;
};
结构帧缓冲区信息获取帧缓冲区信息(常量字符*帧缓冲区设备路径){
结构帧缓冲区信息;
结构fb_变量屏幕信息屏幕信息;
int-fd=-1;
fd=打开(帧缓冲区\设备\路径,O \ RDWR);
如果(fd>=0){
如果(!ioctl(fd、FBIOGET、VSCREENINFO和屏幕信息)){
info.xres\u virtual=屏幕\u info.xres\u virtual;
info.bits\u per_pixel=屏幕信息。bits\u per_pixel;
}
}
退货信息;
};
//C到此结束
int main(int,char**){
const int frame_width=320;
const int frame_height=240;
const int frame_rate=10;
framebuffer_info fb_info=get_framebuffer_info(“/dev/fb0”);
cv::视频捕获上限(0);
如果(!cap.isOpened()){

你为什么要写帧缓冲区?我有一个嵌入式板,有一个最小的Linux映像-没有桌面等。我有一个USB DisplayLink监视器连接。最终我想做一些视频处理,但现在我只是尝试显示来自网络摄像头的图像。如果你有更好的方法,我愿意接受新的ideasW更好的方法是在内核中使用DRM吗?不,最好转移到高级抽象。这是一种过度概括吗?对于像运行Raspian的Raspberry Pi这样没有桌面的嵌入式系统(例如没有X11),有什么理由推荐使用这种方法吗或者竞争者,对于一个专用的应用程序…只有一个图形设备?这肯定是个例外?在这种情况下,我为什么想要抽象的开销?
/**
 * @file fbwrite_video.cpp
 * Displays OpenCV video on framebuffer.
 * Compile with
 * g++ -o fbwrite_video -lopencv_core -lopencv_highgui -lopencv_imgproc fbwrite_video.cpp
 *
 * Contains code from https://stackoverflow.com/questions/4722301/writing-to-frame-buffer
 */

#include <iostream> // for std::cerr
#include <opencv2/imgproc/imgproc.hpp>  // for cv::cvtColor
#include <opencv2/highgui/highgui.hpp> // for cv::VideoCapture
#include <fstream> // for std::ofstream
#include <boost/timer/timer.hpp> // for boost::timer::cpu_timer

// this is C :/
#include <stdint.h> // for uint32_t
#include <sys/ioctl.h> // for ioctl
#include <linux/fb.h> // for fb_
#include <fcntl.h> // for O_RDWR
struct framebuffer_info { 
    uint32_t bits_per_pixel; uint32_t xres_virtual; 
};
struct framebuffer_info get_framebuffer_info(const char* framebuffer_device_path) {
    struct framebuffer_info info;
    struct fb_var_screeninfo screen_info;
    int fd = -1;
    fd = open(framebuffer_device_path, O_RDWR);
    if (fd >= 0) {
        if (!ioctl(fd, FBIOGET_VSCREENINFO, &screen_info)) {
            info.xres_virtual = screen_info.xres_virtual;
            info.bits_per_pixel = screen_info.bits_per_pixel;
        }
    }
    return info;
};
// C ends here

int main(int, char**) {
    const int frame_width = 320;
    const int frame_height = 240;
    const int frame_rate = 10;
    framebuffer_info fb_info = get_framebuffer_info("/dev/fb0");
    cv::VideoCapture cap(0);
    if(!cap.isOpened()) {
        std::cerr << "Could not open video device." << std::endl;
        return 1;
    } else {
        std::cout << "Successfully opened video device." << std::endl;
        cap.set(CV_CAP_PROP_FRAME_WIDTH,frame_width);
        cap.set(CV_CAP_PROP_FRAME_HEIGHT,frame_height);
        cap.set(CV_CAP_PROP_FPS,frame_rate);
        std::ofstream ofs("/dev/fb0");
        cv::Mat frame;
        while (true) {
            cap >> frame;
            if (frame.depth() != CV_8U) {
                std::cerr << "Not 8 bits per pixel and channel." << std::endl;
            } else if (frame.channels() != 3) {
                std::cerr << "Not 3 channels." << std::endl;
            } else {
                // 3 Channels (assumed BGR), 8 Bit per Pixel and Channel
                int framebuffer_width = fb_info.xres_virtual;
                int framebuffer_depth = fb_info.bits_per_pixel;
                cv::Size2f frame_size = frame.size();
                cv::Mat framebuffer_compat;
                switch (framebuffer_depth) {
                    case 16:
                        cv::cvtColor(frame, framebuffer_compat, cv::COLOR_BGR2BGR565);
                        for (int y = 0; y < frame_size.height ; y++) {
                            ofs.seekp(y*framebuffer_width*2);
                            ofs.write(reinterpret_cast<char*>(framebuffer_compat.ptr(y)),frame_size.width*2);
                        }
                    break;
                    case 32: {
                            std::vector<cv::Mat> split_bgr;
                            cv::split(frame, split_bgr);
                            split_bgr.push_back(cv::Mat(frame_size,CV_8UC1,cv::Scalar(255)));
                            cv::merge(split_bgr, framebuffer_compat);
                            for (int y = 0; y < frame_size.height ; y++) {
                                ofs.seekp(y*framebuffer_width*4);
                                ofs.write(reinterpret_cast<char*>(framebuffer_compat.ptr(y)),frame_size.width*4);
                            }
                        } break;
                    default:
                        std::cerr << "Unsupported depth of framebuffer." << std::endl;
                }
            }
        }
    }
}