Real Time Image Compression with Mikrotron MC1324
- http://www.ifu.ethz.ch/publications/software/ptv
- http://alexl.wordpress.com/research/3d-ptv/
- http://www.eng.tau.ac.il/efdl/pmwiki.php?n=Lab.Hardware
- http://www.ioindustries.com/ptv.htm
The camera
The camera is shown and described in details on the website of Mikrotron
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:
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:
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:
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 RAWConversion 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

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.

Page
Place
Space
Comments
No comments for this document