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); }
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(); }
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; }
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(); }
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); }
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; }
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); } } }
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 ' '; }
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; }
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; }
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; }
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; }
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(); }
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 ' '; }
public override void FinaliseState(IotaVtiOcrProcessor stateManager) { }
public void PrepareLastTwoDigitsFromTheFrameNumber(IotaVtiOcrProcessor stateManager, int lastBlockX, int secondLastBlockX) { LastFrameNoDigit = stateManager.GetBlockAtXOffset(Image, lastBlockX, IsOddField); SecondLastFrameNoDigit = stateManager.GetBlockAtXOffset(Image, secondLastBlockX, IsOddField); }
public override void InitialiseState(IotaVtiOcrProcessor stateManager) { m_Width = stateManager.CurrentImageWidth; m_Height = stateManager.CurrentImageHeight; }
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; }
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); }
public void PrepareLastTwoDigitsFromTheFrameNumber(IotaVtiOcrProcessor stateManager) { LastFrameNoDigit = stateManager.GetBlockAtPosition(Image, stateManager.LastFrameNoDigitPosition, IsOddField); SecondLastFrameNoDigit = stateManager.GetBlockAtPosition(Image, stateManager.LastFrameNoDigitPosition - 1, IsOddField); }
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 ' '; }
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; }
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; }
public override void InitialiseState(IotaVtiOcrProcessor stateManager) { m_Width = 0; m_Height = 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); }
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(); }
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; }