Пример #1
0
        public static Bitmap ConvertToBitmap(FastBitmapHSV bitmap)
        {
            Bitmap bmp = new Bitmap(bitmap.Width, bitmap.Height);

            unsafe
            {
                BitmapData bitmapData    = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, bmp.PixelFormat);
                int        bytesPerPixel = Image.GetPixelFormatSize(bmp.PixelFormat) / 8;
                int        bytesPerRow   = bitmapData.Width * bytesPerPixel;

                for (int IdxY = 0; IdxY < bmp.Height; IdxY++)
                {
                    byte *pixels = (byte *)bitmapData.Scan0 + (IdxY * bitmapData.Stride);
                    for (int IdxByte = 0; IdxByte < bytesPerRow; IdxByte += bytesPerPixel)
                    {
                        FastPixelHSV writePx    = bitmap.GetPixel(IdxByte / bytesPerPixel, IdxY);
                        Color        writeColor = Color.FromArgb(writePx.Monochrome, writePx.Monochrome, writePx.Monochrome);
                        pixels[IdxByte + 3] = writeColor.A;
                        pixels[IdxByte + 2] = writeColor.R;
                        pixels[IdxByte + 1] = writeColor.G;
                        pixels[IdxByte + 0] = writeColor.B;
                    }
                }

                bmp.UnlockBits(bitmapData);
            }

            return(bmp);
        }
Пример #2
0
        public static bool TraceLine(FastBitmapHSV bitmap, int posX, int posY, int incX, int incY, int traceLen, FastPixelMatch colorMatch, out Point posHit, bool bDebugMode = false)
        {
            if (bDebugMode)
            {
                Logger.WriteLine("TraceLine [" + posX + ", " + posY + "] -> [" + (posX + (incX * traceLen)) + ", " + (posY + (incY * traceLen)) + "]");
            }

            for (int stepIdx = 0; stepIdx < traceLen; stepIdx++)
            {
                int          scanX       = posX + (stepIdx * incX);
                int          scanY       = posY + (stepIdx * incY);
                FastPixelHSV testPx      = bitmap.GetPixel(scanX, scanY);
                bool         bIsMatching = colorMatch.IsMatching(testPx);

                if (bDebugMode)
                {
                    Logger.WriteLine("  [" + scanX + ", " + scanY + "] " + testPx + " => match:" + bIsMatching);
                }

                if (bIsMatching)
                {
                    posHit = new Point(scanX, scanY);
                    return(true);
                }
            }

            if (bDebugMode)
            {
                Logger.WriteLine("  >> failed");
            }
            posHit = new Point(posX + (traceLen * incX), posY + (traceLen * incY));
            return(false);
        }
Пример #3
0
        public static Color GetColorFromHSV(FastPixelHSV pixel)
        {
            int R = 0, G = 0, B = 0;

            HsvToRgb(pixel.GetHue(), pixel.GetSaturation() / 100.0, pixel.GetValue() / 100.0, out R, out G, out B);
            return(Color.FromArgb(R, G, B));
        }
Пример #4
0
        public static float GetPixelFeaturesM2V2(FastPixelHSV testPx)
        {
            float monoV  = testPx.GetMonochrome() / 255.0f;
            float valV   = testPx.GetValue() / 100.0f;
            float pixelV = monoV * monoV * valV * valV;

            return(pixelV);
        }
Пример #5
0
        public static Bitmap CreateBitmapWithShapes(FastBitmapHSV bitmap, List <Rectangle> listBounds, List <FastBitmapHash> listHashes)
        {
            Bitmap bmp = new Bitmap(bitmap.Width, bitmap.Height);

            unsafe
            {
                BitmapData bitmapData    = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.WriteOnly, bmp.PixelFormat);
                int        bytesPerPixel = Image.GetPixelFormatSize(bmp.PixelFormat) / 8;
                int        bytesPerRow   = bitmapData.Width * bytesPerPixel;

                for (int IdxY = 0; IdxY < bmp.Height; IdxY++)
                {
                    byte *pixels = (byte *)bitmapData.Scan0 + (IdxY * bitmapData.Stride);
                    for (int IdxByte = 0; IdxByte < bytesPerRow; IdxByte += bytesPerPixel)
                    {
                        FastPixelHSV writePx    = bitmap.GetPixel(IdxByte / bytesPerPixel, IdxY);
                        Color        writeColor = Color.FromArgb(writePx.Monochrome, writePx.Monochrome, writePx.Monochrome);
                        pixels[IdxByte + 3] = writeColor.A;
                        pixels[IdxByte + 2] = writeColor.R;
                        pixels[IdxByte + 1] = writeColor.G;
                        pixels[IdxByte + 0] = writeColor.B;
                    }
                }

                bmp.UnlockBits(bitmapData);
            }

            using (Graphics gBmp = Graphics.FromImage(bmp))
            {
                if (listBounds.Count > 0)
                {
                    Pen boundsPen = new Pen(Color.Cyan);
                    gBmp.DrawRectangles(boundsPen, listBounds.ToArray());
                }

                Pen hashPen = new Pen(Color.Magenta);
                foreach (FastBitmapHash hashData in listHashes)
                {
                    gBmp.DrawRectangle(hashPen, hashData.SourceBounds);

                    if (hashData.Pixels != null)
                    {
                        for (int HashX = 0; HashX < hashData.Width; HashX++)
                        {
                            for (int HashY = 0; HashY < hashData.Height; HashY++)
                            {
                                byte  writeValue    = hashData.Pixels[HashX + (HashY * hashData.Width)];
                                int   writeValueInt = Math.Min(255, writeValue * 16);
                                Color writeColor    = Color.FromArgb(writeValueInt, 0, 0);
                                bmp.SetPixel(HashX + hashData.DrawPos.X, HashY + hashData.DrawPos.Y, writeColor);
                            }
                        }
                    }
                }
            }

            return(bmp);
        }
Пример #6
0
        public static List <Point> TraceSpansH(FastBitmapHSV bitmap, Rectangle box, FastPixelMatch colorMatch, int minSize, bool bDebugMode = false)
        {
            List <Point> result    = new List <Point>();
            int          lastX     = -1;
            bool         bHasMatch = false;

            for (int IdxX = box.Left; IdxX <= box.Right; IdxX++)
            {
                bHasMatch = false;
                for (int IdxY = box.Top; IdxY <= box.Bottom; IdxY++)
                {
                    FastPixelHSV testPx = bitmap.GetPixel(IdxX, IdxY);
                    bHasMatch = colorMatch.IsMatching(testPx);
                    if (bHasMatch)
                    {
                        if (bDebugMode)
                        {
                            Logger.WriteLine("[" + IdxX + ", " + IdxY + "] " + testPx + " => match!");
                        }
                        break;
                    }
                }

                if (lastX == -1 && bHasMatch)
                {
                    lastX = IdxX;
                }
                else if (lastX >= 0 && !bHasMatch)
                {
                    int spanSize = IdxX - lastX;
                    if (spanSize > minSize)
                    {
                        if (bDebugMode)
                        {
                            Logger.WriteLine(">> adding span: " + lastX + ", size:" + spanSize);
                        }
                        result.Add(new Point(lastX, spanSize));
                    }

                    lastX = -1;
                }
            }

            if (lastX >= 0 && bHasMatch)
            {
                int spanSize = box.Right - lastX + 1;
                if (spanSize > minSize)
                {
                    if (bDebugMode)
                    {
                        Logger.WriteLine(">> adding span: " + lastX + ", size:" + spanSize);
                    }
                    result.Add(new Point(lastX, spanSize));
                }
            }

            return(result);
        }
Пример #7
0
        public override bool IsMatching(FastPixelHSV pixel)
        {
            int Hue        = pixel.GetHue();
            int Saturation = pixel.GetSaturation();

            return((Hue >= HueMin) && (Hue <= HueMax) &&
                   (Saturation >= SaturationMin) && (Saturation <= SaturationMax) &&
                   (pixel.Value >= ValueMin) && (pixel.Value <= ValueMax));
        }
Пример #8
0
        public override bool IsMatching(FastPixelHSV pixel)
        {
            if ((pixel.Monochrome >= MonoMin) && (pixel.Monochrome <= MonoMax))
            {
                int Hue = pixel.GetHue();
                return((Hue >= HueMin) && (Hue <= HueMax));
            }

            return(false);
        }
Пример #9
0
 public static void FindColorRange(FastBitmapHSV bitmap, Rectangle box, out int minMono, out int maxMono)
 {
     minMono = 255;
     maxMono = 0;
     for (int IdxY = box.Top; IdxY <= box.Bottom; IdxY++)
     {
         for (int IdxX = box.Left; IdxX <= box.Right; IdxX++)
         {
             FastPixelHSV testPx = bitmap.GetPixel(IdxX, IdxY);
             minMono = Math.Min(minMono, testPx.Monochrome);
             maxMono = Math.Max(maxMono, testPx.Monochrome);
         }
     }
 }
Пример #10
0
        public static float GetPixelFeaturesHueMono(FastPixelHSV testPx)
        {
            const int hueSteps  = 16;
            const int monoSteps = 16;

            const float monoScale = 1.0f / monoSteps;
            const float hueScale  = monoScale / hueSteps;

            int hueV  = testPx.GetHue() / (360 / hueSteps);
            int monoV = testPx.GetMonochrome() / (256 / monoSteps);

            float pixelV = (hueV * hueScale) + (monoV * monoScale);

            return(pixelV);
        }
Пример #11
0
        public static float CountFillPct(FastBitmapHSV bitmap, Rectangle box, FastPixelMatch colorMatch)
        {
            int totalPixels = (box.Width + 1) * (box.Height + 1);
            int matchPixels = 0;

            for (int IdxY = box.Top; IdxY <= box.Bottom; IdxY++)
            {
                for (int IdxX = box.Left; IdxX <= box.Right; IdxX++)
                {
                    FastPixelHSV testPx = bitmap.GetPixel(IdxX, IdxY);
                    matchPixels += colorMatch.IsMatching(testPx) ? 1 : 0;
                }
            }

            return((float)matchPixels / totalPixels);
        }
Пример #12
0
        public static FastPixelHSV GetAverageColor(FastBitmapHSV bitmap, Rectangle bounds)
        {
            float scale = 1.0f / (bounds.Width * bounds.Height);
            float accR  = 0.0f;
            float accG  = 0.0f;
            float accB  = 0.0f;

            for (int idxY = 0; idxY < bounds.Height; idxY++)
            {
                for (int idxX = 0; idxX < bounds.Width; idxX++)
                {
                    FastPixelHSV testPx = bitmap.GetPixelRaw(bounds.X + idxX, bounds.Y + idxY);
                    accR += testPx.RawR;
                    accG += testPx.RawG;
                    accB += testPx.RawB;
                }
            }

            FastPixelHSV avgPx = new FastPixelHSV((byte)(accR * scale), (byte)(accG * scale), (byte)(accB * scale));

            avgPx.ExpandHSV();
            return(avgPx);
        }
Пример #13
0
 public override bool IsMatching(FastPixelHSV pixel)
 {
     return((pixel.Monochrome >= MonoMin) && (pixel.Monochrome <= MonoMax));
 }
Пример #14
0
        public static Point TraceBoundsH(FastBitmapHSV bitmap, Rectangle box, FastPixelMatch colorMatch, int maxGapSize, bool bDebugMode = false)
        {
            int boxCenter = (box.Right + box.Left) / 2;

            int  minX       = -1;
            int  gapStart   = -1;
            bool bPrevMatch = false;

            for (int IdxX = box.Left; IdxX < boxCenter; IdxX++)
            {
                bool bHasMatch = false;
                for (int IdxY = box.Top; IdxY <= box.Bottom; IdxY++)
                {
                    FastPixelHSV testPx = bitmap.GetPixel(IdxX, IdxY);
                    bHasMatch = colorMatch.IsMatching(testPx);
                    if (bHasMatch)
                    {
                        if (bDebugMode)
                        {
                            Logger.WriteLine("[" + IdxX + ", " + IdxY + "] " + testPx + " => match!");
                        }
                        break;
                    }
                }

                if (bHasMatch)
                {
                    int gapSize = IdxX - gapStart;
                    if ((gapSize > maxGapSize && gapStart > 0) || (minX < 0))
                    {
                        minX     = IdxX;
                        gapStart = -1;
                    }

                    if (bDebugMode)
                    {
                        Logger.WriteLine(">> gapSize:" + gapSize + ", gapStart:" + gapStart + ", bPrevMatch:" + bPrevMatch + " => minX:" + minX);
                    }
                }
                else
                {
                    if (bPrevMatch)
                    {
                        gapStart = IdxX;
                        if (bDebugMode)
                        {
                            Logger.WriteLine(">> gapStart:" + gapStart);
                        }
                    }
                }

                bPrevMatch = bHasMatch;
            }

            if (minX >= 0)
            {
                int maxX = -1;
                gapStart   = -1;
                bPrevMatch = false;
                for (int IdxX = box.Right; IdxX > boxCenter; IdxX--)
                {
                    bool bHasMatch = false;
                    for (int IdxY = box.Top; IdxY <= box.Bottom; IdxY++)
                    {
                        FastPixelHSV testPx = bitmap.GetPixel(IdxX, IdxY);
                        bHasMatch = colorMatch.IsMatching(testPx);
                        if (bHasMatch)
                        {
                            if (bDebugMode)
                            {
                                Logger.WriteLine("[" + IdxX + ", " + IdxY + "] " + testPx + " => match!");
                            }
                            break;
                        }
                    }

                    if (bHasMatch)
                    {
                        int gapSize = gapStart - IdxX;
                        if ((gapSize > maxGapSize && gapStart > 0) || (maxX < 0))
                        {
                            maxX     = IdxX;
                            gapStart = -1;
                        }

                        if (bDebugMode)
                        {
                            Logger.WriteLine(">> gapSize:" + gapSize + ", gapStart:" + gapStart + ", bPrevMatch:" + bPrevMatch + " => maxX:" + maxX);
                        }
                    }
                    else
                    {
                        if (bPrevMatch)
                        {
                            gapStart = IdxX;
                            if (bDebugMode)
                            {
                                Logger.WriteLine(">> gapStart:" + gapStart);
                            }
                        }
                    }

                    bPrevMatch = bHasMatch;
                }

                if (maxX > minX)
                {
                    return(new Point(minX, maxX - minX));
                }
                else
                {
                    if (bDebugMode)
                    {
                        Logger.WriteLine(">> TraceBoundsH: no match on right side!");
                    }
                }
            }
            else
            {
                if (bDebugMode)
                {
                    Logger.WriteLine(">> TraceBoundsH: no match on left side!");
                }
            }

            return(new Point());
        }
Пример #15
0
 public abstract bool IsMatching(FastPixelHSV pixel);
Пример #16
0
 public static float GetPixelFeaturesMono(FastPixelHSV testPx)
 {
     return(testPx.GetMonochrome() / 255.0f);
 }
Пример #17
0
 public static float GetPixelFeaturesHue(FastPixelHSV testPx)
 {
     return(testPx.GetHue() / 360.0f);
 }
Пример #18
0
        public static List <int> TraceLineSegments(FastBitmapHSV bitmap, int posX, int posY, int incX, int incY, int traceLen,
                                                   FastPixelMatch colorMatch, int minSegSize, int segLimit, bool bDebugMode = false)
        {
            FastPixelHSV[] streakBuffer = new FastPixelHSV[minSegSize];
            int            bufferIdx    = 0;

            for (int Idx = 0; Idx < streakBuffer.Length; Idx++)
            {
                streakBuffer[Idx] = new FastPixelHSV(255, 255, 255);
            }

            List <int> result    = new List <int>();
            bool       bWasMatch = false;

            if (bDebugMode)
            {
                Logger.WriteLine("TraceLineSegments [" + posX + ", " + posY + "] -> [" + (posX + (incX * traceLen)) + ", " + (posY + (incY * traceLen)) + "]");
            }

            for (int stepIdx = 0; stepIdx < traceLen; stepIdx++)
            {
                int          scanX  = posX + (stepIdx * incX);
                int          scanY  = posY + (stepIdx * incY);
                FastPixelHSV testPx = bitmap.GetPixel(scanX, scanY);

                streakBuffer[bufferIdx] = testPx;
                bufferIdx = (bufferIdx + 1) % minSegSize;

                bool bBufferMatching = true;
                for (int Idx = 0; Idx < streakBuffer.Length; Idx++)
                {
                    bBufferMatching = bBufferMatching && colorMatch.IsMatching(streakBuffer[Idx]);
                }

                if (bDebugMode)
                {
                    Logger.WriteLine("  [" + scanX + ", " + scanY + "] " + testPx + " => match:" + colorMatch.IsMatching(testPx) + ", buffer:" + bBufferMatching);
                }

                if (bBufferMatching != bWasMatch)
                {
                    bWasMatch = bBufferMatching;

                    int segPos = bBufferMatching ?
                                 (incX != 0) ? (scanX - (incX * minSegSize)) : (scanY - (incY * minSegSize)) :
                                 (incX != 0) ? scanX : scanY;

                    result.Add(segPos);
                    if (bDebugMode)
                    {
                        Logger.WriteLine("  >> mark segment:" + segPos);
                    }

                    if (result.Count >= segLimit && segLimit > 0)
                    {
                        break;
                    }
                }
            }

            return(result);
        }
Пример #19
0
        public static float[] ExtractImageFeaturesScaled(FastBitmapHSV bitmap, Rectangle bounds, int destWidth, int destHeight, Func <FastPixelHSV, float> pxFunc)
        {
            float[] values = new float[destWidth * destHeight];

            // scale to requested size
            float scaleX = (float)destWidth / bounds.Width;
            float scaleY = (float)destHeight / bounds.Height;
            float endY   = 0.0f;

            for (int hashY = 0; hashY < destHeight; hashY++)
            {
                float startY = endY;
                endY = (hashY + 1) / scaleY;
                if (endY >= bounds.Height)
                {
                    endY = bounds.Height - 0.00001f;
                }
                float endX = 0.0f;

                for (int hashX = 0; hashX < destWidth; hashX++)
                {
                    float startX = endX;
                    endX = (hashX + 1) / scaleX;
                    if (endX >= bounds.Width)
                    {
                        endX = bounds.Width - 0.00001f;
                    }
                    float sum = 0.0f;

                    float sumDiv = 0.00001f;
                    for (int srcY = (int)startY; srcY <= (int)endY; srcY++)
                    {
                        float partY = 1.0f;
                        if (srcY == (int)startY)
                        {
                            partY -= startY - srcY;
                        }
                        if (srcY == (int)endY)
                        {
                            partY -= srcY + 1 - endY;
                        }

                        for (int srcX = (int)startX; srcX <= (int)endX; srcX++)
                        {
                            float partX = 1.0f;
                            if (srcX == (int)startX)
                            {
                                partX -= startX - srcX;
                            }
                            if (srcX == (int)endX)
                            {
                                partX -= srcX + 1 - endX;
                            }

                            FastPixelHSV testPx      = bitmap.GetPixel(bounds.Left + srcX, bounds.Top + srcY);
                            float        testPxValue = pxFunc(testPx);
                            sum    += testPxValue * partY * partX;
                            sumDiv += partY * partX;
                        }
                    }

                    values[hashX + (hashY * destWidth)] = sum / sumDiv;
                }
            }

            return(values);
        }
Пример #20
0
 public void SetPixel(int X, int Y, FastPixelHSV pixel)
 {
     Pixels[X + (Y * Width)] = pixel;
 }
Пример #21
0
        private bool HasCactpotCircleEdgeV(FastBitmapHSV bitmap, int posX, int posY, int sideX, bool bDebugDetection = false)
        {
            const int spreadY     = 2;
            const int offsetDeepX = 5;

            FastPixelHSV testPx = bitmap.GetPixel(posX, posY);

            if (!colorMatchCircleOut.IsMatching(testPx) && !colorMatchCircleOutH.IsMatching(testPx))
            {
                if (bDebugDetection)
                {
                    Logger.WriteLine("HasCactpotCircleEdgeV[" + posX + "," + posY + "] failed: edge center " + testPx);
                }
                return(false);
            }

            testPx = bitmap.GetPixel(posX - (sideX * offsetDeepX), posY);
            if (!colorMatchCircleOut.IsMatching(testPx) && !colorMatchCircleOutH.IsMatching(testPx))
            {
                if (bDebugDetection)
                {
                    Logger.WriteLine("HasCactpotCircleEdgeV[" + posX + "," + posY + "] failed: deep center " + testPx);
                }
                return(false);
            }

            testPx = bitmap.GetPixel(posX, posY - spreadY);
            if (!colorMatchCircleOut.IsMatching(testPx) && !colorMatchCircleOutH.IsMatching(testPx))
            {
                if (bDebugDetection)
                {
                    Logger.WriteLine("HasCactpotCircleEdgeV[" + posX + "," + posY + "] failed: edge top " + testPx);
                }
                return(false);
            }

            testPx = bitmap.GetPixel(posX, posY + spreadY);
            if (!colorMatchCircleOut.IsMatching(testPx) && !colorMatchCircleOutH.IsMatching(testPx))
            {
                if (bDebugDetection)
                {
                    Logger.WriteLine("HasCactpotCircleEdgeV[" + posX + "," + posY + "] failed: edge bottom " + testPx);
                }
                return(false);
            }

            testPx = bitmap.GetPixel(posX + sideX, posY);
            if (!colorMatchBack.IsMatching(testPx) && !colorMatchCircleFade.IsMatching(testPx) && !colorMatchCircleFadeH.IsMatching(testPx))
            {
                if (bDebugDetection)
                {
                    Logger.WriteLine("HasCactpotCircleEdgeV[" + posX + "," + posY + "] failed: edge center prev " + testPx);
                }
                return(false);
            }

            testPx = bitmap.GetPixel(posX + sideX, posY - spreadY);
            if (!colorMatchBack.IsMatching(testPx) && !colorMatchCircleFade.IsMatching(testPx) && !colorMatchCircleFadeH.IsMatching(testPx))
            {
                if (bDebugDetection)
                {
                    Logger.WriteLine("HasCactpotCircleEdgeV[" + posX + "," + posY + "] failed: edge top prev " + testPx);
                }
                return(false);
            }

            testPx = bitmap.GetPixel(posX + sideX, posY + spreadY);
            if (!colorMatchBack.IsMatching(testPx) && !colorMatchCircleFade.IsMatching(testPx) && !colorMatchCircleFadeH.IsMatching(testPx))
            {
                if (bDebugDetection)
                {
                    Logger.WriteLine("HasCactpotCircleEdgeV[" + posX + "," + posY + "] failed: edge bottom prev " + testPx);
                }
                return(false);
            }

            return(true);
        }
Пример #22
0
 public void SetPixel(int Idx, FastPixelHSV pixel)
 {
     Pixels[Idx] = pixel;
 }
Пример #23
0
        public static bool CreateFloodFillBitmap(FastBitmapHSV srcBitmap, Point floodOrigin, Size floodExtent, FastPixelMatch colorMatch,
                                                 out FastBitmapHSV floodBitmap, out Rectangle floodBounds, bool bDebugMode = false)
        {
            List <Point> floodPoints = new List <Point>();
            int          minX        = floodOrigin.X;
            int          maxX        = floodOrigin.X;
            int          minY        = floodOrigin.Y;
            int          maxY        = floodOrigin.Y;
            Rectangle    boundRect   = new Rectangle(floodOrigin.X - floodExtent.Width, floodOrigin.Y - floodExtent.Height, floodExtent.Width * 2, floodExtent.Height * 2);

            Stack <Point> openList = new Stack <Point>();

            openList.Push(floodOrigin);

            while (openList.Count > 0)
            {
                Point testPoint = openList.Pop();
                if (floodPoints.Contains(testPoint))
                {
                    continue;
                }

                FastPixelHSV testPx = srcBitmap.GetPixel(testPoint.X, testPoint.Y);
                if (bDebugMode)
                {
                    Logger.WriteLine("[" + testPoint.X + ", " + testPoint.Y + "] " + testPx + ", match:" + colorMatch.IsMatching(testPx) + ", inBounds:" + boundRect.Contains(testPoint));
                }

                if (colorMatch.IsMatching(testPx) && boundRect.Contains(testPoint))
                {
                    floodPoints.Add(testPoint);

                    minX = Math.Min(minX, testPoint.X);
                    maxX = Math.Max(maxX, testPoint.X);
                    minY = Math.Min(minY, testPoint.Y);
                    maxY = Math.Max(maxY, testPoint.Y);

                    openList.Push(new Point(testPoint.X - 1, testPoint.Y));
                    openList.Push(new Point(testPoint.X + 1, testPoint.Y));
                    openList.Push(new Point(testPoint.X, testPoint.Y - 1));
                    openList.Push(new Point(testPoint.X, testPoint.Y + 1));
                    openList.Push(new Point(testPoint.X - 1, testPoint.Y - 1));
                    openList.Push(new Point(testPoint.X + 1, testPoint.Y - 1));
                    openList.Push(new Point(testPoint.X - 1, testPoint.Y + 1));
                    openList.Push(new Point(testPoint.X + 1, testPoint.Y + 1));
                }
            }

            floodBounds = new Rectangle(minX, minY, maxX - minX + 1, maxY - minY + 1);
            if (floodPoints.Count > 0)
            {
                FastPixelHSV[] bitmapPixels = new FastPixelHSV[floodBounds.Width * floodBounds.Height];
                for (int Idx = 0; Idx < bitmapPixels.Length; Idx++)
                {
                    bitmapPixels[Idx] = new FastPixelHSV(false);
                }

                foreach (Point p in floodPoints)
                {
                    int Idx = (p.X - minX) + ((p.Y - minY) * floodBounds.Width);
                    bitmapPixels[Idx] = new FastPixelHSV(true);
                }

                floodBitmap = new FastBitmapHSV()
                {
                    Pixels = bitmapPixels,
                    Width  = floodBounds.Width,
                    Height = floodBounds.Height,
                };
            }
            else
            {
                floodBitmap = null;
            }

            return(floodBitmap != null);
        }
Пример #24
0
        public static int FindPatternMatch(FastBitmapHSV bitmap, Point pos, FastPixelMatch colorMatch, List <ImagePatternDigit> patterns, out ImageDataDigit digitData, bool bDebugMode = false)
        {
            int   bestValue           = 0;
            int   bestValueExact      = 0;
            float totalBestScore      = 0;
            float totalBestScoreExact = 0;

            const int offsetSize  = 5;
            const int cacheWidth  = offsetSize + 10 + offsetSize;
            const int cacheHeight = offsetSize + 8 + offsetSize;

            byte[] PixelMatch = new byte[cacheWidth * cacheHeight];

            int bestPatternMatchX = 0;
            int bestPatternExactX = 0;
            int bestPatternMatchY = 0;
            int bestPatternExactY = 0;

            foreach (ImagePatternDigit pattern in patterns)
            {
                float bestScore      = 0;
                float bestScoreExact = 0;
                int   bestPosX       = 0;
                int   bestPosXExact  = 0;
                int   bestPosY       = 0;
                int   bestPosYExact  = 0;

                int ByteIdx = 0;
                for (int IdxY = 0; IdxY < cacheHeight; IdxY++)
                {
                    for (int IdxX = 0; IdxX < cacheWidth; IdxX++)
                    {
                        FastPixelHSV testPx = bitmap.GetPixel(pos.X + IdxX - offsetSize, pos.Y + IdxY - offsetSize);
                        PixelMatch[ByteIdx] = colorMatch.IsMatching(testPx) ? (byte)1 : (byte)0;
                        ByteIdx++;
                    }
                }

                /*if (bDebugMode)
                 * {
                 *  bestPosX = 894;
                 *  bestPosY = 615;
                 *  bestScore = HasPatternMatch(PixelMatch, bestPosX - pos.X + offsetSize, bestPosY - pos.Y + offsetSize, cacheWidth,
                 *      pattern, pattern.Value == 3 || pattern.Value == 5 || pattern.Value == 8);
                 * }
                 * else*/
                {
                    for (int offsetX = -offsetSize; offsetX <= offsetSize; offsetX++)
                    {
                        for (int offsetY = -offsetSize; offsetY <= offsetSize; offsetY++)
                        {
                            float testScore = HasPatternMatch(PixelMatch, offsetX + offsetSize, offsetY + offsetSize, cacheWidth, false, pattern);
                            if (testScore > bestScore)
                            {
                                bestPosX  = pos.X + offsetX;
                                bestPosY  = pos.Y + offsetY;
                                bestScore = testScore;
                            }

                            float testScoreExact = HasPatternMatch(PixelMatch, offsetX + offsetSize, offsetY + offsetSize, cacheWidth, true, pattern);
                            if (testScoreExact > bestScoreExact)
                            {
                                bestPosXExact  = pos.X + offsetX;
                                bestPosYExact  = pos.Y + offsetY;
                                bestScoreExact = testScoreExact;
                            }
                        }
                    }
                }

                if (bestScore > totalBestScore)
                {
                    totalBestScore = bestScore;
                    bestValue      = pattern.Value;

                    bestPatternMatchX = bestPosX - pos.X + offsetSize;
                    bestPatternMatchY = bestPosY - pos.Y + offsetSize;
                }

                if (bestScoreExact > totalBestScoreExact)
                {
                    totalBestScoreExact = bestScoreExact;
                    bestValueExact      = pattern.Value;

                    bestPatternExactX = bestPosXExact - pos.X + offsetSize;
                    bestPatternExactY = bestPosYExact - pos.Y + offsetSize;
                }

                if (bDebugMode)
                {
                    Logger.WriteLine("FindPatternMatch: " + pattern.Value +
                                     " best at (" + bestPosX + ", " + bestPosY + ") = " + (int)(100 * bestScore) + "%," +
                                     " exact at (" + bestPosXExact + ", " + bestPosYExact + ") = " + (int)(100 * bestScoreExact) + "%");
                }
            }

            {
                byte[] digitDataPixels = new byte[10];
                for (int IdxX = 0; IdxX < 10; IdxX++)
                {
                    int Value   = 0;
                    int ByteIdx = (bestPatternMatchY * cacheWidth) + bestPatternMatchX + IdxX;
                    for (int IdxY = 0; IdxY < 8; IdxY++)
                    {
                        Value |= (PixelMatch[ByteIdx + (IdxY * cacheWidth)] != 0) ? (1 << IdxY) : 0;
                    }

                    digitDataPixels[IdxX] = (byte)Value;
                }

                digitData = new ImageDataDigit(digitDataPixels);

                if (bDebugMode)
                {
                    for (int IdxY = 0; IdxY < 8; IdxY++)
                    {
                        string debugDesc = "";
                        for (int IdxX = 0; IdxX < 10; IdxX++)
                        {
                            byte ColValue = digitDataPixels[IdxX];
                            byte RowMask  = (byte)(1 << IdxY);
                            debugDesc += ((ColValue & RowMask) != 0 ? "#" : ".") + " ";
                        }

                        Logger.WriteLine(debugDesc);
                    }
                }
            }

            return((totalBestScoreExact > 0.95) ? bestValueExact : (totalBestScore > 0.8) ? bestValue : 0);
        }
Пример #25
0
        public static FastBitmapHash CalculateImageHash(FastBitmapHSV bitmap, Rectangle box, Rectangle contextBox, FastPixelMatch colorMatch, int hashWidth, int hashHeight, bool bNormalizeColors = false)
        {
            byte[] hashImage = new byte[hashWidth * hashHeight];

            // scale to requested size
            float scaleX = (float)hashWidth / box.Width;
            float scaleY = (float)hashHeight / box.Height;
            float endY   = 0.0f;

            for (int hashY = 0; hashY < hashHeight; hashY++)
            {
                float startY = endY;
                endY = (hashY + 1) / scaleY;
                if (endY >= box.Height)
                {
                    endY = box.Height - 0.00001f;
                }
                float endX = 0.0f;

                for (int hashX = 0; hashX < hashWidth; hashX++)
                {
                    float startX = endX;
                    endX = (hashX + 1) / scaleX;
                    if (endX >= box.Width)
                    {
                        endX = box.Width - 0.00001f;
                    }
                    float sum = 0.0f;

                    int sumDivNum = 0;
                    for (int srcY = (int)startY; srcY <= (int)endY; srcY++)
                    {
                        float partY = 1.0f;
                        if (srcY == (int)startY)
                        {
                            partY -= startY - srcY;
                        }
                        if (srcY == (int)endY)
                        {
                            partY -= srcY + 1 - endY;
                        }

                        for (int srcX = (int)startX; srcX <= (int)endX; srcX++)
                        {
                            float partX = 1.0f;
                            if (srcX == (int)startX)
                            {
                                partX -= startX - srcX;
                            }
                            if (srcX == (int)endX)
                            {
                                partX -= srcX + 1 - endX;
                            }

                            FastPixelHSV valuePx      = bitmap.GetPixel(box.Left + srcX, box.Top + srcY);
                            float        srcValueNorm = colorMatch.IsMatching(valuePx) ? (bNormalizeColors ? 1.0f : (valuePx.Monochrome / 255.0f)) : 0.0f;
                            sum += srcValueNorm * partY * partX;
                            sumDivNum++;
                        }
                    }

                    float storeValueNorm = sum / sumDivNum;
                    hashImage[hashX + (hashY * hashWidth)] = (byte)Math.Min(15, 15 * storeValueNorm);
                }
            }

            TlshBuilder hashBuilder = new TlshBuilder();

            hashBuilder.Update(hashImage);
            TlshHash       complexHash    = hashBuilder.IsValid(false) ? hashBuilder.GetHash(false) : null;
            ScanLineHash   simpleHash     = ScanLineHash.CreateFromImage(hashImage, hashWidth, hashHeight);
            HashCollection hashCollection = new HashCollection(complexHash, simpleHash);

            return(new FastBitmapHash
            {
                Hash = hashCollection,
                Height = hashHeight,
                Width = hashWidth,
                Pixels = hashImage,
                SourceBounds = box,
                ContextBounds = contextBox,
                DrawPos = new Point(box.Right + 1, box.Top),
            });
        }
Пример #26
0
        private bool HasCactpotCircleMatch(FastBitmapHSV bitmap, int posX, int posY, int cellSize, int offsetIn, bool bDebugDetection = false)
        {
            int sizeA   = cellSize;
            int offsetB = Math.Max(5, offsetIn - 2);
            int sizeB   = sizeA - (offsetB * 2);

            Point[] testPoints    = new Point[4];
            int     numHighlights = 0;

            // 4 points: corners of cell => dark background
            {
                testPoints[0].X = posX; testPoints[0].Y = posY;
                testPoints[1].X = posX + sizeA; testPoints[1].Y = posY;
                testPoints[2].X = posX; testPoints[2].Y = posY + sizeA;
                testPoints[3].X = posX + sizeA; testPoints[3].Y = posY + sizeA;

                for (int Idx = 0; Idx < 4; Idx++)
                {
                    FastPixelHSV testPx = bitmap.GetPixel(testPoints[Idx].X, testPoints[Idx].Y);
                    //if (bDebugDetection) { Logger.WriteLine("[" + posX + ", " + posY + "] testing A[" + testPoints[Idx].X + "," + testPoints[Idx].Y + "]: " + testPx); }

                    if (!colorMatchBack.IsMatching(testPx))
                    {
                        if (bDebugDetection)
                        {
                            Logger.WriteLine("[" + posX + ", " + posY + "] failed, not background: A[" + testPoints[Idx].X + "," + testPoints[Idx].Y + "]: " + testPx);
                        }
                        return(false);
                    }
                }
            }

            // 4 points: corners with offset B => dark background
            {
                testPoints[0].X = posX + offsetB; testPoints[0].Y = posY + offsetB;
                testPoints[1].X = posX + sizeA - offsetB; testPoints[1].Y = posY + offsetB;
                testPoints[2].X = posX + offsetB; testPoints[2].Y = posY + sizeA - offsetB;
                testPoints[3].X = posX + sizeA - offsetB; testPoints[3].Y = posY + sizeA - offsetB;

                for (int Idx = 0; Idx < 4; Idx++)
                {
                    FastPixelHSV testPx = bitmap.GetPixel(testPoints[Idx].X, testPoints[Idx].Y);
                    //if (bDebugDetection) { Logger.WriteLine("[" + posX + ", " + posY + "] testing B1[" + testPoints[Idx].X + "," + testPoints[Idx].Y + "]: " + testPx); }

                    if (!colorMatchBack.IsMatching(testPx))
                    {
                        if (bDebugDetection)
                        {
                            Logger.WriteLine("[" + posX + ", " + posY + "] failed, not background: B1[" + testPoints[Idx].X + "," + testPoints[Idx].Y + "]: " + testPx);
                        }
                        return(false);
                    }
                }
            }

            Point[] testPointCloser = new Point[4];

            // 4 points: midpoints with offset B => yellow/white
            {
                testPoints[0].X = posX + offsetB; testPoints[0].Y = posY + (sizeA / 2);
                testPoints[1].X = posX + sizeA - offsetB; testPoints[1].Y = posY + (sizeA / 2);
                testPoints[2].X = posX + (sizeA / 2); testPoints[2].Y = posY + offsetB;
                testPoints[3].X = posX + (sizeA / 2); testPoints[3].Y = posY + sizeA - offsetB;

                for (int Idx = 0; Idx < 4; Idx++)
                {
                    FastPixelHSV testPx = bitmap.GetPixel(testPoints[Idx].X, testPoints[Idx].Y);
                    //if (bDebugDetection) { Logger.WriteLine("[" + posX + ", " + posY + "] testing B2[" + testPoints[Idx].X + "," + testPoints[Idx].Y + "]: " + testPx); }

                    if (colorMatchCircleOutH.IsMatching(testPx))
                    {
                        numHighlights++;
                    }
                    else if (!colorMatchCircleOut.IsMatching(testPx))
                    {
                        if (bDebugDetection)
                        {
                            Logger.WriteLine("[" + posX + ", " + posY + "] failed, not circle: B2[" + testPoints[Idx].X + "," + testPoints[Idx].Y + "]: " + testPx);
                        }
                        return(false);
                    }
                }
            }

            // 4 points: midpoints of diagonal lines between midpoints B (C) => yellow/white
            {
                testPoints[0].X = posX + offsetB + (sizeB / 4); testPoints[0].Y = posY + offsetB + (sizeB / 4);
                testPoints[1].X = posX + sizeA - offsetB - (sizeB / 4); testPoints[1].Y = posY + offsetB + (sizeB / 4);
                testPoints[2].X = posX + offsetB + (sizeB / 4); testPoints[2].Y = posY + sizeA - offsetB - (sizeB / 4);
                testPoints[3].X = posX + sizeA - offsetB - (sizeB / 4); testPoints[3].Y = posY + sizeA - offsetB - (sizeB / 4);

                for (int Idx = 0; Idx < 4; Idx++)
                {
                    FastPixelHSV testPx = bitmap.GetPixel(testPoints[Idx].X, testPoints[Idx].Y);
                    //if (bDebugDetection) { Logger.WriteLine("[" + posX + ", " + posY + "] testing B3[" + testPoints[Idx].X + "," + testPoints[Idx].Y + "]: " + testPx); }

                    if (!colorMatchCircleIn.IsMatching(testPx))
                    {
                        if (bDebugDetection)
                        {
                            Logger.WriteLine("[" + posX + ", " + posY + "] failed, not circle: B3[" + testPoints[Idx].X + "," + testPoints[Idx].Y + "]: " + testPx);
                        }
                        return(false);
                    }
                }
            }

            return((numHighlights == 0) || (numHighlights == 4));
        }