Fawkes API
Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * segenerator.cpp - 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 <fvfilters/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 namespace firevision { 00038 #if 0 /* just to make Emacs auto-indent happy */ 00039 } 00040 #endif 00041 00042 /** @class SEGenerator <fvfilters/morphology/segenerator.h> 00043 * Basic generators for structuring elements for morphological filters. 00044 * @author Tim Niemueller 00045 */ 00046 00047 00048 /** Generate linear structuring element. 00049 * @param width width of structuring element 00050 * @param height height of structuring element 00051 * @param proposed_center_x contains the proposed x coordinate of the anchor 00052 * upon return 00053 * @param proposed_center_y contains the proposed y coordinate of the anchor 00054 * upon return 00055 * @param slope_angle_rad the slope of the line in radians 00056 * @return buffer with linear structuring element. The buffer has been allocated 00057 * using malloc(). Use free() to free the memory after you are done with it. 00058 */ 00059 unsigned char * 00060 SEGenerator::linear(unsigned int width, unsigned int height, 00061 unsigned int *proposed_center_x, unsigned int *proposed_center_y, 00062 float slope_angle_rad) 00063 { 00064 00065 // we always start at (0,0) and then calculate the corrensponding 00066 // y of the linear functional 00067 // l: x -> mx + b, where b is 0. 00068 // by tan(slope_angle_rad) = y / x 00069 // => y = x * tan(slope_angle_rad) with x = width 00070 00071 if ( height == 0 ) return NULL; 00072 if ( width == 0) return NULL; 00073 00074 00075 unsigned char *tmp = (unsigned char *)malloc(colorspace_buffer_size(YUV422_PLANAR, width, height)); 00076 memset(tmp, 0, colorspace_buffer_size(YUV422_PLANAR, width, height)); 00077 Drawer *d = new Drawer(); 00078 d->set_buffer(tmp, width, height); 00079 d->set_color(1, 0, 0); 00080 00081 float a = fawkes::normalize_mirror_rad( slope_angle_rad ); 00082 00083 if ( (a == M_PI/2) || (a == -M_PI/2) ) { 00084 // It's just a vertical line 00085 // std::cout << "Drawing line from (0,0) -> (0," << height - 1 << ")" << std::endl; 00086 d->draw_line(0, 0, 0, height - 1); 00087 } else { 00088 00089 // sectors 3 and 4 can be converted to sector 2 and 1 lines 00090 if ( a > M_PI / 2) a -= M_PI; 00091 if ( a < - M_PI / 2) a += M_PI; 00092 00093 int y = (int)roundf(((float)width - 1.f) * tan( a )); 00094 00095 if ( y < 0) { 00096 // std::cout << "Drawing line from (0,0) -> (" << width - 1 << "," << -y << ")" << std::endl; 00097 d->draw_line( 0, 0, width - 1, -y ); 00098 } else { 00099 // std::cout << "Drawing line from (0," << y << ") -> (" << width - 1 << ",0)" << std::endl; 00100 d->draw_line( 0, y, width - 1, 0 ); 00101 } 00102 } 00103 00104 delete d; 00105 00106 unsigned char *se = (unsigned char *)malloc(width * height); 00107 memcpy(se, tmp, width * height); 00108 00109 PNGWriter *png = new PNGWriter(); 00110 png->set_dimensions( width, height ); 00111 png->set_buffer(YUV422_PLANAR, tmp); 00112 png->set_filename("se_test.png"); 00113 png->write(); 00114 delete png; 00115 00116 FvRawWriter *fvraw = new FvRawWriter("se_test.raw", width, height, YUV422_PLANAR, tmp); 00117 fvraw->write(); 00118 delete fvraw; 00119 00120 free( tmp ); 00121 00122 if ( (proposed_center_x != NULL) && (proposed_center_y != NULL) ) { 00123 unsigned int min_x = width; 00124 unsigned int max_x = 0; 00125 unsigned int min_y = height; 00126 unsigned int max_y = 0; 00127 for (unsigned int h = 0; h < height; ++h) { 00128 for (unsigned int w = 0; w < width; ++w) { 00129 if ( se[ h * width + w ] != 0 ) { 00130 if ( w < min_x ) min_x = w; 00131 if ( w > max_x ) max_x = w; 00132 if ( h < min_y ) min_y = h; 00133 if ( h > max_y ) max_y = h; 00134 } 00135 } 00136 } 00137 00138 *proposed_center_x = min_x + (max_x - min_x) / 2; 00139 *proposed_center_y = min_y + (max_y - min_y) / 2; 00140 } 00141 00142 return se; 00143 } 00144 00145 00146 /** Generate square structuring element. 00147 * @param width width of structuring element 00148 * @param height height of structuring element 00149 * @return buffer with square structuring element. The buffer has been allocated 00150 * using malloc(). Use free() to free the memory after you are done with it. 00151 */ 00152 unsigned char * 00153 SEGenerator::square(unsigned int width, unsigned int height) 00154 { 00155 unsigned char *se = (unsigned char *)malloc(width * height); 00156 memset(se, 1, width * height); 00157 return se; 00158 } 00159 00160 00161 /** Draw structuring element. 00162 * This draws the structuring element to an image buffer. 00163 * @param yuv422planar_buffer image buffer 00164 * @param mask structuring element 00165 * @param width width of structuring element 00166 * @param height height of structuring element 00167 */ 00168 void 00169 SEGenerator::drawSE(unsigned char *yuv422planar_buffer, unsigned char *mask, unsigned int width, unsigned int height) 00170 { 00171 memset(yuv422planar_buffer, 128, colorspace_buffer_size(YUV422_PLANAR, width, height) ); 00172 for (unsigned int h = 0; h < height; ++h) { 00173 for (unsigned int w = 0; w < width; ++w) { 00174 if ( mask[ h * width + w ] != 0 ) { 00175 yuv422planar_buffer[ h * width + w ] = 255; 00176 } 00177 } 00178 } 00179 } 00180 00181 00182 /** Draw structuring element. 00183 * This draws the structuring element to a b/w image buffer. 00184 * @param yuv422planar_buffer image buffer 00185 * @param mask structuring element 00186 * @param width width of structuring element 00187 * @param height height of structuring element 00188 */ 00189 void 00190 SEGenerator::drawSEbw(unsigned char *yuv422planar_buffer, unsigned char *mask, unsigned int width, unsigned int height) 00191 { 00192 memset(yuv422planar_buffer, 128, colorspace_buffer_size(YUV422_PLANAR, width, height) ); 00193 memset(yuv422planar_buffer, 255, width * height ); 00194 for (unsigned int h = 0; h < height; ++h) { 00195 for (unsigned int w = 0; w < width; ++w) { 00196 if ( mask[ h * width + w ] != 0 ) { 00197 yuv422planar_buffer[ h * width + w ] = 0; 00198 } 00199 } 00200 } 00201 } 00202 00203 } // end namespace firevision