From: Petr Kubiznak Date: Sat, 29 May 2010 10:25:49 +0000 (+0200) Subject: Image mode added - used on PC to process just one image from file (does not use camer... X-Git-Tag: start2011~7 X-Git-Url: https://rtime.felk.cvut.cz/gitweb/eurobot/public.git/commitdiff_plain/33f412aad5f7ff1a89c2a86af7e619037dd7eb92 Image mode added - used on PC to process just one image from file (does not use camera). Needs to be reviewed and written better! Threshold correction. --- diff --git a/src/camera/rozkuk/rozkuk.cxx b/src/camera/rozkuk/rozkuk.cxx index 1b478ed5..7bee1f94 100644 --- a/src/camera/rozkuk/rozkuk.cxx +++ b/src/camera/rozkuk/rozkuk.cxx @@ -39,13 +39,14 @@ extern "C" { #define MODE_REALTIME 0x02 #define MODE_RECOGNIZE 0x04 #define MODE_WAIT 0x08 +#define MODE_IMAGE 0x10 // mask of all modes / errors -#define MASK_MODES 0x0F +#define MASK_MODES 0x1F #define MASK_ERRORS (~MASK_MODES) // errors -#define ERR_MASK_READ_FAILURE 0x10 +#define ERR_MASK_READ_FAILURE 0x20 // default mode in standard session (i.e. on ppc) #define START_MODE MODE_WAIT @@ -73,6 +74,8 @@ extern "C" { #define KEY_r 0x72 #define KEY_s 0x73 #define KEY_w 0x77 +#define KEY_PLUS -0x55 +#define KEY_MINUS -0x53 // number of frames passed in rozkuk mode before refresh #define PASS_FRAMES 0 @@ -82,7 +85,7 @@ extern "C" { //default threshold and saturation #define THRESHOLD 70 //not used #define SATURATION 1.0 -#define THRESHOLD_SHIFT -10 //improves the automatic threshold by shifting by this value +#define THRESHOLD_SHIFT -25 //improves the automatic threshold by shifting by this value //mask filename pattern #ifdef ROZKUK_DEBUG /************ DEBUG SESSION ONLY ************/ @@ -106,7 +109,7 @@ extern "C" { //camera control system (if true, rozkuk recognizes, else it waits) #ifdef ROZKUK_DEBUG /************ DEBUG SESSION ONLY ************/ -#define ORTE_CAMERA_CONTROL camera_control_on +#define ORTE_CAMERA_CONTROL 1 #else /******************** PPC *******************/ #define ORTE_CAMERA_CONTROL camera_control_on #endif /*------------------------------------------*/ @@ -120,11 +123,13 @@ void drawPauseText(IplImage *img); void displayProduct(const CvMat *floatMat, int sideConfig, int centerConfig); void displayMasksSum(const CvMat *mat1, const CvMat *mat2, const char *windowName); void displayFloatMat(const CvMat *floatMat, const char *windowName); +int getParamI(int argc, char *argv[], char *imgFilename); +int modeImage(char *imageFilename); int modeRealtime(CvCapture* capture); #endif /*----------- DEBUG SESSION ONLY -----------*/ int modeRecognize(CvCapture* capture, CORBA_octet currentColor); int modeWait(CvCapture *capture); -int modeManager(int defaultMode); +int modeManager(int defaultMode, char *paramC=NULL); int countThreshold(const IplImage *frame); int recognize(const CvMat *frame, CvMat **masks, int masksCnt, double *resDist=NULL); int loadMask(const char *filename, CvMat **mask); @@ -233,6 +238,61 @@ void displayFloatMat(const CvMat *floatMat, const char *windowName) { /******************************************************************************/ +/** Simulates MODE_RECOGNIZE over one specified image filename. + * @return Code of mode to switch to. */ +int modeImage(char *imageFilename) { + int thr_change = 0; + IplImage *frame = NULL; // frame from camera + IplImage *thresFrame = cvCreateImage(cvSize(FRAME_WIDTH,FRAME_HEIGHT),IPL_DEPTH_8U,1); //thresholded frame + CvMat *floatMat = NULL; // float <-1,1> image of the frame + int sideConfig, centerConfig; // indices of recognized configurations + double sideDist, centerDist; // distances between the best and second best results + + frame = cvLoadImage(imageFilename); + if(!frame) { + fprintf(stderr, "File %s cannot be loaded as image.\n", imageFilename); + return MODE_QUIT; + } + + while(1) { + int threshold = countThreshold(frame) + THRESHOLD_SHIFT + thr_change; + if(threshold<0) threshold=0; + clr2float(frame, &floatMat, threshold, SATURATION, thresFrame); + //recognize side and center configurations + sideConfig = recognize(floatMat, sideMasks, SIDEMASKSCNT, &sideDist); + centerConfig = recognize(floatMat, centerMasks, CENTERMASKSCNT, ¢erDist); + fprintf(stderr, "SINGLE: thr: %3d (thr_change %d), side: %d (%.2f), center: %d (%.2f)\n", threshold, thr_change, sideConfig, sideDist, centerConfig, centerDist); + + displayProduct(floatMat, sideConfig, centerConfig); + cvShowImage(WINDOW_ORIG, frame); // show image (! Do not release the frame !) + cvShowImage(WINDOW_THRES, thresFrame); + displayMasksSum(sideMasks[sideConfig], centerMasks[centerConfig], WINDOW_MASK); // display selected mask + cvReleaseMat(&floatMat); + + /* keyboard events handeling */ + switch((char)(cvWaitKey(0) & 0xFF)) { // wait infinitely for an event + // increment threshold + case KEY_PLUS: + thr_change++; + break; + // decrement threshold + case KEY_MINUS: + thr_change--; + break; + // quit + case KEY_ESC: + goto QUIT; + break; + } + } +QUIT: + cvReleaseImage(&thresFrame); + cvReleaseImage(&frame); + return MODE_QUIT; +} + +/******************************************************************************/ + /** Displays a real video in a window (only for DEBUG session). * @param capture Pointer to a camera capture. * @return Code of mode to switch to. */ @@ -430,15 +490,16 @@ int modeWait(CvCapture *capture) { /******************************************************************************/ /** Switches between modes of the program. - * @param defaultMode The first mode to run. */ -int modeManager(int defaultMode) { + * @param defaultMode The first mode to run. + * @param paramC Used only in MODE_IMAGE mode. */ +int modeManager(int defaultMode, char *paramC) { int mode=defaultMode; int ret; CvCapture* capture; CORBA_octet color; // connect to a camera - while(!((capture=cvCaptureFromCAM(0)) || (capture=cvCaptureFromCAM(1)))) { + while(!((capture=cvCaptureFromCAM(0)) || (capture=cvCaptureFromCAM(1)) || (defaultMode==MODE_IMAGE))) { fprintf(stderr, "NULL capture (is camera connected?)\n"); orte.camera_result.error |= camera_ERR_NO_VIDEO; ORTEPublicationSend(orte.publication_camera_result); @@ -462,6 +523,20 @@ int modeManager(int defaultMode) { cvDestroyWindow(WINDOW_THRES); mode = modeRealtime(capture); break; + + case MODE_IMAGE: + cvNamedWindow(WINDOW_THRES, CV_WINDOW_AUTOSIZE); + cvMoveWindow(WINDOW_THRES, cvQueryFrame(capture)->width, 0); + cvNamedWindow(WINDOW_MASK, CV_WINDOW_AUTOSIZE); + cvMoveWindow(WINDOW_MASK, 0, cvQueryFrame(capture)->height+50); + cvNamedWindow(WINDOW_PROD, CV_WINDOW_AUTOSIZE); + cvMoveWindow(WINDOW_PROD, cvQueryFrame(capture)->width, cvQueryFrame(capture)->height+50); + //load masks and run recognition mode, then free masks (they are in memory only while in recognition mode) + color = robot_switches_color; + if((ret=loadMasks((color==BLUE ? clBLUE : clYELLOW)))) return ret; + mode = modeImage(paramC); + freeMasks(); + break; #endif /*----------- DEBUG SESSION ONLY -----------*/ case MODE_RECOGNIZE: @@ -532,6 +607,32 @@ int recognize(const CvMat *frame, CvMat **masks, int masksCnt, double *resDist) /******************************************************************************/ +#ifdef ROZKUK_DEBUG /************ DEBUG SESSION ONLY ************/ +/** If "-i filename" is in argv, filename is stored to imgFilename. + * @return True if "-i filename" specified, else false. */ +int getParamI(int argc, char *argv[], char *imgFilename) { + char opt; + + // scan for program arguments + while((opt = getopt(argc, argv, "i:")) != -1) { + switch (opt) { + case 'i': + if(optarg) sprintf(imgFilename, "%s", optarg); //image filename + else { + fprintf(stderr, "Specify image filename to process: rozkuk -i filename\n"); + return -1; + } + return 1; + break; + } + } + + return 0; +} +#endif /*----------- DEBUG SESSION ONLY -----------*/ + +/******************************************************************************/ + /** Loads binary (float) data to *mask from file. * @param filename Path to file to read. * @param mask Address of array, where to alloc memory and store the data. @@ -674,6 +775,12 @@ int main(int argc, char *argv[]) { robottype_subscriber_camera_control_create(&orte, rcv_cmr_ctrl_cb, &orte); robottype_subscriber_robot_switches_create(&orte, rcv_robot_switches_cb, &orte); +#ifdef ROZKUK_DEBUG /************ DEBUG SESSION ONLY ************/ + // if "-i filename" specified, program processes only the one image and terminates + char imgFilename[100]; + if(getParamI(argc, argv, imgFilename)) return modeManager(MODE_IMAGE, imgFilename); +#endif /*----------- DEBUG SESSION ONLY -----------*/ + modeManager(START_MODE); ret = robottype_roboorte_destroy(&orte);