From 835d509da5331b335c5f9e87a0937d486f600445 Mon Sep 17 00:00:00 2001 From: mattmcw Date: Thu, 28 Dec 2023 22:19:10 -0500 Subject: [PATCH] Add current project. Compiles and runs on raspberry pi. Doesn't on ubuntu box (mismatch of opencv versions) --- .gitignore | 3 ++ CMakeLists.txt | 17 +++++++ compile.sh | 9 ++++ opencv_fb.cpp | 120 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 149 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 compile.sh create mode 100644 opencv_fb.cpp diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2bd3664 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +build +bin +cmake-modules \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..b238907 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.1) +PROJECT (opencv_fb) + +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules) + +find_package(OpenCV HINTS /usr/local/opt/opencv /usr/local/Cellar/opencv REQUIRED) + +set( NAME_SRC + opencv_fb.cpp +) + +INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}/include ) +link_directories( ${CMAKE_BINARY_DIR}/bin) +set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin) +add_executable( opencv_fb ${NAME_SRC} ${NAME_HEADERS} ) + +target_link_libraries( opencv_fb ${OpenCV_LIBS} ) \ No newline at end of file diff --git a/compile.sh b/compile.sh new file mode 100644 index 0000000..d018adb --- /dev/null +++ b/compile.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +#mkdir -p bin +#g++ -o bin/opencv_fb -lopencv_core -lopencv_highgui -lopencv_imgproc opencv_fb.cpp + +mkdir -p build +cd build +cmake .. +make -j \ No newline at end of file diff --git a/opencv_fb.cpp b/opencv_fb.cpp new file mode 100644 index 0000000..0dad5a2 --- /dev/null +++ b/opencv_fb.cpp @@ -0,0 +1,120 @@ +/** + * @file opencv_fb.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 // for cerr +#include // for cvtColor +#include // for VideoCapture +#include // for ofstream +#include // for boost::timer::cpu_timer + +using namespace std; +using namespace cv; + +// this is C :/ +#include // for uint32_t +#include // for ioctl +#include // for fb_ +#include // for O_RDWR + +struct framebuffer_info { + uint32_t bits_per_pixel; + uint32_t xres_virtual; + uint32_t yres_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.yres_virtual = screen_info.yres_virtual; + info.bits_per_pixel = screen_info.bits_per_pixel; + } + } + return info; +}; +// C ends here + +void display (Mat frame, framebuffer_info fb_info, ofstream& ofs) { + if (frame.depth() != CV_8U) { + cerr << "Not 8 bits per pixel and channel." << endl; + } else if (frame.channels() != 3) { + cerr << "Not 3 channels." << 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; + Size2f frame_size = frame.size(); + Mat framebuffer_compat; + switch (framebuffer_depth) { + case 16: + cvtColor(frame, framebuffer_compat, COLOR_BGR2BGR565); + for (int y = 0; y < frame_size.height ; y++) { + ofs.seekp(y*framebuffer_width*2); + ofs.write(reinterpret_cast(framebuffer_compat.ptr(y)),frame_size.width*2); + } + break; + case 32: { + vector split_bgr; + split(frame, split_bgr); + split_bgr.push_back(Mat(frame_size,CV_8UC1,Scalar(255))); + merge(split_bgr, framebuffer_compat); + for (int y = 0; y < frame_size.height ; y++) { + ofs.seekp(y*framebuffer_width*4); + ofs.write(reinterpret_cast(framebuffer_compat.ptr(y)),frame_size.width*4); + } + } break; + default: + cerr << "Unsupported depth of framebuffer." << endl; + } + } +} + +Mat frameEffects (Mat frame) { + Mat grey; + Mat contrast; + Mat blur; + Mat flipper; + //flip(frame, flipper, 1); + //cvtColor(flipper, grey, COLOR_BGR2GRAY); + //grey.convertTo(contrast, -1, 1, 0); + //cvtColor(contrast, frame, COLOR_GRAY2BGR); + return frame; +} + +int main(int, char**) { + const int frame_rate = 24; + int frameCount = 0; + framebuffer_info fb_info = get_framebuffer_info("/dev/fb0"); + VideoCapture cap(0); + if(!cap.isOpened()) { + cerr << "Could not open video device." << endl; + return 1; + } else { + cout << "Successfully opened video device." << endl; + cap.set(CAP_PROP_FRAME_WIDTH, 1280); + cap.set(CAP_PROP_FRAME_HEIGHT, 720); + cap.set(CAP_PROP_FPS, frame_rate); + //cap.set(CAP_PROP_BUFFERSIZE,3); + cout << cap.get(CAP_PROP_FRAME_WIDTH) << "x" << cap.get(CAP_PROP_FRAME_HEIGHT) << endl; + ofstream ofs("/dev/fb0"); + Mat frame; + Mat displayFrame; + while (true) { + cap >> frame; + frame = frameEffects(frame); + resize(frame, displayFrame, Size(fb_info.xres_virtual, fb_info.yres_virtual), 2, 2, INTER_CUBIC); + display(displayFrame, fb_info, ofs); + waitKey(42); + } + } +}