00001 #include <math.h>
00002
00003 #include "NuppelVideoPlayer.h"
00004 #include "frame.h"
00005
00006 #include "pgm.h"
00007 #include "CannyEdgeDetector.h"
00008
00009 using namespace edgeDetector;
00010
00011 CannyEdgeDetector::CannyEdgeDetector(void)
00012 : sgm(NULL)
00013 , sgmsorted(NULL)
00014 , ewidth(-1)
00015 , eheight(-1)
00016 {
00017
00018
00019
00020
00021
00022
00023 const int TRUNCATION = 4;
00024 const double sigma = 0.5;
00025 const double TWO_SIGMA2 = 2 * sigma * sigma;
00026
00027 double val, sum;
00028 int mask_width, rr, ii;
00029
00030
00031 mask_radius = max(2, (int)roundf(TRUNCATION * sigma));
00032 mask_width = 2 * mask_radius + 1;
00033
00034
00035 mask = new double[mask_width];
00036 val = 1.0;
00037 mask[mask_radius] = val;
00038 sum = val;
00039 for (rr = 1; rr <= mask_radius; rr++)
00040 {
00041 val = exp(-(rr * rr) / TWO_SIGMA2);
00042 mask[mask_radius + rr] = val;
00043 mask[mask_radius - rr] = val;
00044 sum += 2 * val;
00045 }
00046 for (ii = 0; ii < mask_width; ii++)
00047 mask[ii] /= sum;
00048
00049 memset(&s1, 0, sizeof(s1));
00050 memset(&s2, 0, sizeof(s2));
00051 memset(&convolved, 0, sizeof(convolved));
00052 memset(&edges, 0, sizeof(edges));
00053 memset(&exclude, 0, sizeof(exclude));
00054 }
00055
00056 CannyEdgeDetector::~CannyEdgeDetector(void)
00057 {
00058 avpicture_free(&edges);
00059 avpicture_free(&convolved);
00060 avpicture_free(&s2);
00061 avpicture_free(&s1);
00062 if (sgmsorted)
00063 delete []sgmsorted;
00064 if (sgm)
00065 delete []sgm;
00066 if (mask)
00067 delete []mask;
00068 }
00069
00070 int
00071 CannyEdgeDetector::resetBuffers(int newwidth, int newheight)
00072 {
00073 if (ewidth == newwidth && eheight == newheight)
00074 return 0;
00075
00076 if (sgm) {
00077
00078
00079
00080
00081 avpicture_free(&s1);
00082 avpicture_free(&s2);
00083 avpicture_free(&convolved);
00084 avpicture_free(&edges);
00085 delete []sgm;
00086 delete []sgmsorted;
00087 sgm = NULL;
00088 }
00089
00090 const int padded_width = newwidth + 2 * mask_radius;
00091 const int padded_height = newheight + 2 * mask_radius;
00092
00093 if (avpicture_alloc(&s1, PIX_FMT_GRAY8, padded_width, padded_height))
00094 {
00095 VERBOSE(VB_COMMFLAG, "CannyEdgeDetector::resetBuffers "
00096 "avpicture_alloc s1 failed");
00097 return -1;
00098 }
00099
00100 if (avpicture_alloc(&s2, PIX_FMT_GRAY8, padded_width, padded_height))
00101 {
00102 VERBOSE(VB_COMMFLAG, "CannyEdgeDetector::resetBuffers "
00103 "avpicture_alloc s2 failed");
00104 goto free_s1;
00105 }
00106
00107 if (avpicture_alloc(&convolved, PIX_FMT_GRAY8, padded_width, padded_height))
00108 {
00109 VERBOSE(VB_COMMFLAG, "CannyEdgeDetector::resetBuffers "
00110 "avpicture_alloc convolved failed");
00111 goto free_s2;
00112 }
00113
00114 if (avpicture_alloc(&edges, PIX_FMT_GRAY8, newwidth, newheight))
00115 {
00116 VERBOSE(VB_COMMFLAG, "CannyEdgeDetector::resetBuffers "
00117 "avpicture_alloc edges failed");
00118 goto free_convolved;
00119 }
00120
00121 sgm = new unsigned int[padded_width * padded_height];
00122 sgmsorted = new unsigned int[newwidth * newheight];
00123
00124 ewidth = newwidth;
00125 eheight = newheight;
00126
00127 return 0;
00128
00129 free_convolved:
00130 avpicture_free(&convolved);
00131 free_s2:
00132 avpicture_free(&s2);
00133 free_s1:
00134 avpicture_free(&s1);
00135 return -1;
00136 }
00137
00138 int
00139 CannyEdgeDetector::setExcludeArea(int row, int col, int width, int height)
00140 {
00141 exclude.row = row;
00142 exclude.col = col;
00143 exclude.width = width;
00144 exclude.height = height;
00145 return 0;
00146 }
00147
00148 const AVPicture *
00149 CannyEdgeDetector::detectEdges(const AVPicture *pgm, int pgmheight,
00150 int percentile)
00151 {
00152
00153
00154
00155
00156
00157
00158
00159 const int pgmwidth = pgm->linesize[0];
00160 const int padded_height = pgmheight + 2 * mask_radius;
00161
00162 if (resetBuffers(pgmwidth, pgmheight))
00163 return NULL;
00164
00165 if (pgm_convolve_radial(&convolved, &s1, &s2, pgm, pgmheight,
00166 mask, mask_radius))
00167 return NULL;
00168
00169 if (edge_mark_uniform_exclude(&edges, pgmheight, mask_radius,
00170 sgm_init_exclude(sgm, &convolved, padded_height,
00171 exclude.row + mask_radius, exclude.col + mask_radius,
00172 exclude.width, exclude.height),
00173 sgmsorted, percentile,
00174 exclude.row, exclude.col, exclude.width, exclude.height))
00175 return NULL;
00176
00177 return &edges;
00178 }
00179
00180