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