sobel.cpp

00001
00002 /***************************************************************************
00003  *  sobel.cpp - Implementation of a Sobel filter
00004  *
00005  *  Created: Thu May 12 13:20:43 2005
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 <filters/sobel.h>
00025
00026 #include <core/exception.h>
00027
00028 #include <ippi.h>
00029
00030 
00031 /** @class FilterSobel <filters/sobel.h>
00032  * Sobel filter.
00033  * @author Tim Niemueller
00034  */
00035 
00036 /** Constructor.
00037  * @param ori edge orientation
00038  */
00039 FilterSobel::FilterSobel(orientation_t ori)
00040   : Filter("FilterSobel")
00041 {
00042 }
00043
00044 
00045 /** Generate a sobel kernel for the given orientation.
00046  * @param k matrix for the kernel of size 3x3, contains three
00047  * lines concatenated into an one dimensional array.
00048  * @param ori requested orientation of the filter
00049  */
00050 void
00051 FilterSobel::generate_kernel(int *k, orientation_t ori)
00052 {
00053   // k is the kernel
00054   switch (ori) {
00055   case ORI_DEG_0:
00056   case ORI_DEG_360:
00057     k[0] =  1;    k[1] =  2;    k[2] =  1;
00058     k[3] =  0;    k[4] =  0;    k[5] =  0;
00059     k[6] = -1;    k[7] = -2;    k[8] = -1;
00060     break;
00061   case ORI_DEG_45:
00062     k[0] =  2;    k[1] =  1;    k[2] =  0;
00063     k[3] =  1;    k[4] =  0;    k[5] = -1;
00064     k[6] =  0;    k[7] = -1;    k[8] = -2;
00065     break;
00066   case ORI_DEG_90:
00067     k[0] =  1;    k[1] =  0;    k[2] = -1;
00068     k[3] =  2;    k[4] =  0;    k[5] = -2;
00069     k[6] =  1;    k[7] =  0;    k[8] = -1;
00070     break;
00071   case ORI_DEG_135:
00072     k[0] =  0;    k[1] = -1;    k[2] = -2;
00073     k[3] =  1;    k[4] =  0;    k[5] = -1;
00074     k[6] =  2;    k[7] =  1;    k[8] =  0;
00075     break;
00076   case ORI_DEG_180:
00077     k[0] = -1;    k[1] = -2;    k[2] = -1;
00078     k[3] =  0;    k[4] =  0;    k[5] =  0;
00079     k[6] =  1;    k[7] =  2;    k[8] =  1;
00080     break;
00081   case ORI_DEG_225:
00082     k[0] = -2;    k[1] = -1;    k[2] =  0;
00083     k[3] = -1;    k[4] =  0;    k[5] =  1;
00084     k[6] =  0;    k[7] =  1;    k[8] =  2;
00085     break;
00086   case ORI_DEG_270:
00087     k[0] = -1;    k[1] =  0;    k[2] =  1;
00088     k[3] = -2;    k[4] =  0;    k[5] =  2;
00089     k[6] = -1;    k[7] =  0;    k[8] =  1;
00090     break;
00091   case ORI_DEG_315:
00092     k[0] =  0;    k[1] =  1;    k[2] =  2;
00093     k[3] = -1;    k[4] =  0;    k[5] =  1;
00094     k[6] = -2;    k[7] = -1;    k[8] =  0;
00095     break;
00096   default:
00097     // cout << "FilterSobel: Cannote generate kernel for the given orientation." << endl;
00098     break;
00099   }
00100 }
00101
00102
00103 void
00104 FilterSobel::apply()
00105 {
00106   shrink_region(src_roi[0], 3);
00107   shrink_region(dst_roi, 3);
00108
00109   IppiSize size;
00110   size.width = src_roi[0]->width;
00111   size.height = src_roi[0]->height;
00112
00113   IppStatus status;
00114
00115   if (ori[0] == ORI_HORIZONTAL) {
00116     //                                    base + number of bytes to line y              + pixel bytes
00117     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,
00118                                           dst + (dst_roi->start.y * dst_roi->line_step) + (dst_roi->start.x * dst_roi->pixel_step), dst_roi->line_step,
00119                                           size );
00120   } else if (ori[0] == ORI_VERTICAL) {
00121     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,
00122                                           dst + (dst_roi->start.y * dst_roi->line_step) + (dst_roi->start.x * dst_roi->pixel_step), dst_roi->line_step,
00123                                           size );
00124
00125   } else if ( (ori[0] == ORI_DEG_0) ||
00126               (ori[0] == ORI_DEG_45) ||
00127               (ori[0] == ORI_DEG_90) ||
00128               (ori[0] == ORI_DEG_135) ||
00129               (ori[0] == ORI_DEG_180) ||
00130               (ori[0] == ORI_DEG_225) ||
00131               (ori[0] == ORI_DEG_270) ||
00132               (ori[0] == ORI_DEG_315) ||
00133               (ori[0] == ORI_DEG_360)
00134               ) {
00135
00136     Ipp32s kernel[9];
00137     generate_kernel(kernel, ori[0]);
00138
00139     IppiSize kernel_size;
00140     kernel_size.width = kernel_size.height = 3;
00141
00142     IppiPoint anchor;
00143     anchor.x = anchor.y = 1;
00144
00145     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,
00146                                 dst + (dst_roi->start.y * dst_roi->line_step) + (dst_roi->start.x * dst_roi->pixel_step), dst_roi->line_step,
00147                                 size,
00148                                 kernel, kernel_size,
00149                                 anchor,
00150                                 /* divisor */ 1 );
00151
00152   } else {
00153     // cout << "FilterSobel: Unsupported direction" << endl;
00154     status = ippStsNullPtrErr;
00155   }
00156
00157   if ( status != ippStsNoErr ) {
00158     throw fawkes::Exception("Sobel filter failed with %i\n", status);
00159   }
00160
00161 }