/* =========================================================================== * | | | Copyright (c) 2003, by members of University of Arizona Computer Vision | | group (the authors) including || | Kobus Barnard. | | | | For use outside the University of Arizona Computer Vision group please | | contact Kobus Barnard. | | | * =========================================================================== */ /* * This is an example program to get help those wanting to try using the vision * group's software library. This library is currently undergoing adaptation * from a bunch of research code written by Kobus and others to a comprehensive * library to support the acitivities of the vision group. Thus there will be * problems--please report them--and have some patience. Thanks! * * Resources * * Manpages (MANPATH ~kobus/doc/man) * Start with a "man kjb". Note that the first part of the document is a bit * overwhelming, as it is geared towards writing substantive vision * copmponents shared with the group and/or, writing code for the library * itself (hence this example!!!). This document essentially gives you a * template for the "INCLUDE AND LOAD" strategy described by "man kjb". * * A key point is that "man kjb" gives a machine generated list of all * routines which have at least minimal documentation. (Perhaps 1/2 of the * routines of interest are documented.) * * Note that there are man pages for the main data types. In particular, you * can do: * man Vector * man Matrix * man KJB_image * man Pixel * * Other documenation * There are some documentation files which attempt to explain some of the * less conventional things about the library in the following directory: * ~kobus/doc/programming * I wrote it a few years back--hopefully it is not too out of date. * * The accomponying file "compile_line" gives the incantation to compile this * program. It is: * gcc -W -Wall -ansi -DLINUX_386 -DLINUX_386_ATHLON \ -DHAVE_TIFF -DHAVE_JPEG -DHAVE_SLATEC -DHAVE_LAPACK \ -I ~kobus/include/kjb \ example.c \ -L ~kobus/load/linux_386_p4 \ -L/usr/X11R6/lib/ \ -lKJB -lXext -lX11 -lcurses -llapack -lblas -ltiff -ljpeg -lg2c -lm \ -o example * * What the program does * * The program reads a matrix from the file "matrix.txt", insisting that the * matrix has at least 2 columns, and at least as many rows as columns. (An * example can be found in "matrix.txt"). Having read the matrix, it sets the * upper left corner element to 10, and switches columns one and two. Having * done that, it computes the transpose multiplied by the matrix, and finds the * eigenvectors and eigenvalues of the result. * * The program then checks for a file "image.tiff" in the current directory. If * it exists, then it read it, averages 2 by 2 pixels blocks to reduce the * size, and convolves it with a Gaussian filter which blurs it, displays the * result, and also writes it to "result.tiff". * * ONE SLIGHTLY TRICKY BIT * * I like to check the return values of functions. To keep the example short, I * have employed an ugly looking macro EPETE, which checks for error return, * and if there is one, prints a message and forces a program exit. To * understand what the code does when there are no error conditions, you can * ignore the wrapper. (A C++ programmer would likely handle this with * exceptions which has advantages and disadvantages). */ /* Either include specific .h files, or the whole lot with kjb.h */ #include "i/i_incl.h" #include "m/m_incl.h" #include "n/n_incl.h" /* #include "kjb.h" */ int main(int argc, char** argv) { /* Important note: These things need to be initialzed to NULL !!! */ Matrix* mp = NULL; Matrix* square_mp = NULL; Vector* col1_vp = NULL; Vector* col2_vp = NULL; Matrix* eigen_vectors_mp = NULL; Vector* eigen_values_vp = NULL; KJB_image* ip = NULL; KJB_image* result_ip = NULL; /* Not absolutely necessary, but recommended. */ kjb_init(); /* * EPETE just wraps the function in case of error. (See comment above). */ EPETE(read_matrix(&mp, "matrix.txt")); if ((mp->num_rows < mp->num_cols) || (mp->num_cols < 2)) { p_stderr("This program needs a matrix with at least two columns\n"); p_stderr("and at least as many rows as columns.\n"); kjb_exit(EXIT_FAILURE); } /* Set first element to 10 */ mp->elements[ 0 ][ 0 ] = 10; /* Swap the columns one and two. */ EPETE(get_matrix_col(&col1_vp, mp, 0)); EPETE(get_matrix_col(&col2_vp, mp, 1)); EPETE(put_matrix_col(mp, col1_vp, 1)); EPETE(put_matrix_col(mp, col2_vp, 0)); /* * Write the result to stdout to check it. */ pso("The mucked matrix:\n"); /* This is an extended printf */ EPETE(write_matrix(mp, NULL)); /* * Put (transpose(mp))*mp into square_mp. */ EPETE(multiply_with_transpose(&square_mp, mp, mp)); /* * Find the eigen-values and eigen-vectors. */ EPETE(diagonalize(square_mp, &eigen_vectors_mp, &eigen_values_vp)); /* * Lets have a look. */ pso("\nThe eigenvalues (note that we do biggest first--opposit of Matlab:\n"); EPETE(write_col_vector(eigen_values_vp, NULL)); pso("\nThe eigenvectors:\n"); EPETE(write_matrix(eigen_vectors_mp, NULL)); pso("\n"); if (kjb_read_image_2(&ip, "image.tiff") == ERROR) { kjb_print_error(); } else { EPETE(ave_image(&result_ip, ip, 2 , 2)); EPETE(ow_gauss_convolve_image(result_ip, 4.0)); /* This uses a pipe to an appropriate display program which has to be in * your path. */ EPETE(kjb_display_image(result_ip, (char*)NULL)); /* The display of the image will die with the program. If you want to * have the display of the image survie, you would use EPETE(fork_display_image(result_ip, (char*)NULL)); * However, here we will ask the user to tell use that they are done * looking at it: */ prompt_to_continue(); /* Note that the image format is specifed by the suffix, so we get a * tiff image (ImageMagick convention). */ EPETE(kjb_write_image(result_ip, "result.tiff")); } /* * Don't forget to clean up (OK, not absolutely necessary, as the program is * about to end, but a good habbit). */ free_matrix(mp); free_matrix(square_mp); free_matrix(eigen_vectors_mp); free_vector(eigen_values_vp); free_vector(col1_vp); free_vector(col2_vp); kjb_free_image(result_ip); kjb_free_image(ip); /* Normally not needed but recommended just in case--doing it twice is OK.*/ kjb_cleanup(); return EXIT_SUCCESS; }