Main Page   Class Hierarchy   Compound List   File List   Compound Members   File Members   Related Pages  

ImageGrey.cpp

Go to the documentation of this file.
00001 /**************************************************************************
00008  *
00009  * Source code for Real Time Image Library (libRTImage)
00010  *
00011  * Leeds Vision Group give permission for this code to be copied, modified 
00012  * and distributed within the University of Leeds subject to the following 
00013  * conditions:-
00014  *
00015  * - The code is not to be used for commercial gain.
00016  * - The code and use thereof will be attributed to the author where
00017  *   appropriate (inluding demonstrations which rely on it's use).
00018  * - All modified, distributions of the source files will retain this header.
00019  *
00020  ****************************************************************************/
00021 
00022 #include <new>          // bad_alloc exception
00023 #include <string.h>     // memcpy
00024 #include <MicrosoftBMP_RT.h>
00025 #include <MicrosoftRCBMP_RT.h>
00026 #include <MicrosoftMonoBMP_RT.h>
00027 #include <math.h>
00028 #include <limits.h>
00029 #include <stdlib.h>
00030 #include <iostream>
00031 
00032 using namespace std;
00033  
00034 #include "ImageGrey.h"
00035 
00036 static int int_compare(const void *i1, const void *i2) ;
00037 
00038 ImageGrey::ImageGrey(ImageGrey& img) : ImageBase(img)
00044 {
00045         unsigned int array_size = img.width * img.height;
00046         brightness = new PixelGrey[array_size];
00047 
00048         *this = img;
00049 }
00050 
00051 
00052 ImageGrey::ImageGrey(unsigned int w, unsigned int h) : ImageBase(w,h)
00059 {
00060         unsigned int array_size = width * height;
00061         brightness = new PixelGrey[array_size];
00062 
00063 //      clear();
00064 }
00065 
00066 ImageGrey::ImageGrey(char *filename, FileFormat format)
00075 {
00076 
00077     if(format == FORMAT_BMP_24){
00078         MicrosoftBMP_RT bmp(filename) ;
00079 
00080         if(!bmp.read()) throw("Invalid Bitmap file specified") ;
00081 
00082         width = bmp.ImageWidth ;
00083         height = bmp.ImageHeight ;
00084 
00085         brightness = new int[width*height] ;
00086 
00087         bmp.extract_data_grey((int *)brightness) ;
00088     }
00089     else if(format == FORMAT_BMP_RC){
00090         MicrosoftRCBMP_RT bmp(filename) ;
00091 
00092         if(!bmp.read()) throw("Invalid Bitmap file specified") ;
00093 
00094         width = bmp.ImageWidth ;
00095         height = bmp.ImageHeight ;
00096 
00097         brightness = new int[width*height] ;
00098 
00099         bmp.extract_data_grey((int *)brightness) ;
00100     }
00101     else if(format == FORMAT_BMP_MONO){
00102         MicrosoftMonoBMP_RT bmp(filename) ;
00103 
00104         if(!bmp.read()) throw("Invalid Bitmap file specified") ;
00105 
00106         width = bmp.ImageWidth ;
00107         height = bmp.ImageHeight ;
00108 
00109         brightness = new int[width*height] ;
00110 
00111         bmp.extract_data_grey((int *)brightness) ;
00112     }
00113     else if(format == FORMAT_BMP_ANY){
00114     // Check all formats
00115          MicrosoftBMP_RT* bmp ;
00116          MicrosoftRCBMP_RT *bmp_rc;
00117          MicrosoftMonoBMP_RT *bmp_mono;
00118 
00119          if((bmp = new  MicrosoftBMP_RT(filename)) != NULL &&
00120             bmp->read()){
00121          // 24 bit bmp
00122             width = bmp->ImageWidth ;
00123             height = bmp->ImageHeight ;
00124 
00125             brightness = new int[width*height] ;
00126 
00127             bmp->extract_data_grey((int *)brightness) ;
00128          }
00129          else if((bmp_rc = new  MicrosoftRCBMP_RT(filename)) != NULL &&
00130             bmp_rc->read()){
00131          // Reduced clour (palette) bmp
00132             width = bmp_rc->ImageWidth ;
00133             height = bmp_rc->ImageHeight ;
00134 
00135             brightness = new int[width*height] ;
00136 
00137             bmp_rc->extract_data_grey((int *)brightness) ;
00138 
00139          }
00140          else if((bmp_mono = new  MicrosoftMonoBMP_RT(filename)) != NULL &&
00141             bmp_mono->read()){
00142          // Monochrome (b+w) bmp
00143             width = bmp_mono->ImageWidth ;
00144             height = bmp_mono->ImageHeight ;
00145 
00146             brightness = new int[width*height] ;
00147 
00148             bmp_mono->extract_data_grey((int *)brightness) ;
00149          }
00150     }
00151 
00152 
00153 
00154 
00155 }
00156 
00157 
00158 ImageGrey::ImageGrey(ImageGrey&    img,
00159                      unsigned int min_x,
00160                      unsigned int min_y,
00161                      unsigned int max_x,
00162                      unsigned int max_y) : 
00163                                         ImageBase(max_x-min_x+1, max_y-min_y+1)
00172 {
00173         brightness = new int[width*height];
00174         copy(img, min_x, min_y, max_x, max_y, 0, 0) ;
00175 }
00176 
00177 
00178 ImageGrey::~ImageGrey()
00182 {
00183     delete [] brightness;
00184 }
00185 
00186 
00187 void ImageGrey::set_pixel(unsigned int x, unsigned int y, PixelGrey level)
00195 {
00196         // Check that co-ords are valid. 
00197         if (x > width || y > height)
00198                 throw "Invalid Coordinates in method set_rgb";
00199 
00200         unsigned int offset = y * width + x;
00201         brightness[offset]  = level;
00202 }
00203 
00204 
00205 void ImageGrey::get_pixel(unsigned int x, unsigned int y, PixelGrey& p)
00213 {
00214         p = brightness[y * width + x];
00215 }
00216 
00217 
00218 
00219 ImageGrey& ImageGrey::clear(int k)
00225 {
00226         int *start = brightness;
00227         int *end   = start + width * height;
00228                 
00229         for (int *d = start; d < end; d++) *d = k;
00230 
00231         return *this;
00232 }
00233 
00234 
00235 ImageGrey& ImageGrey::copy(ImageGrey& img)
00242 {       
00243         /* check we're not trying to copy ourself */
00244         if (this == &img)
00245                 throw "Source and Destination are same Image";
00246         
00247         /* First check images are the same size and valid */
00248         if (width  != img.width || height != img.height) 
00249                 throw "Difference in image dimensions"; 
00250         
00251         /* Perform copy */
00252         memcpy(brightness, img.brightness, width * height * sizeof(int));
00253 
00254         return *this;
00255 }
00256 
00257 ImageGrey& ImageGrey::copy(ImageGrey&    img,
00258                            unsigned int min_x,
00259                            unsigned int min_y,
00260                            unsigned int max_x,
00261                            unsigned int max_y,
00262                            unsigned int start_x,
00263                            unsigned int start_y)
00276 {
00277         unsigned int sx ;
00278         unsigned int sy ;
00279         unsigned int cntx ;
00280         unsigned int cnty ;
00281         int          *s_ptr ;
00282         int          *d_ptr ;
00283         unsigned int s_width ;
00284 
00285         s_width = img.get_width() ;
00286 
00287         /* check we're not trying to copy ourself */
00288         if (this == &img)
00289                 throw "Source and Destination are same Image";
00290 
00291         /* check sanity */
00292         if(min_x > max_x || min_y > max_y)
00293                 throw "Invalid arguments to ImageRGB::copy()" ;
00294 
00295         /* Check images are big enough */
00296         sx = max_x - min_x + 1 ;
00297         sy = max_y - min_y + 1 ;
00298 
00299         if(sx+start_x > width ||
00300            sy+start_y > height)
00301                 throw "Dest. image is not big enough" ;
00302 
00303          if(max_x > s_width ||
00304             max_y > img.get_height() )
00305                 throw "Source images is not big enough" ;
00306 
00307          for(cnty=0 ; cnty<sy ; cnty++){
00308 
00309                  s_ptr = (int*)img.brightness + (min_x + (min_y+cnty)*s_width) ;
00310                  d_ptr = (int*)brightness + (start_x + (start_y+cnty)*width) ;
00311 
00312                  for(cntx=0 ; cntx<sx ; cntx++){
00313                                      
00314                          *(d_ptr++) = *(s_ptr++) ;
00315                  }
00316          }
00317 
00318          return *this;
00319 }
00320 
00321 ImageGrey& ImageGrey::operator += (int fact) 
00327 {
00328     unsigned int cnt ;
00329     unsigned int sz ;
00330     int          *p1 ;
00331 
00332     sz = width * height ;
00333     p1 = brightness ;
00334 
00335     for(cnt=0 ; cnt<sz ; cnt++, p1++){
00336         *p1 += fact ;
00337     }
00338 
00339     return *this;
00340 }
00341 
00342 ImageGrey& ImageGrey::operator -= (int fact)
00348 {
00349     unsigned int cnt ;
00350     unsigned int sz ;
00351     int          *p1 ;
00352 
00353     sz = width * height ;
00354     p1 = brightness ;
00355 
00356     for(cnt=0 ; cnt<sz ; cnt++, p1++){
00357         *p1 -= fact ;
00358     }
00359 
00360     return *this;
00361 }
00362 
00363 ImageGrey& ImageGrey::operator *= (int fact)
00369 {
00370     unsigned int cnt ;
00371     unsigned int sz ;
00372     int          *p1 ;
00373 
00374     sz = width * height ;
00375     p1 = brightness ;
00376 
00377     for(cnt=0 ; cnt<sz ; cnt++, p1++){
00378         *p1 *= fact ;
00379     }
00380 
00381     return *this;
00382 }
00383 
00384 ImageGrey& ImageGrey::operator /= (int fact)
00390 {
00391     unsigned int cnt ;
00392     unsigned int sz ;
00393     int          *p1 ;
00394 
00395     sz = width * height ;
00396     p1 = brightness ;
00397 
00398     for(cnt=0 ; cnt<sz ; cnt++, p1++){
00399         *p1 /= fact ;
00400     }
00401 
00402     return *this;
00403 }
00404 
00405 
00406 ImageGrey& ImageGrey::operator -= (ImageGrey& img) 
00412 {
00413     unsigned int cnt ;
00414     unsigned int sz ;
00415     int          *p1 ;
00416     int          *p2 ;
00417 
00418     sz = width * height ;
00419     p1 = brightness ;
00420     p2 = img.brightness ;
00421 
00422     for(cnt=0 ; cnt<sz ; cnt++, p1++, p2++){
00423         *p1 -= *p2 ;
00424     } 
00425 
00426     return *this;
00427 }
00428 
00429 void ImageGrey::absolute()
00434 {
00435     unsigned int cnt ; 
00436     unsigned int sz ;
00437     int          *p1 ;
00438 
00439     p1 = brightness ;
00440     sz = width * height ;
00441 
00442     for(cnt=0 ; cnt<sz ; cnt++, p1++){
00443         if(*p1<0) *p1 = -(*p1) ;
00444     }
00445 
00446     return ;
00447 }
00448 
00449 void ImageGrey::threshold(int thresh)
00455 {
00456     unsigned int cnt ;
00457     unsigned int sz ;
00458     int          *p1 ;
00459 
00460     p1 = brightness ;
00461     sz = width * height ;
00462 
00463     for(cnt=0 ; cnt<sz ; cnt++, p1++){
00464         if(*p1<thresh) *p1 = 0 ;
00465         else           *p1 = 255 ;
00466     }
00467 
00468     return ;
00469 }
00470 
00471 bool ImageGrey::save(char *filename, FileFormat format)
00478 {
00479  
00480     bool            ret_val = true ;
00481 
00482     if(format == FORMAT_BMP_24){
00483     // 24 Bit (full colour) bitmap 
00484         MicrosoftBMP_RT *btmp;
00485         btmp = new MicrosoftBMP_RT(filename);
00486         if(btmp==NULL) ret_val = false ;
00487         else if(!btmp->set_size(width,height)) ret_val = false ;
00488         else{
00489             btmp->put_data_grey((int *)brightness) ;
00490             ret_val = btmp->write();
00491         }
00492         delete btmp ;
00493     }
00494     if(format == FORMAT_BMP_RC || format == FORMAT_BMP_ANY){
00495     // Greyscale bitmap (+default)
00496         MicrosoftRCBMP_RT *btmp;
00497         btmp = new MicrosoftRCBMP_RT(filename);
00498         if(btmp==NULL) ret_val = false ;
00499         else if(!btmp->set_size(width,height)) ret_val = false ;
00500         else if(!btmp->set_palette_grey256()) ret_val = false ;
00501         else{
00502             btmp->put_data_grey((int *)brightness) ;
00503             ret_val = btmp->write();
00504         }
00505         delete btmp ;
00506     }
00507     if(format == FORMAT_BMP_MONO){
00508     // Greyscale bitmap
00509         MicrosoftMonoBMP_RT *btmp;
00510         btmp = new MicrosoftMonoBMP_RT(filename);
00511         if(btmp==NULL) ret_val = false ;
00512         else if(!btmp->set_size(width,height)) ret_val = false ;
00513         else{
00514             btmp->put_data_grey((int *)brightness) ;
00515             ret_val = btmp->write();
00516         }
00517         delete btmp ;
00518     }
00519  
00520 
00521  
00522     return ret_val ;
00523 }
00524 
00525 bool ImageGrey::sobel_horizontal(ImageGrey &result)
00532 {
00533     bool     ret_val = true ;
00534     int      *ob_ptr ;
00535     int      *rs_ptr ;
00536     int      *tl_ptr ;
00537     int      *tr_ptr ;
00538     int      *b_ptr ;
00539     int      *t_ptr ;
00540     int      *bl_ptr ;
00541     int      *br_ptr ;
00542     unsigned int cnt_x ;
00543     unsigned int cnt_y ;
00544     register int pix_val ;
00545 
00546     if(result.get_width() != width   ||
00547        result.get_height() != height ){
00548         ret_val = false ;
00549     }
00550     else{
00551         ob_ptr = brightness ;
00552         rs_ptr = result.brightness ;
00553         tl_ptr = ob_ptr - width - 1 ;
00554         tr_ptr = ob_ptr - width + 1 ;
00555         t_ptr  = ob_ptr - width ;
00556         b_ptr  = ob_ptr + width ;
00557         bl_ptr = ob_ptr + width - 1 ;
00558         br_ptr = ob_ptr + width + 1 ;
00559         for(cnt_y=0 ; cnt_y<height ; cnt_y++){
00560             for(cnt_x=0 ; cnt_x<width ; cnt_x++, ob_ptr++, rs_ptr++, tl_ptr++,
00561                 tr_ptr++,b_ptr++,t_ptr++,bl_ptr++,br_ptr++){
00562                 if(cnt_y>0 &&
00563                    cnt_x>0 &&
00564                    cnt_y<height-1 &&
00565                    cnt_x<width-1 ){
00566                     pix_val = -1 * (*tl_ptr) +
00567                               -2 * (*t_ptr)  +
00568                               -1 * (*tr_ptr) +
00569                                1 * (*bl_ptr) +
00570                                2 * (*b_ptr)  +
00571                                1 * (*br_ptr)  ;
00572                     *rs_ptr = pix_val / 8 ;
00573                 }
00574                 else{
00575                     *rs_ptr = 0 ;
00576                 }
00577             }
00578         }
00579     }
00580 
00581     return ret_val ;
00582  
00583 }
00584 
00585 bool ImageGrey::sobel_vertical(ImageGrey &result)
00592 {
00593     bool     ret_val = true ;
00594     int      *ob_ptr ;
00595     int      *rs_ptr ;
00596     int      *tl_ptr ;
00597     int      *tr_ptr ;
00598     int      *l_ptr ;
00599     int      *r_ptr ;
00600     int      *bl_ptr ;
00601     int      *br_ptr ;
00602     unsigned int cnt_x ;
00603     unsigned int cnt_y ;
00604     register int pix_val ;
00605 
00606     if(result.get_width() != width   ||
00607        result.get_height() != height ){
00608         ret_val = false ;
00609     }
00610     else{
00611         ob_ptr = brightness ;
00612         rs_ptr = result.brightness ;
00613         l_ptr = ob_ptr - 1 ;
00614         r_ptr = ob_ptr + 1 ;
00615         tl_ptr = ob_ptr - width - 1 ;
00616         tr_ptr = ob_ptr - width + 1 ;
00617         bl_ptr = ob_ptr + width - 1 ;
00618         br_ptr = ob_ptr + width + 1 ;
00619         for(cnt_y=0 ; cnt_y<height ; cnt_y++){
00620             for(cnt_x=0 ; cnt_x<width ; cnt_x++, ob_ptr++, rs_ptr++, tl_ptr++,
00621                 tr_ptr++,l_ptr++,r_ptr++,bl_ptr++,br_ptr++){
00622                if(cnt_y>0 &&
00623                    cnt_x>0 &&
00624                    cnt_y<height-1 &&
00625                    cnt_x<width-1 ){
00626 
00627                     pix_val = -1 * *tl_ptr +
00628                               -2 * *l_ptr  +
00629                               -1 * *bl_ptr +
00630                                1 * *tr_ptr +
00631                                2 * *r_ptr  +
00632                                1 * *br_ptr ;
00633                     *rs_ptr = pix_val / 8 ;
00634                 }
00635                 else{
00636                     *rs_ptr = 0 ;
00637                 }
00638             }
00639         }
00640     }
00641 
00642     return ret_val ;
00643 }
00644 
00645 bool ImageGrey::sobel(ImageGrey &result)
00653 {
00654     bool     ret_val = true ;
00655     int      *ob_ptr ;
00656     int      *rs_ptr ;
00657     int      *tl_ptr ;
00658     int      *tr_ptr ;
00659     int      *l_ptr ;
00660     int      *r_ptr ;
00661     int      *t_ptr ;
00662     int      *b_ptr ;
00663     int      *bl_ptr ;
00664     int      *br_ptr ;
00665     unsigned int cnt_x ;
00666     unsigned int cnt_y ;
00667     register int pix_val_h ;
00668     register int pix_val_v ;
00669 
00670     if(result.get_width() != width   ||
00671        result.get_height() != height ){
00672         ret_val = false ;
00673     }
00674     else{
00675         ob_ptr = brightness ;
00676         rs_ptr = result.brightness ;
00677         l_ptr = ob_ptr - 1 ;
00678         r_ptr = ob_ptr + 1 ;
00679         t_ptr  = ob_ptr - width ;
00680         b_ptr  = ob_ptr + width ;
00681         tl_ptr = ob_ptr - width - 1 ;
00682         tr_ptr = ob_ptr - width + 1 ;
00683         bl_ptr = ob_ptr + width - 1 ;
00684         br_ptr = ob_ptr + width + 1 ;
00685         for(cnt_y=0 ; cnt_y<height ; cnt_y++){
00686             for(cnt_x=0 ; cnt_x<width ; cnt_x++, ob_ptr++, rs_ptr++, tl_ptr++,
00687                 tr_ptr++,l_ptr++,r_ptr++,bl_ptr++,br_ptr++, t_ptr++, b_ptr++){
00688                if(cnt_y>0 &&
00689                    cnt_x>0 &&
00690                    cnt_y<height-1 &&
00691                    cnt_x<width-1 ){
00692 
00693                     pix_val_h = -1 * (*tl_ptr) +
00694                                 -2 * (*t_ptr)  +
00695                                 -1 * (*tr_ptr) +
00696                                  1 * (*bl_ptr) +
00697                                  2 * (*b_ptr)  +
00698                                  1 * (*br_ptr)  ;
00699 
00700                     pix_val_v = -1 * *tl_ptr +
00701                                 -2 * *l_ptr  +
00702                                 -1 * *bl_ptr +
00703                                  1 * *tr_ptr +
00704                                  2 * *r_ptr  +
00705                                  1 * *br_ptr ;
00706 
00707                     *rs_ptr = (int)sqrt((double)(pix_val_h*pix_val_h + 
00708                                                  pix_val_v*pix_val_v)) ;
00709                 }
00710                 else{
00711                     *rs_ptr = 0 ;
00712                 }
00713             }
00714         }
00715     }
00716 
00717     return ret_val ;
00718 }
00719 
00720 bool ImageGrey::dilate(ImageGrey &result)
00728 {
00729     bool         ret_val = true ;
00730     unsigned int cnt_x ;
00731     unsigned int cnt_y ;
00732     int          *ob_ptr ;
00733     int          *rs_ptr ;
00734     int          *ne_ptr ;
00735 
00736     ob_ptr = brightness ;
00737     rs_ptr = result.brightness ;
00738 
00739     if(result.get_width() != width   ||
00740        result.get_height() != height ){
00741     /* Inputs are invalid */
00742         ret_val = false ;
00743     }
00744     else{
00745         for(cnt_y=0; cnt_y<height; cnt_y++){
00746             for(cnt_x=0; cnt_x<width; cnt_x++, ob_ptr++, rs_ptr++){
00747                 *rs_ptr = *ob_ptr ;
00748                 if( cnt_y>0 &&
00749                     cnt_x>0 &&
00750                     cnt_x<width-1 &&
00751                     cnt_y<height-1){
00752                 /* Pixel is NOT a border pixel */
00753                     if(!(*ob_ptr)){
00754                     /* Pixel is black */
00755                         ne_ptr = ob_ptr - width - 1 ;
00756                         if(*(ne_ptr++)) *rs_ptr = 255 ;
00757                         if(*(ne_ptr++)) *rs_ptr = 255 ;
00758                         if(*ne_ptr)     *rs_ptr = 255 ;
00759                         ne_ptr += width ;
00760                         if(*(ne_ptr--)) *rs_ptr = 255 ;
00761                         ne_ptr-- ;
00762                         if(*ne_ptr)     *rs_ptr = 255 ;
00763                         ne_ptr += width ;
00764                         if(*(ne_ptr++)) *rs_ptr = 255 ;
00765                         if(*(ne_ptr++)) *rs_ptr = 255 ;
00766                         if(*ne_ptr)     *rs_ptr = 255 ;
00767                     }
00768                 }
00769             }
00770         }
00771     }
00772 
00773     return ret_val ;
00774 
00775 }
00776 
00777 bool ImageGrey::errode(ImageGrey &result)
00781 {
00782     return erode(result) ;
00783 }
00784 
00785 bool ImageGrey::erode(ImageGrey &result)
00793 {
00794     bool         ret_val = true ;
00795     unsigned int cnt_x ;
00796     unsigned int cnt_y ;
00797     int          *ob_ptr ;
00798     int          *rs_ptr ;
00799     int          *ne_ptr ;
00800 
00801     ob_ptr = brightness ;
00802     rs_ptr = result.brightness ;
00803 
00804     if(result.get_width() != width   ||
00805        result.get_height() != height ){
00806     /* Inputs are invalid */
00807         ret_val = false ;
00808     }
00809     else{
00810         for(cnt_y=0; cnt_y<height; cnt_y++){
00811             for(cnt_x=0; cnt_x<width; cnt_x++, ob_ptr++, rs_ptr++){
00812                 *rs_ptr = *ob_ptr ;
00813                 if( cnt_y>0 &&
00814                     cnt_x>0 &&
00815                     cnt_x<width-1 &&
00816                     cnt_y<height-1){
00817                 /* Pixel is NOT a border pixel */
00818                     if(*ob_ptr){
00819                     /* Pixel is white */
00820                         ne_ptr = ob_ptr - width - 1 ;
00821                         if(!*(ne_ptr++)) *rs_ptr = 0 ;
00822                         if(!*(ne_ptr++)) *rs_ptr = 0 ;
00823                         if(!*ne_ptr)     *rs_ptr = 0 ;
00824                         ne_ptr += width ;
00825                         if(!*(ne_ptr--)) *rs_ptr = 0 ;
00826                         ne_ptr-- ;
00827                         if(!*ne_ptr)     *rs_ptr = 0 ;
00828                         ne_ptr += width ;
00829                         if(!*(ne_ptr++)) *rs_ptr = 0 ;
00830                         if(!*(ne_ptr++)) *rs_ptr = 0 ;
00831 
00832                         if(!*ne_ptr)     *rs_ptr = 0 ;
00833                     }
00834                 }
00835             }
00836         }
00837     }
00838 
00839     return ret_val ;
00840 }
00841 
00842 bool ImageGrey::extract_region(int region_no, ImageGrey &result)
00850 {
00851     int    *ob_ptr ;
00852     int    *rs_ptr ;
00853     bool   ret_val = true ;
00854 
00855     if(result.get_width() != width    ||
00856        result.get_height() != height  ){
00857     /* Inputs are invalid */
00858         ret_val = false ;
00859     }
00860     else{
00861         for( ob_ptr = brightness, rs_ptr = result.brightness ;
00862              ob_ptr < brightness + width*height ;
00863              ob_ptr++, rs_ptr++){
00864         /* Loop through all pixels */
00865             if(*ob_ptr == region_no){
00866                 *rs_ptr = 255 ;
00867             }
00868             else{
00869                 *rs_ptr = 0 ;
00870             }
00871         }
00872     }
00873 
00874     return ret_val;
00875 }
00876 
00877 bool ImageGrey::region_identify(unsigned int max_regions,
00878                                 unsigned int &actual_regions,
00879                                 ImageGrey    &result)
00891 {
00892     bool         ret_val = true ;
00893     int          next_label = 1 ;
00894     equivalence  *equiv_latest=NULL;
00895     equivalence  *equiv_ptr=NULL;
00896     int          *ob_ptr ;
00897     int          *rs_ptr ;
00898     int          *ne_ptr = NULL ;
00899     unsigned int cnt_x;
00900     unsigned int cnt_y;
00901     int          cnt;
00902     int          cnt2;
00903     unsigned int region_no;
00904     unsigned int region_freq;
00905     int          neighbours[4] ;
00906     int          *frequency;
00907     bool         is_significant;
00908 
00909     ob_ptr = brightness ;
00910     rs_ptr = result.brightness ;
00911 
00912     if( max_regions <= 0            ||
00913         result.get_width() != width  ||
00914         result.get_height() != height ){
00915     /* Inputs are invalid */
00916         ret_val = false ;
00917     }
00918     else{
00919         /*
00920          * First sweep set true pixels to :
00921          *      next_label if surrounded by bgd or not determined pixels.
00922          *   or lowest label of a neighbouring pixel.
00923          * If there is more than one option add an equivalence to the
00924          * equivalence linked list pointed to by equiv_start.
00925          */
00926 
00927         for( ob_ptr = brightness, rs_ptr = result.brightness, cnt_x=0,
00928              cnt_y=0;
00929              (unsigned long)(ob_ptr - brightness) <width*height;
00930              cnt_x++, ob_ptr++, rs_ptr++){
00931             /* Loop round all pixels, this is coded for speed not beauty! */
00932                 *rs_ptr = 0;
00933                 if(cnt_x==width){
00934                 /* Reached end of line */
00935                     cnt_x=0;
00936                     cnt_y++;
00937                 }
00938                 else if( cnt_y>0           &&
00939                          cnt_y<height-1    &&
00940                          cnt_x>0           &&
00941                          cnt_x<width-1     &&
00942                          *ob_ptr           ){
00943                 /* This is a true, non-border pixel */
00944                     ne_ptr = rs_ptr - width - 1 ;
00945                     neighbours[0] = *(ne_ptr++);
00946                     neighbours[1] = *(ne_ptr++);
00947                     neighbours[2] = *ne_ptr++;
00948                     neighbours[3] = *(rs_ptr-1);
00949                     qsort(neighbours , 4, sizeof(int), int_compare);
00950 
00951                     if(neighbours[3] == 0){
00952                     /* No processed neighbours are 'object' */
00953                         *rs_ptr = next_label++;
00954                     }
00955                     else{
00956                     /* Pixel has neighbours that are 'object' */
00957                         for(cnt=3; cnt>=0 && ret_val; cnt--){
00958                             if(neighbours[cnt]){
00959                                 *rs_ptr=neighbours[cnt];
00960                                 if(neighbours[cnt] != neighbours[3]){
00961                                     ret_val = new_equivalence(neighbours[cnt],
00962                                                               neighbours[3],
00963                                                               &equiv_latest);
00964                                 }
00965                             }
00966                         }
00967                     }
00968                 }
00969          }
00970         /*
00971          * Second sweep sets all equivalences to the lowest. We start with the
00972          * highest equivalence.
00973          */
00974         frequency = new int[next_label];
00975 
00976         if(frequency==NULL) ret_val = false ;
00977         for(cnt=0; cnt<next_label && ret_val; cnt++) frequency[cnt]=0;
00978 
00979         for( ob_ptr = brightness, rs_ptr = result.brightness, cnt_x=0,
00980              cnt_y=0;
00981              (unsigned long)(ob_ptr - brightness) <width*height && ret_val;
00982              cnt_x++, ob_ptr++, rs_ptr++){
00983             /* Loop round all pixels, this is coded for speed not beauty! */
00984                 if(cnt_x==width){
00985                 /* Reached end of line */
00986                     cnt_x=0;
00987                     cnt_y++;
00988                 }
00989                 else if( cnt_y>0           &&
00990                          cnt_y<height-1    &&
00991                          cnt_x>0           &&
00992                          cnt_x<width-1     &&
00993                          *rs_ptr           ){
00994                 /* This is a true, non-border pixel */
00995                     for(cnt=next_label-1; cnt>=0; cnt--){
00996                         equiv_ptr = equiv_latest ;
00997                         while(equiv_ptr != NULL){
00998                         /* Loop through equivalences */
00999                             if(*rs_ptr == cnt && equiv_ptr->eq2 == cnt){
01000                                 *rs_ptr = equiv_ptr->eq1;
01001                             }
01002                             equiv_ptr = equiv_ptr->next ;
01003                         }
01004                     }
01005                     frequency[*rs_ptr]++;
01006                 }
01007         }
01008 
01009     /*
01010      * At this point regions have a unique region numbers however they are not
01011      * in frequency order and there are gaps.
01012      */
01013         free_equivalence(&equiv_latest);
01014 
01015         actual_regions = 0 ;
01016 
01017         for(cnt=0; cnt<(int)max_regions; cnt++){
01018             region_freq=frequency[1];
01019             region_no = 1;
01020             for(cnt2=1; cnt2<next_label-1; cnt2++){
01021                 if(frequency[cnt2] > (int)region_freq){
01022                     region_freq = frequency[cnt2];
01023                     region_no   = cnt2;
01024                 }
01025             }
01026             if(region_freq){
01027                 frequency[region_no] = 0;
01028                 ret_val = new_equivalence(cnt+1,
01029                                           region_no,
01030                                           &equiv_latest);
01031                 actual_regions++;
01032             }
01033         }
01034 
01035    /*
01036     * Third loop sets result to ordered value an removes smaller objects.
01037     */
01038         for( ob_ptr = brightness, rs_ptr = result.brightness, cnt_x=0,
01039              cnt_y=0;
01040              (unsigned long)(ob_ptr - brightness) <width*height && ret_val;
01041              cnt_x++, ob_ptr++, rs_ptr++){
01042             /* Loop round all pixels, this is coded for speed not beauty! */
01043                 if(cnt_x==width){
01044                 /* Reached end of line */
01045                     cnt_x=0;
01046                     cnt_y++;
01047                 }
01048                 else if( cnt_y>0           &&
01049                          cnt_y<height-1    &&
01050                          cnt_x>0           &&
01051                          cnt_x<width-1     &&
01052                          *rs_ptr           ){
01053                 /* This is a true, non-border pixel */
01054                         equiv_ptr = equiv_latest ;
01055                         is_significant=false;
01056                         while(equiv_ptr != NULL && !is_significant){
01057                         /* Loop through equivalences */
01058                             if(*rs_ptr == equiv_ptr->eq2){
01059                                 *rs_ptr = equiv_ptr->eq1;
01060                                 is_significant=true;
01061                             }
01062                             equiv_ptr = equiv_ptr->next ;
01063                         }
01064                         if(!is_significant){
01065                         /* Remove small object */
01066                             *rs_ptr = 0;
01067                         }
01068                 }
01069         }
01070     }
01071 
01072     return ret_val;
01073 
01074 }
01075 
01076 static int int_compare(const void *i1, const void *i2)
01077 {
01078 /*
01079  * Function to compare two integers for qsort().
01080  */
01081 
01082     int ret_val ;
01083 
01084     if( *((int *)i1) < *((int *)i2) ){
01085         ret_val = -1 ;
01086     }
01087     else{
01088         ret_val = 1 ;
01089     }
01090     return ret_val ;
01091 }
01092 
01093 bool ImageGrey::new_equivalence(int low, int high, equivalence **latest)
01094 {
01095 /*
01096  * This method adds a new equivalence to the linked list who's last element is
01097  * pointed to by *latest. It returns false if memory allocation is unsuccessful.
01098  */
01099 
01100     bool        ret_val = true;
01101     equivalence *new_eq=NULL;
01102     equivalence *eq_ptr = *latest ;
01103     bool        exists = false ;
01104 
01105     /* First search for an equivalence with the same upper number */
01106 
01107     while(eq_ptr != NULL && !exists){
01108         if(eq_ptr->eq2 == high) {exists = true;}
01109         else                    {eq_ptr = eq_ptr->next;}
01110     }
01111 
01112     if(!exists){
01113     /* Create an equivalence */
01114         new_eq = new equivalence ;
01115         if(new_eq == NULL) ret_val = false;
01116     }
01117 
01118     if(ret_val && exists && low<eq_ptr->eq1){
01119     /* Modify existing equivalence and create new one */
01120         ret_val = new_equivalence(low,eq_ptr->eq1,latest);
01121         eq_ptr->eq1 = low;
01122     }
01123     else if(ret_val && exists && low>eq_ptr->eq1){
01124         ret_val = new_equivalence(eq_ptr->eq1, low, latest);
01125     }
01126 
01127     if (ret_val && !exists){
01128 
01129         new_eq->eq1 = low;
01130         new_eq->eq2 = high;
01131         new_eq->next = *latest;
01132         *latest = new_eq ;
01133     }
01134 
01135     return ret_val;
01136 }
01137 
01138 void ImageGrey::free_equivalence(equivalence **eq)
01139 {
01140 /*
01141  * Function to free memory allocated to equivalence linked list.
01142  */
01143 
01144     equivalence *eq_ptr1 = *eq;
01145     equivalence *eq_ptr2;
01146 
01147     while(eq_ptr1 != NULL){
01148         eq_ptr2 = eq_ptr1->next ;
01149         delete eq_ptr1;
01150         eq_ptr1= eq_ptr2 ;
01151     }
01152 
01153     *eq = NULL;
01154 }
01155 
01156 void ImageGrey::normalise_intensity(float mean,
01157                                     float sd)
01165 {
01166     unsigned int cnt ;
01167     unsigned int sz ;
01168     int          *ptr ;
01169     float        c_mean = 0 ;
01170     float        c_sd = 0 ;
01171     float        nval ;
01172     float        sf ;
01173 
01174     sz = width*height ;
01175 
01176     // First calculate actual mean / sd
01177     for(cnt=0, ptr=brightness ; cnt<sz ; cnt++, ptr++){
01178         c_mean += *ptr ;
01179         c_sd += *ptr * *ptr ;
01180     }
01181     c_mean /= sz ;
01182     c_sd /= sz ;
01183     c_sd -= c_mean*c_mean ;
01184     c_sd = sqrt(c_sd) ;
01185 
01186     sf = sd / c_sd ;
01187 
01188     // Normalise 
01189      for(cnt=0, ptr=brightness ; cnt<sz ; cnt++, ptr++){
01190         nval = *ptr - c_mean ;
01191         nval *= sf ;
01192         nval += mean ;
01193         *ptr = (int)nval ;
01194     }
01195 }
01196 
01197 void ImageGrey::normalise_intensity_range() 
01202 {
01203     unsigned int cnt ;
01204     unsigned int sz ;
01205     int          *ptr ;
01206     int          min = INT_MAX ;
01207     int          max = -INT_MAX ;
01208     float        sf ;
01209 
01210     sz = width*height ;
01211 
01212     // Calculate min / max
01213     for(cnt=0, ptr=brightness ; cnt<sz ; cnt++, ptr++){
01214         if(*ptr < min) min = *ptr ;
01215         if(*ptr > max) max = *ptr ;
01216     }
01217 
01218     if(max > min){
01219         sf = 255.0 / (float)(max - min) ;
01220     }
01221     else{
01222         return ;
01223     }
01224 
01225     // Normalise
01226     for(cnt=0, ptr=brightness ; cnt<sz ; cnt++, ptr++){
01227         *ptr -= min ;
01228         *ptr *= sf ;
01229     }
01230 }
01231 
01232 bool ImageGrey:: median(unsigned int n, unsigned int m, 
01233                         ImageGrey &result)
01238 {
01239     bool         ret_val = true ;
01240     unsigned int border_x;
01241     unsigned int border_y;
01242     unsigned int image_x ;
01243     unsigned int image_y ;
01244     unsigned int matrix_x ;
01245     unsigned int matrix_y ;
01246     int          *neighbourhood;
01247     unsigned int n_count;
01248 
01249     border_x = n / 2 ;
01250     border_y = m/ 2 ;
01251 
01252     /* Create an array for neighbourhood data for use by qsort() */
01253     neighbourhood = new int[n*m] ;
01254 
01255     for(image_y=0; image_y<height; image_y++){
01256         for(image_x=0; image_x<width; image_x++){
01257             if(image_y<border_y ||
01258                image_x<border_x ||
01259                image_y>=height-border_y ||
01260                image_x>=width-border_x){
01261             /* This is a border pixel, set it to black */
01262                 result.brightness[image_y*width + image_x] = 0;
01263             }
01264             else{
01265                 n_count = 0 ;
01266                 for(matrix_x=0; matrix_x<n; matrix_x++){
01267                     for(matrix_y=0; matrix_y<m; matrix_y++){
01268                         neighbourhood[n_count] = 
01269                              brightness[(image_y+matrix_y-border_y)*width
01270                                          + image_x + matrix_x - border_x] ;
01271                         n_count++;
01272                     }
01273                 }
01274                 qsort(neighbourhood , n*m, sizeof(int), int_compare);
01275                 result.brightness[image_y*width + image_x] =
01276                                           neighbourhood[n*m/2+1] ;
01277             }
01278         }
01279     }
01280 
01281     delete [] neighbourhood ;
01282 
01283     return ret_val ;
01284 }
01285 
01286 bool ImageGrey::remove_point_noise(ImageGrey &result)
01291 {
01292     unsigned int image_x ;
01293     unsigned int image_y ;
01294     int          *ptr ;
01295     int          *rptr ;
01296 
01297     ptr = brightness ;
01298     rptr = result.brightness ;
01299     for(image_y=0; image_y<height; image_y++){
01300         for(image_x=0; image_x<width; image_x++, ptr++, rptr++){
01301             if(*ptr &&
01302                ((image_x==0 && image_y==0) || *(ptr-width-1)==0) &&
01303                (image_y==0 || *(ptr-width)==0) &&
01304                ((image_x==width-1 && image_y==0) || *(ptr-width+1)==0) &&
01305                (image_x==0 || *(ptr-1)==0) &&
01306                (image_x==width-1 || *(ptr+1)==0) &&
01307                ((image_x==0 && image_y==height-1) || *(ptr+width-1)==0) &&
01308                (image_y==height-1 || *(ptr+width)==0) &&
01309                ((image_x==width-1 && image_y==height-1) || *(ptr+width+1)==0)){
01310             // True, but no neighbours
01311                 *rptr = 0 ;
01312             }
01313             else{
01314                 *rptr = *ptr ;
01315             }
01316         }
01317     } 
01318 
01319     return true ;
01320 }
01321 

Generated at Fri Aug 13 17:29:21 2004 for libRTImage by doxygen1.2.8.1 written by Dimitri van Heesch, © 1997-2001