utils.c
来自「Rob Hess Linux下的SIFT提取源码」· C语言 代码 · 共 420 行
C
420 行
/* Miscellaneous utility functions. Copyright (C) 2006-2007 Rob Hess <hess@eecs.oregonstate.edu> @version 1.1.1-20070913*/#include "utils.h"#include <cv.h>#include <cxcore.h>#include <highgui.h>#include <gdk/gdk.h>#include <gtk/gtk.h>#include <errno.h>#include <string.h>#include <stdlib.h>/*************************** Function Definitions ****************************//* Prints an error message and aborts the program. The error message is of the form "Error: ...", where the ... is specified by the \a format argument @param format an error message format string (as with \c printf(3)).*/void fatal_error(char* format, ...){ va_list ap; fprintf( stderr, "Error: "); va_start( ap, format ); vfprintf( stderr, format, ap ); va_end( ap ); fprintf( stderr, "\n" ); abort();}/* Replaces a file's extension, which is assumed to be everything after the last dot ('.') character. @param file the name of a file @param extn a new extension for \a file; should not include a dot (i.e. \c "jpg", not \c ".jpg") unless the new file extension should contain two dots. @return Returns a new string formed as described above. If \a file does not have an extension, this function simply adds one.*/char* replace_extension( const char* file, const char* extn ){ char* new_file, * lastdot; new_file = calloc( strlen( file ) + strlen( extn ) + 2, sizeof( char ) ); strcpy( new_file, file ); lastdot = strrchr( new_file, '.' ); if( lastdot ) *(lastdot + 1) = '\0'; else strcat( new_file, "." ); strcat( new_file, extn ); return new_file;}/* Prepends a path to a filename. @param path a path @param file a file name @return Returns a new string containing a full path name consisting of \a path prepended to \a file.*/char* prepend_path( const char* path, const char* file ){ int n = strlen(path) + strlen(file) + 2; char* pathname = calloc( n, sizeof(char) ); snprintf( pathname, n, "%s/%s", path, file ); return pathname;}/* A function that removes the path from a filename. Similar to the Unix basename command. @param pathname a (full) path name @return Returns the basename of \a pathname.*/char* basename( const char* pathname ){ char* base, * last_slash; last_slash = strrchr( pathname, '/' ); if( ! last_slash ) { base = calloc( strlen( pathname ) + 1, sizeof( char ) ); strcpy( base, pathname ); } else { base = calloc( strlen( last_slash++ ), sizeof( char ) ); strcpy( base, last_slash ); } return base;}/* Displays progress in the console with a spinning pinwheel. Every time this function is called, the state of the pinwheel is incremented. The pinwheel has four states that loop indefinitely: '|', '/', '-', '\'. @param done if 0, this function simply increments the state of the pinwheel; otherwise it prints "done"*/void progress( int done ){ char state[4] = { '|', '/', '-', '\\' }; static int cur = -1; if( cur == -1 ) fprintf( stderr, " " ); if( done ) { fprintf( stderr, "\b\bdone\n"); cur = -1; } else { cur = ( cur + 1 ) % 4; fprintf( stdout, "\b\b%c ", state[cur] ); fflush(stderr); }}/* Erases a specified number of characters from a stream. @param stream the stream from which to erase characters @param n the number of characters to erase*/void erase_from_stream( FILE* stream, int n ){ int j; for( j = 0; j < n; j++ ) fprintf( stream, "\b" ); for( j = 0; j < n; j++ ) fprintf( stream, " " ); for( j = 0; j < n; j++ ) fprintf( stream, "\b" );}/* Doubles the size of an array with error checking @param array pointer to an array whose size is to be doubled @param n number of elements allocated for \a array @param size size in bytes of elements in \a array @return Returns the new number of elements allocated for \a array. If no memory is available, returns 0.*/int array_double( void** array, int n, int size ){ void* tmp; tmp = realloc( *array, 2 * n * size ); if( ! tmp ) { fprintf( stderr, "Warning: unable to allocate memory in array_double()," " %s line %d\n", __FILE__, __LINE__ ); if( *array ) free( *array ); *array = NULL; return 0; } *array = tmp; return n*2;}/* Calculates the squared distance between two points. @param p1 a point @param p2 another point*/double dist_sq_2D( CvPoint2D64f p1, CvPoint2D64f p2 ){ double x_diff = p1.x - p2.x; double y_diff = p1.y - p2.y; return x_diff * x_diff + y_diff * y_diff;}/* Draws an x on an image. @param img an image @param pt the center point of the x @param r the x's radius @param w the x's line weight @param color the color of the x*/void draw_x( IplImage* img, CvPoint pt, int r, int w, CvScalar color ){ cvLine( img, pt, cvPoint( pt.x + r, pt.y + r), color, w, 8, 0 ); cvLine( img, pt, cvPoint( pt.x - r, pt.y + r), color, w, 8, 0 ); cvLine( img, pt, cvPoint( pt.x + r, pt.y - r), color, w, 8, 0 ); cvLine( img, pt, cvPoint( pt.x - r, pt.y - r), color, w, 8, 0 );}/* Combines two images by scacking one on top of the other @param img1 top image @param img2 bottom image @return Returns the image resulting from stacking \a img1 on top if \a img2*/extern IplImage* stack_imgs( IplImage* img1, IplImage* img2 ){ IplImage* stacked = cvCreateImage( cvSize( MAX(img1->width, img2->width), img1->height + img2->height ), IPL_DEPTH_8U, 3 ); cvZero( stacked ); cvSetImageROI( stacked, cvRect( 0, 0, img1->width, img1->height ) ); cvAdd( img1, stacked, stacked, NULL ); cvSetImageROI( stacked, cvRect(0, img1->height, img2->width, img2->height) ); cvAdd( img2, stacked, stacked, NULL ); cvResetImageROI( stacked ); return stacked;}/* Displays an image, making sure it fits on screen. cvWaitKey() must be called after this function so the event loop is entered and the image is displayed. @param img an image, possibly too large to display on-screen @param title the title of the window in which \a img is displayed*/void display_big_img( IplImage* img, char* title ){ IplImage* small; GdkScreen* scr; int scr_width, scr_height; double img_aspect, scr_aspect, scale; /* determine screen size to see if image fits on screen */ gdk_init( NULL, NULL ); scr = gdk_screen_get_default(); scr_width = gdk_screen_get_width( scr ); scr_height = gdk_screen_get_height( scr ); if( img->width >= 0.90 * scr_width || img->height >= 0.90 * scr_height ) { img_aspect = (double)(img->width) / img->height; scr_aspect = (double)(scr_width) / scr_height; if( img_aspect > scr_aspect ) scale = 0.90 * scr_width / img->width; else scale = 0.90 * scr_height / img->height; small = cvCreateImage( cvSize( img->width * scale, img->height * scale ), img->depth, img->nChannels ); cvResize( img, small, CV_INTER_AREA ); } else small = cvCloneImage( img ); cvNamedWindow( title, 1 ); cvShowImage( title, small ); cvReleaseImage( &small );}/* Allows user to view an array of images as a video. Keyboard controls are as follows: <ul> <li>Space - start and pause playback</li> <li>Page Down - skip forward 10 frames</li> <li>Page Up - jump back 10 frames</li> <li>Right Arrow - skip forward 1 frame</li> <li>Left Arrow - jump back 1 frame</li> <li>Backspace - jump back to beginning</li> <li>Esc - exit playback</li> <li>Closing the window also exits playback</li> </ul> @param imgs an array of images @param n number of images in \a imgs @param win_name name of window in which images are displayed*/void vid_view( IplImage** imgs, int n, char* win_name ){ int k, i = 0, playing = 0; display_big_img( imgs[i], win_name ); while( ! win_closed( win_name ) ) { /* if already playing, advance frame and check for pause */ if( playing ) { i = MIN( i + 1, n - 1 ); display_big_img( imgs[i], win_name ); k = cvWaitKey( 33 ); if( k == ' ' || i == n - 1 ) playing = 0; } else { k = cvWaitKey( 0 ); switch( k ) { /* space */ case ' ': playing = 1; break; /* esc */ case 27: case 1048603: cvDestroyWindow( win_name ); break; /* backspace */ case '\b': i = 0; display_big_img( imgs[i], win_name ); break; /* left arrow */ case 65288: case 1113937: i = MAX( i - 1, 0 ); display_big_img( imgs[i], win_name ); break; /* right arrow */ case 65363: case 1113939: i = MIN( i + 1, n - 1 ); display_big_img( imgs[i], win_name ); break; /* page up */ case 65365: case 1113941: i = MAX( i - 10, 0 ); display_big_img( imgs[i], win_name ); break; /* page down */ case 65366: case 1113942: i = MIN( i + 10, n - 1 ); display_big_img( imgs[i], win_name ); break; } } }}/* Checks if a HighGUI window is still open or not @param name the name of the window we're checking @return Returns 1 if the window named \a name has been closed or 0 otherwise*/int win_closed( char* win_name ){ if( ! cvGetWindowHandle(win_name) ) return 1; return 0;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?