|
MythTV
0.26-pre
|
00001 // ANSI C headers 00002 #include <cmath> 00003 00004 // MythTV headers 00005 #include "mythplayer.h" 00006 #include "frame.h" // VideoFrame 00007 #include "mythlogging.h" 00008 00009 // Commercial Flagging headers 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 * In general, the Gaussian mask is truncated at a point where values cease 00023 * to make any meaningful contribution. The sigma=>truncation computation 00024 * is best done by table lookup (which I don't have here). For sigma=0.5, 00025 * the magic truncation value is 4. 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 /* The SGM computations require that mask_radius >= 2. */ 00035 mask_radius = max(2, (int)roundf(TRUNCATION * sigma)); 00036 mask_width = 2 * mask_radius + 1; 00037 00038 /* Compute Gaussian mask. */ 00039 mask = new double[mask_width]; 00040 val = 1.0; /* Initialize center of Gaussian mask (rr=0 => exp(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); // Gaussian weight(rr,sigma) 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; /* normalize to [0,1] */ 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 * Sentinel value to determine whether or not stuff has already been 00083 * allocated. 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 * Canny edge detection 00158 * 00159 * See 00160 * http://www.cs.cornell.edu/courses/CS664/2003fa/handouts/664-l6-edges-03.pdf 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 /* vim: set expandtab tabstop=4 shiftwidth=4: */
1.7.6.1