Fawkes API
Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * sobel.cpp - Implementation of a Sobel filter 00004 * 00005 * Created: Thu May 12 13:20:43 2005 00006 * Copyright 2005-2012 Tim Niemueller [www.niemueller.de] 00007 ****************************************************************************/ 00008 00009 /* This program is free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. A runtime exception applies to 00013 * this software (see LICENSE.GPL_WRE file mentioned below for details). 00014 * 00015 * This program is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 * GNU Library General Public License for more details. 00019 * 00020 * Read the full text in the LICENSE.GPL_WRE file in the doc directory. 00021 */ 00022 00023 #include <fvfilters/sobel.h> 00024 00025 #include <core/exception.h> 00026 00027 #ifdef HAVE_IPP 00028 # include <ippi.h> 00029 #elif defined(HAVE_OPENCV) 00030 # include <cv.h> 00031 #else 00032 # error "Neither IPP nor OpenCV available" 00033 #endif 00034 00035 00036 namespace firevision { 00037 #if 0 /* just to make Emacs auto-indent happy */ 00038 } 00039 #endif 00040 00041 /** @class FilterSobel <fvfilters/sobel.h> 00042 * Sobel filter. 00043 * @author Tim Niemueller 00044 */ 00045 00046 /** Constructor. 00047 * @param ori edge orientation 00048 */ 00049 FilterSobel::FilterSobel(orientation_t ori) 00050 : Filter("FilterSobel") 00051 { 00052 } 00053 00054 00055 /** Generate a sobel kernel for the given orientation. 00056 * @param k matrix for the kernel of size 3x3, contains three 00057 * lines concatenated into an one dimensional array. 00058 * @param ori requested orientation of the filter 00059 */ 00060 static inline void 00061 generate_kernel( 00062 #ifdef HAVE_IPP 00063 int *k, 00064 #else 00065 float *k, 00066 #endif 00067 orientation_t ori) 00068 { 00069 // k is the kernel 00070 switch (ori) { 00071 case ORI_DEG_0: 00072 case ORI_DEG_360: 00073 k[0] = 1; k[1] = 2; k[2] = 1; 00074 k[3] = 0; k[4] = 0; k[5] = 0; 00075 k[6] = -1; k[7] = -2; k[8] = -1; 00076 break; 00077 case ORI_DEG_45: 00078 k[0] = 2; k[1] = 1; k[2] = 0; 00079 k[3] = 1; k[4] = 0; k[5] = -1; 00080 k[6] = 0; k[7] = -1; k[8] = -2; 00081 break; 00082 case ORI_DEG_90: 00083 k[0] = 1; k[1] = 0; k[2] = -1; 00084 k[3] = 2; k[4] = 0; k[5] = -2; 00085 k[6] = 1; k[7] = 0; k[8] = -1; 00086 break; 00087 case ORI_DEG_135: 00088 k[0] = 0; k[1] = -1; k[2] = -2; 00089 k[3] = 1; k[4] = 0; k[5] = -1; 00090 k[6] = 2; k[7] = 1; k[8] = 0; 00091 break; 00092 case ORI_DEG_180: 00093 k[0] = -1; k[1] = -2; k[2] = -1; 00094 k[3] = 0; k[4] = 0; k[5] = 0; 00095 k[6] = 1; k[7] = 2; k[8] = 1; 00096 break; 00097 case ORI_DEG_225: 00098 k[0] = -2; k[1] = -1; k[2] = 0; 00099 k[3] = -1; k[4] = 0; k[5] = 1; 00100 k[6] = 0; k[7] = 1; k[8] = 2; 00101 break; 00102 case ORI_DEG_270: 00103 k[0] = -1; k[1] = 0; k[2] = 1; 00104 k[3] = -2; k[4] = 0; k[5] = 2; 00105 k[6] = -1; k[7] = 0; k[8] = 1; 00106 break; 00107 case ORI_DEG_315: 00108 k[0] = 0; k[1] = 1; k[2] = 2; 00109 k[3] = -1; k[4] = 0; k[5] = 1; 00110 k[6] = -2; k[7] = -1; k[8] = 0; 00111 break; 00112 default: 00113 throw fawkes::Exception("Cannot generate Sobel kernel for the given orientation"); 00114 break; 00115 } 00116 } 00117 00118 void 00119 FilterSobel::apply() 00120 { 00121 shrink_region(src_roi[0], 3); 00122 shrink_region(dst_roi, 3); 00123 00124 #if defined(HAVE_IPP) 00125 IppiSize size; 00126 size.width = src_roi[0]->width; 00127 size.height = src_roi[0]->height; 00128 00129 IppStatus status; 00130 00131 if (ori[0] == ORI_HORIZONTAL) { 00132 // base + number of bytes to line y + pixel bytes 00133 status = ippiFilterSobelHoriz_8u_C1R( src[0] + (src_roi[0]->start.y * src_roi[0]->line_step) + (src_roi[0]->start.x * src_roi[0]->pixel_step), src_roi[0]->line_step, 00134 dst + (dst_roi->start.y * dst_roi->line_step) + (dst_roi->start.x * dst_roi->pixel_step), dst_roi->line_step, 00135 size ); 00136 } else if (ori[0] == ORI_VERTICAL) { 00137 status = ippiFilterSobelHoriz_8u_C1R( src[0] + (src_roi[0]->start.y * src_roi[0]->line_step) + (src_roi[0]->start.x * src_roi[0]->pixel_step), src_roi[0]->line_step, 00138 dst + (dst_roi->start.y * dst_roi->line_step) + (dst_roi->start.x * dst_roi->pixel_step), dst_roi->line_step, 00139 size ); 00140 00141 } else if ( (ori[0] == ORI_DEG_0) || 00142 (ori[0] == ORI_DEG_45) || 00143 (ori[0] == ORI_DEG_90) || 00144 (ori[0] == ORI_DEG_135) || 00145 (ori[0] == ORI_DEG_180) || 00146 (ori[0] == ORI_DEG_225) || 00147 (ori[0] == ORI_DEG_270) || 00148 (ori[0] == ORI_DEG_315) || 00149 (ori[0] == ORI_DEG_360) 00150 ) { 00151 00152 Ipp32s kernel[9]; 00153 generate_kernel(kernel, ori[0]); 00154 00155 IppiSize kernel_size; 00156 kernel_size.width = kernel_size.height = 3; 00157 00158 IppiPoint anchor; 00159 anchor.x = anchor.y = 1; 00160 00161 status = ippiFilter_8u_C1R( src[0] + (src_roi[0]->start.y * src_roi[0]->line_step) + (src_roi[0]->start.x * src_roi[0]->pixel_step), src_roi[0]->line_step, 00162 dst + (dst_roi->start.y * dst_roi->line_step) + (dst_roi->start.x * dst_roi->pixel_step), dst_roi->line_step, 00163 size, 00164 kernel, kernel_size, 00165 anchor, 00166 /* divisor */ 1 ); 00167 00168 } else { 00169 // cout << "FilterSobel: Unsupported direction" << endl; 00170 status = ippStsNullPtrErr; 00171 } 00172 00173 if ( status != ippStsNoErr ) { 00174 throw fawkes::Exception("Sobel filter failed with %i", status); 00175 } 00176 #elif defined(HAVE_OPENCV) 00177 cv::Mat srcm(src_roi[0]->height, src_roi[0]->width, CV_8UC1, 00178 src[0] + 00179 (src_roi[0]->start.y * src_roi[0]->line_step) + 00180 (src_roi[0]->start.x * src_roi[0]->pixel_step), 00181 src_roi[0]->line_step); 00182 00183 if (dst == NULL) { dst = src[0]; dst_roi = src_roi[0]; } 00184 00185 cv::Mat dstm(dst_roi->height, dst_roi->width, CV_8UC1, 00186 dst + 00187 (dst_roi->start.y * dst_roi->line_step) + 00188 (dst_roi->start.x * dst_roi->pixel_step), 00189 dst_roi->line_step); 00190 00191 if (ori[0] == ORI_HORIZONTAL) { 00192 if ((dst == NULL) || (dst == src[0])) { 00193 throw fawkes::Exception("OpenCV-based Sobel filter cannot be in-place"); 00194 } 00195 00196 cv::Sobel(srcm, dstm, /* ddepth */ -1, /* xorder */ 1, /* yorder */ 0, 00197 /* ksize */ 3, /* scale */ 1); 00198 } else if (ori[0] == ORI_VERTICAL) { 00199 if ((dst == NULL) || (dst == src[0])) { 00200 throw fawkes::Exception("OpenCV-based Sobel filter cannot be in-place"); 00201 } 00202 00203 cv::Sobel(srcm, dstm, /* ddepth */ -1, /* xorder */ 0, /* yorder */ 1, 00204 /* ksize */ 3, /* scale */ 1); 00205 } else if ( (ori[0] == ORI_DEG_0) || 00206 (ori[0] == ORI_DEG_45) || 00207 (ori[0] == ORI_DEG_90) || 00208 (ori[0] == ORI_DEG_135) || 00209 (ori[0] == ORI_DEG_180) || 00210 (ori[0] == ORI_DEG_225) || 00211 (ori[0] == ORI_DEG_270) || 00212 (ori[0] == ORI_DEG_315) || 00213 (ori[0] == ORI_DEG_360) 00214 ) 00215 { 00216 cv::Mat kernel(3, 3, CV_32F); 00217 generate_kernel((float *)kernel.ptr(), ori[0]); 00218 00219 cv::filter2D(srcm, dstm, /* ddepth */ -1, kernel, cv::Point(1, 1)); 00220 } else { 00221 throw fawkes::Exception("Unknown filter sobel orientation"); 00222 00223 } 00224 #endif 00225 00226 } 00227 00228 } // end namespace firevision