예제 #1
0
        public bool ProcessCalibrationFrame(int frameNo, uint[] oddPixels, uint[] evenPixels, int width, int height, bool isTVSafeModeGuess)
        {
            if (m_Processor == null)
            {
                m_FieldAreaHeight             = height;
                m_FieldAreaWidth              = width;
                m_OddFieldPixels              = new uint[m_FieldAreaWidth * m_FieldAreaHeight];
                m_EvenFieldPixels             = new uint[m_FieldAreaWidth * m_FieldAreaHeight];
                m_OddFieldPixelsPreProcessed  = new uint[m_FieldAreaWidth * m_FieldAreaHeight];
                m_EvenFieldPixelsPreProcessed = new uint[m_FieldAreaWidth * m_FieldAreaHeight];

                m_Processor = new IotaVtiOcrProcessor(isTVSafeModeGuess);
            }

            bool wasCalibrated = m_Processor.IsCalibrated;

            if (!m_Processor.IsCalibrated)
            {
                m_Processor.Process(oddPixels, width, height, null, frameNo, true);
            }

            if (!m_Processor.IsCalibrated)
            {
                m_Processor.Process(evenPixels, width, height, null, frameNo, false);
            }

            if (!wasCalibrated && m_Processor.IsCalibrated)
            {
                m_TimeStampComposer = new VtiTimeStampComposer(m_Processor.VideoFormat, m_InitializationData.IntegratedAAVFrames, m_Processor.EvenBeforeOdd, false /* Duplicated fields not supported for IOTA-VTI */, m_VideoController, this, () => m_Processor.CurrentImage);
            }

            return(m_Processor.IsCalibrated);
        }
예제 #2
0
 public void Initialize(TimestampOCRData initializationData, IVideoController videoController, int performanceMode)
 {
     m_InitializationData     = initializationData;
     m_VideoController        = videoController;
     m_Processor              = null;
     m_UseNativePreProcessing = performanceMode > 0;
     m_ForceErrorReport       = initializationData.ForceErrorReport;
     m_CalibrationImages.Clear();
 }
예제 #3
0
        public int GetLastFrameNoDigitPosition(IotaVtiOcrProcessor stateManager)
        {
            for (int i = IotaVtiOcrProcessor.FIRST_FRAME_NO_DIGIT_POSITIONS; i <= IotaVtiOcrProcessor.MAX_POSITIONS; i++)
            {
                uint[] pixels = stateManager.GetBlockAtPosition(Image, i, IsOddField);
                int nuberSignalPixels = pixels.Count(x => x < 127);
                if (stateManager.IsMatchingSignature(nuberSignalPixels) /* Matches to blank block */)
                    return i;
            }

            return -1;
        }
예제 #4
0
        private void btnReload_Click(object sender, EventArgs e)
        {
            m_CurrentIndex = -1;
            m_InputFiles.Clear();
            m_InputFiles.AddRange(TestCaseHelper.LoadTestImages(tbxInputFolder.Text, cbxReverseEvenOdd.Checked));

            m_Processor = new IotaVtiOcrProcessor(cbxIsTvSafe.Checked);

            if (m_InputFiles.Count > 0)
            {
                m_CurrentIndex = 0;
            }
            ProcessCurrentImage();
        }
예제 #5
0
        public override void Process(IotaVtiOcrProcessor stateManager, Graphics graphics, int frameNo, bool isOddField)
        {
            if (m_Width != stateManager.CurrentImageWidth || m_Height != stateManager.CurrentImageHeight)
            {
                stateManager.ChangeState<IotaVtiOcrCalibratingState>();
                return;
            }

            uint[] pixels = stateManager.CurrentImage;
            IotaVtiTimeStampStrings ocredValue = OcrField(pixels, stateManager, isOddField);
            stateManager.SetOcredString(ocredValue);

            if (graphics != null)
                base.PlotImage(graphics, stateManager, isOddField);
        }
예제 #6
0
        internal static IotaVtiTimeStampStrings OcrField(uint[] pixels, IotaVtiOcrProcessor stateManager, bool isOddField)
        {
            char char1 = OcrBlock(pixels, stateManager, 1, isOddField);
            char char3 = OcrBlock(pixels, stateManager, 3, isOddField);
            char char4 = OcrBlock(pixels, stateManager, 4, isOddField);
            char char6 = OcrBlock(pixels, stateManager, 6, isOddField);
            char char7 = OcrBlock(pixels, stateManager, 7, isOddField);
            char char9 = OcrBlock(pixels, stateManager, 9, isOddField);
            char char10 = OcrBlock(pixels, stateManager, 10, isOddField);

            char char12 = OcrBlock(pixels, stateManager, 12, isOddField);
            char char13 = OcrBlock(pixels, stateManager, 13, isOddField);
            char char14 = OcrBlock(pixels, stateManager, 14, isOddField);
            char char15 = OcrBlock(pixels, stateManager, 15, isOddField);

            char char17 = OcrBlock(pixels, stateManager, 17, isOddField);
            char char18 = OcrBlock(pixels, stateManager, 18, isOddField);
            char char19 = OcrBlock(pixels, stateManager, 19, isOddField);
            char char20 = OcrBlock(pixels, stateManager, 20, isOddField);

            char char22 = OcrBlock(pixels, stateManager, 22, isOddField);
            char char23 = OcrBlock(pixels, stateManager, 23, isOddField);
            char char24 = OcrBlock(pixels, stateManager, 24, isOddField);
            char char25 = OcrBlock(pixels, stateManager, 25, isOddField);
            char char26 = OcrBlock(pixels, stateManager, 26, isOddField);
            char char27 = OcrBlock(pixels, stateManager, 27, isOddField);
            char char28 = OcrBlock(pixels, stateManager, 28, isOddField);

            var rv = new IotaVtiTimeStampStrings()
            {
                NumSat = char1,
                HH = string.Format("{0}{1}", char3, char4).TrimEnd(),
                MM = string.Format("{0}{1}", char6, char7).TrimEnd(),
                SS = string.Format("{0}{1}", char9, char10).TrimEnd(),
                FFFF1 = string.Format("{0}{1}{2}{3}", char12, char13, char14, char15).TrimEnd(),
                FFFF2 = string.Format("{0}{1}{2}{3}", char17, char18, char19, char20).TrimEnd(),
                FRAMENO = string.Format("{0}{1}{2}{3}{4}{5}{6}", char22, char23, char24, char25, char26, char27, char28).TrimEnd()
            };

            return rv;
        }
예제 #7
0
        private void TryInitializeProcessor(uint[] data)
        {
            InitiazliationError = null;

            if (m_Processor == null)
            {
                if (LocateTimestampPosition(data))
                {
                    m_FieldAreaHeight             = (m_ToLine - m_FromLine) / 2;
                    m_FieldAreaWidth              = m_InitializationData.FrameWidth;
                    m_OddFieldPixels              = new uint[m_InitializationData.FrameWidth * m_FieldAreaHeight];
                    m_EvenFieldPixels             = new uint[m_InitializationData.FrameWidth * m_FieldAreaHeight];
                    m_OddFieldPixelsPreProcessed  = new uint[m_InitializationData.FrameWidth * m_FieldAreaHeight];
                    m_EvenFieldPixelsPreProcessed = new uint[m_InitializationData.FrameWidth * m_FieldAreaHeight];
                    m_OddFieldPixelsDebugNoLChD   = new uint[m_InitializationData.FrameWidth * m_FieldAreaHeight];
                    m_EvenFieldPixelsDebugNoLChD  = new uint[m_InitializationData.FrameWidth * m_FieldAreaHeight];

                    m_InitializationData.OSDFrame.Width  = m_FieldAreaWidth;
                    m_InitializationData.OSDFrame.Height = m_FieldAreaHeight;

                    m_Processor = new IotaVtiOcrProcessor(m_TVSafeModeGuess);
                }
            }
        }
예제 #8
0
        private char OcrBlock(IotaVtiOcrProcessor stateManager, uint[] image, int startingPosition, bool isOddField, out int rating)
        {
            uint[] block = stateManager.GetBlockAtXOffset(image, startingPosition, isOddField);

            int[] diffSignatures = new int[10];
            int[] diffDigits = new int[10];
            diffSignatures[0] = GetDiffSignature(block, stateManager.ZeroDigitPattern);
            diffDigits[0] = 0;
            diffSignatures[1] = GetDiffSignature(block, stateManager.OneDigitPattern);
            diffDigits[1] = 1;
            diffSignatures[2] = GetDiffSignature(block, stateManager.TwoDigitPattern);
            diffDigits[2] = 2;
            diffSignatures[3] = GetDiffSignature(block, stateManager.ThreeDigitPattern);
            diffDigits[3] = 3;
            diffSignatures[4] = GetDiffSignature(block, stateManager.FourDigitPattern);
            diffDigits[4] = 4;
            diffSignatures[5] = GetDiffSignature(block, stateManager.FiveDigitPattern);
            diffDigits[5] = 5;
            diffSignatures[6] = GetDiffSignature(block, stateManager.SixDigitPattern);
            diffDigits[6] = 6;
            diffSignatures[7] = GetDiffSignature(block, stateManager.SevenDigitPattern);
            diffDigits[7] = 7;
            diffSignatures[8] = GetDiffSignature(block, stateManager.EightDigitPattern);
            diffDigits[8] = 8;
            diffSignatures[9] = GetDiffSignature(block, stateManager.NineDigitPattern);
            diffDigits[9] = 9;

            Array.Sort(diffSignatures, diffDigits);

            if (stateManager.IsMatchingSignature(diffSignatures[0]))
            {
                if (diffDigits[0] == 8 || diffDigits[0] == 6 || diffDigits[0] == 9)
                {
                    // If we matched to a 6, 8 or 9, then do additional check as those three characters are too similar
                }

                rating = diffSignatures[0];
                return diffDigits[0].ToString()[0];
            }

            rating = int.MaxValue;
            return ' ';
        }
예제 #9
0
        public bool ProcessCalibrationFrame(int frameNo, uint[] oddPixels, uint[] evenPixels, int width, int height, bool isTVSafeModeGuess)
        {
            if (m_Processor == null)
            {
                m_FieldAreaHeight = height;
                m_FieldAreaWidth = width;
                m_OddFieldPixels = new uint[m_FieldAreaWidth * m_FieldAreaHeight];
                m_EvenFieldPixels = new uint[m_FieldAreaWidth * m_FieldAreaHeight];
                m_OddFieldPixelsPreProcessed = new uint[m_FieldAreaWidth * m_FieldAreaHeight];
                m_EvenFieldPixelsPreProcessed = new uint[m_FieldAreaWidth * m_FieldAreaHeight];

                m_Processor = new IotaVtiOcrProcessor(isTVSafeModeGuess);
            }

            bool wasCalibrated = m_Processor.IsCalibrated;

            if (!m_Processor.IsCalibrated)
                m_Processor.Process(oddPixels, width, height, null, frameNo, true);

            if (!m_Processor.IsCalibrated)
                m_Processor.Process(evenPixels, width, height, null, frameNo, false);

            if (!wasCalibrated && m_Processor.IsCalibrated)
                m_Corrector.Reset(m_Processor.VideoFormat);

            return m_Processor.IsCalibrated;
        }
예제 #10
0
        private bool LocateRemainingBlockPositions(IotaVtiOcrProcessor stateManager)
        {
            var confirmedBlockPositions = new List<int>();

            foreach (CalibratedBlockPosition blockPosition in m_CalibratedPositons)
            {
                int prevMatchLocation = -1;
                int pendingLocation = -1;
                int pendingRating = int.MaxValue;

                for (int i = 0; i < stateManager.LastBlockOffsetsX; i++)
                {
                    // Try to match each learned digit to every position
                    int rating = 0;
                    char ch = OcrBlock(stateManager, blockPosition.Image, i, blockPosition.IsOddField, out rating);
                    if (ch != ' ')
                    {
                        if (prevMatchLocation == -1 ||
                            i == prevMatchLocation + 1)
                        {
                            // Sequential matches
                            if (pendingRating > rating)
                            {
                                pendingRating = rating;
                                pendingLocation = i;
                            }

                            prevMatchLocation = i;
                        }

                        Trace.WriteLine(string.Format("IOTA-VTI OCR: Recognized '{0}' at position {1} with score {2}.", ch, i, rating));
                    }
                    else
                    {
                        if (pendingLocation > 0)
                            // Save the location
                            confirmedBlockPositions.Add(pendingLocation);

                        prevMatchLocation = -1;
                        pendingLocation = -1;
                        pendingRating = int.MaxValue;
                    }
                }
            }

            List<int> distinctPositions = confirmedBlockPositions.Distinct().ToList();
            distinctPositions.Sort();

            int posIdx = 0;
            stateManager.BlockOffsetsX = new int[IotaVtiOcrProcessor.MAX_POSITIONS];
            for (int i = 0; i < IotaVtiOcrProcessor.MAX_POSITIONS; i++)
                stateManager.BlockOffsetsX[i] = -1;

            int[] CHAR_INDEXES = stateManager.IsTvSafeMode
                ? new int[] { 3, 4, 6, 7, 9, 10, 12, 13, 14, 15, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28 }
                : new int[] { 1, 3, 4, 6, 7, 9, 10, 12, 13, 14, 15, 17, 18, 19, 20, 22, 23, 24, 25, 26, 27, 28 };

            if (!stateManager.IsTvSafeMode)
                // In Non TV-Safe mode, make sure we are not trying to recognize the GPS Fix character, where 'P' can be mistaken for an '8'
                distinctPositions.RemoveAll(x => x < stateManager.BlockWidth);

            while (distinctPositions.Count > 0)
            {
                int nextPos = distinctPositions[0];
                if (distinctPositions.Count > 1 && distinctPositions[1] == nextPos + 1)
                {
                    int occurances0 = confirmedBlockPositions.Count(x => x == distinctPositions[0]);
                    int occurances1 = confirmedBlockPositions.Count(x => x == distinctPositions[1]);
                    if (occurances1 > occurances0)
                        nextPos = distinctPositions[1];

                    distinctPositions.RemoveAt(0);
                }

                stateManager.BlockOffsetsX[CHAR_INDEXES[posIdx]] = nextPos;
                posIdx++;
                distinctPositions.RemoveAt(0);
            }

            stateManager.BlockOffsetsX[CHAR_INDEXES[posIdx]] = stateManager.LastBlockOffsetsX;

            return true;
        }
예제 #11
0
        private int GetLastFrameNoDigitStartPosition(IotaVtiOcrProcessor stateManager)
        {
            uint[] result = new uint[m_CalibratedPositons[0].Image.Length];
            for (int i = 0; i < m_CalibratedPositons.Count - 2; i++)
            {
                uint[] prev = m_CalibratedPositons[i].Image;
                uint[] next = m_CalibratedPositons[i + 1].Image;

                for (int j = 0; j < result.Length; j++)
                {
                    int x = j % stateManager.CurrentImageWidth;
                    if (x > ROUTH_START_FRAME_NUMBER_BLOCKS && prev[j] != next[j])
                        result[j]++;
                }
            }

            int bestRating = -1;
            int bestStartPosition = -1;
            int oneOfEvenOrOddY = stateManager.BlockOffsetY(false);

            for (int x = ROUTH_START_FRAME_NUMBER_BLOCKS; x < stateManager.CurrentImageWidth - stateManager.BlockWidth; x++)
            {
                int currentRating = 0;

                for (int y = 0; y < stateManager.BlockHeight; y++)
                {
                    for (int k = 0; k < stateManager.BlockWidth; k++)
                    {
                        if (result[x + k + (oneOfEvenOrOddY + y) * stateManager.CurrentImageWidth] > 0)
                            currentRating++;
                    }
                }

                if (currentRating > bestRating)
                {
                    bestStartPosition = x;
                    bestRating = currentRating;
                }
            }

            return bestStartPosition;
        }
예제 #12
0
        private bool DigitPatternsRecognized(IotaVtiOcrProcessor stateManager, out List<CalibratedBlockPosition> normalizedPositions)
        {
            normalizedPositions = new List<CalibratedBlockPosition>();
            Trace.Assert(m_CalibratedPositons.Count == 10);

            List<int> forwardDiffs = m_CalibratedPositons
                .Select(x => GetDiffSignature(x.SecondLastFrameNoDigit, m_CalibratedPositons[0].SecondLastFrameNoDigit))
                .ToList();

            List<int> backwardDiffs = m_CalibratedPositons
                .Select(x => GetDiffSignature(x.SecondLastFrameNoDigit, m_CalibratedPositons[m_CalibratedPositons.Count - 1].SecondLastFrameNoDigit))
                .ToList();

            BinirizeDiffArray(forwardDiffs);
            BinirizeDiffArray(backwardDiffs);

            int forwardChangeIndex = forwardDiffs.FindIndex(x => x == 1);
            int backwardChangeIndex = backwardDiffs.FindIndex(x => x == 0);

            bool swapped = false;
            bool isMatch = forwardChangeIndex == backwardChangeIndex &&
                           forwardDiffs.FindIndex(forwardChangeIndex, x => x == 0) == -1 &&
                           backwardDiffs.FindIndex(backwardChangeIndex, x => x == 1) == -1;

            if (!isMatch)
            {
                // Try with swapped fields
                for (int i = 0; i < forwardDiffs.Count / 2; i++)
                {
                    int tmp = forwardDiffs[2 * i];
                    forwardDiffs[2 * i] = forwardDiffs[2 * i + 1];
                    forwardDiffs[2 * i + 1] = tmp;

                    tmp = backwardDiffs[2 * i];
                    backwardDiffs[2 * i] = backwardDiffs[2 * i + 1];
                    backwardDiffs[2 * i + 1] = tmp;
                }

                forwardChangeIndex = forwardDiffs.FindIndex(x => x == 1);
                backwardChangeIndex = backwardDiffs.FindIndex(x => x == 0);

                isMatch = forwardChangeIndex == backwardChangeIndex &&
                           forwardDiffs.FindIndex(forwardChangeIndex, x => x == 0) == -1 &&
                           backwardDiffs.FindIndex(backwardChangeIndex, x => x == 1) == -1;
                swapped = true;
            }

            if (isMatch)
            {

                if (swapped)
                {
                    for (int i = 0; i < m_CalibratedPositons.Count / 2; i++)
                    {
                        normalizedPositions.Add(m_CalibratedPositons[2 * i + 1]);
                        normalizedPositions.Add(m_CalibratedPositons[2 * i]);
                    }
                }
                else
                    normalizedPositions.AddRange(m_CalibratedPositons);

                int indexPixelPrev = forwardChangeIndex > 0 ? forwardChangeIndex - 1 : 9;
                int indexPixelNext = forwardChangeIndex < normalizedPositions.Count - 1 ? forwardChangeIndex + 1 : forwardChangeIndex - 9;
                int signalChange = normalizedPositions[forwardChangeIndex].LastFrameNoDigit.Count(x => x < 127);
                int signalPixelsPrev = normalizedPositions[indexPixelPrev].LastFrameNoDigit.Count(x => x < 127);
                int signalPixelsNext = normalizedPositions[indexPixelNext].LastFrameNoDigit.Count(x => x < 127);

                // OneAfterZero: 9 - 0 - 1
                // ZeroAfterOne: 8 - 1 - 0

                if (signalChange < signalPixelsPrev && signalChange < signalPixelsNext)
                {
                    // One before Zero
                    stateManager.LearnDigitPattern(normalizedPositions[indexPixelNext].LastFrameNoDigit, 0);
                    stateManager.LearnDigitPattern(normalizedPositions[forwardChangeIndex].LastFrameNoDigit, 1);
                    stateManager.LearnDigitPattern(normalizedPositions[indexPixelPrev].LastFrameNoDigit, 8);

                    // 3 - 2 - 5 - 4 - 7 - 6 - 9 - (8 - 1 - 0) - 3 - 2 - 5 - 4 - 7 - 6  - 9 - 8

                    int walkBackIndex = indexPixelPrev - 1;
                    if (walkBackIndex >= 0) stateManager.LearnDigitPattern(normalizedPositions[walkBackIndex].LastFrameNoDigit, 9);
                    walkBackIndex--;
                    if (walkBackIndex >= 0) stateManager.LearnDigitPattern(normalizedPositions[walkBackIndex].LastFrameNoDigit, 6);
                    walkBackIndex--;
                    if (walkBackIndex >= 0) stateManager.LearnDigitPattern(normalizedPositions[walkBackIndex].LastFrameNoDigit, 7);
                    walkBackIndex--;
                    if (walkBackIndex >= 0) stateManager.LearnDigitPattern(normalizedPositions[walkBackIndex].LastFrameNoDigit, 4);
                    walkBackIndex--;
                    if (walkBackIndex >= 0) stateManager.LearnDigitPattern(normalizedPositions[walkBackIndex].LastFrameNoDigit, 5);
                    walkBackIndex--;
                    if (walkBackIndex >= 0) stateManager.LearnDigitPattern(normalizedPositions[walkBackIndex].LastFrameNoDigit, 2);
                    walkBackIndex--;
                    if (walkBackIndex >= 0) stateManager.LearnDigitPattern(normalizedPositions[walkBackIndex].LastFrameNoDigit, 3);

                    int walkForwardIndex = indexPixelNext + 1;
                    if (walkForwardIndex < 10) stateManager.LearnDigitPattern(normalizedPositions[walkForwardIndex].LastFrameNoDigit, 3);
                    walkForwardIndex++;
                    if (walkForwardIndex < 10) stateManager.LearnDigitPattern(normalizedPositions[walkForwardIndex].LastFrameNoDigit, 2);
                    walkForwardIndex++;
                    if (walkForwardIndex < 10) stateManager.LearnDigitPattern(normalizedPositions[walkForwardIndex].LastFrameNoDigit, 5);
                    walkForwardIndex++;
                    if (walkForwardIndex < 10) stateManager.LearnDigitPattern(normalizedPositions[walkForwardIndex].LastFrameNoDigit, 4);
                    walkForwardIndex++;
                    if (walkForwardIndex < 10) stateManager.LearnDigitPattern(normalizedPositions[walkForwardIndex].LastFrameNoDigit, 7);
                    walkForwardIndex++;
                    if (walkForwardIndex < 10) stateManager.LearnDigitPattern(normalizedPositions[walkForwardIndex].LastFrameNoDigit, 6);
                    walkForwardIndex++;
                    if (walkForwardIndex < 10) stateManager.LearnDigitPattern(normalizedPositions[walkForwardIndex].LastFrameNoDigit, 9);

                    SetupSixEightNineThreeDiffs(stateManager);

                    stateManager.SwapFieldsOrder = true;

                    return true;
                }
                else if (signalPixelsNext < signalChange && signalPixelsNext < signalPixelsPrev)
                {
                    stateManager.LearnDigitPattern(normalizedPositions[forwardChangeIndex].LastFrameNoDigit, 0);

                    // One after Zero
                    int nextDigitIndex = indexPixelNext;
                    for (int i = 0; i < 9; i++)
                    {
                        stateManager.LearnDigitPattern(normalizedPositions[nextDigitIndex].LastFrameNoDigit, 1 + i);

                        nextDigitIndex++;
                        if (nextDigitIndex > 9) nextDigitIndex -= 10;
                    }

                    stateManager.SwapFieldsOrder = false;

                    SetupSixEightNineThreeDiffs(stateManager);

                    return true;
                }
                else
                    return false;
            }

            return false;
        }
예제 #13
0
 public void Initialize(TimestampOCRData initializationData, IVideoController videoController, int performanceMode)
 {
     m_InitializationData = initializationData;
     m_VideoController = videoController;
     m_Processor = null;
     m_UseNativePreProcessing = performanceMode > 0;
     m_ForceErrorReport = initializationData.ForceErrorReport;
     m_FrameStep = -1;
     m_CalibrationImages.Clear();
 }
예제 #14
0
        private static char OcrBlock(uint[] fieldPixels, IotaVtiOcrProcessor stateManager, int blockIndex, bool isOddField)
        {
            uint[] block = stateManager.GetBlockAtPosition(fieldPixels, blockIndex, isOddField);

            s_DiffSignatures[0] = GetDiffSignature(block, stateManager.ZeroDigitPattern);
            s_DiffDigits[0] = 0;
            s_DiffSignatures[1] = GetDiffSignature(block, stateManager.OneDigitPattern);
            s_DiffDigits[1] = 1;
            s_DiffSignatures[2] = GetDiffSignature(block, stateManager.TwoDigitPattern);
            s_DiffDigits[2] = 2;
            s_DiffSignatures[3] = GetDiffSignature(block, stateManager.ThreeDigitPattern);
            s_DiffDigits[3] = 3;
            s_DiffSignatures[4] = GetDiffSignature(block, stateManager.FourDigitPattern);
            s_DiffDigits[4] = 4;
            s_DiffSignatures[5] = GetDiffSignature(block, stateManager.FiveDigitPattern);
            s_DiffDigits[5] = 5;
            s_DiffSignatures[6] = GetDiffSignature(block, stateManager.SixDigitPattern);
            s_DiffDigits[6] = 6;
            s_DiffSignatures[7] = GetDiffSignature(block, stateManager.SevenDigitPattern);
            s_DiffDigits[7] = 7;
            s_DiffSignatures[8] = GetDiffSignature(block, stateManager.EightDigitPattern);
            s_DiffDigits[8] = 8;
            s_DiffSignatures[9] = GetDiffSignature(block, stateManager.NineDigitPattern);
            s_DiffDigits[9] = 9;

            double maxStrictMatch = stateManager.BlockWidth * stateManager.BlockHeight / 12.0;
            double maxMatch = stateManager.BlockWidth * stateManager.BlockHeight / 8.0;
            int strictMatchesIdx = 0;
            int matchesIdx = 0;

            for (int i = 0; i < 10; i++)
            {
                if (s_DiffSignatures[i] < maxStrictMatch && strictMatchesIdx < MAX_MATCHES)
                {
                    s_StrictMatches[strictMatchesIdx] = s_DiffDigits[i];
                    strictMatchesIdx++;
                }

                if (s_DiffSignatures[i] < maxMatch && matchesIdx < MAX_MATCHES)
                {
                    s_Matches[matchesIdx] = s_DiffDigits[i];
                    matchesIdx++;
                }
            }

            if (strictMatchesIdx == 1)
            {
                return s_StrictMatches[0].ToString()[0];
            }
            else if (strictMatchesIdx == 0 && matchesIdx == 1)
            {
                return s_Matches[0].ToString()[0];
            }
            else if (strictMatchesIdx > 1 || matchesIdx > 1)
            {
                var allMatches = new List<int>();
                if (strictMatchesIdx > 1)
                {
                    for (int i = 0; i < strictMatchesIdx; i++)
                        allMatches.Add(s_StrictMatches[i]);
                }
                else if (matchesIdx > 1)
                {
                    for (int i = 0; i < matchesIdx; i++)
                        allMatches.Add(s_Matches[i]);
                }

                bool areAll8693Items = !allMatches.Any(x => x != 3 && x != 6 && x != 9 && x != 8);
                if (areAll8693Items)
                {
                    bool is8Present = allMatches.Contains(8);
                    bool is9Present = allMatches.Contains(9);
                    bool is6Present = allMatches.Contains(6);
                    bool is3Present = allMatches.Contains(3);
                    return DistinguishEightFromSimilarChars(block, stateManager, is9Present, is6Present, is3Present, is8Present);

                }
            }

            return ' ';
        }
예제 #15
0
 public override void FinaliseState(IotaVtiOcrProcessor stateManager)
 {
 }
예제 #16
0
 public void PrepareLastTwoDigitsFromTheFrameNumber(IotaVtiOcrProcessor stateManager, int lastBlockX, int secondLastBlockX)
 {
     LastFrameNoDigit = stateManager.GetBlockAtXOffset(Image, lastBlockX, IsOddField);
     SecondLastFrameNoDigit = stateManager.GetBlockAtXOffset(Image, secondLastBlockX, IsOddField);
 }
예제 #17
0
        private void TryInitializeProcessor(uint[] data)
        {
            InitiazliationError = null;

            if (m_Processor == null)
            {
                if (LocateTimestampPosition(data))
                {
                    m_FieldAreaHeight = (m_ToLine - m_FromLine) / 2;
                    m_FieldAreaWidth = m_InitializationData.FrameWidth;
                    m_OddFieldPixels = new uint[m_InitializationData.FrameWidth * m_FieldAreaHeight];
                    m_EvenFieldPixels = new uint[m_InitializationData.FrameWidth * m_FieldAreaHeight];
                    m_OddFieldPixelsPreProcessed = new uint[m_InitializationData.FrameWidth * m_FieldAreaHeight];
                    m_EvenFieldPixelsPreProcessed = new uint[m_InitializationData.FrameWidth * m_FieldAreaHeight];
                    m_OddFieldPixelsDebugNoLChD = new uint[m_InitializationData.FrameWidth * m_FieldAreaHeight];
                    m_EvenFieldPixelsDebugNoLChD = new uint[m_InitializationData.FrameWidth * m_FieldAreaHeight];

                    m_InitializationData.OSDFrame.Width = m_FieldAreaWidth;
                    m_InitializationData.OSDFrame.Height = m_FieldAreaHeight;

                    m_Processor = new IotaVtiOcrProcessor(m_TVSafeModeGuess);
                }
            }
        }
예제 #18
0
 public override void InitialiseState(IotaVtiOcrProcessor stateManager)
 {
     m_Width = stateManager.CurrentImageWidth;
     m_Height = stateManager.CurrentImageHeight;
 }
예제 #19
0
        private bool RecognizedTimestampsConsistent(IotaVtiOcrProcessor stateManager, List<CalibratedBlockPosition> normalizedPositions)
        {
            var allTimeStamps = new List<IotaVtiTimeStamp>();
            int index = 0;
            int totalTimestamps = normalizedPositions.Count;

            for (; ; )
            {
                if (index == totalTimestamps - 1)
                    break;

                IotaVtiTimeStampStrings timeStampStrings = IotaVtiOcrCalibratedState.OcrField(normalizedPositions[index].Image, stateManager, normalizedPositions[index].IsOddField);
                if (!timeStampStrings.AllCharsPresent())
                {
                    return false;
                }

                var timeStamp = new IotaVtiTimeStamp(timeStampStrings);

                if (stateManager.SwapFieldsOrder)
                {
                    if (index + 1 == totalTimestamps - 1)
                        break;

                    IotaVtiTimeStampStrings timeStampStrings2 = IotaVtiOcrCalibratedState.OcrField(normalizedPositions[index + 1].Image, stateManager, normalizedPositions[index + 1].IsOddField);
                    if (!timeStampStrings2.AllCharsPresent())
                    {
                        return false;
                    }
                    var timeStamp2 = new IotaVtiTimeStamp(timeStampStrings2);
                    allTimeStamps.Add(timeStamp2);

                    index++;
                }

                allTimeStamps.Add(timeStamp);

                index++;
            }

            float fieldDurationMS = 0;

            for (int i = 0; i < allTimeStamps.Count - 1; i++)
            {
                if (allTimeStamps[i].FrameNumber != allTimeStamps[i + 1].FrameNumber - 1 &&
                    allTimeStamps[i].FrameNumber != allTimeStamps[i + 1].FrameNumber + 1)
                    return false;

                int totalMillisecondsThis = (allTimeStamps[i].Hours * 3600 + allTimeStamps[i].Minutes * 60 + allTimeStamps[i].Seconds) * 10000 + allTimeStamps[i].Milliseconds10;
                int totalMillisecondsNext = (allTimeStamps[i + 1].Hours * 3600 + allTimeStamps[i + 1].Minutes * 60 + allTimeStamps[i + 1].Seconds) * 10000 + allTimeStamps[i + 1].Milliseconds10;

                fieldDurationMS = Math.Abs((totalMillisecondsNext - totalMillisecondsThis) / 10f);

                if (Math.Abs(fieldDurationMS - IotaVtiOcrProcessor.FIELD_DURATION_PAL) > 0.15 && Math.Abs(fieldDurationMS - IotaVtiOcrProcessor.FIELD_DURATION_NTSC) > 0.15)
                    return false;
            }

            if (Math.Abs(fieldDurationMS - IotaVtiOcrProcessor.FIELD_DURATION_PAL) < 0.15)
                stateManager.VideoFormat = VideoFormat.PAL;
            else if (Math.Abs(fieldDurationMS - IotaVtiOcrProcessor.FIELD_DURATION_NTSC) < 0.15)
                stateManager.VideoFormat = VideoFormat.NTSC;
            else
                stateManager.VideoFormat = null;

            return true;
        }
예제 #20
0
        public override void Process(IotaVtiOcrProcessor stateManager, Graphics graphics, int frameNo, bool isOddField)
        {
            if (m_Width != stateManager.CurrentImageWidth || m_Height != stateManager.CurrentImageHeight)
            {
                Reinitialise(stateManager.CurrentImageWidth, stateManager.CurrentImageHeight);
                ROUTH_START_FRAME_NUMBER_BLOCKS = (int)Math.Round(IotaVtiOcrProcessor.COEFF_FIRST_FRAME_NO_DIGIT_POSITION * stateManager.CurrentImageWidth);
            }

            CalibrateBlockPositonsTop(stateManager, isOddField);
            CalibrateBlockPositonsWidth(stateManager, isOddField);

            if (m_CalibratedPositons.Count == 10)
            {
                stateManager.BlockOffsetYOdd = m_CalibratedPositons.Where(x => x.IsOddField).MostCommonValue(x => x.BlockOffsetY);
                stateManager.BlockOffsetYEven = m_CalibratedPositons.Where(x => !x.IsOddField).MostCommonValue(x => x.BlockOffsetY);

                var normalizedPositions = new List<CalibratedBlockPosition>();

                if (CalibrateFrameNumberBlockPositions(stateManager, out normalizedPositions) &&
                    RecognizedTimestampsConsistent(stateManager, normalizedPositions))
                {
                    stateManager.ChangeState<IotaVtiOcrCalibratedState>();
                    stateManager.Process(stateManager.CurrentImage, stateManager.CurrentImageWidth, stateManager.CurrentImageHeight, graphics, frameNo, isOddField);
                    return;
                }
                else
                {
                    // Make sure we always remove the whole frame, so swapped fields create less issues when learning the characters
                    m_CalibratedPositons.RemoveAt(0);
                    m_CalibratedPositons.RemoveAt(0);
                }
            }

            if (graphics != null)
                base.PlotImage(graphics, stateManager, isOddField);
        }
예제 #21
0
 public void PrepareLastTwoDigitsFromTheFrameNumber(IotaVtiOcrProcessor stateManager)
 {
     LastFrameNoDigit = stateManager.GetBlockAtPosition(Image, stateManager.LastFrameNoDigitPosition, IsOddField);
     SecondLastFrameNoDigit = stateManager.GetBlockAtPosition(Image, stateManager.LastFrameNoDigitPosition - 1, IsOddField);
 }
예제 #22
0
        private static char DistinguishEightFromSimilarChars(uint[] block, IotaVtiOcrProcessor stateManager, bool couldBeNine, bool couldBeSix, bool couldBeThree, bool couldBeEight)
        {
            int chanceToBeSix = couldBeSix ? GetPercentSimilarities(block, stateManager.SixEightXorPattern, stateManager.SixEightXorPatternFactor) : 0;
            int chanceToBeNine = couldBeNine ? GetPercentSimilarities(block, stateManager.NineEightXorPattern, stateManager.NineEightXorPatternFactor) : 0;
            int chanceToBeThree = couldBeThree ? GetPercentSimilarities(block, stateManager.ThreeEightXorPattern, stateManager.ThreeEightXorPatternFactor) : 0;

            int minRequiredChance = couldBeEight ? 50 : 0;

            if (chanceToBeThree > minRequiredChance && chanceToBeThree > chanceToBeSix && chanceToBeThree > chanceToBeNine)
            {
                return '3';
            }
            else if (chanceToBeSix > minRequiredChance && chanceToBeSix > chanceToBeNine && chanceToBeSix > chanceToBeThree)
            {
                return '6';
            }
            else if (chanceToBeNine > minRequiredChance && chanceToBeNine > chanceToBeSix && chanceToBeNine > chanceToBeThree)
            {
                return '9';
            }
            else if (couldBeEight)
            {
                return '8';
            }

            return ' ';
        }
예제 #23
0
        private void SetupSixEightNineThreeDiffs(IotaVtiOcrProcessor stateManager)
        {
            uint[] eightPattern = stateManager.EightDigitPattern;
            int numDifferentPixels;
            uint[] xoredPattern;

            uint[] sixPattern = stateManager.SixDigitPattern;
            xoredPattern = XorPatterns(eightPattern, sixPattern, out numDifferentPixels);
            stateManager.SixEightXorPattern = xoredPattern;
            stateManager.SixEightXorPatternFactor = numDifferentPixels;

            uint[] ninePattern = stateManager.NineDigitPattern;
            xoredPattern = XorPatterns(eightPattern, ninePattern, out numDifferentPixels);
            stateManager.NineEightXorPattern = xoredPattern;
            stateManager.NineEightXorPatternFactor = numDifferentPixels;

            uint[] threePattern = stateManager.ThreeDigitPattern;
            xoredPattern = XorPatterns(eightPattern, threePattern, out numDifferentPixels);
            stateManager.ThreeEightXorPattern = xoredPattern;
            stateManager.ThreeEightXorPatternFactor = numDifferentPixels;
        }
예제 #24
0
        private void CalibrateBlockPositonsTop(IotaVtiOcrProcessor stateManager, bool isOddField)
        {
            int count = 0;
            int maxRating = -1;

            int bestYOffs = -1;
            int bestHeight = -1;

            int imageHeight = stateManager.CurrentImageHeight;
            int imageWidth = stateManager.CurrentImageWidth;

            for (int top = 0; top < 20; top++)
            {
                for (int y = m_MinBlockHeight; y <= m_MaxBlockHeight; y++)
                {
                    int totalRating = 0;

                    int bottom = top + y;

                    bool bottomOk = (bottom - 1) < imageHeight;
                    bool bottom2Ok = bottom < imageHeight;
                    bool bottom3Ok = (bottom + 1) < imageHeight;

                    for (int x = 0; x < stateManager.CurrentImageWidth; x++)
                    {
                        if (x >= stateManager.CurrentImageWidth || x < 0) continue;
                        if (top < 0) continue;
                        if (bottom - 1 >= stateManager.CurrentImageHeight) continue;

                        if (bottomOk && stateManager.CurrentImage[x + imageWidth * (bottom - 1)] < 127 &&
                           ((bottom2Ok && stateManager.CurrentImage[x + imageWidth * bottom] > 127) || bottom == imageHeight) &&
                           ((bottom3Ok && stateManager.CurrentImage[x + imageWidth * (bottom + 1)] > 127) || bottom >= imageHeight - 1))
                            totalRating++;

                        if (stateManager.CurrentImage[x + imageWidth * (top + 1)] < 127 &&
                           stateManager.CurrentImage[x + imageWidth * top] > 127 &&
                           (top == 0 || stateManager.CurrentImage[x + imageWidth * (top - 1)] > 127))
                            totalRating++;
                    }

                    if (totalRating > maxRating)
                    {
                        maxRating = totalRating;
                        bestYOffs = top;
                        bestHeight = y;
                    }

                    count++;
                }
            }

            stateManager.BlockHeight = bestHeight;
            if (isOddField)
                stateManager.BlockOffsetYOdd = bestYOffs;
            else
                stateManager.BlockOffsetYEven = bestYOffs;
        }
예제 #25
0
 public override void InitialiseState(IotaVtiOcrProcessor stateManager)
 {
     m_Width = 0;
     m_Height = 0;
 }
예제 #26
0
        private void CalibrateBlockPositonsWidth(IotaVtiOcrProcessor stateManager, bool isOddField)
        {
            int maxRating = -1;

            int bestWidth = -1;
            var bestStartingPositions = new List<int>();

            // Determined previously
            int bestHeight = stateManager.BlockHeight;
            int bestYOffs = stateManager.BlockOffsetY(isOddField);

            int imageWidth = stateManager.CurrentImageWidth;
            var startingPositions = new List<int>();

            for (int width = m_MinBlockWidth; width <= m_MaxBlockWidth; width++)
            {
                int totalRating = 0;
                startingPositions.Clear();

                for (int x = 1; x < stateManager.CurrentImageWidth - width - 1; x++)
                {
                    bool prevTwoVerticalsAreWhite = true;

                    for (int y = bestYOffs; y < bestYOffs + bestHeight + 1; y++)
                    {
                        if (y >= stateManager.CurrentImageHeight) continue;

                        if (stateManager.CurrentImage[x - 1 + imageWidth * y] < 127 || stateManager.CurrentImage[x + imageWidth * y] < 127)
                        {
                            prevTwoVerticalsAreWhite = false;
                            break;
                        }
                    }

                    if (!prevTwoVerticalsAreWhite)
                        continue;

                    for (int y = bestYOffs; y < bestYOffs + bestHeight + 1; y++)
                    {
                        if (y >= stateManager.CurrentImageHeight) continue;

                        if (stateManager.CurrentImage[x + 1 + imageWidth * y] < 127)
                        {
                            totalRating++;

                            if (stateManager.CurrentImage[x + width - 1 + imageWidth * y] < 127 &&
                                stateManager.CurrentImage[x + width + imageWidth * y] > 127 &&
                                stateManager.CurrentImage[x + width + 1 + imageWidth * y] > 127)
                            {
                                startingPositions.Add(x);
                                totalRating++;
                            }
                        }
                    }
                }

                if (totalRating > maxRating)
                {
                    // Collect stats about the starting positions ??
                    maxRating = totalRating;
                    bestWidth = width;
                    bestStartingPositions.Clear();
                    bestStartingPositions.AddRange(startingPositions);
                }
            }

            stateManager.BlockWidth = bestWidth;

            var calibrationBlock = new CalibratedBlockPosition(stateManager.CurrentImage)
            {
                BlockWidth = bestWidth,
                BlockHeight = bestHeight,
                BlockOffsetY = bestYOffs,
                BestStartingPositions = bestStartingPositions.ToArray(),
                IsOddField = isOddField
            };
            m_CalibratedPositons.Add(calibrationBlock);
        }
예제 #27
0
파일: frmMain.cs 프로젝트: hpavlov/tangra3
        private void btnReload_Click(object sender, EventArgs e)
        {
            m_CurrentIndex = -1;
            m_InputFiles.Clear();
            m_InputFiles.AddRange(TestCaseHelper.LoadTestImages(tbxInputFolder.Text, cbxReverseEvenOdd.Checked));

            m_Processor = new IotaVtiOcrProcessor(cbxIsTvSafe.Checked);

            if (m_InputFiles.Count > 0) m_CurrentIndex = 0;
            ProcessCurrentImage();
        }
예제 #28
0
        private bool CalibrateFrameNumberBlockPositions(IotaVtiOcrProcessor stateManager, out List<CalibratedBlockPosition> normalizedPositions)
        {
            int last = GetLastFrameNoDigitStartPosition(stateManager);

            if (last > -1)
            {
                int secondLast = last - stateManager.BlockWidth;

                // We now know the position of the two digits. We can now 'learn' the digits from '0' to '9' finding the change of the second last digit
                // and then infering the values from '0' to '9' of the last digit

                foreach (CalibratedBlockPosition blockPosition in m_CalibratedPositons)
                    blockPosition.PrepareLastTwoDigitsFromTheFrameNumber(stateManager, last, secondLast);

                if (DigitPatternsRecognized(stateManager, out normalizedPositions))
                {
                    stateManager.LastBlockOffsetsX = last;
                    stateManager.SecondLastBlockOffsetsX = secondLast;

                    // Now go and determine the positions of the remaining blocks by matching their value to the 'learned' digits
                    return LocateRemainingBlockPositions(stateManager);
                }
            }
            else
                normalizedPositions = new List<CalibratedBlockPosition>();

            return false;
        }