Using GigE Cameras with
Aravis | OpenCV | Gstreamer [UPDATED]

Configuring Imaging Source GigE Cameras on Ubuntu 14.04 / Linux using Aravis, and OpenCV (Updated with Python-Aravis)

I have written a wrapper for using Aravis with OpenCV’s IplImage or Mat type. Check it out here https://github.com/kushalvyas/Aravis-OpenCV-Wrapper

So I’m working on this awesome vision project and I’m using the Imaging Source’s DML 33GR0134 camera which is POE ! (powered over ethernet). This is cool!. Still I’m using the 12V supply rather than the 48V. Anyway, here’s a tutorial on how to configure these camera for ubuntu. Imaging Source gives Windows softwares and have provided a github repository as well.

https://github.com/TheImagingSource/tiscamera

Here you go!

Now Ill move on to the article. I’ll start with setting up the above repository, followed by tutorials on aravis, and lastly using opencv with it.

Thing covered:

  1. Setting up tiscamera (Imaging Source Module)
  2. Setting up Aravis (Utility for GigE cameras)
  3. Using Aravis : arv.h
  4. Opencv with Aravis

im3

The camera is a GigE camera ; meaning Gigabit Ethernet Camera. GigE Vision as described on Wiki, is an industrial standard for high performance camera. You can connect multiple cameras over ethernet networks. One of the manufacturers is Imaging Source.

Lets proceed

TISCAMERA

This is the The Imaging Source Linux Repository and it has multiple elements such as

  1. gstreamer elements
  2. gobject introspection
  3. uvc extensions
  4. firmware update tools
  5. examples on how to interact with your camera

Installing TISCAMERA

All of it is mentioned on the repository’s README. I’m just rewriting it here. these instructions are simply copied from their README.

Firstly, for TISCAMERA , we will need to download the following packages

    git cmake pkg-config libudev-dev libtinyxml-dev libgstreamer1.0-dev libglib2.0-dev libgirepository1.0-dev libusb-1.0-0-dev libzip-dev python-setuptools libxml2-dev libaudit-dev libpcap-dev libnotify-dev

you can simply do sudo apt-get install followed by the above list. If some of the packages are unable to get located, just google search with the packages’ name, and you’ll get the alternative.

For Ubuntu 14.04, you can just wrap it up in

    # Build dependencies
    sudo apt-get install git g++ cmake pkg-config libudev-dev libudev1 libtinyxml-dev libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libglib2.0-dev libgirepository1.0-dev libusb-1.0-0-dev libzip-dev uvcdynctrl python-setuptools libxml2-dev libpcap-dev libaudit-dev libnotify-dev autoconf intltool gtk-doc-tools

    # Runtime dependencies
    sudo apt-get install gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly libxml2 libpcap0.8 libaudit1 libnotify4


Building TISCAMERA

First , clone the repository

    git clone --recursive https://github.com/TheImagingSource/tiscamera.git
    cd tiscamera
    mkdir build
    cd build


Now, we want to build with ARAVIS, because GigE camera’s use ARAVIS. Hence,

    # With ARAVIS:
    cmake -DBUILD_ARAVIS=ON -DBUILD_GST_1_0=ON -DBUILD_TOOLS=ON -DBUILD_V4L2=ON -DCMAKE_INSTALL_PREFIX=/usr ..
    # Without ARAVIS
    cmake -DBUILD_ARAVIS=OFF -DBUILD_GST_1_0=ON -DBUILD_TOOLS=ON -DBUILD_V4L2=ON -DCMAKE_INSTALL_PREFIX=/usr ..

    make
    sudo make install

And that’s all. You have finished installing TISCAMERA and ARAVIS together.


Running the gige-daemon on TISCAMERA

The gige-daemon is a daemon process to check the incoming of the gige camera. Once your TISCAMERA has been installed, goto build/tools/gige-daemon where you can run this process.

    <path_to_tiscamera>/build/tools/gige-daemon/./gige-daemon start  # this starts the daemon



Configuring a GigE camera for tiscamera:

This is W.R.T Imaging Source GigE camera (please check their documentation for more options). We will setup a static IP address over the Ethernet port.

img_network


Only after doing this, will you be able to even detect the camera


Building ARAVIS (if you have already not done it with TISCAMERA)

Clone the repository from https://github.com/AravisProject/aravis

Run ./configure (you can check for options by doing ./configure –help) Then run make Eventually make install

And we’re done.

Test it

    arv-tool-<version_number> list

This gives you the connected IP camera

Lastly, add this to your profile / bsarhc / or_where_ever_you store your paths

    #### aravis exports #####
    export GI_TYPELIB_PATH="$GI_TYPELIB_PATH:<path to aravis>/src"
    export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:<path to aravis>/src/.libs"

Building ARAVIS with OpenCV

This is also as small as the above installation.

  1. Clone the repository at https://github.com/opencv/opencv. OpenCV has ARAVIS support from version 3.2. You can look at the Changelog (thanks to @ArkadiuszRaj)
  2. cd <opencv_source_path>
  3. mkdir build && cd build
  4. Run CMAKE
    cmake -D CMAKE_BUILD_TYPE=RELEASE -D INSTALL_C_EXAMPLES=OFF -D PYTHON_EXECUTABLE=<path_to_python_venv>/aravis_opencv/gige_py/bin/python -D WITH_GSTREAMER=ON  -D WITH_ARAVIS=ON  ..
    

Make sure you have a WITH_ARAVIS=ON flag as your CMAKE parameter

  1. make -j4
  2. sudo make install / make install (if you plan to link and include opencv with every c/c++ program)

Using ARAVIS standalone

/*  TEST SETUP FOR CAMERA  */

    // system and aravis includes
    #include "glib.h"
    #include "arv.h"
    #include <stdlib.h>
    #include <signal.h>
    #include <stdio.h>
    #include <iostream>

    int main(){

        ArvCamera *camera;
        ArvBuffer *buffer;
        std::string filename="test.png";
        camera = arv_camera_new (argc > 1 ? argv[1] : NULL);
        buffer = arv_camera_acquisition (camera, 0);
        if (ARV_IS_BUFFER (buffer)){
            printf ("Image successfully acquired\n");
            arv_save_png(buffer, filename.c_str());
          }
          else{
            printf ("Failed to acquire a single image\n");
           }
        g_clear_object (&camera);
        g_clear_object (&buffer);

        return 0;

    }

To compile use the following G++ Command

g++ -o main  main.cpp -L/usr/lib -L/usr/local/lib -I/home/path_to_installs/gige/utils/aravis/src/ -L/home/path_to_installs/gige/utils/aravis/src/.libs/ -I/usr/include/glib-2.0/ -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -laravis-0.6 -lglib-2.0 -lm -pthread -lgio-2.0 -lgobject-2.0 -lxml2 -lgthread-2.0 -lglib-2.0 -lz -lusb-1.0  -lpng

Using Opencv with ARAVIS

If you open opencv’s video I/O source code, you can find the following lines

aravis_doc

as seen, the flag is CAP_ARAVIS, which has a value of 2100

/*  TEST SETUP FOR CAMERA  */

    // system and aravis includes
    #include "glib.h"
    #include "arv.h"
    #include <stdlib.h>
    #include <signal.h>
    #include <stdio.h>
    #include <iostream>


    // opencv includes
    #include "opencv2/opencv.hpp"


    int main(){

        std::cout << "OpenCV Version : " << CV_VERSION << std::endl ;
        printf("Value of CAP_ARAVIS is %d\n", cv::CAP_ARAVIS);
        cv::VideoCapture cam; // constant for ARAVIS SDK
        cam.open(2100);

        std::cout << "Camera Status : " << cam.isOpened() << std::endl;
        if(!cam.isOpened()){
            printf("Error in opening camera\n");
            return 0;
        }

        cv::namedWindow("frame", 1);
        while(true){
            cv::Mat frame;
            bool ret = cam.read(frame);
            cv::imshow("frame", frame);
            int ch = cv::waitKey(1) & 0xFF; 
            if (ch == 27){
                break;
            }

        }
        cam.release();
        cv::destroyAllWindows();

        return 0;

    }

Converting ARAVIS Packet to OpenCV Mat/ IPLImage

But, there’s is one problem here. There are many places, and even I have personally faced that using VideoCaptures set property methods sometimes don’t yield the desired results. Hence, one can actually set them through Aravis and then use the aravis acquired image through opencv. This is what I’m covering next.

I’ll just use the above code to explain what additions are made

    // system and aravis includes
    #include "glib.h"
    #include "arv.h"
    #include <stdlib.h>
    #include <signal.h>
    #include <stdio.h>
    #include <iostream>

    // my includes
    #include "camera_settings.h"

    // awesome github repo for saving aravis buffers to png
    // check it out at https://github.com/szmoore/aravis-save-png
    #include "save_png.c"

    // opencv includes
    #include "opencv2/opencv.hpp"

    using namespace cv;
    using namespace std;


    int main (int argc, char **argv){
        ArvCamera *camera;
        ArvBuffer *buffer;
        void *framebuffer;
        framebuffer = NULL;
        IplImage *frame;
        frame = NULL;

        camera = arv_camera_new (argc > 1 ? argv[1] : NULL);


        /*
            Here I am setting gain to 5.85 db

         */
        arv_camera_set_gain(camera, 5.85);

        buffer = arv_camera_acquisition (camera, 0);

        if (ARV_IS_BUFFER (buffer)){
            printf ("Image successfully acquired\n");
            printf (" Converting Image to MAT\n");

            IplImage src;

            size_t buffer_size;
            framebuffer = (void*)arv_buffer_get_data (buffer, &buffer_size);

            cvInitImageHeader( &src, cvSize( 1280, 960 ), IPL_DEPTH_8U, 1, IPL_ORIGIN_TL, 4 );
            cvSetData(&src, framebuffer, src.widthStep);
            if ( !frame || frame->width != src.width || \
                frame->height != src.height || \
                frame->depth != src.depth || \
                frame->nChannels != src.nChannels) {
                    cvReleaseImage( &frame );
                    frame = cvCreateImage( cvGetSize(&src), src.depth, 1 );
            }
            cvCopy(&src, frame);    
            cv::Mat m = cv::cvarrToMat(frame);

            imshow("frame", m);
            waitKey();
            destroyAllWindows();


        }
        else{
            printf ("Failed to acquire a single image\n");
        }

        g_clear_object (&camera);
        g_clear_object (&buffer);

        return EXIT_SUCCESS;
        return 0;
    }


In the above code, do check out save_png.c, created by git-@szmoore. This is the repo link : https://github.com/szmoore/aravis-save-png

We’re done with simple connection of camera and single photo capture using Aravis and OpenCv, now’s the time to write a live video preview application. Aravis uses GLIB to manage threading, and handle callbacks. So will we!. We’ll integrate gstreamer, aravis for streaming. Also, feel free to incorporate features like controlling camera properties using a GUI/much like ARAVIS Viewer.

Just an FYI, there are some of the properties one can set using a DMK[A-Za-z0-9]+ camera (yea.. that was regexp :P).

  1. arv_camera_set_region()
  2. arv_camera_set_binning()
  3. arv_camera_set_pixel_format()
  4. arv_camera_set_acquisition_mode()
  5. arv_camera_set_frame_count()
  6. arv_camera_set_frame_rate()
  7. and many more

Check out the docs here. there’s a big list of such implementations that will help make the best use of the camera.

It’s just amazing to use Glib. (it’s my first time with using glib)

I’m shifting systems from Ubuntu to Debian. So till then enjoy. Also, Big thanks to THE ARAVIS PROJECT for making our lives easy :)

UPDATED WITH PYTHON-ARARVIS

So aravis has beautiful python bindings, making my job a lot lot easier (atleast in the prototyping phase. However, I’ll have to write in bare bones C for deployment on DebianRT. Can’t use python everywhere :P ). Hence I’ll just illustrate a short example on capturing frames with aravis in Python.

Now, you can connect a real camera to the ehternet card, or use the ARV-FAKE-GV-CAM, with the command arv-fake-gv-camera-0.6.

    kushal@kushal:~/kushalvyas.github.io$ arv-fake-gv-camera-0.6

    And to see the output, use the arv-tool

    kushal@kushal:~/kushalvyas.github.io$ arv-tool-0.6 
    >>> Aravis-GV01 (127.0.0.1)


I’m assuming that the reader has already “build and make” Aravis, so the python bindings are already generated. Also, the gi-repository in python has been installed.

    # Ararvis python videcapture
    import gi
    gi.require("Aravis", "0.6") # or whatever version number you have installed
    from gi.repository import Aravis

    # other imports
    import cv2
    import ctypes
    import numpy as np


Initializing Aravis, setup Camera, Buffer, and Stream. As seen in the above C code, we had initialized Aravis camera, buffer and stream pointers. We do the same in python.

    #continue code from above

    Aravis.enable_interface("Fake") # using arv-fake-gv-camera-0.6
    camera = Aravis.Camera.new(None)
    stream = camera.create_stream (None, None)

    payload = camera.get_payload ()

    for i in range(0,50):
        stream.push_buffer (Aravis.Buffer.new_allocate (payload))

    def convert(buf):
        ''' explained later '''

Moving on, to video capture.

    #continue code from above

    print "Start acquisition"
    camera.start_acquisition()

    while True:
        buffer = stream.try_pop_buffer()
        print buffer 
        if buffer:
            frame = convert(buffer)
            stream.push_buffer(buffer) #push buffer back into stream

            cv2.imshow("frame", frame)
            ch = cv2.waitKey(1) & 0xFF
            if ch == 27 or ch == ord('q'):
                break
            elif ch == ord('s'):
                cv2.imwrite("imagename.png",frame)


    camera.stop_acquisition()

###################################################################

Output

output


As seen in the above code snippet, I have used a function convert(buffer). This method converts the Aravis buffer to a numpy array. It’s source can be found at the Python-Aravis binding on github: https://github.com/SintefRaufossManufacturing/python-aravis. However i’ll still put it here. All credits goes to https://github.com/SintefRaufossManufacturing/python-aravis for creating it. Plus, they have awesome examples on their repository, so check it out too.

    ''' 
    https://github.com/SintefRaufossManufacturing/python-aravis/blob/master/aravis.py#L181
    '''

    def convert(buf):
        if not buf:
            return None
        pixel_format = buf.get_image_pixel_format()
        bits_per_pixel = pixel_format >> 16 & 0xff
        if bits_per_pixel == 8:
            INTP = ctypes.POINTER(ctypes.c_uint8)
        else:
            INTP = ctypes.POINTER(ctypes.c_uint16)
        addr = buf.get_data()
        ptr = ctypes.cast(addr, INTP)
        im = np.ctypeslib.as_array(ptr, (buf.get_image_height(), buf.get_image_width()))
        im = im.copy()
        return im


Lastly, since I’ll be exploring more of gige cams, using them with Glib / python / opencv / c I’ll keep updating this article continuously with new snippets.

Also, a small trick for OpenCv users. There are many time (even I have faced such) where using the Opencv set property method for VideoCapture objects doesn’t seem to work. One fix that I’ve used is to first use Aravis *camera to set the property as shown above. Then call a g_object_clear(camera), and then call OpenCV’s VideoCapture cam(2100);. The camera inherits the last setting.

UPDATE w: Gstreamer GST-Launch

I’ll list down the Gstreamer command that can launch Aravis supported cameras. So when you build aravis from source, there will be a folder called gstand gst-0.10 being created . This contains the gstreamer plugin for Aravis cameras.

    - aravis root dir
        |   
        | - build ... 
        | - src ... 
        | - gst (gstreamer-1.0 plugin)
        | - gst-0.10 (gstreamer 0.1 plugin)
        | - tools
        | - aravis_viewer ( needs gtk-3+, glib and gobject for compiling)

Firstly, make sure Aravis gstremer directories are added to this environment variable GST_PLUGIN_PATH_1_0 (since I use gst-1.0 ) .

And then run the command :

    gst-launch-1.0 aravissrc camera-name="Aravis-GV01" ! videoconvert ! xvimagesink

The following output is expected

xim

That’s all for now. Enjoy using gige!

References:

[1]. Aravis : https://github.com/AravisProject/aravis

[2]. Save_png.c : https://github.com/szmoore/aravis-save-png

[3]. Python-Aravis Bindings : https://github.com/SintefRaufossManufacturing/python-aravis

[4]. The Imaging Source Linux Repository