The source code is posted on google code.  You can download it straight from the interwebs with beagleboard.  Download the folder, run the Makefile, run ./slGPIO.cpp, and push the button to start scanning!  Once completed if the program finds a usbdrive it will save the point cloud there.  If not it will be saved in the results folder.

Contents

  • Graycoded Structured Light images [20]
  • Makefile  // includes links to openCV cflags and libs.  Use this to natively compile SL code.
  • sl.cpp  //sl program
  • slGPIO.cpp  // starting point.  Initializes GPIO interrupt and calls sl.cpp
  • results folder //result go here if no SDcard is found
Makefile
Makefiles are a timesaver, so Ill post the entire contents here for copy/paste purposes (myself included).  Notice the shell call to pkg-config.  This is a really handy way to link to the location of the openCV cflags and libs
# 'make'        build executable file 'mycc'
# 'make clean'  removes all .o and executable files

.PHONY: depend clean

SCAN = slGPIO
DISPLAY = display

CC = gcc
CFLAGS := -g -Wall -DLINUX $(shell pkg-config opencv --cflags)
LIBs := $(shell pkg-config opencv --libs)
LFLAGS =

# Source files
SRCs := \
	slGPIO.cpp
	#sl.cpp \

# List of object files to compile
OBJs = $(SRCs:.cpp=.o)

all: $(SCAN)

$(DISPLAY): display.o
	gcc -g -Wall 

$(SCAN): $(OBJs)
	$(CC) $(CFLAGS) $(INCLUDES) -o $(SCAN) $(OBJs) $(LFLAGS) $(LIBs)

# 	cp $(SCAN) Release/

%.o: %.cpp %.h
	$(CC) $(CFLAGS) $(INCLUDES) -c $<  -o $@

clean:
	$(RM) *.o *~ $(SCAN)
sl.cpp

The sl code was written by myself and Peter Hokanson.  Its not to long and is broken up into 3 sections.  The source code will likely be easier to read with proper highlighting.  OpenCV was only used to manipulate the camera and projector.  Part 1 below projects and captures the images:

#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <assert.h> // For my own paranoia's sake
#include <opencv/cv.h>
#include <opencv/highgui.h>
#define WHITE_THRESHOLD 5
#define BLACK_THRESHOLD -5
#define NUM_IMAGES 18
#define CAM_WIDTH 640
#define PROJ_WIDTH 640
#define Z_SCALE 500   //250 works

//#define TEST_RECOGNIZER

int gray2bin(int gray);
bool file_exists(const char * filename);
int slScanner(void);

int slScanner(void)
{
	//*********PART1 - Project SL and Cap Imgs************
	//Initialize
	IplImage* slPat[NUM_IMAGES] = {0};
	IplImage* capImg[NUM_IMAGES + 1] = {0};
// 	int height,width,step,channels;
	uchar *data;
	char s[128];
	int i,outFileNum=0;

	//Usage
	//if(argc>1){
	//	printf("Usage: sl images are in same folder named grayIMGx.png and range from 0-19\n");
	//	exit(0);
	//}

	//Load sl images
#ifndef TEST_RECOGNIZER
	for(int i=0;i<NUM_IMAGES;i++){
		sprintf(s,"%d.png",i+1);
		slPat[i]=cvLoadImage(s);
		if(!slPat[i]){
			printf("Could not load image file: %s\n",s);
			exit(0);
		}
	}

	// create a window
	cvStartWindowThread();
	cvNamedWindow("mainWin", CV_WINDOW_NORMAL);
	cvSetWindowProperty("mainWin", CV_WND_PROP_FULLSCREEN, CV_WINDOW_FULLSCREEN);

	// pause
	cvWaitKey(500);

	// set up camera
	CvCapture* capture = cvCaptureFromCAM( CV_CAP_ANY );
	if (!capture){
		fprintf( stderr, "Camera not found \n");
		getchar();
		exit(0);
	}
	cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 480);
	cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 640);
	//cvSetCaptureProperty(capture, CV_CAP_PROP_FPS, 5);
	//cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_COUNT, 1);
	//Maybe this will fix the frame delay?

	//Display images and capture
	for(int i=0;i<NUM_IMAGES;i++){

		// show the image
		cvShowImage("mainWin", slPat[i] );

		// pause
		cvWaitKey(5);

		// capture the image
		cvGrabFrame(capture);
		cvGrabFrame(capture);
		cvGrabFrame(capture);
		cvGrabFrame(capture);
		cvGrabFrame(capture); //Get to last frame in buffer
		capImg[NUM_IMAGES + 1] = cvRetrieveFrame(capture);   

		// write the image
		//cvWriteFrame(writer, capImg[i]);
		capImg[i] = cvCloneImage(capImg[NUM_IMAGES + 1]);
		sprintf(s,"results/%d.png",i+1);
		cvSaveImage(s,capImg[i]);
	}

	cvReleaseCapture(&capture);

	//Display captured images for debug
	for(int i=0;i<NUM_IMAGES;i++){

		// show the image (for debug)
		cvShowImage("mainWin", capImg[i] );

		// pause
		cvWaitKey(100);
	}

#else // TEST_RECOGNIZER
	for(int i=0;i<NUM_IMAGES;i++) {
		sprintf(s,"setupp/%d.png",i+1);
		capImg[i]=cvLoadImage(s);
		if(!capImg[i]){
			printf("Could not load image file: %s\n",s);
			exit(0);
		}
	}
#endif

Part 2 contains the SL decoding and depth redering algorithm:

	//*********PART2 - Decode captured images************

	// First initialize a matrix for showing the decoded values, needs 10 bits,
	// so could move to short* if memory becomes an issue.
	int *columnmap = (int*)calloc(capImg[0]->imageSize, sizeof(int));
	if(columnmap == NULL) {
		printf("Allocation for column map failed! Aborting\n");
		return 1;
	}

	// We're going to step over matching inverse pairs of projected patterns, and
	// perform a threshold operation to determine whether a given pixel is white
	// or not.
	for(int i=0;i<NUM_IMAGES;i+=2){
		printf("Processing scan patterns %d, %d\n",i,i+1);
		uchar* data1 = (uchar*)capImg[i]->imageData;
		uchar* data0 = (uchar*)capImg[i+1]->imageData;

		for(int y=0;y<capImg[i]->height;y++){
			for(int x=0;x<capImg[i]->width;x++) {
				int u = y*capImg[i]->widthStep+x*capImg[i]->nChannels;
				if(columnmap[u] == -1){
					// We have discarded this pixel
					continue;
				}
				int gray1 = data1[u] + data1[u+1] + data1[u+2];
				int gray0 = data0[u] + data0[u+1] + data0[u+2]; 

				// Shift our Gray code bit vector
				columnmap[u] = columnmap[u] << 1;
				if(gray1 - gray0 > WHITE_THRESHOLD){
					// We have a white pixel!
					assert((columnmap[u] & 1) == 0);
					columnmap[u] |= 1;
				} else if(gray1 - gray0 < BLACK_THRESHOLD){
					// A black pixel
					assert((columnmap[u] & 1) == 0);
					columnmap[u] |= 0;
				} else {
					// Not quite sure about this pixel: Punt!
					columnmap[u] = -1;
				}
			}
		}

		// Avoid memory leaks!
// 		printf("Releasing images %d, %d\n", i,i+1);
// 		cvReleaseImage(&capImg[i]);
// 		cvReleaseImage(&capImg[i+1]);
	}

	// Convert Gray code to decimal
	for(i = 0; i < capImg[0]->imageSize; i++){
// 		int tmp = columnmap[i];
		columnmap[i] = gray2bin(columnmap[i]);
// 		printf("Gray: %4x -> Binary %4x\n",tmp,columnmap[i]);
	}

	// TODO: Test against projector patterns -> 0 disparity
	// TODO: Test with SL images

    //Find available filename on jumpdrive
    sprintf(s,"/media/sda1/result%d.xyz",outFileNum);
    while (file_exists(s)) {
        outFileNum++;
        sprintf(s,"/media/sda1/result%d.xyz",outFileNum);
    }

	// Write the pointcloud
	FILE *f = fopen(s,"w");
	if(f == NULL) {
	  printf("Error opening %s:  Trying local directory...\n",s);
	  FILE *f = fopen("result.xyz","w");
	  if(f == NULL) {
            printf("Error opening result.xyz:  Aborting!\n");
            return 1;
	  }
	}

	printf("Writing pointcloud...\n");
	for(int y = 0;y < capImg[0]->height; y++){
		for(int x = 0;x < capImg[0]->width; x++) {
			int u = y*capImg[0]->widthStep+x*capImg[0]->nChannels;

			if(columnmap[u] == -1) continue; // Discarded!

			float disp = (float)columnmap[u]/(PROJ_WIDTH) - (float)x/CAM_WIDTH;
// 			printf("%f\n",disp);
			if(disp == 0.0) continue;
			float z = (float)Z_SCALE/(disp);

			fprintf(f,"%d %d %f\n",x,y,z);
		}
	}

	fclose(f);

Part 3 is a work in progress.  All thats contained here is some cleanup.

	//*******Part3 - Project 3D object with openGL*********

	for(int i = 0; i < NUM_IMAGES; i++){
		cvReleaseImage(&capImg[i]);
		//cvReleaseImage(&slPat[i]);
	}
	//Exit
	cvDestroyWindow("mainWin");
	free(columnmap);
	return 0;
}

<–Previous     Project Home     Next –>


Be Sociable, Share!
  1. ryan says:

    When I run the slGPIO command it says starting scanning then quickly gives up with a gtk error cant find display
    I have the same setup as you have here, other than my switch is just 2 pins joined together and my camera is the 5mp one which seems to be working ok