Ticket #10793: logodetector.patch
File logodetector.patch, 27.6 KB (added by , 12 years ago) |
---|
-
mythtv/libs/libmythtv/avformatdecoder.cpp
diff --git a/mythtv/libs/libmythtv/avformatdecoder.cpp b/mythtv/libs/libmythtv/avformatdecoder.cpp index 9439d39..3c95424 100644
a b void AvFormatDecoder::InitVideoCodec(AVStream *stream, AVCodecContext *enc, 1372 1372 } 1373 1373 1374 1374 if (FlagIsSet(kDecodeLowRes)) 1375 enc->lowres = 2; // 1 = 1/2 size, 2 = 1/4 size 1375 { 1376 if (enc->height > 720) 1377 enc->lowres = 2; // 2 = 1/4 size 1378 else 1379 enc->lowres = 1; // 1 = 1/2 size 1380 } 1376 1381 } 1377 1382 else if (CODEC_ID_H264 == codec->id) 1378 1383 { -
mythtv/programs/mythcommflag/ClassicCommDetector.cpp
diff --git a/mythtv/programs/mythcommflag/ClassicCommDetector.cpp b/mythtv/programs/mythcommflag/ClassicCommDetector.cpp index 800e83d..bb83323 100644
a b ClassicCommDetector::ClassicCommDetector(SkipType commDetectMethod_in, 152 152 preRoll(0), postRoll(0) 153 153 { 154 154 commDetectBorder = 155 gCoreContext->GetNumSetting("CommDetectBorder", 20);155 gCoreContext->GetNumSetting("CommDetectBorder", 5); 156 156 commDetectBlankFrameMaxDiff = 157 157 gCoreContext->GetNumSetting("CommDetectBlankFrameMaxDiff", 25); 158 158 commDetectDarkBrightness = … … void ClassicCommDetector::Init() 206 206 .arg(width).arg(height) 207 207 .arg(player->GetFrameRate()).arg(commDetectMethod)); 208 208 209 if ((width * height) > 1000000) 210 { 211 horizSpacing = 10; 212 vertSpacing = 10; 213 } 214 else if ((width * height) > 800000) 215 { 216 horizSpacing = 8; 217 vertSpacing = 8; 218 } 219 else if ((width * height) > 400000) 220 { 221 horizSpacing = 6; 222 vertSpacing = 6; 223 } 224 else if ((width * height) > 300000) 225 { 226 horizSpacing = 6; 227 vertSpacing = 4; 228 } 229 else 230 { 231 horizSpacing = 4; 232 vertSpacing = 4; 233 } 209 horizSpacing = 1; 210 vertSpacing = 1; 234 211 235 212 LOG(VB_COMMFLAG, LOG_INFO, 236 213 QString("Using Sample Spacing of %1 horizontal & %2 vertical pixels.") -
mythtv/programs/mythcommflag/ClassicLogoDetector.cpp
diff --git a/mythtv/programs/mythcommflag/ClassicLogoDetector.cpp b/mythtv/programs/mythcommflag/ClassicLogoDetector.cpp index f961af0..6db9e12 100644
a b 6 6 7 7 // MythTV headers 8 8 #include "mythcorecontext.h" 9 #include "myth player.h"9 #include "mythcommflagplayer.h" 10 10 11 11 // Commercial Flagging headers 12 12 #include "ClassicLogoDetector.h" 13 13 #include "ClassicCommDetector.h" 14 15 typedef struct edgemaskentry 16 { 17 int isedge; 18 int horiz; 19 int vert; 20 int rdiag; 21 int ldiag; 22 } 23 EdgeMaskEntry; 24 14 #include <ffmpeg-mmx.h> 15 #include <lzoconf.h> 25 16 26 17 ClassicLogoDetector::ClassicLogoDetector(ClassicCommDetector* commdetector, 27 18 unsigned int w, unsigned int h, … … ClassicLogoDetector::ClassicLogoDetector(ClassicCommDetector* commdetector, 29 20 unsigned int xspacing_in, 30 21 unsigned int yspacing_in) 31 22 : LogoDetectorBase(w,h), 32 commDetector(commdetector), frameNumber(0), 33 previousFrameWasSceneChange(false), 34 xspacing(xspacing_in), yspacing(yspacing_in), 35 commDetectBorder(commdetectborder_in), edgeMask(new EdgeMaskEntry[width * height]), 36 logoMaxValues(new unsigned char[width * height]), logoMinValues(new unsigned char[width * height]), 37 logoFrame(new unsigned char[width * height]), logoMask(new unsigned char[width * height]), 38 logoCheckMask(new unsigned char[width * height]), tmpBuf(new unsigned char[width * height]), 39 logoEdgeDiff(0), logoFrameCount(0), 40 logoMinX(0), logoMaxX(0), 41 logoMinY(0), logoMaxY(0), 42 logoInfoAvailable(false) 23 commDetector(commdetector), commDetectBorder(commdetectborder_in), 24 logoInfoAvailable(false), logoEdgeDiff(0), 25 logoMinX(0), logoWidth(0), 26 logoMinY(0), logoHeight(0) 43 27 { 44 28 commDetectLogoSamplesNeeded = 45 29 gCoreContext->GetNumSetting("CommDetectLogoSamplesNeeded", 240); … … unsigned int ClassicLogoDetector::getRequiredAvailableBufferForSearch() 63 47 void ClassicLogoDetector::deleteLater(void) 64 48 { 65 49 commDetector = 0; 66 if (edgeMask) 67 delete [] edgeMask; 68 if (logoFrame) 69 delete [] logoFrame; 70 if (logoMask) 71 delete [] logoMask; 72 if (logoCheckMask) 73 delete [] logoCheckMask; 74 if (logoMaxValues) 75 delete [] logoMaxValues; 76 if (logoMinValues) 77 delete [] logoMinValues; 78 if (tmpBuf) 79 delete [] tmpBuf; 80 50 81 51 LogoDetectorBase::deleteLater(); 82 52 } 83 53 … … bool ClassicLogoDetector::searchForLogo(MythPlayer* player) 88 58 long long seekFrame; 89 59 int loops; 90 60 int maxLoops = commDetectLogoSamplesNeeded; 91 EdgeMaskEntry *edgeCounts; 92 unsigned int pos, i, x, y, dx, dy; 93 int edgeDiffs[] = {5, 7, 10, 15, 20, 30, 40, 50, 60, 0 }; 94 95 61 const int edgeDiffs[] = {55, 25, 13, 6, 0}; 62 96 63 LOG(VB_COMMFLAG, LOG_INFO, "Searching for Station Logo"); 97 64 98 65 logoInfoAvailable = false; 99 66 100 edgeCounts = new EdgeMaskEntry[width * height];67 int *edgeCounts = new int[width * height]; 101 68 102 for (i = 0; edgeDiffs[i] != 0 && !logoInfoAvailable; i++)69 for (int i = 0; edgeDiffs[i] != 0 && !logoInfoAvailable; i++) 103 70 { 104 71 int pixelsInMask = 0; 105 72 106 73 LOG(VB_COMMFLAG, LOG_INFO, QString("Trying with edgeDiff == %1") 107 74 .arg(edgeDiffs[i])); 108 75 109 memset(edgeCounts, 0, sizeof( EdgeMaskEntry) * width * height);110 memset(edgeMask, 0, sizeof(EdgeMaskEntry) * width * height);76 memset(edgeCounts, 0, sizeof(int) * width * height); 77 edgeMask.clear(); 111 78 112 79 player->DiscardVideoFrame(player->GetRawVideoFrame(0)); 113 80 … … bool ClassicLogoDetector::searchForLogo(MythPlayer* player) 115 82 seekFrame = commDetector->preRoll + seekIncrement; 116 83 while(loops < maxLoops && !player->GetEof()) 117 84 { 118 VideoFrame* vf = player->GetRawVideoFrame(seekFrame);119 120 85 if ((loops % 50) == 0) 121 86 commDetector->logoDetectorBreathe(); 122 87 88 if (!commDetector->fullSpeed) 89 usleep(10000); 90 91 VideoFrame* vf = player->GetRawVideoFrame(seekFrame); 92 DetectEdges(vf, edgeCounts, edgeDiffs[i]); 93 player->DiscardVideoFrame(vf); 94 123 95 if (commDetector->m_bStop) 124 96 { 125 player->DiscardVideoFrame(vf);126 97 delete[] edgeCounts; 127 98 return false; 128 99 } 129 130 if (!commDetector->fullSpeed) 131 usleep(10000); 132 133 DetectEdges(vf, edgeCounts, edgeDiffs[i]); 134 100 135 101 seekFrame += seekIncrement; 136 102 loops++; 137 138 player->DiscardVideoFrame(vf);139 }140 141 LOG(VB_COMMFLAG, LOG_INFO, "Analyzing edge data");142 143 #ifdef SHOW_DEBUG_WIN144 unsigned char *fakeFrame;145 fakeFrame = new unsigned char[width * height * 3 / 2];146 memset(fakeFrame, 0, width * height * 3 / 2);147 #endif148 149 for (y = 0; y < height; y++)150 {151 if ((y > (height/4)) && (y < (height * 3 / 4)))152 continue;153 154 for (x = 0; x < width; x++)155 {156 if ((x > (width/4)) && (x < (width * 3 / 4)))157 continue;158 159 pos = y * width + x;160 161 if (edgeCounts[pos].isedge > (maxLoops * 0.66))162 {163 edgeMask[pos].isedge = 1;164 pixelsInMask++;165 #ifdef SHOW_DEBUG_WIN166 fakeFrame[pos] = 0xff;167 #endif168 169 }170 171 if (edgeCounts[pos].horiz > (maxLoops * 0.66))172 edgeMask[pos].horiz = 1;173 174 if (edgeCounts[pos].vert > (maxLoops * 0.66))175 edgeMask[pos].vert = 1;176 177 if (edgeCounts[pos].ldiag > (maxLoops * 0.66))178 edgeMask[pos].ldiag = 1;179 if (edgeCounts[pos].rdiag > (maxLoops * 0.66))180 edgeMask[pos].rdiag = 1;181 }182 }183 184 SetLogoMaskArea();185 186 for (y = logoMinY; y < logoMaxY; y++)187 {188 for (x = logoMinX; x < logoMaxX; x++)189 {190 int neighbors = 0;191 192 if (!edgeMask[y * width + x].isedge)193 continue;194 195 for (dy = y - 2; dy <= (y + 2); dy++ )196 {197 for (dx = x - 2; dx <= (x + 2); dx++ )198 {199 if (edgeMask[dy * width + dx].isedge)200 neighbors++;201 }202 }203 204 if (neighbors < 5)205 edgeMask[y * width + x].isedge = 0;206 }207 103 } 104 105 player->DiscardVideoFrame(player->GetRawVideoFrame(0)); 208 106 209 SetLogoMaskArea(); 107 pixelsInMask = AnalyzeEdgeCounts(edgeCounts, maxLoops * 2 / 3); 108 210 109 LOG(VB_COMMFLAG, LOG_INFO, 211 QString("Testing Logo area: topleft (%1,%2), bottomright(%3,%4)")110 QString("Testing Logo area: topleft (%1,%2), size (%3,%4)") 212 111 .arg(logoMinX).arg(logoMinY) 213 .arg(logoMaxX).arg(logoMaxY)); 214 215 #ifdef SHOW_DEBUG_WIN 216 for (x = logoMinX; x < logoMaxX; x++) 217 { 218 pos = logoMinY * width + x; 219 fakeFrame[pos] = 0x7f; 220 pos = logoMaxY * width + x; 221 fakeFrame[pos] = 0x7f; 222 } 223 for (y = logoMinY; y < logoMaxY; y++) 224 { 225 pos = y * width + logoMinX; 226 fakeFrame[pos] = 0x7f; 227 pos = y * width + logoMaxX; 228 fakeFrame[pos] = 0x7f; 229 } 230 231 comm_debug_show(fakeFrame); 232 delete [] fakeFrame; 112 .arg(logoWidth).arg(logoHeight)); 233 113 234 cerr << "Hit ENTER to continue" << endl; 235 getchar(); 236 #endif 237 if (((logoMaxX - logoMinX) < (width / 4)) && 238 ((logoMaxY - logoMinY) < (height / 4)) && 239 (pixelsInMask > 50)) 114 if (pixelsInMask > 100 && 115 (logoWidth < (width / 6) || logoHeight < (height / 6))) 240 116 { 241 117 logoInfoAvailable = true; 242 118 logoEdgeDiff = edgeDiffs[i]; … … bool ClassicLogoDetector::searchForLogo(MythPlayer* player) 245 121 QString("Using Logo area: topleft (%1,%2), " 246 122 "bottomright (%3,%4)") 247 123 .arg(logoMinX).arg(logoMinY) 248 .arg(logo MaxX).arg(logoMaxY));124 .arg(logoWidth).arg(logoHeight)); 249 125 } 250 126 else 251 127 { … … bool ClassicLogoDetector::searchForLogo(MythPlayer* player) 254 130 "bottomright (%3,%4), pixelsInMask (%5). " 255 131 "Not within specified limits.") 256 132 .arg(logoMinX).arg(logoMinY) 257 .arg(logo MaxX).arg(logoMaxY)133 .arg(logoWidth).arg(logoHeight) 258 134 .arg(pixelsInMask)); 259 135 } 260 136 } … … bool ClassicLogoDetector::searchForLogo(MythPlayer* player) 263 139 264 140 if (!logoInfoAvailable) 265 141 LOG(VB_COMMFLAG, LOG_NOTICE, "No suitable logo area found."); 266 267 player->DiscardVideoFrame(player->GetRawVideoFrame(0)); 142 else 143 DumpLogo(); 144 268 145 return logoInfoAvailable; 269 146 } 270 147 271 272 void ClassicLogoDetector::SetLogoMaskArea() 148 int ClassicLogoDetector::AnalyzeEdgeCounts(int *edgeCounts, int threshold) 273 149 { 274 LOG(VB_COMMFLAG, LOG_INFO, "SetLogoMaskArea()"); 275 150 const int minNeighbors = 2; 151 int pixelsInMask = 0; 152 unsigned int logoMaxX = 0, logoMaxY = 0; 153 276 154 logoMinX = width - 1; 277 logoMaxX = 0;278 155 logoMinY = height - 1; 279 logoMaxY = 0; 280 156 157 LOG(VB_COMMFLAG, LOG_INFO, "Analyzing edge data"); 158 159 QBitArray tmpMask(width*height); 160 281 161 for (unsigned int y = 0; y < height; y++) 282 162 { 283 163 for (unsigned int x = 0; x < width; x++) 284 164 { 285 if (edgeMask[y * width + x].isedge) 165 unsigned int pos = y * width + x; 166 if (edgeCounts[pos] < threshold) 167 continue; 168 169 int neighbors = 0; 170 171 // 3x3 block 172 for (int dy = y - 1; dy <= (y + 1); dy++) 173 { 174 for (int dx = x - 1; dx <= (x + 1); dx++) 175 { 176 unsigned int dp = dy * width + dx; 177 if (edgeCounts[dp] >= threshold) 178 { 179 neighbors++; 180 if (neighbors > minNeighbors) 181 break; 182 } 183 } 184 } 185 186 if (neighbors > minNeighbors) 286 187 { 188 tmpMask[pos] = true; 189 190 pixelsInMask++; 191 287 192 if (x < logoMinX) 288 193 logoMinX = x; 289 194 if (y < logoMinY) … … void ClassicLogoDetector::SetLogoMaskArea() 293 198 if (y > logoMaxY) 294 199 logoMaxY = y; 295 200 } 296 } 297 } 298 299 logoMinX -= 5; 300 logoMaxX += 5; 301 logoMinY -= 5; 302 logoMaxY += 5; 303 304 if (logoMinX < 4) 305 logoMinX = 4; 306 if (logoMaxX > (width-5)) 307 logoMaxX = (width-5); 308 if (logoMinY < 4) 309 logoMinY = 4; 310 if (logoMaxY > (height-5)) 311 logoMaxY = (height-5); 312 } 313 314 void ClassicLogoDetector::SetLogoMask(unsigned char *mask) 315 { 316 int pixels = 0; 317 318 memcpy(logoMask, mask, width * height); 319 320 SetLogoMaskArea(); 321 322 for(unsigned int y = logoMinY; y <= logoMaxY; y++) 323 for(unsigned int x = logoMinX; x <= logoMaxX; x++) 324 if (!logoMask[y * width + x] == 1) 325 pixels++; 326 327 if (pixels < 30) 328 return; 329 330 // set the pixels around our logo 331 for(unsigned int y = (logoMinY - 1); y <= (logoMaxY + 1); y++) 332 { 333 for(unsigned int x = (logoMinX - 1); x <= (logoMaxX + 1); x++) 334 { 335 if (!logoMask[y * width + x]) 201 else 336 202 { 337 for (unsigned int y2 = y - 1; y2 <= (y + 1); y2++) 338 { 339 for (unsigned int x2 = x - 1; x2 <= (x + 1); x2++) 340 { 341 if ((logoMask[y2 * width + x2] == 1) && 342 (!logoMask[y * width + x])) 343 { 344 logoMask[y * width + x] = 2; 345 x2 = x + 2; 346 y2 = y + 2; 347 348 logoCheckMask[y2 * width + x2] = 1; 349 logoCheckMask[y * width + x] = 1; 350 } 351 } 352 } 203 tmpMask[pos] = false; 353 204 } 354 } 355 } 356 357 for(unsigned int y = (logoMinY - 2); y <= (logoMaxY + 2); y++) 205 } // end for x 206 } // end for y 207 208 logoMinX -= 1; 209 logoMaxX += 1; 210 logoMinY -= 1; 211 logoMaxY += 1; 212 213 if (logoMinX < commDetectBorder) 214 logoMinX = commDetectBorder; 215 if (logoMaxX > (width-commDetectBorder)) 216 logoMaxX = (width-commDetectBorder); 217 if (logoMinY < commDetectBorder) 218 logoMinY = commDetectBorder; 219 if (logoMaxY > (height-commDetectBorder)) 220 logoMaxY = (height-commDetectBorder); 221 222 if (pixelsInMask > 0 && logoMaxX > logoMinX && logoMaxY > logoMinY) 358 223 { 359 for(unsigned int x = (logoMinX - 2); x <= (logoMaxX + 2); x++) 224 logoWidth = logoMaxX - logoMinX; 225 logoHeight = logoMaxY - logoMinY; 226 227 edgeMask.resize(logoWidth * logoHeight); 228 for (unsigned int y = 0; y < logoHeight; ++y) 360 229 { 361 if (!logoMask[y * width + x])230 for (unsigned int x = 0; x < logoWidth; ++x) 362 231 { 363 for (unsigned int y2 = y - 1; y2 <= (y + 1); y2++) 364 { 365 for (unsigned int x2 = x - 1; x2 <= (x + 1); x2++) 366 { 367 if ((logoMask[y2 * width + x2] == 2) && 368 (!logoMask[y * width + x])) 369 { 370 logoMask[y * width + x] = 3; 371 x2 = x + 2; 372 y2 = y + 2; 373 374 logoCheckMask[y * width + x] = 1; 375 } 376 } 377 } 232 edgeMask[y * logoWidth + x] = tmpMask[(y + logoMinY) * width + (x + logoMinX)]; 378 233 } 379 234 } 380 235 } 381 382 #ifdef SHOW_DEBUG_WIN 383 DumpLogo(true,framePtr); 384 #endif 385 386 logoFrameCount = 0; 387 logoInfoAvailable = true; 236 237 return pixelsInMask; 388 238 } 389 239 390 391 void ClassicLogoDetector::DumpLogo(bool fromCurrentFrame, 392 unsigned char* framePtr) 240 void ClassicLogoDetector::DumpLogo() 393 241 { 394 char scrPixels[] = " .oxX"; 395 396 if (!logoInfoAvailable) 397 return; 398 399 cerr << "\nLogo Data "; 400 if (fromCurrentFrame) 401 cerr << "from current frame\n"; 402 403 cerr << "\n "; 404 405 for(unsigned int x = logoMinX - 2; x <= (logoMaxX + 2); x++) 406 cerr << (x % 10); 407 cerr << "\n"; 408 409 for(unsigned int y = logoMinY - 2; y <= (logoMaxY + 2); y++) 242 cerr << "Logo data (" << logoMinX << "," << logoMinY << ") x (" 243 << logoWidth << "," << logoHeight << ") @ " 244 << logoEdgeDiff << ":\n"; 245 246 for (unsigned int y = 0; y < logoHeight; y++) 410 247 { 411 QString tmp = QString("%1: ").arg(y, 3); 412 QString ba = tmp.toAscii(); 413 cerr << ba.constData(); 414 for(unsigned int x = logoMinX - 2; x <= (logoMaxX + 2); x++) 248 for (unsigned int x = 0; x < logoWidth; x++) 415 249 { 416 if (fromCurrentFrame) 417 { 418 cerr << scrPixels[framePtr[y * width + x] / 50]; 419 } 250 unsigned int pos = y * logoWidth + x; 251 if (edgeMask[pos]) 252 cerr << "#"; 420 253 else 421 { 422 switch (logoMask[y * width + x]) 423 { 424 case 0: 425 case 2: cerr << " "; 426 break; 427 case 1: cerr << "*"; 428 break; 429 case 3: cerr << "."; 430 break; 431 } 432 } 254 cerr << " "; 433 255 } 434 256 cerr << "\n"; 435 257 } 436 cerr.flush(); 258 259 cerr << "\n\n\n"; 437 260 } 438 261 262 bool ClassicLogoDetector::pixelInsideLogo(unsigned int x, unsigned int y) 263 { 264 if (!logoInfoAvailable) 265 return false; 266 267 int xd = x - logoMinX; 268 int yd = y - logoMinY; 269 270 return xd >= 0 && xd < (int)logoWidth && 271 yd >= 0 && yd < (int)logoHeight; 272 } 439 273 440 /* ideas for this method ported back from comskip.c mods by Jere Jones 441 * which are partially mods based on Myth's original commercial skip442 * code written by Chris Pinkham. */443 bool ClassicLogoDetector::doesThisFrameContainTheFoundLogo( 444 unsigned char* framePtr)274 bool ClassicLogoDetector::isSobelEdgeAt(unsigned char *buf, 275 unsigned int x, 276 unsigned int y, 277 unsigned int width, 278 unsigned char edgeDiff) 445 279 { 446 int radius = 2; 447 unsigned int x, y; 448 int pos1, pos2, pos3; 449 int pixel; 450 int goodEdges = 0; 451 int badEdges = 0; 452 int testEdges = 0; 453 int testNotEdges = 0; 280 int center = y * width + x; 281 int above = center - width; 282 int below = center + width; 283 284 int gx = 0; 285 gx -= buf[above - 1]; 286 gx -= (buf[center - 1]*2); 287 gx -= buf[below - 1]; 288 289 gx += buf[above + 1]; 290 gx += (buf[center + 1]*2); 291 gx += buf[below + 1]; 292 293 int gy = 0; 294 gy -= buf[above - 1]; 295 gy -= (buf[above]*2); 296 gy -= buf[above + 1]; 297 298 gy += buf[below - 1]; 299 gy += (buf[below]*2); 300 gy += buf[below + 1]; 301 302 return abs(gx) + abs(gy) > 3*edgeDiff; 303 } 454 304 455 for (y = logoMinY; y <= logoMaxY; y++ ) 305 bool ClassicLogoDetector::doesThisFrameContainTheFoundLogo(unsigned char *framePtr) 306 { 307 if (!logoInfoAvailable) 308 return false; 309 310 unsigned int x, y; 311 unsigned int correct = 0, total = 0; 312 313 for (y = 0; y < logoHeight; y++ ) 456 314 { 457 for (x = logoMinX; x <= logoMaxX; x++ )315 for (x = 0; x < logoWidth; x++ ) 458 316 { 459 pos1 = y * width + x; 460 pos2 = (y - radius) * width + x; 461 pos3 = (y + radius) * width + x; 462 463 pixel = framePtr[pos1]; 464 465 if (edgeMask[pos1].horiz) 466 { 467 if ((abs(framePtr[pos1 - radius] - pixel) >= logoEdgeDiff) || 468 (abs(framePtr[pos1 + radius] - pixel) >= logoEdgeDiff)) 469 goodEdges++; 470 testEdges++; 471 } 472 else 473 { 474 if ((abs(framePtr[pos1 - radius] - pixel) >= logoEdgeDiff) || 475 (abs(framePtr[pos1 + radius] - pixel) >= logoEdgeDiff)) 476 badEdges++; 477 testNotEdges++; 478 } 479 480 if (edgeMask[pos1].vert) 481 { 482 if ((abs(framePtr[pos2] - pixel) >= logoEdgeDiff) || 483 (abs(framePtr[pos3] - pixel) >= logoEdgeDiff)) 484 goodEdges++; 485 testEdges++; 486 } 487 else 317 if (edgeMask[y * logoWidth + x]) 488 318 { 489 if ((abs(framePtr[pos2] - pixel) >= logoEdgeDiff) || 490 (abs(framePtr[pos3] - pixel) >= logoEdgeDiff)) 491 badEdges++; 492 testNotEdges++; 319 if (isSobelEdgeAt(framePtr, x + logoMinX, y + logoMinY, width, logoEdgeDiff)) 320 correct++; 321 total ++; 493 322 } 494 323 } 495 324 } 496 497 frameNumber++; 498 double goodEdgeRatio = (double)goodEdges / (double)testEdges; 499 double badEdgeRatio = (double)badEdges / (double)testNotEdges; 500 if ((goodEdgeRatio > commDetectLogoGoodEdgeThreshold) && 501 (badEdgeRatio < commDetectLogoBadEdgeThreshold)) 502 return true; 503 else 504 return false; 505 } 506 507 bool ClassicLogoDetector::pixelInsideLogo(unsigned int x, unsigned int y) 508 { 509 if (!logoInfoAvailable) 510 return false; 511 512 return ((x > logoMinX) && (x < logoMaxX) && 513 (y > logoMinY) && (y < logoMaxY)); 325 326 double d = (double)correct / (double)total; 327 return d >= commDetectLogoGoodEdgeThreshold; 514 328 } 515 329 516 void ClassicLogoDetector::DetectEdges(VideoFrame *frame, EdgeMaskEntry *edges, 517 int edgeDiff) 330 void ClassicLogoDetector::DetectEdges(VideoFrame *frame, int *edgeCounts, int edgeDiff) 518 331 { 519 int r = 2; 520 unsigned char *buf = frame->buf; 521 unsigned char p; 522 unsigned int pos, x, y; 523 524 for (y = commDetectBorder + r; y < (height - commDetectBorder - r); y++) 332 unsigned int x, y; 333 334 unsigned int hOneThird = height / 3; 335 unsigned int hTwoThirds = hOneThird*2; 336 unsigned int wOneThird = width / 3; 337 unsigned int wTwoThirds = wOneThird*2; 338 339 for (y = commDetectBorder; y < height - commDetectBorder; ++y) 525 340 { 526 if ((y > (height/4)) && (y < (height * 3 / 4))) 527 continue; 528 529 for (x = commDetectBorder + r; x < (width - commDetectBorder - r); x++) 341 for (x = commDetectBorder; x < width - commDetectBorder; ++x) 530 342 { 531 int edgeCount = 0; 532 533 if ((x > (width/4)) && (x < (width * 3 / 4))) 534 continue; 535 536 pos = y * width + x; 537 p = buf[pos]; 538 539 if (( abs(buf[y * width + (x - r)] - p) >= edgeDiff) || 540 ( abs(buf[y * width + (x + r)] - p) >= edgeDiff)) 541 { 542 edges[pos].horiz++; 543 edgeCount++; 544 } 545 if (( abs(buf[(y - r) * width + x] - p) >= edgeDiff) || 546 ( abs(buf[(y + r) * width + x] - p) >= edgeDiff)) 547 { 548 edges[pos].vert++; 549 edgeCount++; 550 } 551 552 if (( abs(buf[(y - r) * width + (x - r)] - p) >= edgeDiff) || 553 ( abs(buf[(y + r) * width + (x + r)] - p) >= edgeDiff)) 343 if (y > hOneThird && y < hTwoThirds && 344 x > wOneThird && x < wTwoThirds) 554 345 { 555 edges[pos].ldiag++; 556 edgeCount++; 346 x = wTwoThirds - 1; 557 347 } 558 559 if (( abs(buf[(y - r) * width + (x + r)] - p) >= edgeDiff) || 560 ( abs(buf[(y + r) * width + (x - r)] - p) >= edgeDiff)) 348 else if (isSobelEdgeAt(frame->buf, x, y, width, edgeDiff)) 561 349 { 562 edges[pos].rdiag++; 563 edgeCount++; 350 edgeCounts[y * width + x]++; 564 351 } 565 566 if (edgeCount >= 3)567 edges[pos].isedge++;568 352 } 569 353 } 570 354 } 571 355 572 356 /* vim: set expandtab tabstop=4 shiftwidth=4: */ 573 -
mythtv/programs/mythcommflag/ClassicLogoDetector.h
diff --git a/mythtv/programs/mythcommflag/ClassicLogoDetector.h b/mythtv/programs/mythcommflag/ClassicLogoDetector.h index d589df5..a78ce4c 100644
a b 2 2 #define _CLASSICLOGOGEDETECTOR_H_ 3 3 4 4 #include "LogoDetectorBase.h" 5 #include <qbitarray.h> 5 6 6 typedef struct edgemaskentry EdgeMaskEntry;7 7 typedef struct VideoFrame_ VideoFrame; 8 8 class ClassicCommDetector; 9 9 … … class ClassicLogoDetector : public LogoDetectorBase 16 16 virtual void deleteLater(void); 17 17 18 18 bool searchForLogo(MythPlayer* player); 19 bool doesThisFrameContainTheFoundLogo(unsigned char * frame);19 bool doesThisFrameContainTheFoundLogo(unsigned char *framePtr); 20 20 bool pixelInsideLogo(unsigned int x, unsigned int y); 21 21 22 22 unsigned int getRequiredAvailableBufferForSearch(); 23 23 24 void DumpLogo(); 25 static bool isSobelEdgeAt(unsigned char *buf, unsigned int x, unsigned int y, unsigned int width, unsigned char edgeDiff); 26 24 27 protected: 25 28 virtual ~ClassicLogoDetector() {} 26 29 27 30 private: 28 void SetLogoMaskArea(); 29 void SetLogoMask(unsigned char *mask); 30 void DumpLogo(bool fromCurrentFrame,unsigned char* framePtr); 31 void DetectEdges(VideoFrame *frame, EdgeMaskEntry *edges, int edgeDiff); 32 31 int AnalyzeEdgeCounts(int *edgeCounts, int threshold); 32 void DetectEdges(VideoFrame *frame, int *edgeCounts, int edgeDiff); 33 33 34 ClassicCommDetector* commDetector; 34 unsigned int frameNumber;35 bool previousFrameWasSceneChange;36 unsigned int xspacing, yspacing;37 35 unsigned int commDetectBorder; 38 36 39 37 int commDetectLogoSamplesNeeded; 40 38 int commDetectLogoSampleSpacing; 41 39 int commDetectLogoSecondsNeeded; 42 40 double commDetectLogoGoodEdgeThreshold; 43 41 double commDetectLogoBadEdgeThreshold; 42 43 QBitArray edgeMask; 44 44 45 EdgeMaskEntry *edgeMask; 46 47 unsigned char *logoMaxValues; 48 unsigned char *logoMinValues; 49 unsigned char *logoFrame; 50 unsigned char *logoMask; 51 unsigned char *logoCheckMask; 52 unsigned char *tmpBuf; 53 45 bool logoInfoAvailable; 54 46 int logoEdgeDiff; 55 unsigned int logoFrameCount;56 47 unsigned int logoMinX; 57 unsigned int logo MaxX;48 unsigned int logoWidth; 58 49 unsigned int logoMinY; 59 unsigned int logoMaxY; 60 61 bool logoInfoAvailable; 50 unsigned int logoHeight; 62 51 }; 63 52 64 53 #endif