Example libdc1394 for capturing stereo images

I intend to create a program that will capture stereo images from a FireWire 1394 Point Gray Bumblebee2 camera. Here is a simple example to grab a color image from libdc1394.

#include <stdio.h>
#include <stdint.h>
#include <dc1394/dc1394.h>
#include <stdlib.h>
#include <inttypes.h>


#define IMAGE_FILE_NAME "ImageRGB.ppm"

/*-----------------------------------------------------------------------
 *  Prints the type of format to standard out
 *-----------------------------------------------------------------------*/
void print_format( uint32_t format )
{
#define print_case(A) case A: printf(#A ""); break;

    switch( format ) {
        print_case(DC1394_VIDEO_MODE_160x120_YUV444);
        print_case(DC1394_VIDEO_MODE_320x240_YUV422);
        print_case(DC1394_VIDEO_MODE_640x480_YUV411);
        print_case(DC1394_VIDEO_MODE_640x480_YUV422);
        print_case(DC1394_VIDEO_MODE_640x480_RGB8);
        print_case(DC1394_VIDEO_MODE_640x480_MONO8);
        print_case(DC1394_VIDEO_MODE_640x480_MONO16);
        print_case(DC1394_VIDEO_MODE_800x600_YUV422);
        print_case(DC1394_VIDEO_MODE_800x600_RGB8);
        print_case(DC1394_VIDEO_MODE_800x600_MONO8);
        print_case(DC1394_VIDEO_MODE_1024x768_YUV422);
        print_case(DC1394_VIDEO_MODE_1024x768_RGB8);
        print_case(DC1394_VIDEO_MODE_1024x768_MONO8);
        print_case(DC1394_VIDEO_MODE_800x600_MONO16);
        print_case(DC1394_VIDEO_MODE_1024x768_MONO16);
        print_case(DC1394_VIDEO_MODE_1280x960_YUV422);
        print_case(DC1394_VIDEO_MODE_1280x960_RGB8);
        print_case(DC1394_VIDEO_MODE_1280x960_MONO8);
        print_case(DC1394_VIDEO_MODE_1600x1200_YUV422);
        print_case(DC1394_VIDEO_MODE_1600x1200_RGB8);
        print_case(DC1394_VIDEO_MODE_1600x1200_MONO8);
        print_case(DC1394_VIDEO_MODE_1280x960_MONO16);
        print_case(DC1394_VIDEO_MODE_1600x1200_MONO16);

    default:
        dc1394_log_error("Unknown format\n");
        exit(1);
    }

}

/*-----------------------------------------------------------------------
 *  Returns the number of pixels in the image based upon the format
 *-----------------------------------------------------------------------*/
uint32_t get_num_pixels(dc1394camera_t *camera, uint32_t format ) {
    uint32_t w,h;

    dc1394_get_image_size_from_video_mode(camera, format,&w,&h);

    return w*h;
}

/*-----------------------------------------------------------------------
 *  Prints the type of color encoding
 *-----------------------------------------------------------------------*/
void print_color_coding( uint32_t color_id )
{
    switch( color_id ) {
    case DC1394_COLOR_CODING_MONO8:
        printf("MONO8");
        break;
    case DC1394_COLOR_CODING_YUV411:
        printf("YUV411");
        break;
    case DC1394_COLOR_CODING_YUV422:
        printf("YUV422");
        break;
    case DC1394_COLOR_CODING_YUV444:
        printf("YUV444");
        break;
    case DC1394_COLOR_CODING_RGB8:
        printf("RGB8");
        break;
    case DC1394_COLOR_CODING_MONO16:
        printf("MONO16");
        break;
    case DC1394_COLOR_CODING_RGB16:
        printf("RGB16");
        break;
    case DC1394_COLOR_CODING_MONO16S:
        printf("MONO16S");
        break;
    case DC1394_COLOR_CODING_RGB16S:
        printf("RGB16S");
        break;
    case DC1394_COLOR_CODING_RAW8:
        printf("RAW8");
        break;
    case DC1394_COLOR_CODING_RAW16:
        printf("RAW16");
        break;
    default:
        dc1394_log_error("Unknown color coding = %d\n",color_id);
        exit(1);
    }
}

/*-----------------------------------------------------------------------
 *  Prints various information about the mode the camera is in
 *-----------------------------------------------------------------------*/
void print_mode_info( dc1394camera_t *camera , uint32_t mode )
{
    int j;

    printf("Mode: ");
    print_format(mode);
    printf("\n");

    dc1394framerates_t framerates;
    dc1394error_t err;
    err=dc1394_video_get_supported_framerates(camera,mode,&framerates);
    DC1394_ERR(err,"Could not get frame rates");

    printf("Frame Rates:\n");
    for( j = 0; j < framerates.num; j++ ) {
        uint32_t rate = framerates.framerates[j];
        float f_rate;
        dc1394_framerate_as_float(rate,&f_rate);
        printf("  [%d] rate = %f\n",j,f_rate );
    }

}

/*-----------------------------------------------------------------------
 *  Releases the cameras and exits
 *-----------------------------------------------------------------------*/
void cleanup_and_exit(dc1394camera_t *camera)
{
    dc1394_video_set_transmission(camera, DC1394_OFF);
    dc1394_capture_stop(camera);
    dc1394_camera_free(camera);
    exit(1);
}

int main(int argc, char *argv[])
{
    FILE* imagefile;
    dc1394camera_t *camera;
    unsigned int width, height;
    dc1394video_frame_t *frame=NULL;
    dc1394_t * d;
    dc1394camera_list_t * list;

    dc1394error_t err;

    d = dc1394_new ();
    err=dc1394_camera_enumerate (d, &list);
    DC1394_ERR_RTN(err,"Failed to enumerate cameras");

    if (list->num == 0) {
        dc1394_log_error("No cameras found");
        return 1;
    }

    camera = dc1394_camera_new (d, list->ids[0].guid);
    if (!camera) {
        dc1394_log_error("Failed to initialize camera with guid %llx", list->ids[0].guid);
        return 1;
    }
    dc1394_camera_free_list (list);

    printf("Using camera with GUID %"PRIx64"\n", camera->guid);

    dc1394video_modes_t modes;

    /*-----------------------------------------------------------------------
     *  list Capture Modes
     *-----------------------------------------------------------------------*/
    err=dc1394_video_get_supported_modes(camera, &modes);
    DC1394_ERR_RTN(err,"Could not get list of modes");

    uint32_t selected_mode = modes.modes[modes.num-1];

    /*-----------------------------------------------------------------------
     *  setup capture
     *-----------------------------------------------------------------------*/

    err=dc1394_video_set_iso_speed(camera, DC1394_ISO_SPEED_400);
    DC1394_ERR_CLN_RTN(err,cleanup_and_exit(camera),"Could not set iso speed");

    err=dc1394_video_set_mode(camera, selected_mode);
    DC1394_ERR_CLN_RTN(err,cleanup_and_exit(camera),"Could not set video mode\n");

    err=dc1394_video_set_framerate(camera, DC1394_FRAMERATE_7_5);
    DC1394_ERR_CLN_RTN(err,cleanup_and_exit(camera),"Could not set framerate\n");

    err=dc1394_capture_setup(camera,4, DC1394_CAPTURE_FLAGS_DEFAULT);
    DC1394_ERR_CLN_RTN(err,cleanup_and_exit(camera),"Could not setup camera-\nmake sure that the video mode and framerate are\nsupported by your camera\n");

    /*-----------------------------------------------------------------------
     *  have the camera start sending us data
     *-----------------------------------------------------------------------*/
    err=dc1394_video_set_transmission(camera, DC1394_ON);
    DC1394_ERR_CLN_RTN(err,cleanup_and_exit(camera),"Could not start camera iso transmission\n");

    /*-----------------------------------------------------------------------
     *  capture one frame
     *-----------------------------------------------------------------------*/
    err=dc1394_capture_dequeue(camera, DC1394_CAPTURE_POLICY_WAIT, &frame);
    DC1394_ERR_CLN_RTN(err,cleanup_and_exit(camera),"Could not capture a frame\n");

    /*-----------------------------------------------------------------------
     *  stop data transmission
     *-----------------------------------------------------------------------*/
    err=dc1394_video_set_transmission(camera,DC1394_OFF);
    DC1394_ERR_CLN_RTN(err,cleanup_and_exit(camera),"Could not stop the camera?\n");

    /*-----------------------------------------------------------------------
     *  convert the image from what ever format it is to its RGB8
     *-----------------------------------------------------------------------*/

    dc1394_get_image_size_from_video_mode(camera, selected_mode, &width, &height);
    uint64_t numPixels = height*width;

    dc1394video_frame_t *new_frame=calloc(1,sizeof(dc1394video_frame_t));
    new_frame->color_coding=DC1394_COLOR_CODING_RGB8;
    dc1394_convert_frames(frame, new_frame);

    /*-----------------------------------------------------------------------
     *  save image as 'Image.pgm'
     *-----------------------------------------------------------------------*/
    imagefile=fopen(IMAGE_FILE_NAME, "wb");

    if( imagefile == NULL) {
        perror( "Can't create '" IMAGE_FILE_NAME "'");
        cleanup_and_exit(camera);
    }


    fprintf(imagefile,"P6\n%u %u\n255\n", width, height);
    fwrite((const char *)new_frame->image, 1,numPixels*3, imagefile);
    fclose(imagefile);
    printf("wrote: " IMAGE_FILE_NAME "\n");

    /*-----------------------------------------------------------------------
     *  close camera
     *-----------------------------------------------------------------------*/
    free(new_frame->image);
    free(new_frame);
    dc1394_video_set_transmission(camera, DC1394_OFF);
    dc1394_capture_stop(camera);
    dc1394_camera_free(camera);
    dc1394_free (d);

    return 0;
}

      

Can someone help me convert this code to capture stereo images. I also looked into the coriander source code and have already spent two days using that source code to get it to work for stereo images. I would be very grateful.

+3


source to share


2 answers


Finally, it works. Point Gray bumblebee2 camera with libdc1394

#include <stdio.h>
#include <stdint.h>
#include <dc1394/dc1394.h>
#include <stdlib.h>
#include <inttypes.h>

#include <endian.h>

#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"


#ifndef _WIN32
#include <unistd.h>
#endif


/*-----------------------------------------------------------------------
 *  Releases the cameras and exits
 *-----------------------------------------------------------------------*/
void cleanup_and_exit(dc1394camera_t *camera)
{
    dc1394_video_set_transmission(camera, DC1394_OFF);
    dc1394_capture_stop(camera);
    dc1394_camera_free(camera);
    exit(1);
}

int main(int argc, char *argv[])
{
    FILE* imagefile;
    dc1394camera_t *camera;
    unsigned int width, height;
    dc1394video_frame_t *frame=NULL;
    dc1394video_frame_t stereo;

    //dc1394featureset_t features;
    dc1394_t * d;
    dc1394camera_list_t * list;
    dc1394error_t err;     
    //
    // Create an OpenCV window
    //
    cv::namedWindow( "Stereo image", CV_WINDOW_AUTOSIZE );             

    d = dc1394_new ();
    if (!d)
        return 1;
    err=dc1394_camera_enumerate (d, &list);
    DC1394_ERR_RTN(err,"Failed to enumerate cameras");

    if (list->num == 0) {
        dc1394_log_error("No cameras found");
        return 1;
    }

    camera = dc1394_camera_new (d, list->ids[0].guid);
    if (!camera) {
        dc1394_log_error("Failed to initialize camera with guid %llx", list->ids[0].guid);
        return 1;
    }
    dc1394_camera_free_list (list);

    printf("Using camera with GUID %i \n", camera->guid);


    /*-----------------------------------------------------------------------
     *  setup capture
     *-----------------------------------------------------------------------*/

    err=dc1394_video_set_operation_mode(camera, DC1394_OPERATION_MODE_LEGACY );
    DC1394_ERR_CLN_RTN(err,cleanup_and_exit(camera),"Could not set 1394A mode");

    err=dc1394_video_set_iso_speed(camera, DC1394_ISO_SPEED_400 );
    DC1394_ERR_CLN_RTN(err,cleanup_and_exit(camera),"Could not set iso speed");

    err=dc1394_video_set_mode(camera, DC1394_VIDEO_MODE_FORMAT7_3 );
    DC1394_ERR_CLN_RTN(err,cleanup_and_exit(camera),"Could not set video mode\n");

    err=dc1394_format7_set_roi(camera, DC1394_VIDEO_MODE_FORMAT7_3, DC1394_COLOR_CODING_RAW16, DC1394_USE_MAX_AVAIL, 0, 0, 1024, 768 );       
    DC1394_ERR_CLN_RTN(err,cleanup_and_exit(camera),"Could not ROI\n");

    err=dc1394_capture_setup(camera,4, DC1394_CAPTURE_FLAGS_DEFAULT );
    DC1394_ERR_CLN_RTN(err,cleanup_and_exit(camera),"Could not setup camera-\nmake sure that the video mode and framerate are\nsupported by your camera\n");


    /*-----------------------------------------------------------------------
     *  GIJS edit: show F7 info
     *-----------------------------------------------------------------------*/
    uint32_t unit_bytes;
    uint32_t max_bytes;
    err=dc1394_format7_get_packet_parameters(camera, DC1394_VIDEO_MODE_FORMAT7_3, &unit_bytes, &max_bytes );
    printf("\n[DEBUG] F7 Info\n");
    printf("[DEBUG] unit_byte: %d (error %d)\n", unit_bytes, err );   
    printf("[DEBUG] max_bytes: %d (error %d)\n", max_bytes, err );
    uint32_t packet_size;
    err=dc1394_format7_get_packet_size(camera, DC1394_VIDEO_MODE_FORMAT7_3, &packet_size );
    printf("[DEBUG] packet_size: %d (error %d)\n", packet_size, err );
    uint32_t packets_per_frame;
    err=dc1394_format7_get_packets_per_frame(camera, DC1394_VIDEO_MODE_FORMAT7_3, &packets_per_frame );     
    printf("[DEBUG] packets_per_frame: %d (error %d)\n", packets_per_frame, err );
    uint32_t pixels_per_frame;
    err=dc1394_format7_get_pixel_number(camera, DC1394_VIDEO_MODE_FORMAT7_3, &pixels_per_frame );   
    printf("[DEBUG] pixels_per_frame: %d (error %d)\n", pixels_per_frame, err );
    uint32_t recommended_packet_size;
    err=dc1394_format7_get_recommended_packet_size(camera, DC1394_VIDEO_MODE_FORMAT7_3, &recommended_packet_size );
    printf("[DEBUG] recommended_packet_size: %d (error %d)\n", recommended_packet_size, err );
    uint64_t total_bytes;
    err=dc1394_format7_get_total_bytes(camera, DC1394_VIDEO_MODE_FORMAT7_3, &total_bytes );
    printf("[DEBUG] total_size: %d (error %d)\n", total_bytes, err );


    /*-----------------------------------------------------------------------
     *  have the camera start sending us data
     *-----------------------------------------------------------------------*/
    err=dc1394_video_set_transmission(camera, DC1394_ON);
    DC1394_ERR_CLN_RTN(err,cleanup_and_exit(camera),"Could not start camera iso transmission\n");


    //
    // Test loop
    //
    cv::Mat StereoImage = cv::Mat( 1536, 1024, CV_8UC1 );
    cv::Mat dispImage   = cv::Mat( 1536, 1024, CV_8UC3 );
    short int* source;
    short int* dest;

    for( int n = 0; n < 1000; n++ )
    {

      /*-----------------------------------------------------------------------
      *  capture one frame
      *-----------------------------------------------------------------------*/
      err=dc1394_capture_dequeue(camera, DC1394_CAPTURE_POLICY_WAIT, &frame);
      DC1394_ERR_CLN_RTN(err,cleanup_and_exit(camera),"Could not capture a frame\n");


      /*-----------------------------------------------------------------------
      *  check if frame is corrupt
      *-----------------------------------------------------------------------*/      
      if( dc1394_capture_is_frame_corrupt( camera, frame) )
      printf("\n[DEBUG] frame is corrupt!\n"); 

      /*-----------------------------------------------------------------------
      *  copy the buffer data, but only copy the pointer to the image
      *  we don't allocate the image buffer of tempframe (pointer copy from the DMA ring buffer)
      *  so the alloc should be zero
      *-----------------------------------------------------------------------*/ 
      memcpy( &stereo, frame, sizeof(dc1394video_frame_t) );
      stereo.allocated_image_bytes=0;


      /*-----------------------------------------------------------------------
      *  check if frame is corrupt
      *-----------------------------------------------------------------------*/ 
      stereo.image=NULL;
      dc1394_deinterlace_stereo_frames( frame, &stereo, DC1394_STEREO_METHOD_INTERLACED );    


      /*-----------------------------------------------------------------------
      *  copy to opencv
      *-----------------------------------------------------------------------*/          
      dest   = (short int*)&StereoImage.data[0];
      source = (short int*)&stereo.image[0];
      memcpy( dest, source, 1536*1024 );                


      /*-----------------------------------------------------------------------
     *  show frame info
     *-----------------------------------------------------------------------*/
      printf("\n[DEBUG] Frame Info\n");
      printf("[DEBUG] image_bytes: %d\n",           stereo.image_bytes);
      printf("[DEBUG] size[0]: %d\n",               stereo.size[0]);
      printf("[DEBUG] size[1]: %d\n",               stereo.size[1]);      
      printf("[DEBUG] allocated_image_bytes: %d\n", stereo.allocated_image_bytes );
      printf("[DEBUG] total_bytes: %d\n",           stereo.total_bytes );
      printf("[DEBUG] color_coding: %d\n",          stereo.color_coding);     
      printf("[DEBUG] color_filter: %d\n",          stereo.color_filter);
      printf("[DEBUG] packet_size: %d\n",           stereo.packet_size);      
      printf("[DEBUG] packets_per_frame: %d\n",     stereo.packets_per_frame);
      printf("[DEBUG] padding_bytes: %d\n",         stereo.padding_bytes);
      printf("[DEBUG] timestamp: %d\n",             stereo.timestamp);
      printf("[DEBUG] stride: %d\n",                stereo.stride);
      printf("[DEBUG] data_depth: %d\n",            stereo.data_depth);
      printf("[DEBUG] id: %d\n",                    stereo.id);
      printf("[DEBUG] frames_behind: %d\n",         stereo.frames_behind);
      printf("[DEBUG] image: %u\n",                 stereo.image); 


      /*-----------------------------------------------------------------------
      *  convert to color image
      *-----------------------------------------------------------------------*/
      cvtColor( StereoImage, dispImage, CV_BayerGR2RGB );


      /*-----------------------------------------------------------------------
      *  Show OpenCV image
      *-----------------------------------------------------------------------*/
      imshow("Stereo image", dispImage );
      cv::waitKey(10);


      /*-----------------------------------------------------------------------
      *  Give back frame to queue
      *-----------------------------------------------------------------------*/
      dc1394_capture_enqueue(camera,frame);


      /*-----------------------------------------------------------------------
      * Free the memory
      *-----------------------------------------------------------------------*/
      free(stereo.image);

    }

    /*-----------------------------------------------------------------------
     *  stop data transmission
     *-----------------------------------------------------------------------*/
    err=dc1394_video_set_transmission(camera,DC1394_OFF);
    DC1394_ERR_CLN_RTN(err,cleanup_and_exit(camera),"Could not stop the camera?\n");

    /*-----------------------------------------------------------------------
     *  close camera
     *-----------------------------------------------------------------------*/
    dc1394_video_set_transmission(camera, DC1394_OFF);
    dc1394_capture_stop(camera);
    dc1394_camera_free(camera);
    dc1394_free (d);
    return 0;
}

      



Here is the result

enter image description here

+2


source


Ok, my first step was to move all the stuff from main () to another function and call it from main () with one line that passes the camera address, output file name, etc. The function should work without globals or statics, only locals. Do it right.

Then modify the function so that it only accepts one structure pointer as its only parameter. In main (), dynamicaly-allocate struct 'params' to contain the camera address, etc. And call the "camera" function with its address. Do it right.

Then, instead of calling the "camera" function directly from the main one, skip it by passing a pointer to "params" as a void * parameter to pthread_create. Do it right.



Last - start two "camera" streams from the main one with different addresses and output files.

You may need / need to do more later, eg. ordering frames from both cameras to main () with some queue of producer-consumers and matching frames to stereopairs with some timestamp, but this is between you and your requirements :)

Note that this answer is just a "best guess" design and development strategy that tries to use the code you already have, works :)

+3


source







All Articles