This site contains a collection of C++ examples demonstrating the usage of the FPGA-ImageRAM and other FPGA-functions like 3×3-filtering, (Color-)JPEG compression, etc. In general all examples on this site are developed for the 640×480 camera, but can easily be adapted to work with the other sensor variants.
The follwing source code is the common base for all subsequent examples. It contains:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> /* close() */ #include <sys/types.h> /* open() */ #include <sys/stat.h> /* open() */ #include <fcntl.h> /* open() */ #include <sys/ioctl.h> /* ioctl() */ #include <errno.h> #include <stdint.h> #include <string.h> #include "OCamera.h" /* camera image acquisition API */ #include "jpconv.h" /* additional jpeg functions */ #define WIDTH 256 #define HEIGHT 256 #define FRAMESIZE WIDTH*HEIGHT #define IMGRAM_START_ADDR_1 0 #define IMGRAM_START_ADDR_2 IMGRAM_START_ADDR_1+FRAMESIZE /* error check macro used for camera-api calls */ #define CHECK_ERROR(msg,value) { if (value) { \ printf("%s returned %d",msg, value); \ goto error_exit; \ }} OCameraImage img; OCamera *pCamera; /* * The following function does the basic setup needed for operating the camera. * This includes: * - opening the driver's interface * - setting camera window, shuttertime, illumination behaviour, etc. * - The acquisition mode is set to stop. */ int init_camera() { int ret; /* creating and opening the camera interface * be sure to specify the correct sensor type here */ pCamera = OCamera::CreateCameraInterface(OCamera::CAM_TYPE_MT9V403); if (!pCamera) { printf("sorry, cannot open the camera API"); goto error_exit; } ret = pCamera->Open(FRAMESIZE*10); /* frame buffer = 10 images */ CHECK_ERROR("Open()",ret); /* basic camera setup */ ret = pCamera->SetCameraWindow(0,0,WIDTH,HEIGHT); CHECK_ERROR("SetCameraWindow()",ret); ret = pCamera->SetFrequency(OCamera::FREQU_60MHz); CHECK_ERROR("SetFrequency()",ret); ret = pCamera->SetShutterTime(1000); /* 10ms */ CHECK_ERROR("SetShutterTime()",ret); ret = pCamera->SetGain(8); CHECK_ERROR("SetGain()",ret); ret = pCamera->SetFrameRate(20); /* 20 fps */ CHECK_ERROR("SetFrameRate()",ret); ret = pCamera->SetIlluminationTiming(0,0); CHECK_ERROR("SetIlluminationTiming()",ret); ret = pCamera->SetIlluminationMode(OCamera::ILL_MODE_OFF); CHECK_ERROR("SetIlluminationMode()",ret); ret = pCamera->SetIlluminationModeExternal(OCamera::ILL_MODE_EXT_OFF); CHECK_ERROR("SetIlluminationModeExternal()",ret); ret = pCamera->SetTriggerSource(OCamera::TRIG_SRC_SOFTWARE); CHECK_ERROR("SetTriggerSource()",ret); ret = pCamera->SetTriggerDelay(0); CHECK_ERROR("SetTriggerDelay()",ret); ret = pCamera->SetReadTimeout(2000000); CHECK_ERROR("SetReadTimeout()",ret); ret = pCamera->SetCircularOverwrite(true); CHECK_ERROR("SetCircularOverwrite()",ret); /* starting image aquisition */ ret = pCamera->SetAcquisitionMode(OCamera::ACQ_MODE_SINGLE_SHOT); CHECK_ERROR("SetAcquisitionMode()",ret); error_exit: return ret; } int deinit_camera() { int ret; /* stopping image aquisition */ ret = pCamera->SetAcquisitionMode(OCamera::ACQ_MODE_STOP); CHECK_ERROR("SetAcquisitionMode()",ret); pCamera->Close(); /* close camera API */ pCamera->Destroy(); /* destroy/free the interface */ error_exit: return ret; } /* ------------------------------------------------------------------------- * prints a given area of the pxa memorry to a file * ------------------------------------------------------------------------- */ int file_write(unsigned char *startaddr, unsigned int bytes, char *filename) { unsigned char *runner, *endaddr; FILE *f = fopen(filename,"w+b"); if (!f) return -1; runner = startaddr; endaddr = runner+bytes; while (runner<endaddr) { fwrite(runner,1,sizeof(char),f); runner++; } fclose(f); return 0; } /* ------------------------------------------------------------------------- * creates a test image in the user space memory * ------------------------------------------------------------------------- */ int create_test_image(unsigned char *dst, int width, int height) { for(int i=0;i<height;i++) { for(int j=0;j<width;j++) { if (j<width*9/9) { dst[i*width+j] = 255; }; if (j<width*8/9) { dst[i*width+j] = 223; }; if (j<width*7/9) { dst[i*width+j] = 191; }; if (j<width*6/9) { dst[i*width+j] = 159; }; if (j<width*5/9) { dst[i*width+j] = 127; }; if (j<width*4/9) { dst[i*width+j] = 95; }; if (j<width*3/9) { dst[i*width+j] = 63; }; if (j<width*2/9) { dst[i*width+j] = 31; }; if (j<width*1/9) { dst[i*width+j] = 0; }; } } return 0; } /* ------------------------------------------------------------------------- * * ------------------------------------------------------------------------- */ int setup_hw_whitebalancing(OCamera *pCamera, OCamera::eBayerPattern ePattern) { int ret; unsigned char pLut[768]; /* building the whitebalancing factors based on the values stored on the camera * (in /ffx/etc/wb.conf; they are written by webcam.cgi) * alternativly you can build the pLut[768] table by yourself. The three tables * in pLut are ordered GBR! */ ret = OCameraTools::SetupHardwareWhitebalancingFactors(pLut); CHECK_ERROR("SetupHardwareWhitebalancingFactors()",ret); /* writing the tables to the FPGA. * The tables can be reseted to linear values by calling SetWhiteBalance(ePattern, 0); */ ret = pCamera->SetWhiteBalance(ePattern, pLut); CHECK_ERROR("SetWhiteBalance()",ret); error_exit: return ret; }
This example works on color cameras only.
A define allows switching between sensor image and an artificial test image
int example1(int argc, char *argv[]) { int ret; unsigned char *src, *dst; unsigned char *src32, *dst32; printf("starting test:"); /* creating 32 byte alligned buffers for source/destination of data transfers from/to the * FPGA-attached image-RAM. The allignmend is necessary for DMA transfers. */ src = (unsigned char*) malloc((FRAMESIZE+32)*sizeof(unsigned char)); if (src == 0) goto exit1; src32 = (unsigned char*) (src+32-(unsigned long)src%32); dst = (unsigned char*) malloc((FRAMESIZE+32)*sizeof(unsigned char)); if (dst == 0) goto exit2; dst32 = (unsigned char*) (dst+32-(unsigned long)dst%32); if (init_camera() != 0) goto exit3; /* enabling the FPGA attached image-RAM */ ret = pCamera->InitImageRAM(); ret = pCamera->InitColor(); CHECK_ERROR("InitImageRAM",ret); #define SENSOR_IMG #ifdef SENSOR_IMG /* Getting an image from the sensor to the ImageRAM */ ret = pCamera->GetImageToImageRAM(IMGRAM_START_ADDR_1); CHECK_ERROR("GetImageToImageRAM()",ret); #else /* alternatively an image can be created and transfered from the PXA-memory */ create_test_image(src32, WIDTH, HEIGHT); CHECK_ERROR("create_test_image()",ret); ret = pCamera->WriteImageRAM(src32, IMGRAM_START_ADDR_1, FRAMESIZE); CHECK_ERROR("WriteImageRAM()",ret); #endif /* transfering the image from one address to another one in the Image Ram. * hereby filtering is enabled. */ /* when transfering data over a filter out of the image Ram, we must explicitly set the picture size */ ret = pCamera->SetImageRAMPictureSize(WIDTH,HEIGHT); CHECK_ERROR("SetImageRAMPictureSize",ret); ret = pCamera->SetBayer2X(OCamera::BAYER_OUTPUT_R, OCamera::BAYER_PATTERN_GRGR); CHECK_ERROR("SetBayer2X()",ret); ret = pCamera->SetFilter(OCamera::FILTER_SOBEL); CHECK_ERROR("SetFilter()",ret); ret = pCamera->ImageRAMToImageRAM(IMGRAM_START_ADDR_1, FRAMESIZE, IMGRAM_START_ADDR_2, FRAMESIZE); CHECK_ERROR("ImageRAMToImageRAM",ret); /* disabling the filter */ ret = pCamera->SetBayer2X(OCamera::BAYER_OUTPUT_RAW, OCamera::BAYER_PATTERN_GRGR); CHECK_ERROR("SetBayer2X()",ret); ret = pCamera->SetFilter(OCamera::FILTER_OFF); CHECK_ERROR("SetFilter",ret); ret = pCamera->SetImageRAMPictureSize(0,0); CHECK_ERROR("SetImageRAMPictureSize",ret); /* transfering the filtered image to the PXA memory */ ret = pCamera->ReadImageRAM(dst32, IMGRAM_START_ADDR_2, FRAMESIZE); CHECK_ERROR("ReadImageRAM()",ret); /* storing the picture to a file */ ret = file_write(dst32, FRAMESIZE, "output.raw"); CHECK_ERROR("file_write",ret); error_exit: /* disabling the FPGA Image RAM */ pCamera->DisableImageRAM(); exit3: /* cleaning up and exiting */ ret = deinit_camera(); if (ret != 0) goto exit2; exit2: free(dst); exit1: free(src); printf("done."); return ret; }
This example shows:
This sample only works on color cameras.
int example2(int argc, char *argv[]) { int ret; unsigned char *dst; unsigned char *dst32; unsigned long jpeg_stream_size; printf("starting test:"); /* creating 32 byte alligned buffers for source/destination of data transfers from/to the * FPGA-attached image-RAM. The allignmend is necessary for DMA transfers. */ dst = (unsigned char*) malloc((FRAMESIZE+32)*sizeof(unsigned char)); if (dst == 0) goto exit2; dst32 = (unsigned char*) (dst+32-(unsigned long)dst%32); if (init_camera() != 0) goto exit3; /* setting the driver into color mode. This must be done always when you program for a color camera! */ ret = pCamera->InitColor(); CHECK_ERROR("InitColor()",ret); /* enabling the FPGA attached image-RAM */ ret = pCamera->InitImageRAM(); CHECK_ERROR("InitImageRAM",ret); /* setting up FPGA-White balancing */ ret= setup_hw_whitebalancing(pCamera, OCamera::BAYER_PATTERN_GRGR); CHECK_ERROR("setup_hw_whitebalancing()",ret); /* Getting an image from the sensor to the ImageRAM */ ret = pCamera->GetImageToImageRAM(IMGRAM_START_ADDR_1); CHECK_ERROR("GetImageToImageRAM()",ret); /* setting up Color JPEG compression */ ret = pCamera->SetJPEG(true,OCamera::JPEG_QUALITY_GOOD, true, OCamera::BAYER_PATTERN_GRGR, false); CHECK_ERROR("SetJPEG()",ret); /* compressing image and transfering it to the PXA memory */ ret = pCamera->ReadImageRAMReducedData(dst32, IMGRAM_START_ADDR_1, FRAMESIZE, &jpeg_stream_size); CHECK_ERROR("ReadImageRAMReduecdDate()",ret); /* adding header to jpeg stream and and storing the picture to a file */ ret =write_jpeg_file(dst32, jpeg_stream_size, "output.jpg", WIDTH, HEIGHT, QTAB_QUALITY_GOOD, true, true); CHECK_ERROR("write_jpeg_file",ret); /* disabling color jpeg encoder */ ret = pCamera->SetJPEG(false); CHECK_ERROR("SetJPEG()",ret); error_exit: /* disabling the FPGA Image RAM */ pCamera->DisableImageRAM(); exit3: /* cleaning up and exiting */ ret = deinit_camera(); if (ret != 0) goto exit2; exit2: free(dst); printf("done."); return ret; }
The following source shows, how filtering and binarization can be used on greyscale or color cameras (this selection is done with help of a #define statement).
int example3(int argc, char *argv[]) { int ret; printf("starting test:"); if (init_camera() != 0) goto exit2; #define COLOR #ifdef COLOR /* setting the driver into color mode. This must be done always when you program for a color camera! */ ret = pCamera->InitColor(); CHECK_ERROR("InitColor()",ret); /* setting up the Bayer2X unit for calculating one single color channel out of the sensor's RAW image */ ret = pCamera->SetBayer2X(OCamera::BAYER_OUTPUT_I, OCamera::BAYER_PATTERN_GRGR); CHECK_ERROR("SetBayer2X()",ret); #endif /* setting up the filter set this to FILTER_BINARIZE_ONLY if you only want binarization */ ret = pCamera->SetFilter(OCamera::FILTER_SOBEL); CHECK_ERROR("SetFilter()",ret); /* setting up the binarization. here we have to fill the parameter struct with the needed thresholds */ OCamera::sBinarizationParamType binarizationparam; binarizationparam.bInvert = false; binarizationparam.nNumThreshold = 2; binarizationparam.nThreshold1 = 16; binarizationparam.nThreshold2 = 32; ret = pCamera->SetBinarization(true, &binarizationparam); CHECK_ERROR("SetBinarization()",ret); /* trigger camera and read an image to container */ ret = pCamera->GetImage(&img); CHECK_ERROR("GetImage()",ret); /* disabling everything ... */ ret = pCamera->SetBinarization(false); CHECK_ERROR("SetBinarization()",ret); ret = pCamera->SetFilter(OCamera::FILTER_OFF); CHECK_ERROR("SetFilter()",ret); ret = pCamera->SetBayer2X(OCamera::BAYER_OUTPUT_RAW, OCamera::BAYER_PATTERN_GRGR); CHECK_ERROR("SetBayer2X",ret); /* storing the picture to a file */ ret = file_write(img.pData, FRAMESIZE, "output.raw"); CHECK_ERROR("file_write",ret); /* trigger camera and read an image to container */ ret = pCamera->ReleaseImage(&img); CHECK_ERROR("ReleaseImate",ret); error_exit: /* cleaning up and exiting */ deinit_camera(); exit2: printf("done."); return ret; }
The following code demonstrates how the correction unit can be used.
In this sample the correction unit replaces the sensor image by an test image transfered to the FPGA-ImageRAM at the beginning. Works on color and greyscale cameras.
/* ------------------------------------------------------------------------- * Using image correction unit! * Greyscale + Color Camera * ------------------------------------------------------------------------- */ int example4(int argc, char *argv[]) { int ret; unsigned char *src, *src32; printf("starting test:"); if (init_camera() != 0) goto exit3; /* creating 32 byte alligned buffers for source/destination of data transfers from/to the * FPGA-attached image-RAM. The allignmend is necessary for DMA transfers. */ src = (unsigned char*) malloc((FRAMESIZE+32)*sizeof(unsigned char)); if (src == 0) goto exit2; src32 = (unsigned char*) (src+32-(unsigned long)src%32); /* enabling the FPGA attached image-RAM */ ret = pCamera->InitImageRAM(); CHECK_ERROR("InitImageRAM()",ret); /* preparing correction data in image ram */ create_test_image(src32, WIDTH, HEIGHT); CHECK_ERROR("create_test_image()",ret); ret = pCamera->WriteImageRAM(src32, IMGRAM_START_ADDR_1, FRAMESIZE); CHECK_ERROR("WriteImageRAM()",ret); /* setting up the image correction */ ret = pCamera->SetupImageCorrection(true, OCamera::CORRECTION_REPLACE, IMGRAM_START_ADDR_1, 1); CHECK_ERROR("SetupImageCorrection()",ret); /* trigger camera and read an image to container */ ret = pCamera->GetImage(&img); CHECK_ERROR("GetImage()",ret); /* disabling image correction unit */ ret = pCamera->SetupImageCorrection(false, OCamera::CORRECTION_REPLACE, IMGRAM_START_ADDR_1, 1); CHECK_ERROR("SetupImageCorrection()",ret); /* storing the picture to a file */ ret = file_write(img.pData, FRAMESIZE, "output_corr.raw"); CHECK_ERROR("file_write()",ret); /* trigger camera and read an image to container */ ret = pCamera->ReleaseImage(&img); CHECK_ERROR("ReleaseImage()",ret); error_exit: pCamera->DisableImageRAM(); free(src); exit3: /* cleaning up and exiting */ ret = deinit_camera(); if (ret != 0) goto exit2; exit2: printf("done."); return ret; }
The following example shows how FPGA data splitting can be used. The example works on greyscale and color cameras.
int example5(int argc, char *argv[]) { int ret; unsigned char *dst, *dst32; printf("starting test:"); /* creating 32 byte alligned buffers for source/destination of data transfers from/to the * FPGA-attached image-RAM. The allignmend is necessary for DMA transfers. */ dst = (unsigned char*) malloc((FRAMESIZE+32)*sizeof(unsigned char)); if (dst == 0) goto exit2; dst32 = (unsigned char*) (dst+32-(unsigned long)dst%32); if (init_camera() != 0) goto exit3; /* enabling the FPGA attached image-RAM */ ret = pCamera->InitImageRAM(); CHECK_ERROR("InitImageRAM()",ret); ret = pCamera->SetupImageSplitting(OCamera::SPLIT_RAW, IMGRAM_START_ADDR_1, FRAMESIZE); CHECK_ERROR("SetupImageSplitting()",ret); ret = pCamera->SetFilter(OCamera::FILTER_MEDIAN); CHECK_ERROR("SetFilter()",ret); ret = pCamera->GetImage(&img); CHECK_ERROR("GetImage()",ret); ret = pCamera->SetupSplitting(OCamera::SPLIT_OFF, IMGRAM_START_ADDR_1, FRAMESIZE); CHECK_ERROR("SetupImageSplitting()",ret); // reading image from SDRAM and write it to a file ret = pCamera->SetFilter(OCamera::FILTER_OFF); CHECK_ERROR("SetFilter()",ret); printf("saving raw pxa picture"); ret = file_write(img.pData,img.nSize, "output_pxa.raw"); CHECK_ERROR("file_write()",ret); pCamera->ReleaseImage(&img); CHECK_ERROR("ReleaseImage",ret); ret = pCamera->ReadImageRAM(dst32, IMGRAM_START_ADDR_1, FRAMESIZE); CHECK_ERROR("ReadImageRAM",ret); printf("saving sdram picture"); ret = file_write(dst32, FRAMESIZE, "output_sdram.raw"); CHECK_ERROR("SetFilter()",ret); error_exit: ret = pCamera->DisableImageRAM(); exit3: /* cleaning up and exiting */ ret = deinit_camera(); if (ret != 0) goto exit2; exit2: free(dst); printf("done."); return ret; }