segenerator.cpp

00001
00002 /***************************************************************************
00003  *  segenerator.h - Class that helps to create some standard structuring
00004  *                  elements
00005  *
00006  *  Created: Wed Jun 07 11:23:03 2006
00007  *  Copyright  2005-2007  Tim Niemueller [www.niemueller.de]
00008  *
00009  ****************************************************************************/
00010
00011 /*  This program is free software; you can redistribute it and/or modify
00012  *  it under the terms of the GNU General Public License as published by
00013  *  the Free Software Foundation; either version 2 of the License, or
00014  *  (at your option) any later version. A runtime exception applies to
00015  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00016  *
00017  *  This program is distributed in the hope that it will be useful,
00018  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00019  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00020  *  GNU Library General Public License for more details.
00021  *
00022  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00023  */
00024
00025 #include <filters/morphology/segenerator.h>
00026
00027 #include <utils/math/angle.h>
00028
00029 #include <fvutils/draw/drawer.h>
00030 #include <fvutils/color/colorspaces.h>
00031 #include <fvutils/writers/png.h>
00032 #include <fvutils/writers/fvraw.h>
00033
00034 #include <cstdlib>
00035 #include <cstring>
00036 
00037 /** @class SEGenerator <filters/morphology/segenerator.h>
00038  * Basic generators for structuring elements for morphological filters.
00039  * @author Tim Niemueller
00040  */
00041
00042 
00043 /** Generate linear structuring element.
00044  * @param width width of structuring element
00045  * @param height height of structuring element
00046  * @param proposed_center_x contains the proposed x coordinate of the anchor
00047  * upon return
00048  * @param proposed_center_y contains the proposed y coordinate of the anchor
00049  * upon return
00050  * @param slope_angle_rad the slope of the line in radians
00051  * @return buffer with linear structuring element. The buffer has been allocated
00052  * using malloc(). Use free() to free the memory after you are done with it.
00053  */
00054 unsigned char *
00055 SEGenerator::linear(unsigned int width, unsigned int height,
00056                     unsigned int *proposed_center_x, unsigned int *proposed_center_y,
00057                     float slope_angle_rad)
00058 {
00059
00060   // we always start at (0,0) and then calculate the corrensponding
00061   // y of the linear functional
00062   // l: x -> mx + b, where b is 0.
00063   // by tan(slope_angle_rad) = y / x
00064   // => y = x * tan(slope_angle_rad)    with x = width
00065
00066   if ( height == 0 ) return NULL;
00067   if ( width == 0) return NULL;
00068
00069
00070   unsigned char *tmp = (unsigned char *)malloc(colorspace_buffer_size(YUV422_PLANAR, width, height));
00071   memset(tmp, 0, colorspace_buffer_size(YUV422_PLANAR, width, height));
00072   Drawer *d = new Drawer();
00073   d->set_buffer(tmp, width, height);
00074   d->set_color(1, 0, 0);
00075
00076   float a = fawkes::normalize_mirror_rad( slope_angle_rad );
00077
00078   if ( (a == M_PI/2) || (a == -M_PI/2) ) {
00079     // It's just a vertical line
00080     // std::cout << "Drawing line from (0,0) -> (0," << height - 1 << ")" << std::endl;
00081     d->draw_line(0, 0, 0, height - 1);
00082   } else {
00083
00084     // sectors 3 and 4 can be converted to sector 2 and 1 lines
00085     if ( a > M_PI / 2)    a -= M_PI;
00086     if ( a < - M_PI / 2)  a += M_PI;
00087
00088     int y = (int)roundf(((float)width - 1.f) * tan( a ));
00089
00090     if ( y < 0) {
00091       // std::cout << "Drawing line from (0,0) -> (" << width - 1 << "," << -y << ")" << std::endl;
00092       d->draw_line( 0, 0, width - 1, -y );
00093     } else {
00094       // std::cout << "Drawing line from (0," << y << ") -> (" << width - 1 << ",0)" << std::endl;
00095       d->draw_line( 0, y, width - 1, 0 );
00096     }
00097   }
00098
00099   delete d;
00100
00101   unsigned char *se = (unsigned char *)malloc(width * height);
00102   memcpy(se, tmp, width * height);
00103
00104   PNGWriter *png = new PNGWriter();
00105   png->set_dimensions( width, height );
00106   png->set_buffer(YUV422_PLANAR, tmp);
00107   png->set_filename("se_test.png");
00108   png->write();
00109   delete png;
00110
00111   FvRawWriter *fvraw = new FvRawWriter("se_test.raw", width, height, YUV422_PLANAR, tmp);
00112   fvraw->write();
00113   delete fvraw;
00114
00115   free( tmp );
00116
00117   if ( (proposed_center_x != NULL) && (proposed_center_y != NULL) ) {
00118     unsigned int min_x = width;
00119     unsigned int max_x = 0;
00120     unsigned int min_y = height;
00121     unsigned int max_y = 0;
00122     for (unsigned int h = 0; h < height; ++h) {
00123       for (unsigned int w = 0; w < width; ++w) {
00124         if ( se[ h * width + w ] != 0 ) {
00125           if ( w < min_x ) min_x = w;
00126           if ( w > max_x ) max_x = w;
00127           if ( h < min_y ) min_y = h;
00128           if ( h > max_y ) max_y = h;
00129         }
00130       }
00131     }
00132
00133     *proposed_center_x = min_x + (max_x - min_x) / 2;
00134     *proposed_center_y = min_y + (max_y - min_y) / 2;
00135   }
00136
00137   return se;
00138 }
00139
00140 
00141 /** Generate square structuring element.
00142  * @param width width of structuring element
00143  * @param height height of structuring element
00144  * @return buffer with square structuring element. The buffer has been allocated
00145  * using malloc(). Use free() to free the memory after you are done with it.
00146  */
00147 unsigned char *
00148 SEGenerator::square(unsigned int width, unsigned int height)
00149 {
00150   unsigned char *se = (unsigned char *)malloc(width * height);
00151   memset(se, 1, width * height);
00152   return se;
00153 }
00154
00155 
00156 /** Draw structuring element.
00157  * This draws the structuring element to an image buffer.
00158  * @param yuv422planar_buffer image buffer
00159  * @param mask structuring element
00160  * @param width width of structuring element
00161  * @param height height of structuring element
00162  */
00163 void
00164 SEGenerator::drawSE(unsigned char *yuv422planar_buffer, unsigned char *mask, unsigned int width, unsigned int height)
00165 {
00166   memset(yuv422planar_buffer, 128, colorspace_buffer_size(YUV422_PLANAR, width, height) );
00167   for (unsigned int h = 0; h < height; ++h) {
00168     for (unsigned int w = 0; w < width; ++w) {
00169       if ( mask[ h * width + w ] != 0 ) {
00170         yuv422planar_buffer[ h * width + w ] = 255;
00171       }
00172     }
00173   }
00174 }
00175
00176 
00177 /** Draw structuring element.
00178  * This draws the structuring element to a b/w image buffer.
00179  * @param yuv422planar_buffer image buffer
00180  * @param mask structuring element
00181  * @param width width of structuring element
00182  * @param height height of structuring element
00183  */
00184 void
00185 SEGenerator::drawSEbw(unsigned char *yuv422planar_buffer, unsigned char *mask, unsigned int width, unsigned int height)
00186 {
00187   memset(yuv422planar_buffer, 128, colorspace_buffer_size(YUV422_PLANAR, width, height) );
00188   memset(yuv422planar_buffer, 255, width * height );
00189   for (unsigned int h = 0; h < height; ++h) {
00190     for (unsigned int w = 0; w < width; ++w) {
00191       if ( mask[ h * width + w ] != 0 ) {
00192         yuv422planar_buffer[ h * width + w ] = 0;
00193       }
00194     }
00195   }
00196 }