Fawkes API Fawkes Development Version

imagediff.cpp

00001 
00002 /***************************************************************************
00003  *  imagediff.cpp - check images if they are different
00004  *
00005  *  Generated: Tue Jun 06 10:22:49 2006
00006  *  Copyright  2005-2007  Tim Niemueller [www.niemueller.de]
00007  *
00008  ****************************************************************************/
00009 
00010 /*  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version. A runtime exception applies to
00014  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU Library General Public License for more details.
00020  *
00021  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00022  */
00023 
00024 #include <fvutils/statistical/imagediff.h>
00025 #include <fvutils/color/yuv.h>
00026 
00027 #include <cstdlib>
00028 
00029 namespace firevision {
00030 #if 0 /* just to make Emacs auto-indent happy */
00031 }
00032 #endif
00033 
00034 /** @class ImageDiff <fvutils/statistical/imagediff.h>
00035  * Image difference checker.
00036  * @author Tim Niemueller
00037  */
00038 
00039 /** Constructor.
00040  * @param scanline_model scanlinemodel to use, if null all pixels
00041  * are compared.
00042  */
00043 ImageDiff::ImageDiff(ScanlineModel *scanline_model)
00044 {
00045   this->scanline_model = scanline_model;
00046 }
00047 
00048 
00049 /** Constructor.
00050  * Use this constructor to compare all pixels.
00051  */
00052 ImageDiff::ImageDiff()
00053 {
00054   scanline_model = NULL;
00055 }
00056 
00057 
00058 /** Destructor. */
00059 ImageDiff::~ImageDiff()
00060 {
00061 }
00062 
00063 
00064 /** Set first buffer.
00065  * @param yuv422planar_buffer buffer
00066  * @param width image width in pixels
00067  * @param height image height in pixels
00068  */
00069 void
00070 ImageDiff::setBufferA(unsigned char *yuv422planar_buffer,
00071                       unsigned int width, unsigned int height)
00072 {
00073   buffer_a = yuv422planar_buffer;
00074   width_a  = width;
00075   height_a = height;
00076 }
00077 
00078 
00079 /** Set second buffer.
00080  * @param yuv422planar_buffer buffer
00081  * @param width image width in pixels
00082  * @param height image height in pixels
00083  */
00084 void
00085 ImageDiff::setBufferB(unsigned char *yuv422planar_buffer,
00086                       unsigned int width, unsigned int height)
00087 {
00088   buffer_b = yuv422planar_buffer;
00089   width_b  = width;
00090   height_b = height;
00091 }
00092 
00093 
00094 /** Check if images are different.
00095  * This method will compare the two images. If any pixel marked by
00096  * the scanline or any pixel at all if no scanline model is given
00097  * differ the images are considered to be different. The same applies
00098  * if any buffer is unset or the widths or heights are not the same.
00099  * @return true if images are different, false otherwise
00100  */
00101 bool
00102 ImageDiff::different()
00103 {
00104   if ( (buffer_a == NULL) && (buffer_b == NULL) ) return false;
00105   if ( (buffer_a == NULL) && (buffer_b != NULL) ) return true;
00106   if ( (buffer_a != NULL) && (buffer_b == NULL) ) return true;
00107   if ( (width_a != width_b) || (height_a != height_b) ) return true;
00108 
00109   if ( scanline_model != NULL ) {
00110     // use the supplied scanline model
00111 
00112     unsigned int x, y;
00113     unsigned char y_a, u_a, v_a, y_b, u_b, v_b;
00114 
00115     scanline_model->reset();
00116     while (! scanline_model->finished() ) {
00117       x = (*scanline_model)->x;
00118       y = (*scanline_model)->y;
00119       
00120       YUV422_PLANAR_YUV(buffer_a, width_a, height_a, x, y, y_a, u_a, v_a);
00121       YUV422_PLANAR_YUV(buffer_b, width_b, height_b, x, y, y_b, u_b, v_b);
00122       
00123       if ( (y_a != y_b) || (u_a != u_b) || (v_a != v_b) ) {
00124         return true;
00125       }
00126     }
00127   } else {
00128     // no scanline model, check every single pixel
00129 
00130     unsigned char *ypa = buffer_a;
00131     unsigned char *ypb = buffer_b;
00132 
00133     for ( unsigned int i = 0; i < (width_a * height_a); ++i) {
00134       if ( *ypa != *ypb ) {
00135         return true;
00136       }
00137       ++ypa;
00138       ++ypb;
00139     }
00140   }
00141 
00142   return false;
00143 }
00144 
00145 
00146 /** Number of differing pixels.
00147  * Executes the same routine as different(). But instead of just saying that
00148  * the images are different will tell how many pixels differ.
00149  * @return number of different pixels
00150  */
00151 unsigned int
00152 ImageDiff::numDifferingPixels()
00153 {
00154   if ( (buffer_a == NULL) && (buffer_b == NULL) ) return 0;
00155   if ( (buffer_a == NULL) && (buffer_b != NULL) ) return (width_b * height_b);
00156   if ( (buffer_a != NULL) && (buffer_b == NULL) ) return (width_a * height_a);
00157   if ( (width_a != width_b) || (height_a != height_b) ) {
00158     return abs(width_a - width_b) * abs(height_a - height_b);
00159   }
00160 
00161   unsigned int num = 0;
00162   if ( scanline_model != NULL ) {
00163     // use the supplied scanline model
00164 
00165     unsigned int x, y;
00166     unsigned char y_a, u_a, v_a, y_b, u_b, v_b;
00167 
00168     scanline_model->reset();
00169     while (! scanline_model->finished() ) {
00170       x = (*scanline_model)->x;
00171       y = (*scanline_model)->y;
00172 
00173       YUV422_PLANAR_YUV(buffer_a, width_a, height_a, x, y, y_a, u_a, v_a);
00174       YUV422_PLANAR_YUV(buffer_b, width_b, height_b, x, y, y_b, u_b, v_b);
00175       
00176       if ( (y_a != y_b) || (u_a != u_b) || (v_a != v_b) ) {
00177         ++num;
00178       }
00179     }
00180   } else {
00181     // no scanline model, check every single pixel
00182 
00183     unsigned char *ypa = buffer_a;
00184     unsigned char *ypb = buffer_b;
00185 
00186     for ( unsigned int i = 0; i < (width_a * height_a); ++i) {
00187       if ( *ypa++ != *ypb++ ) ++num;
00188     }
00189   }
00190   return num;
00191 }
00192 
00193 } // end namespace firevision
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends