📄 motionsearcher.hh
字号:
== (*itHere).m_tnMotionY); ++itNext;#endif // NDEBUG // Check just that one pixel-group. PIXELINDEX tnX = (m_tnX + (*itHere).m_tnMotionX); PIXELINDEX tnY = (m_tnY + (*itHere).m_tnMotionY); if (tnX < 0 || tnX >= m_tnWidth - PGW + 1 || tnY < 0 || tnY >= m_tnHeight - PGH + 1) continue; const SearchWindowCell &rCell = m_oSearchWindow.GetCell (tnY, tnX); if (rCell.m_pForward != NULL) { assert (rCell.m_tnX == m_tnX + (*itHere).m_tnMotionX); assert (rCell.m_tnY == m_tnY + (*itHere).m_tnMotionY); if (rCell.IsWithinTolerance (oCurrentGroup, m_tnTolerance#ifdef THROTTLE_PIXELSORTER_WITH_SAD , tnSAD#endif // THROTTLE_PIXELSORTER_WITH_SAD )) {#ifdef PRINT_SEARCHBORDER if (frame == 61 && DIM == 2) fprintf (stderr, "Found match at " "(%d,%d), motion vector (%d,%d)\n", int (m_tnX), int (m_tnY), int (rCell.m_tnX - m_tnX), int (rCell.m_tnY - m_tnY));#endif#ifndef USE_SEARCH_BORDER #error Expand-regions code needs the search-border#endif // USE_SEARCH_BORDER // Add this match to our growing set of // moved regions. FRAMESIZE tnThisMatch = m_oSearchBorder.AddNewMatch (a_reStatus, rCell); if (a_reStatus != g_kNoError) return; // That's one more match. ++tnMatches; // Keep track of the smallest/largest // region. tnSmallestMatch = Min (tnSmallestMatch, tnThisMatch); tnLargestMatch = Max (tnLargestMatch, tnThisMatch); } } } }#endif // EXPAND_REGIONS // If the expanding-regions code couldn't run, or if it // didn't find any matches, then use the pixel-sorter to // find matches for the current pixel-group. if (tnMatches == 0) { // HACK //fprintf (stderr, ", consulting pixel-sorter.\n"); #ifndef THROTTLE_PIXELSORTER_WITH_SAD PIXELINDEX tnBestMotionX, tnBestMotionY; FRAMESIZE tnBestMotionXXYY; // The best match found, and its length.#endif // THROTTLE_PIXELSORTER_WITH_SAD // Set up the search-window in a radius around the // current pixel-group. m_oSearchWindow.PrepareForSearch (a_reStatus, true); if (a_reStatus != g_kNoError) return; // Search for matches for the current pixel-group // within the search radius. m_oSearchWindow.StartSearch (itMatch, oCurrentGroup);#ifdef THROTTLE_PIXELSORTER_WITH_SAD m_setMatches.Clear(); while (pMatch = m_oSearchWindow.FoundNextMatch (itMatch, tnSAD), pMatch != NULL)#else // THROTTLE_PIXELSORTER_WITH_SAD tnBestMotionX = m_tnSearchRadiusX + 1; tnBestMotionY = m_tnSearchRadiusY + 1; tnBestMotionXXYY = FRAMESIZE (tnBestMotionX) * FRAMESIZE (tnBestMotionX) + FRAMESIZE (tnBestMotionY) * FRAMESIZE (tnBestMotionY); while (pMatch = m_oSearchWindow.FoundNextMatch (itMatch), pMatch != NULL)#endif // THROTTLE_PIXELSORTER_WITH_SAD {#ifdef PRINT_SEARCHBORDER if (frame == 61 && DIM == 2) fprintf (stderr, "Found match at (%d,%d), " "motion vector (%d,%d)\n", int (m_tnX), int (m_tnY), int (pMatch->m_tnX - m_tnX), int (pMatch->m_tnY - m_tnY));#endif // PRINT_SEARCHBORDER // Make sure this match is within the search // radius. assert (AbsoluteValue (pMatch->m_tnX - m_tnX) <= m_tnSearchRadiusX); assert (AbsoluteValue (pMatch->m_tnY - m_tnY) <= m_tnSearchRadiusY); #ifdef THROTTLE_PIXELSORTER_WITH_SAD // If this match is better than our worst so // far, get rid of our worst & use the new one // instead. if (m_setMatches.Size() == m_nMatchCountThrottle) { typename MatchedPixelGroupSet::Iterator itWorst; // The worst match found so far. // Get the worst match. (It's at the end of // the list.) itWorst = m_setMatches.End(); --itWorst; // If the new item is better than our worst, // get rid of our worst to make room for the // new item. if (tnSAD < (*itWorst).m_tnSAD) m_setMatches.Erase (itWorst); } // If this match is close enough to the current // pixel-group, make a note of it. if (m_setMatches.Size() < m_nMatchCountThrottle) { m_setMatches.Insert (a_reStatus, MatchedPixelGroup (tnSAD, pMatch)); if (a_reStatus != g_kNoError) return; }#else // THROTTLE_PIXELSORTER_WITH_SAD#ifdef USE_SEARCH_BORDER // Add this match to our growing set of moved // regions. FRAMESIZE tnThisMatch = m_oSearchBorder.AddNewMatch (a_reStatus, *pMatch); if (a_reStatus != g_kNoError) return; // Keep track of the smallest/largest region. tnSmallestMatch = Min (tnSmallestMatch, tnThisMatch); tnLargestMatch = Max (tnLargestMatch, tnThisMatch);#else // USE_SEARCH_BORDER PIXELINDEX tnMotionX, tnMotionY; FRAMESIZE tnMotionXXYY; // The motion vector of this match. // Calculate the motion vector of this match. tnMotionX = pMatch->m_tnX - m_tnX; tnMotionY = pMatch->m_tnY - m_tnY; tnMotionXXYY = FRAMESIZE (tnMotionX) * FRAMESIZE (tnMotionX) + FRAMESIZE (tnMotionY) * FRAMESIZE (tnMotionY); // If this is the best match so far (i.e. the // one closest to the origin), use it. (This // isn't a great test, but it's the one that // was accidentally being used for a long time, // and the results seemed OK, so what the heck.) if (tnBestMotionXXYY > tnMotionXXYY) { tnBestMotionXXYY = tnMotionXXYY; tnBestMotionX = tnMotionX; tnBestMotionY = tnMotionY; }#endif // USE_SEARCH_BORDER // That's one more match. ++tnMatches;#endif // THROTTLE_PIXELSORTER_WITH_SAD } #ifdef THROTTLE_PIXELSORTER_WITH_SAD // Now loop through all the good matches found, // flood-fill each one, and use the first one that // fills a large enough area. for (itBestMatch = m_setMatches.Begin(); itBestMatch != m_setMatches.End(); ++itBestMatch) { PIXELINDEX tnMotionX, tnMotionY; // The motion vector of this match. // Get the current match. const MatchedPixelGroup &rMatch = *itBestMatch; // Calculate its motion vector. tnMotionX = rMatch.m_pGroup->m_tnX - m_tnX; tnMotionY = rMatch.m_pGroup->m_tnY - m_tnY;#ifdef USE_SEARCH_BORDER // Add this match to our growing set of moved // regions. FRAMESIZE tnThisMatch = m_oSearchBorder.AddNewMatch (a_reStatus, tnMotionX, tnMotionY); if (a_reStatus != g_kNoError) return; // That's one more match. ++tnMatches; // Keep track of the smallest/largest region. tnSmallestMatch = Min (tnSmallestMatch, tnThisMatch); tnLargestMatch = Max (tnLargestMatch, tnThisMatch);#else // USE_SEARCH_BORDER // Set up a region describing the current // pixel-group. m_oMatchThrottleRegion.Clear(); { PIXELINDEX tnY; // Used to loop through the // pixel-group's lines. for (tnY = m_tnY; tnY < m_tnY + PGH; ++tnY) { m_oMatchThrottleRegion.Merge (a_reStatus, tnY, m_tnX, m_tnX + PGW); if (a_reStatus != g_kNoError) return; } } // Set its motion vector. m_oMatchThrottleRegion.SetMotionVector (tnMotionX, tnMotionY); // Flood-fill this match, so as to get its full // extent. m_oMatchThrottleFloodFillControl .SetupForFloodFill (tnMotionX, tnMotionY); m_oMatchThrottleRegion.FloodFill (a_reStatus, m_oMatchThrottleFloodFillControl, false); if (a_reStatus != g_kNoError) return; // Get the size of the flood-filled region. FRAMESIZE tnThisMatch = m_oMatchThrottleRegion.NumberOfPoints(); // If this match is big enough, keep it. if (tnThisMatch >= m_nMatchSizeThrottle * PGH * PGW) { ApplyRegionToNewFrame (a_reStatus, m_oMatchThrottleRegion); if (a_reStatus != g_kNoError) return; // That's one more match. ++tnMatches; // That's more pixels found by // flood-filling. if (tnMotionX == 0 && tnMotionY == 0) tnNotMovedFloodedPixels += tnThisMatch; else tnFloodedPixels += tnThisMatch; // Stop looking. break; }#endif // USE_SEARCH_BORDER } // All done with the matches. m_setMatches.Clear();#else // THROTTLE_PIXELSORTER_WITH_SAD#ifndef USE_SEARCH_BORDER // Now flood-fill the best match and apply it to // the new frame. if (tnMatches > 0) { PIXELINDEX tnY; // Used to loop through the pixel-group // lines. // Set up the region with the current // pixel-group. m_oMatchThrottleRegion.Clear(); for (tnY = m_tnY; tnY < m_tnY + PGH; ++tnY) { m_oMatchThrottleRegion.Union (a_reStatus, tnY, m_tnX, m_tnX + PGW); if (a_reStatus != g_kNoError) return; } // Set its motion vector. m_oMatchThrottleRegion.SetMotionVector (tnBestMotionX, tnBestMotionY); // Flood-fill this match, so as to get its full // extent. m_oMatchThrottleFloodFillControl .SetupForFloodFill (tnBestMotionX, tnBestMotionY); m_oMatchThrottleRegion.FloodFill (a_reStatus, m_oMatchThrottleFloodFillControl, false); if (a_reStatus != g_kNoError) return; // Get the size of the flood-filled region. FRAMESIZE tnThisMatch = m_oMatchThrottleRegion.NumberOfPoints(); // Apply the match to the new frame right now. ApplyRegionToNewFrame (a_reStatus, m_oMatchThrottleRegion); if (a_reStatus != g_kNoError) return; // That's more pixels found by flood-filling. if (tnBestMotionX == 0 && tnBestMotionY == 0) tnNotMovedFloodedPixels += tnThisMatch; else tnFloodedPixels += tnThisMatch; }#endif // !USE_SEARCH_BORDER#endif // THROTTLE_PIXELSORTER_WITH_SAD } // If no matches were found for the current pixel-group, // and there are no active border-regions in the area, // then we've found new information. // NOTE: this dramatically speeds up the analysis of // frames that contain mostly new info, but probably // impacts quality. Flood-fills are allowed to override // the result, though. if (tnMatches == 0#ifdef USE_SEARCH_BORDER && m_oSearchBorder.NumberOfActiveRegions() == 0#endif // USE_SEARCH_BORDER ) { PIXELINDEX tnX, tnY; for (tnY = m_tnY; tnY < m_tnY + PGH; ++tnY) { for (tnX = m_tnX; tnX < m_tnX + PGW; ++tnX) { // Allocate a new reference pixel. ReferencePixel_t *pNewPixel = m_oPixelPool.Allocate(); // Store the new pixel in the reference // frame. m_pNewFrame->SetPixel (tnX, tnY, pNewPixel); // Give it the value from the new frame. pNewPixel->AddSample (a_pPixels[tnY * m_tnWidth + tnX]); } } }#ifdef USE_SEARCH_BORDER // If it's time to flood-fill, do so. if (tnMatches >= FRAMESIZE (m_nMatchCountThrottle) || tnLargestMatch >= FRAMESIZE (m_nMatchSizeThrottle * PGH * PGW)) { FRAMESIZE tnFlooded; PIXELINDEX tnMotionX, tnMotionY; // Take the biggest region that the current // pixel-group matched, flood-fill it, and apply it // to the new frame now, eliminating all competing // moved-regions. tnFlooded = SearchBorder_FloodFill (a_reStatus, tnMotionX, tnMotionY); if (a_reStatus != g_kNoError) return; #if 0 // HACK fprintf (stderr, "Match throttle: frame %d, " "x %03d, y %03d, %03d matches, "
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -