Create
Subscribe RSS feeds Click & copy/paste URL
Toolbox

     - Page -
PDF
Print
     - Space -
Index
     - Place -
What's new
     - Support -
Contact
FAQ
Features
Feedback
Participate
Tutorial
Wiki Syntax

Members

Real Time Image Compression with Mikrotron MC1324


High-speed (500fps) 3DPTV for 10K$ is not a dream

Mikrotron GmbH let us to test the last generation of MC1324 cameras. This is a relatively small CMOS camera (C-mount in the present configuration, but F-mount is also an option). ETH and TAU already use similar ones for the 500 frame-per-second (fps) systems (4 cameras each) in conjunction with the IO Industries real-time streaming and storage system (otherwise called Digital Video Recording systems). For more details about the high-speed, long-recording, real-time-streaming solutions, you can look at any of these sites:

In this, new generation, MC132x camera has an addition, but really a breakthrough option - built-in Sobel filter, implemented in FPGA, on-board (in the camera). Therefore, the camera can send a signal through a simple Ethernet cable (GigE interface) to a simple Ethernet card in the PC. This opens a new way of real-time image compression, similar to the idea of Greg Voth: his recent paper is linked here

The camera

The camera is shown and described in details on the website of Mikrotron

mc1324.jpg
Figure 1: MC1324 CMOS camera with the FPGA Sobel filter (courtesy of Mikrotron GmbH)

and the FPGA Sobel filter is described in their PDF file

The photos of the camera which we used with the four-view image splitter (or adaptor, see below), are shown here:

Image014.jpg
Figure 2: MC1324 installation at IfU, including 4-view mirror splitter


Note the yellow cable - it replaces all the blue cables (not really fair comparison, but makes the point clear) shown below:

Image020.jpg http://ptvwiki.netcipia.net/xwiki/bin/download/Main/Scanning+3D%2DPTV/project_image.php.jpg
Figure 3: (left) Yellow Ethernet cable linked next to the fibre channel cables of IO Industries real-time recording system, (right) Schematic view of the image splitter


Operation and recording

The camera is installed in a very easy way. The main issue is to install the Ethernet PCI card (Intel Pro 10 / 100) and the special drivers (Ebus Optimal drivers) that extract the maximal speed from the card. Camera needs no installation after that. It was operated by the Mikrotron software, called Coyote:

Image010.jpgImage023.jpg
Figure 4: (left) 20 bytes x 512 rows image representing the compressed image in real-time at 500 fps, seen as a long and thin strip (ala Matrix). (right) Special viewing option of Coyette (Mikrtoron software) to see both original image of the particles and Sobel filtered one, shifted to the right.

Recording at 500 fps through the SINGLE, INTERNET cable

The system can record compressed images (of a special format, provided by Mikrotron) in which (at this point) 512 objects which are processed by the Sobel filter, edge detected, filled and identified as objects due to some criteria. An example of the RAW file is attached here RAW

Conversion of RAW to ASCII (temporary solution)

This part is existing due to the great help of Mr. Andreas Ertl from Mikrotron GmbH, who wrote the following C++ code to convert RAW into ASCII text files raw2points.cpp

// raw2txt.cpp : Defines the entry point for the console application.
//

\#define LITTLE_ENDIAN

#if defined(BIG_ENDIAN)

\#define htons(A) (A) \#define htonl(A) (A) \#define ntohs(A) (A) \#define ntohl(A) (A)

\#elif defined(LITTLE_ENDIAN)

\#define htons(A) ((((A) & 0xff00) >> 8) | ((A) & 0x00ff) << 8))

\#define htonl(A) ((((A) & 0xff000000) >> 24) | (((A) & 0x00ff0000) >> 8) | \ (((A) & 0x0000ff00) << 8) | (((A) & 0x000000ff) << 24))

\#define ntohs htons \#define ntohl htonl

#else

#error "One of BIG_ENDIAN or LITTLE_ENDIAN must be #define'd."

\#endif

#include <stdio.h> #include <stdlib.h>

struct BinaryImageInfo { unsigned long dummy[Main.5]; unsigned long ulImageNumber; unsigned long ulAcquisitionTime; unsigned long ulFlashDuration; unsigned long ulExposureDuration; };

struct BinaryTarget { unsigned int sum_gu: 29; unsigned int sp8: 1; unsigned int dummy: 2; unsigned int sum_gv: 28; unsigned int sp47: 4; unsigned int sum_g: 18; unsigned int max_v: 10; unsigned int sp03: 4; unsigned int min_u: 11; unsigned int max_u: 11; unsigned int min_v: 10; unsigned int dummy2: 32; }; // The one and only application object

void main(int argc, char **argv)

{ int i_seq, i, j, n, trajid, maxvector; int firstframe, lastframe, numframes; int *vectors; double prev;

unsigned char buff[Main.40]; struct BinaryImageInfo *pImageInfo; struct BinaryTarget *pTarget;

FILE *FILEIN, *FILEOUT; char filein[Main.100], fileout[Main.100], prefix[Main.50];

/* Main loop */

if(argc != 3) { printf("\n Usage: raw2txt <firstdatasetnum> <lastdatasetnum> !!!\n"); exit(1); } firstframe = atoi(argv[Main.1]); lastframe = atoi(argv[Main.2]);

numframes = lastframe - firstframe + 1; //number of frames

/* Main loop */ for (i_seq=firstframe; i_seq <= lastframe; i_seq++) { sprintf (filein,"%08d.raw", i_seq); sprintf (fileout,"%08d.txt", i_seq); printf("%s -- > %s\n", filein, fileout); FILEIN = fopen (filein, "rb"); if (! FILEIN) continue; //open the file in binary mode FILEOUT = fopen (fileout, "w"); if (! FILEOUT); fread(buff, sizeof(unsigned char),40,FILEIN); pImageInfo = (struct BinaryImageInfo *)buff; pTarget = (struct BinaryTarget *)buff; // fprintf(FILEOUT,"ImageHeader:\n"); // for (i=0; i < 5; i++) // fprintf(FILEOUT,"%08X", ntohl(pImageInfo->dummy[Main.i])); // fprintf(FILEOUT,"\nImage Number: %d\n\n", pImageInfo->ulImageNumber);

i = 0; int read ; do { read = 0; read = fread(buff, 1, 20, FILEIN); // rawFile.Read(buff, 20); if (pImageInfo->dummy[Main.0] != ntohl(0x00102030)) { /** fprintf(FILEOUT,"Target %03d: COG U: %7.2f, V: %7.2f; Area: %d\n", i, (float)pTarget->sum_gu/pTarget->sum_g, (float)pTarget->sum_gv/pTarget->sum_g, (pTarget->sp8<<8)+(pTarget->sp47)+pTarget->sp03); **/ fprintf(FILEOUT,"%7.2f %7.2f \n", (float)pTarget->sum_gu/pTarget->sum_g, (float)pTarget->sum_gv/pTarget->sum_g);

} i++; } while (pImageInfo->dummy[Main.0] != ntohl(0x00102030));

/** prev = 0.0; for (i=0;i<512;i++) { fread(buff, sizeof(unsigned char),20,FILEIN); // rawFile.Read(buff, 20); if (pTarget->sum_gu/pTarget->sum_g != prev){ fprintf(FILEOUT,"Target %03d: COG U: %6.4f, V: %6.4f; Area: %6.4f\n", i, double(pTarget->sum_gu/pTarget->sum_g), double(pTarget->sum_gv/pTarget->sum_g), double((pTarget->sp8<<8)+(pTarget->sp47)+pTarget->sp03)); prev = pTarget->sum_gu/pTarget->sum_g; } }**/ // fread(buff+20, sizeof(unsigned char),20,FILEIN); // rawFile.Read(buff + 20, 20); // fprintf(FILEOUT,"\n\nImageCloser:\n"); // for (i=0; i < 5; i++) // fprintf(FILEOUT,"%08X", ntohl(pImageInfo->dummy[Main.i])); // fprintf(FILEOUT,"\nImage Number: %d\n", pImageInfo->ulImageNumber); fclose(FILEIN); fclose(FILEOUT); } exit(0); } /** { rawFile.Read(buff, 40); pImageInfo = (struct BinaryImageInfo *)buff; pTarget = (struct BinaryTarget *) buff; printf("ImageHeader:\n"); for (i=0; i < 5; i++) printf("%08X", ntohl(pImageInfo->dummy[Main.i])); printf("\nImage Number: %d\n\n", pImageInfo->ulImageNumber);

i = 0; do { rawFile.Read(buff, 20); if (pImageInfo->dummy[Main.0] != 0x30201000) { printf("Target %03d: COG U: %4d, V: %4d; Area: %d\n", i, pTarget->sum_gu/pTarget->sum_g, pTarget->sum_gv/pTarget->sum_g, (pTarget->sp8<<8)+(pTarget->sp47)+pTarget->sp03);

} i++; }while (pImageInfo->dummy[Main.0] != 0x30201000);

rawFile.Read(buff + 20, 20); printf("\n\nImageCloser:\n"); for (i=0; i < 5; i++) printf("%08X", ntohl(pImageInfo->dummy[Main.i])); printf("\nImage Number: %d\n", pImageInfo->ulImageNumber);

} cin>>buff[Main.0];

}

return nRetCode; } **/

Next step is to convert TXT files into TIFF images ("brute force" but works)

We should modify the existing 3D-PTV code in such a way that it does not work with images anymore, but with text files, generated by raw2points.cpp (or even reading/writing RAW files, saving another conversion). However, since it will take too much time, in order to test the things quickly we took the TXT files and using the attached Matlab code (sorry Python :-)) we generate TIFF images that are read by the 3D-PTV software.

% txt2image_v3
% using plot_circle and poly2mask
%

sy = 1280; sx = 1024; Radius = 5; % small dots

plotoutput = true; saveoutput = true; % cd('sobel_2\txt'); % cd('sobel_070822/cal1'); directoryname = uigetdir('f:\ptv\sobel'); curdir = cd; addpath(curdir); cd(directoryname); if ~exist('img2','dir'), mkdir('img2'), end

d = dir('*.txt');

% f = @(x) mean2(x);

if plotoutput, figure; end

for i = 1:length(d) [filepath,filename,fileext] = fileparts(d(i).name); points = load(fullfile(filepath,d(i).name)); x = points(:,1); % 1280 y = points(:,2); % 1024 bw = uint8(zeros(sx,sy));

tic for j = 1:length(x) output_coord = plot_circle(x(j),y(j),Radius); bw = imadd(bw,uint8(poly2mask(output_coord(:,1),output_coord(:,2),sx,sy))); end toc

bw(bw>0) = 255; bw = flipud(bw); cam1 = bw(1:ceil(sx/2),1:ceil(sy/2)); cam2 = bw(1:ceil(sx/2),ceil(sy/2)+1:end); cam3 = bw(ceil(sx/2)+1:end,1:ceil(sy/2)); cam4 = bw(ceil(sx/2)+1:end,ceil(sy/2)+1:end);

if plotoutput subplot(221), imshow(cam1) subplot(222), imshow(cam2) subplot(223), imshow(cam3) subplot(224), imshow(cam4) drawnow end

if saveoutput imwrite(cam1,['./img2/Cam1.',filename(4:end)],'tiff','compression','none'); imwrite(cam3,['./img2/Cam2.',filename(4:end)],'tiff','compression','none'); imwrite(cam2,['./img2/Cam3.',filename(4:end)],'tiff','compression','none'); imwrite(cam4,['./img2/Cam4.',filename(4:end)],'tiff','compression','none'); end end cd(curdir);

Preliminary results


test.jpg

Figure 5: Original image of the calibration target through the 4-view splitter and red cirlces marking the detected particles from the FPGA Sobel filter.

Appendix

Visit of Mr. Andreas Ertl, Mikrotron GmbH





Comments

No comments for this document
legal terms | privacy policy | contact | © 2006-2008 Netcipia® Inc. - All rights reserved