Video++, a C++14 high performance video and image processing library.

Overview

Travis build status

Video++

Video++ is a video and image processing library taking advantage of the C++14 standard to ease the writing of fast video and image processing applications. The idea behind Video++ performance is to generate via meta-programming code that the compiler can easily optimize. Its main features are:

  • Generic N-dimensional image containers.
  • A growing set of image processing algorithms.
  • Zero-cost abstractions to easily write image processing algorithms for multicore SIMD processors.
  • An embedded language to evaluate image expressions.

Tested compilers: G++6, Clang++ 3.8.0 Dependencies:

Video++ is free of use (BSD). If you you are using Video++ in research related work, you are welcome to cite us :

@inproceedings{garrigues2014video++,
  title={Video++, a modern image and video processing C++ framework},
  author={Garrigues, Matthieu and Manzanera, Antoine},
  booktitle={Design and Architectures for Signal and Image Processing (DASIP), 2014 Conference on},
  pages={1--6},
  year={2014},
  organization={IEEE}
}

Getting Started

Installation

Before installing Video++, you need to get Eigen3 and Boost on your system. Your package managers will probably help you to install these libraries. Then, use the install.sh script to install iod and vpp :

git clone https://github.com/matt-42/vpp.git
cd vpp
./install.sh your_install_prefix # Install iod and vpp in a given prefix

Video++ is a header-only library, so you just need include the vpp.hh header to access all the basic features of the library:

#include <vpp/vpp.hh>

If you use the parallel constructs of Video++ and need to target multiple cores, activate the OpenMP optimizations:

g++ -I __your_isntall_prefix__ main.cc -fopenmp -lgomp

Image Containers

The generic container imageNd<V, N> represents a dense N-dimensional rectangle set of pixels with values of type V. For convenience, image1d, image2d, image3d are respectively aliases to imageNd<V, 1>, imageNd<V, 2>, and imageNd<V, 3>.

// Allocates a 100 rows x 200 columns 2d image of integers.
image2d<int> A(100, 200);

These types provide accesses to the pixel buffer and to other piece of information useful to process the image. In contrast to std::vector, assigning an image to the other does not copy the data, but share them so no accidental expensive deep copy happen.

image2d<int> B = A; // B now points to A's data.

Image options

_border and _aligned

Image constructors also take special image options. _border (default: 0) set the border surrounding the pixels so filter accessing neighborhood access to valid pixels when traversing image borders. _aligned (default: 16 bytes) set the alignment in bytes of the beginning of the first pixel of each row (border excluded) to enable aligned SIMD memory instructions.

// Allocates a 100x100 image with a border of 3 pixels
// and rows aligned on 32 bytes (best for 256 bits SIMD
// units like AVX2).
image2d<int> C(100, 100, _border = 3, _aligned = 32);

_data and _pitch

To use image buffers allocated by external libraries, the _data and _pitch options respectively pass the pointer to the first pixel of the image and the distance in bytes between the first pixels of two consecutive rows. When setting these options, video++ is not responsible of freeing the data buffer.

// Wraps an external images of 100x100 pixels, with a pitch
// of 1000 bytes.
image2d<int> C(100, 100, _data = my_data_ptr, _pitch = 1000);

OpenCV interoperability

The header vpp/utils/opencv_bridge.hh (not included by vpp/vpp.hh) provides explicit conversions to and from OpenCV image types. It allows running video++ algorithms on OpenCV images and to run OpenCV algorithms on video++ images, without cloning the pixel buffer. Ownership of the buffer will switch to OpenCV or Video++ depending of the order of the destructor calls.

// Load JPG image in a vpp image using OpenCV imread.
image2d<vuchar3> img = from_opencv<vuchar3>(cv::imread("image.jpg"));

// Write a vpp image using OpenCV imwrite.
cv::imwrite("in.jpg", to_opencv(img));

Note: Since it is not possible to opencv to free video++ images, an OpenCV image must not be the last one to hold a video++ image.

Vector Types

Video++ vector types are aliases to eigen3 vectors, providing fast linear algebra. The syntax is v{T}{N} such as

  • T is one the following : char, short, int, float, double, uchar, ushort, uint.
  • N is an integer in [0, 4].

For example, the type image2d<vuchar4> can handle an image of RGBA 8-bit.

Pixel Wise Kernels

The pixel_wise construct allows to easily and efficiently map simple kernel functions on all the pixels of a set of images. It relies on OpenMP to spread the processing on all the available cores, and SIMD-vectorize the processing of rows when possible. If the kernel function returns a value, pixel_wise will return a newly allocated image filled with the results of the kernel. Given A and B two 2d images of integers:

// Compute C, the parallel pixel wise sum of A and B.
auto C = pixel_wise(A, B) | [] (int& a, int& b) { return a + b; };

// Compute the average of the c4 neighborhood.
pixel_wise(relative_access(A), B) | [] (auto a, int& b) {
  b = (a(-1, 0) + a(1, 0) + a(0, 1) + a(0, -1)) / 4;
};

Kernel arguments

Given pixel_wise(I_0, ..., I_N) | my_kernel, pixel_wise will traverse the domain of I_0 and for every pixel location P call my_kernel(I_0(P), ..., I_N(P)) with I_N(P) a reference to the pixel of I_N located at location P.

Parallelism and traversal directions

By default, pixel_wise traverses the image from left to right and top to bottom and spread the processing of different row on different cores. The following options allow to change this defaut behavior:

  • _no_thread: disable the parallelism.

  • _left_to_right: Traverse each row from left to right.

  • _right_to_left: Traverse each row from right to left.

  • _top_to_bottom: Traverse the rows from top to bottom.

  • _bottom_to_top: Traverse the rows from bottom to top.

Accessing Neighborhood

Video++ provides fast access to rectangular pixel neighbors inside pixel_wise kernels. The speed of access mainly comes from the direct 2d indexing of the neighborhood, and the ability of the compiler to vectorize these accesses using SIMD vector extensions. To stay portable, no explicit SIMD optimization is done by video++. On the other hand, the generated code was designed to be trivial for the compiler to vectorize if the kernel does not contain conditional branching.

The accesses are expressed in relative coordinates. For example, nbh(1,1) accesses the bottom right neighbor of the current pixel, and nbh(0,0) refers to the current pixel.

// Define a 3x3 neighborhood accessor on image B.
// Note that for performance reasons, the boundaries
// of the neighborhood are static.

pixel_wise(S, relative_access(B)) | [&] (auto& s, auto b) {

  // Average the pixels in the c4 neighborhood.
  s = (b(-1,0) + b(0, -1) +
      b(1,0) + b(0,1)) / 4;
};

Block Wise Kernels

Theblock_wise construct allows to map a function on every cell of a given grid. This construct is similar to pixel_wise, but instead of processing one pixel, the block_wise kernel processes a given cell.

// Given a grid with cell of size 10x10 pixels.
block_wise(vint2{10, 10}, A, B, C, A.domain()) |
  [] (auto a, auto b, auto c, box2d box)
  {
  
    // a, b and c are sub images representing A, B
    // and C at the current cell.
    // All the algorithms of the library work on sub images.

    // The box argument is the cell representation of A.domain() and holds
    // the coordinates of the current cell. box.p1() and box.p2() are
    // respectively the first and the last pixel of the cell.
};

Row Wise and Col Wise Kernels

row_wise and col_wise are shortcuts to process the image by row or by column. For example, the following compute row wise sums of a given image:

std::vector<int> sums(A.nrows(), 0);
row_wise(A, A.domain()) | [] (auto& a, vint2 coord)
{
  sums[coord[0]] += a;
};

Contributing

Contributions are welcome. Do not hesitate to fill issues, send pull requests, or send me emails at [email protected].

Comments
  • make: *** No rule to make target `ins'.  Stop.

    make: *** No rule to make target `ins'. Stop.

    $ ./install.sh ins Cloning into 'iod'... remote: Counting objects: 1086, done. remote: Total 1086 (delta 0), reused 0 (delta 0), pack-reused 1086 Receiving objects: 100% (1086/1086), 353.14 KiB | 249.00 KiB/s, done. Resolving deltas: 100% (737/737), done. -- Building for: Visual Studio 15 2017 -- The C compiler identification is MSVC 19.10.25019.0 -- The CXX compiler identification is MSVC 19.10.25019.0 -- Check for working C compiler: E:/Program Files (x86)/Microsoft Visual Studio/2017/Professional/VC/Tools/MSVC/14.10.25017/bin/HostX86/x86/cl.exe -- Check for working C compiler: E:/Program Files (x86)/Microsoft Visual Studio/2017/Professional/VC/Tools/MSVC/14.10.25017/bin/HostX86/x86/cl.exe -- works -- Detecting C compiler ABI info -- Detecting C compiler ABI info - done -- Check for working CXX compiler: E:/Program Files (x86)/Microsoft Visual Studio/2017/Professional/VC/Tools/MSVC/14.10.25017/bin/HostX86/x86/cl.exe -- Check for working CXX compiler: E:/Program Files (x86)/Microsoft Visual Studio/2017/Professional/VC/Tools/MSVC/14.10.25017/bin/HostX86/x86/cl.exe -- works -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Detecting CXX compile features -- Detecting CXX compile features - done -- Boost version: 1.64.0 -- Configuring done -- Generating done CMake Warning: Manually-specified variables were not used by the project:

    IOD_INCLUDE_DIR
    

    -- Build files have been written to: C:/MyLibs/CloneByGit/vpp/externals/iod/vpp_build make: *** No rule to make target `ins'. Stop. Cannot install /c/MyLibs/CloneByGit/vpp/externals/iod/vpp_build.

    What's the problem ? PS : windows 10.

    opened by mbenmahdjoub 5
  • Video Extruder Performance

    Video Extruder Performance

    Hi,

    Again fantastic library! I was wondering what kind of performance you were getting on the video extruder. I modified the example to use a live camera and it runs at like 1 frame a second. Any thoughts on why. It seems the draw_trajectories and video_extruder_update take a while. Any thoughts on how to speed this up?

    Thanks again!

    opened by pducks32 2
  • Problem Building Examples

    Problem Building Examples

    Hi, great library but I haven't been able to build the examples I keep getting this error on my macOS Sierra, clang, MacBook pro.

    error: use of undeclared identifier 'box_nbh2d' auto nbh = box_nbh2d<vuchar3, 3, 3>(img);

    Any help would be great. Thanks!

    opened by pducks32 2
  • Conan package for VPP

    Conan package for VPP

    Hello, Do you know about Conan? Conan is modern dependency manager for C++. And will be great if your library will be available via package manager for other developers.

    Here you can find example, how you can create package for the library.

    If you have any questions, just ask :-)

    opened by zamazan4ik 0
  • Error while installng vpp while running the command

    Error while installng vpp while running the command "./install.sh vpp"

    Hello,

    I am new to c++14 and I am trying to install vpp by executing the command

    "./install.sh vpp"

    But it gives me following error.

    tests/CMakeFiles/fill.dir/build.make:62: recipe for target 'tests/CMakeFiles/fill.dir/fill.cc.o' failed make[2]: *** [tests/CMakeFiles/fill.dir/fill.cc.o] Error 1 CMakeFiles/Makefile2:271: recipe for target 'tests/CMakeFiles/fill.dir/all' failed make[1]: *** [tests/CMakeFiles/fill.dir/all] Error 2 Makefile:138: recipe for target 'all' failed make: *** [all] Error 2 Cannot install /home/bhushan/vpp/vpp_build.

    I am using ubuntu 16.04 on Virtual box.

    "gcc --version" gives me below output.

    --gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609

    Please, let me know about it.

    Thank you.

    opened by muthiyanbhushan 2
  • Examples do not build with gcc version 4.9.2

    Examples do not build with gcc version 4.9.2

    Tried -std=c++14 and it still gives errors like this

    /home/markit/vpp/examples/../vpp/core/pixel_wise.hpp: In instantiation of ‘auto vpp::pixel_wise_impl<OPTS, Params>::make_orders() [with OPTS = iod::sio<>; Params = {vpp::imageNd<Eigen::Matrix<unsigned char, 4, 1, 0, 4, 1>, 2u>&}]’:
    /home/markit/vpp/examples/../vpp/core/pixel_wise.hpp:154:33:   required from ‘auto vpp::pixel_wise_impl<OPTS, Params>::run(F, std::index_sequence<I ...>) [with F = paint(std::vector<vpp::keypoint_trajectory>&, vpp::image2d<Eigen::Matrix<unsigned char, 4, 1, 0, 4, 1> >&)::<lambda(vpp::vuchar4&)>; long unsigned int ...I = {0ul}; OPTS = iod::sio<>; Params = {vpp::imageNd<Eigen::Matrix<unsigned char, 4, 1, 0, 4, 1>, 2u>&}; std::index_sequence<I ...> = std::integer_sequence<long unsigned int, 0ul>]’
    /home/markit/vpp/examples/../vpp/core/pixel_wise.hpp:193:30:   required from ‘vpp::pixel_wise_impl<OPTS, Params>::operator|(F)::<lambda(auto:37)> [with auto:37 = paint(std::vector<vpp::keypoint_trajectory>&, vpp::image2d<Eigen::Matrix<unsigned char, 4, 1, 0, 4, 1> >&)::<lambda(vpp::vuchar4&)>; F = paint(std::vector<vpp::keypoint_trajectory>&, vpp::image2d<Eigen::Matrix<unsigned char, 4, 1, 0, 4, 1> >&)::<lambda(vpp::vuchar4&)>; OPTS = iod::sio<>; Params = {vpp::imageNd<Eigen::Matrix<unsigned char, 4, 1, 0, 4, 1>, 2u>&}]’
    /home/markit/vpp/externals/iod/iod/utils.hh:14:43:   required from ‘decltype(auto) iod::static_if_<true>::operator()(F, G, A&& ...) [with F = vpp::pixel_wise_impl<OPTS, Params>::operator|(F) [with F = paint(std::vector<vpp::keypoint_trajectory>&, vpp::image2d<Eigen::Matrix<unsigned char, 4, 1, 0, 4, 1> >&)::<lambda(vpp::vuchar4&)>; OPTS = iod::sio<>; Params = {vpp::imageNd<Eigen::Matrix<unsigned char, 4, 1, 0, 4, 1>, 2u>&}]::<lambda(auto:37)>; G = vpp::pixel_wise_impl<OPTS, Params>::operator|(F) [with F = paint(std::vector<vpp::keypoint_trajectory>&, vpp::image2d<Eigen::Matrix<unsigned char, 4, 1, 0, 4, 1> >&)::<lambda(vpp::vuchar4&)>; OPTS = iod::sio<>; Params = {vpp::imageNd<Eigen::Matrix<unsigned char, 4, 1, 0, 4, 1>, 2u>&}]::<lambda(auto:38)>; A = {paint(std::vector<vpp::keypoint_trajectory>&, vpp::image2d<Eigen::Matrix<unsigned char, 4, 1, 0, 4, 1> >&)::<lambda(vpp::vuchar4&)>&}]’
    /home/markit/vpp/externals/iod/iod/utils.hh:31:64:   required from ‘decltype(auto) iod::static_if(F, G, A&& ...) [with bool C = true; F = vpp::pixel_wise_impl<OPTS, Params>::operator|(F) [with F = paint(std::vector<vpp::keypoint_trajectory>&, vpp::image2d<Eigen::Matrix<unsigned char, 4, 1, 0, 4, 1> >&)::<lambda(vpp::vuchar4&)>; OPTS = iod::sio<>; Params = {vpp::imageNd<Eigen::Matrix<unsigned char, 4, 1, 0, 4, 1>, 2u>&}]::<lambda(auto:37)>; G = vpp::pixel_wise_impl<OPTS, Params>::operator|(F) [with F = paint(std::vector<vpp::keypoint_trajectory>&, vpp::image2d<Eigen::Matrix<unsigned char, 4, 1, 0, 4, 1> >&)::<lambda(vpp::vuchar4&)>; OPTS = iod::sio<>; Params = {vpp::imageNd<Eigen::Matrix<unsigned char, 4, 1, 0, 4, 1>, 2u>&}]::<lambda(auto:38)>; A = {paint(std::vector<vpp::keypoint_trajectory>&, vpp::image2d<Eigen::Matrix<unsigned char, 4, 1, 0, 4, 1> >&)::<lambda(vpp::vuchar4&)>&}]’
    /home/markit/vpp/examples/../vpp/core/pixel_wise.hpp:212:13:   required from ‘auto vpp::pixel_wise_impl<OPTS, Params>::operator|(F) [with F = paint(std::vector<vpp::keypoint_trajectory>&, vpp::image2d<Eigen::Matrix<unsigned char, 4, 1, 0, 4, 1> >&)::<lambda(vpp::vuchar4&)>; OPTS = iod::sio<>; Params = {vpp::imageNd<Eigen::Matrix<unsigned char, 4, 1, 0, 4, 1>, 2u>&}]’
    /home/markit/vpp/examples/video_extruder_paint.cc:25:3:   required from here
    /home/markit/vpp/examples/../vpp/core/pixel_wise.hpp:143:44: error: use of ‘template<class ... T> auto iod::D(T&& ...)’ before deduction of ‘auto’
               [] () { return _left_to_right; }));
    
    
    opened by seken 0
  • Bridges for other imaging I/O systems

    Bridges for other imaging I/O systems

    E.g. CImg.h[0], mahotas-imread[1], ffmpeg[2], etc. Maybe even Apple ImageIO (or its Windows equivalent)?

    I would personally be interested in making such contributions if there was any interest!

    [0] http://cimg.sourceforge.net/download.shtml [1] https://github.com/luispedro/imread – a python module, but with a C++ I/O backend [2] https://www.ffmpeg.org

    opened by fish2000 3
Releases(v0.1-alpha)
Video, Image and GIF upscale/enlarge(Super-Resolution) and Video frame interpolation. Achieved with Waifu2x, SRMD, RealSR, Anime4K, RIFE, CAIN, DAIN and ACNet.

Video, Image and GIF upscale/enlarge(Super-Resolution) and Video frame interpolation. Achieved with Waifu2x, SRMD, RealSR, Anime4K, RIFE, CAIN, DAIN and ACNet.

Aaron Feng 8.7k Jan 7, 2023
C++ image processing and machine learning library with using of SIMD: SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX-512, VMX(Altivec) and VSX(Power7), NEON for ARM.

Introduction The Simd Library is a free open source image processing and machine learning library, designed for C and C++ programmers. It provides man

Ihar Yermalayeu 1.7k Jan 5, 2023
The CImg Library is a small and open-source C++ toolkit for image processing

http://cimg.eu The CImg Library is a small and open-source C++ toolkit for image processing, designed with these properties in mind: CImg defines clas

David Tschumperlé 1.2k Jan 3, 2023
A fast image processing library with low memory needs.

libvips : an image processing library Introduction libvips is a demand-driven, horizontally threaded image processing library. Compared to similar lib

libvips 26 Nov 10, 2022
GLSL Image Processing System

GIPS: The GLSL Image Processing System An image processing application that applies filters written in the OpenGL Shading Language (GLSL). This means

Martin Fiedler 57 Nov 29, 2022
PoC black/white image sequence to dumpy gif image sequence converter

PoC black/white image sequence to dumpy gif image sequence converter

null 69 Dec 9, 2022
The “Quite OK Image” format for fast, lossless image compression

The “Quite OK Image” format for fast, lossless image compression

Dominic Szablewski 6k Dec 30, 2022
HDRView is a simple research-oriented image viewer with an emphasis on examining and comparing high-dynamic range (HDR) images

HDRView is a simple research-oriented high-dynamic range image viewer with an emphasis on examining and comparing images, and including minimalistic tonemapping capabilities. HDRView currently supports reading EXR, PNG, TGA, BMP, HDR, JPG, GIF, PNM, PFM, and PSD images and writing EXR, HDR, PNG, TGA, PPM, PFM, and BMP images.

Wojciech Jarosz 177 Jan 5, 2023
Qt5 image viewer with optional video support

Qt5 image viewer with optional video support

null 1.5k Jan 1, 2023
This library provides a cross-platform image loading library in C11 for projects based on our foundation library

Image Library - Public Domain This library provides a cross-platform image loading library in C11 for projects based on our foundation library.

Mattias Jansson 1 Jan 29, 2022
Reading, writing, and processing images in a wide variety of file formats, using a format-agnostic API, aimed at VFX applications.

README for OpenImageIO Introduction The primary target audience for OIIO is VFX studios and developers of tools such as renderers, compositors, viewer

OpenImageIO 1.6k Jan 2, 2023
a generic C++ library for image analysis

VIGRA Computer Vision Library Copyright 1998-2013 by Ullrich Koethe This file is part of the VIGRA computer vision library. You may use,

Ullrich Koethe 378 Dec 30, 2022
Intel® Open Image Denoise library

Intel Open Image Denoise is an open source library of high-performance, high-quality denoising filters for images rendered with ray tracing

Intel® Open Image Denoise 1.3k Dec 28, 2022
Arduino PNG image decoder library

An 'embedded-friendly' (aka Arduino) PNG image decoding library

Larry Bank 102 Jan 6, 2023
libvot - A C++11 multi-thread library for image retrieval

libvot is a fast implementation of vocabulary tree, which is an algorithm widely used in image retrieval and computer vision. It usually comprises three components to build a image retrieval system using vocabulary tree: build a k-means tree using sift descriptors from images, register images into the database, query images against the database. I

Tianwei Shen 174 Dec 22, 2022
An 'embedded-friendly' (aka Arduino) JPEG image encoding library

Starting in the late 80's I wrote my own imaging codecs for the existing standards (CCITT G3/G4 was the first). I soon added GIF, JPEG and not long after that, the PNG specification was ratified. All of this code was "clean room" - written just from the specification. I used my imaging library in many projects and products over the years and recently decided that some of my codecs could get a new lease on life as open source, embedded-friendly libraries for microcontrollers.

Larry Bank 38 Dec 30, 2022
Small header-only C library to decompress any BC compressed image

Small header-only C library to decompress any BC compressed image

null 92 Jan 1, 2023
An image and texture viewer for tga, png, apng, exr, dds, gif, hdr, jpg, tif, ico, webp, and bmp files

An image and texture viewer for tga, png, apng, exr, dds, gif, hdr, jpg, tif, ico, webp, and bmp files. Uses Dear ImGui, OpenGL, and Tacent. Useful for game devs as it displays information like the presence of an alpha channel and querying specific pixels for their colour.

Tristan Grimmer 159 Dec 31, 2022