Пример #1
0
        private static bool FindDeathsRecursive(VideoCapture capture, List <int> deaths, float videoScale, int startFrame, int endFrame, float stepSize = 4)
        {
            capture.Set(VideoCaptureProperties.PosMsec, 0);
            double fps = capture.Get(VideoCaptureProperties.Fps);

            int stepSizeFrames = (int)(stepSize * capture.Fps);

            int currentLives = -1;
            int lastFrame    = 0;

            for (int frame = startFrame; frame < endFrame; frame += stepSizeFrames)
            {
                int lifeCount = LifeCounter.GetLifeCount(capture, frame / fps, videoScale);

                if (currentLives == -1)
                {
                    currentLives = lifeCount;
                }

                if (lifeCount > 0)
                {
                    if (lifeCount < currentLives)
                    {
                        if (stepSizeFrames <= 1)
                        {
                            if (!deaths.Contains(lastFrame))
                            {
                                deaths.Add(lastFrame);
                            }

                            Mat dbgMat = new Mat();
                            capture.Read(dbgMat);

                            return(true);
                        }
                        else
                        {
                            // Try first half, then second half
                            if (!FindDeathsRecursive(capture, deaths, videoScale, lastFrame, frame + stepSizeFrames / 2, stepSize / 2))
                            {
                                FindDeathsRecursive(capture, deaths, videoScale, lastFrame + stepSizeFrames / 2, frame,
                                                    stepSize / 2);
                            }
                        }
                    }

                    currentLives = lifeCount;
                }

                lastFrame = frame;
            }

            return(false);
        }
Пример #2
0
        public static List <Load> GetOverworldLoads(VideoCapture capture, float scale, float timeStart, float timeEnd,
                                                    LoadType loadTypes,
                                                    Action <LoadRemover.ProgressPhase, float> updateProgress)
        {
            List <Load> loads           = new List <Load>();
            var         binocularFrames = FindBinocularFrames(capture, timeStart, timeEnd);
            List <int>  startingFrames  = new List <int>();
            List <int>  endingFrames    = new List <int>();
            int         lastFrame       = -2;

            foreach (var frame in binocularFrames)
            {
                if (frame > lastFrame + 1)
                {
                    startingFrames.Add(frame);
                    endingFrames.Add(lastFrame);
                }

                lastFrame = frame;
            }

            float fps      = (float)capture.Fps;
            int   progress = 0;

            if (loadTypes.HasFlag(LoadType.Overworld))
            {
                foreach (var f in startingFrames)
                {
                    updateProgress.Invoke(LoadRemover.ProgressPhase.Phase_6_OverworldLoads,
                                          0.5f + ((progress++) / (float)startingFrames.Count) * 0.25f);

                    // 30 fps -> 10 frozen frames
                    // 60 fps -> 20 frozen frames
                    Rect cropRect   = new Rect(0, 0, (int)(capture.FrameWidth * 0.5f), capture.FrameHeight);
                    var  _loadStart = Util.CountFrozenFrames(LoadType.Overworld, capture, f / fps, (int)(fps / 3),
                                                             (int)fps * 25, cropRect);

                    if (!_loadStart.HasValue)
                    {
                        continue;
                    }

                    var loadStart = _loadStart.Value;

                    // Check when the life counter first appears, skip three seconds
                    for (int i = (int)fps * 3; i < fps * 20; i++)
                    {
                        var lifeCount = LifeCounter.GetLifeCount(capture, (f + i) / fps, scale);
                        if (lifeCount >= 0)
                        {
                            loads.Add(new Load(LoadType.Overworld, loadStart.FrameStart, f + i));
                            break;
                        }
                    }
                }
            }

            updateProgress.Invoke(LoadRemover.ProgressPhase.Phase_6_OverworldLoads, 0.66f);

            progress = 0;


            if (loadTypes.HasFlag(LoadType.BackSign))
            {
                foreach (var f in startingFrames)
                {
                    updateProgress.Invoke(LoadRemover.ProgressPhase.Phase_6_OverworldLoads,
                                          0.75f + ((progress++) / (float)startingFrames.Count) * 0.25f);

                    // Check back sign loads
                    var _backSignLoad = Util.CountFrozenFrames(LoadType.BackSign, capture,
                                                               (f / fps) - backSignLoadMaxDuration, (int)fps * 1, (int)fps * backSignLoadMaxDuration);

                    if (!_backSignLoad.HasValue)
                    {
                        continue;
                    }

                    loads.Add(_backSignLoad.Value);
                }
            }

            return(loads);
        }
        public static List <Load> GetEndSignLoads(VideoCapture capture, float scale, int startingFrame, int endingFrame,
                                                  Action <LoadRemover.ProgressPhase, float> updateProgress)
        {
            List <Load> loads           = new List <Load>();
            List <int>  potentialFrames = new List <int>();

            Mat   lastMat        = null;
            float lastBrightness = float.NaN;

            for (int f = startingFrame; f < endingFrame; f += (int)(capture.Fps * EndSignLoadMinDuration * 0.5f))
            {
                updateProgress.Invoke(LoadRemover.ProgressPhase.Phase_5_EndSignLoads, ((float)f / capture.FrameCount) * 0.5f);

                capture.PosFrames = f;
                var m = new Mat();
                capture.Read(m);

                float brightness = Util.GetAverageBrightness(m);
                if (float.IsNaN(lastBrightness))
                {
                    lastBrightness = brightness;
                }

                if (lastMat != null)
                {
                    float brightnessDiff = brightness - lastBrightness;

                    if (Math.Abs(brightnessDiff) < MaxBrightnessDeltaForCheck &&
                        Util.GetMaxDifference(m, lastMat) < Util.MaxDifferenceIdenticalFrames)
                    {
                        // Either have a visible lifecount or the left part of the screen isn't dark (to prevent the musician cutscene from being detected)
                        if (LifeCounter.GetLifeCount(capture, f / capture.Fps, scale) >= 0 ||
                            Util.GetAverageBrightness(m[0, m.Height, 0, (int)(m.Width * (3f / 16))]) > Util.DarknessMaxBrightness)
                        {
                            f += CheckPotentialFrames(capture, f, potentialFrames);
                        }
                    }

                    lastBrightness = brightness;
                }

                lastMat = m;
            }

            int pfProgress = 0;

            foreach (var pf in potentialFrames)
            {
                updateProgress.Invoke(LoadRemover.ProgressPhase.Phase_5_EndSignLoads, 0.5f + ((float)pfProgress / potentialFrames.Count) * 0.5f);

                var load = Util.CountFrozenFrames(LoadType.EndSign, capture, pf / capture.Fps,
                                                  (int)(capture.Fps * EndSignLoadMinDuration), (int)(EndSignLoadMaxDuration * capture.Fps));

                if (load.HasValue)
                {
                    var loadEndMat = new Mat();
                    capture.PosFrames = (int)(load.Value.FrameEnd + capture.Fps * 1.0f); // Check last frame + 1 second
                    capture.Read(loadEndMat);

                    // Not a binocular frame or life count found?
                    //if (!OverworldLoads.IsBinocularFrame(loadEndMat) ||
                    //LifeCounter.GetLifeCount(capture, capture.PosFrames / capture.Fps, scale) >= 0) {
                    loads.Add(load.Value);
                    //}
                }
            }

            return(loads);
        }