Пример #1
0
        private void PrepareOsdArea(uint[] dataIn, uint[] dataOut, uint[] dataDebugNoLChD, int width, int height)
        {
            //DebugPrepareOsdArea(dataIn, dataOut, width, height);
            //return;

            // Split into fields only in the region where IOTA-VTI could be, Then threat as two separate images, and for each of them do:
            // 1) Gaussian blur (small) BitmapFilter.LOW_PASS_FILTER_MATRIX
            // 2) Sharpen BitmapFilter.SHARPEN_MATRIX
            // 3) Binarize - get Average, all below change to 0, all above change to Max (256)
            // 4) De-noise BitmapFilter.DENOISE_MATRIX

            if (m_UseNativePreProcessing)
            {
                TangraCore.PrepareImageForOCR(dataIn, dataOut, width, height);
            }
            else
            {
                uint median = dataIn.Median();
                for (int i = 0; i < dataIn.Length; i++)
                {
                    int darkCorrectedValue = (int)dataIn[i] - (int)median;
                    if (darkCorrectedValue < 0)
                    {
                        darkCorrectedValue = 0;
                    }
                    dataIn[i] = (uint)darkCorrectedValue;
                }

                uint[] blurResult = BitmapFilter.GaussianBlur(dataIn, 8, width, height);

                uint   average       = 128;
                uint[] sharpenResult = BitmapFilter.Sharpen(blurResult, 8, width, height, out average);

                // Binerize and Inverse
                for (int i = 0; i < sharpenResult.Length; i++)
                {
                    sharpenResult[i] = sharpenResult[i] > average ? (uint)0 : (uint)255;
                }

                uint[] denoised = BitmapFilter.Denoise(sharpenResult, 8, width, height, out average, false);

                for (int i = 0; i < denoised.Length; i++)
                {
                    dataOut[i] = denoised[i] < 127 ? (uint)0 : (uint)255;
                }

                Array.Copy(dataOut, dataDebugNoLChD, dataOut.Length);

                LargeChunkDenoiser.Process(false, dataOut, width, height);
            }
        }
Пример #2
0
        private bool LocateTimestampPosition(uint[] data, int frameWidth, int frameHeight)
        {
            uint[] preProcessedPixels = new uint[data.Length];
            Array.Copy(data, preProcessedPixels, data.Length);

            // Process the image
            uint median = preProcessedPixels.Median();

            for (int i = 0; i < preProcessedPixels.Length; i++)
            {
                int darkCorrectedValue = (int)preProcessedPixels[i] - (int)median;
                if (darkCorrectedValue < 0)
                {
                    darkCorrectedValue = 0;
                }
                preProcessedPixels[i] = (uint)darkCorrectedValue;
            }

            if (median > 250)
            {
                //InitiazliationError = "The background is too bright.";
                return(false);
            }

            uint[] blurResult = BitmapFilter.GaussianBlur(preProcessedPixels, 8, frameWidth, frameHeight);
            uint   average    = 128;

            uint[] sharpenResult = BitmapFilter.Sharpen(blurResult, 8, frameWidth, frameHeight, out average);

            // Binerize and Inverse
            for (int i = 0; i < sharpenResult.Length; i++)
            {
                sharpenResult[i] = sharpenResult[i] > average ? (uint)0 : (uint)255;
            }
            uint[] denoised = BitmapFilter.Denoise(sharpenResult, 8, frameWidth, frameHeight, out average, false);

            for (int i = 0; i < denoised.Length; i++)
            {
                preProcessedPixels[i] = denoised[i] < 127 ? (uint)0 : (uint)255;
            }

            int bestBottomPosition = -1;
            int bestTopPosition    = -1;

            LocateTopAndBottomLineOfTimestamp(
                preProcessedPixels,
                frameWidth,
                frameHeight / 2 + 1,
                frameHeight,
                out bestTopPosition,
                out bestBottomPosition);

            if (bestBottomPosition - bestTopPosition < 10 || bestBottomPosition - bestTopPosition > 60 || bestTopPosition < 0 || bestBottomPosition > frameHeight)
            {
                return(false);
            }

            int fromLine = bestTopPosition - 1;
            int toLine   = bestBottomPosition + 3;

            if (toLine > frameHeight)
            {
                toLine = frameHeight - 2;
            }

            if ((toLine - fromLine) % 2 == 1)
            {
                if (fromLine % 2 == 1)
                {
                    fromLine--;
                }
                else
                {
                    toLine++;
                }
            }

            #region We need to make sure that the two fields have the same top and bottom lines

            // Create temporary arrays so the top/bottom position per field can be further refined
            int    fieldAreaHeight             = (toLine - fromLine) / 2;
            int    fieldAreaWidth              = frameWidth;
            uint[] oddFieldPixelsPreProcessed  = new uint[frameWidth * fieldAreaHeight];
            uint[] evenFieldPixelsPreProcessed = new uint[frameWidth * fieldAreaHeight];

            int[] DELTAS       = new int[] { 0, -1, 1 };
            int   fromLineBase = fromLine;
            int   toLineBase   = toLine;
            bool  matchFound   = false;

            for (int deltaIdx = 0; deltaIdx < DELTAS.Length; deltaIdx++)
            {
                fromLine = fromLineBase + DELTAS[deltaIdx];
                toLine   = toLineBase + DELTAS[deltaIdx];

                int bestBottomPositionOdd  = -1;
                int bestTopPositionOdd     = -1;
                int bestBottomPositionEven = -1;
                int bestTopPositionEven    = -1;

                LocateTopAndBottomLineOfTimestamp(
                    oddFieldPixelsPreProcessed,
                    fieldAreaWidth, 1, fieldAreaHeight - 1,
                    out bestTopPositionOdd, out bestBottomPositionOdd);

                LocateTopAndBottomLineOfTimestamp(
                    evenFieldPixelsPreProcessed,
                    fieldAreaWidth, 1, fieldAreaHeight - 1,
                    out bestTopPositionEven, out bestBottomPositionEven);

                if (bestBottomPositionOdd == bestBottomPositionEven &&
                    bestTopPositionOdd == bestTopPositionEven)
                {
                    matchFound = true;
                    fromLine   = fromLineBase;
                    toLine     = toLineBase;

                    break;
                }
            }
            #endregion

            if (matchFound)
            {
                UpdateVtiOsdPositions(fromLine, toLine);
            }

            return(matchFound);
        }
Пример #3
0
        private void DebugPrepareOsdArea(uint[] dataIn, uint[] dataOut, int width, int height)
        {
            // NOTE: Because of different rounding in C++ and C# there may be a difference of "1" between pixels

            uint[] nativeIn      = new uint[dataIn.Length];
            uint[] nativeOut     = new uint[dataOut.Length];
            uint   nativeAverage = 0;

            for (int i = 0; i < dataIn.Length; i++)
            {
                nativeIn[i] = dataIn[i];
            }

            uint median = dataIn.Median();

            for (int i = 0; i < dataIn.Length; i++)
            {
                int darkCorrectedValue = (int)dataIn[i] - (int)median;
                if (darkCorrectedValue < 0)
                {
                    darkCorrectedValue = 0;
                }
                dataIn[i] = (uint)darkCorrectedValue;
            }

            TangraCore.PrepareImageForOCRSingleStep(nativeIn, nativeOut, width, height, 0, ref nativeAverage);
            Trace.Assert(Math.Abs(median - nativeAverage) <= 1);
            for (int i = 0; i < nativeOut.Length; i++)
            {
                Trace.Assert(Math.Abs(nativeOut[i] - dataIn[i]) <= 1);
            }

            for (int i = 0; i < dataIn.Length; i++)
            {
                nativeIn[i] = dataIn[i];
            }

            uint[] blurResult = BitmapFilter.GaussianBlur(dataIn, 8, width, height);

            TangraCore.PrepareImageForOCRSingleStep(nativeIn, nativeOut, width, height, 1, ref nativeAverage);
            for (int i = 0; i < nativeOut.Length; i++)
            {
                Trace.Assert(Math.Abs(nativeOut[i] - blurResult[i]) <= 1);
            }

            for (int i = 0; i < blurResult.Length; i++)
            {
                nativeIn[i] = blurResult[i];
            }

            uint average = 128;

            uint[] sharpenResult = BitmapFilter.Sharpen(blurResult, 8, width, height, out average);

            TangraCore.PrepareImageForOCRSingleStep(nativeIn, nativeOut, width, height, 2, ref nativeAverage);
            Trace.Assert(Math.Abs(average - nativeAverage) <= 1);
            for (int i = 0; i < nativeOut.Length; i++)
            {
                Trace.Assert(Math.Abs(nativeOut[i] - sharpenResult[i]) <= 1);
            }


            for (int i = 0; i < sharpenResult.Length; i++)
            {
                nativeIn[i] = sharpenResult[i];
            }
            TangraCore.PrepareImageForOCRSingleStep(nativeIn, nativeOut, width, height, 3, ref nativeAverage);

            // Binerize and Inverse
            for (int i = 0; i < sharpenResult.Length; i++)
            {
                sharpenResult[i] = sharpenResult[i] > average ? (uint)0 : (uint)255;
            }

            for (int i = 0; i < nativeOut.Length; i++)
            {
                Trace.Assert(Math.Abs(nativeOut[i] - sharpenResult[i]) <= 1);
            }

            for (int i = 0; i < sharpenResult.Length; i++)
            {
                nativeIn[i] = sharpenResult[i];
            }
            TangraCore.PrepareImageForOCRSingleStep(nativeIn, nativeOut, width, height, 4, ref nativeAverage);

            uint[] denoised = BitmapFilter.Denoise(sharpenResult, 8, width, height, out average, false);

            for (int i = 0; i < denoised.Length; i++)
            {
                Trace.Assert(Math.Abs(nativeOut[i] - denoised[i]) <= 1);
            }

            for (int i = 0; i < denoised.Length; i++)
            {
                nativeIn[i] = denoised[i];
            }
            TangraCore.PrepareImageForOCRSingleStep(nativeIn, nativeOut, width, height, 5, ref nativeAverage);

            for (int i = 0; i < denoised.Length; i++)
            {
                dataOut[i] = denoised[i] < 127 ? (uint)0 : (uint)255;
            }

            for (int i = 0; i < denoised.Length; i++)
            {
                Trace.Assert(Math.Abs(nativeOut[i] - dataOut[i]) <= 1);
            }


            LargeChunkDenoiser.Process(false, dataOut, width, height);
            LargeChunkDenoiser.Process(true, nativeOut, width, height);

            for (int i = 0; i < dataOut.Length; i++)
            {
                Trace.Assert(Math.Abs(nativeOut[i] - dataOut[i]) <= 1);
            }
            for (int i = 0; i < nativeOut.Length; i++)
            {
                dataOut[i] = nativeOut[i];
            }
        }
Пример #4
0
        private bool LocateTimestampPosition(uint[] data)
        {
            uint[] preProcessedPixels = new uint[data.Length];
            Array.Copy(data, preProcessedPixels, data.Length);

            // Process the image
            uint median = preProcessedPixels.Median();

            for (int i = 0; i < preProcessedPixels.Length; i++)
            {
                int darkCorrectedValue = (int)preProcessedPixels[i] - (int)median;
                if (darkCorrectedValue < 0)
                {
                    darkCorrectedValue = 0;
                }
                preProcessedPixels[i] = (uint)darkCorrectedValue;
            }

            if (median > 250)
            {
                InitiazliationError = "The background is too bright.";
                return(false);
            }

            uint[] blurResult = BitmapFilter.GaussianBlur(preProcessedPixels, 8, m_InitializationData.FrameWidth, m_InitializationData.FrameHeight);
            uint   average    = 128;

            uint[] sharpenResult = BitmapFilter.Sharpen(blurResult, 8, m_InitializationData.FrameWidth, m_InitializationData.FrameHeight, out average);

            // Binerize and Inverse
            for (int i = 0; i < sharpenResult.Length; i++)
            {
                sharpenResult[i] = sharpenResult[i] > average ? (uint)0 : (uint)255;
            }
            uint[] denoised = BitmapFilter.Denoise(sharpenResult, 8, m_InitializationData.FrameWidth, m_InitializationData.FrameHeight, out average, false);

            for (int i = 0; i < denoised.Length; i++)
            {
                preProcessedPixels[i] = denoised[i] < 127 ? (uint)0 : (uint)255;
            }

            int bestBottomPosition = -1;
            int bestTopPosition    = -1;

            LocateTopAndBottomLineOfTimestamp(
                preProcessedPixels,
                m_InitializationData.FrameWidth,
                m_InitializationData.FrameHeight / 2 + 1,
                m_InitializationData.FrameHeight,
                out bestTopPosition,
                out bestBottomPosition);

            if (bestBottomPosition - bestTopPosition < 10 || bestBottomPosition - bestTopPosition > 60)
            {
                bool tryBestTopAndLastLine = m_InitializationData.FrameHeight - bestTopPosition > 10 && m_InitializationData.FrameHeight - bestTopPosition < 60;

                if (tryBestTopAndLastLine)
                {
                    bestBottomPosition = m_InitializationData.FrameHeight - 1;
                }
                else
                {
                    if (m_ForceErrorReport)
                    {
                        if (m_ForceErrorReport &&
                            !m_CalibrationImages.ContainsKey("LocateTimestampPositionOrg.bmp"))
                        {
                            uint[] pixelsOriginal = new uint[data.Length];
                            Array.Copy(data, pixelsOriginal, data.Length);
                            AddErrorImage("LocateTimestampPositionOrg.bmp", pixelsOriginal, 0, 0);

                            uint[] pixelsPreProcessed = new uint[data.Length];
                            Array.Copy(preProcessedPixels, pixelsPreProcessed, data.Length);
                            AddErrorImage("LocateTimestampPositionProcessed.bmp", pixelsPreProcessed, 0, 0);
                        }
                    }

                    InitiazliationError = "Cannot locate the OSD timestamp on the frame.";
                    return(false);
                }
            }

            m_FromLine = bestTopPosition - 10;
            m_ToLine   = bestBottomPosition + 10;
            if (m_ToLine > m_InitializationData.FrameHeight)
            {
                m_ToLine = m_InitializationData.FrameHeight - 2;
            }

            if ((m_ToLine - m_FromLine) % 2 == 1)
            {
                if (m_FromLine % 2 == 1)
                {
                    m_FromLine--;
                }
                else
                {
                    m_ToLine++;
                }
            }

            #region We need to make sure that the two fields have the same top and bottom lines

            // Create temporary arrays so the top/bottom position per field can be further refined
            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];

            int[] DELTAS       = new int[] { 0, -1, 1 };
            int   fromLineBase = m_FromLine;
            int   toLineBase   = m_ToLine;

            PrepareOsdVideoFields(data);

            for (int deltaIdx = 0; deltaIdx < DELTAS.Length; deltaIdx++)
            {
                m_FromLine = fromLineBase + DELTAS[deltaIdx];
                m_ToLine   = toLineBase + DELTAS[deltaIdx];

                int bestBottomPositionOdd  = -1;
                int bestTopPositionOdd     = -1;
                int bestBottomPositionEven = -1;
                int bestTopPositionEven    = -1;

                LocateTopAndBottomLineOfTimestamp(
                    m_OddFieldPixelsPreProcessed,
                    m_FieldAreaWidth, 1, m_FieldAreaHeight - 1,
                    out bestTopPositionOdd, out bestBottomPositionOdd);

                LocateTopAndBottomLineOfTimestamp(
                    m_EvenFieldPixelsPreProcessed,
                    m_FieldAreaWidth, 1, m_FieldAreaHeight - 1,
                    out bestTopPositionEven, out bestBottomPositionEven);

                if (bestBottomPositionOdd == bestBottomPositionEven &&
                    bestTopPositionOdd == bestTopPositionEven)
                {
                    m_FromLine = fromLineBase;
                    m_ToLine   = toLineBase;

                    break;
                }
            }
            #endregion

            m_TVSafeModeGuess = m_ToLine + (m_ToLine - m_FromLine) / 2 < m_InitializationData.FrameHeight;

            return(true);
        }