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) { Console.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) { Console.WriteLine(" [" + scanX + ", " + scanY + "] " + testPx + " => match:" + bIsMatching); } if (bIsMatching) { posHit = new Point(scanX, scanY); return(true); } } if (bDebugMode) { Console.WriteLine(" >> failed"); } posHit = new Point(posX + (traceLen * incX), posY + (traceLen * incY)); return(false); }
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)); }
private bool HasBurstMarker(FastBitmapHSV bitmap, int testX, int testY) { //bool wantsLogs = testX == 153 && testY == 112; for (int idx = 0; idx < posBurstMarkerI.Length; idx++) { FastPixelHSV testPx = bitmap.GetPixel(posBurstMarkerI[idx].X + testX, posBurstMarkerI[idx].Y + testY); bool isMatch = matchBurstMarker.IsMatching(testPx); //if (wantsLogs) Console.WriteLine("HasBurstMarker({0}, {1}) - inner[{2}]({3},{4}) = {5}", testX, testY, idx, posBurstMarkerI[idx].X + testX, posBurstMarkerI[idx].Y + testY, testPx); if (!isMatch) { return(false); } } for (int idx = 0; idx < posBurstMarkerO.Length; idx++) { FastPixelHSV testPx = bitmap.GetPixel(posBurstMarkerO[idx].X + testX, posBurstMarkerO[idx].Y + testY); bool isMatch = matchBurstMarker.IsMatching(testPx); //if (wantsLogs) Console.WriteLine("HasBurstMarker({0}, {1}) - outer[{2}]({3},{4}) = {5}", testX, testY, idx, posBurstMarkerO[idx].X + testX, posBurstMarkerO[idx].Y + testY, testPx); if (isMatch) { return(false); } } return(true); }
public float[] ExtractActionSlotWeaponData(FastBitmapHSV bitmap, int slotIdx) { // scan area: 10x10 (rectActionIcon) float[] values = new float[10 * 10]; for (int idx = 0; idx < values.Length; idx++) { values[idx] = 0.0f; } const int monoSteps = 16; const float monoScale = 1.0f / monoSteps; Point slotPos = rectActionSlots[slotIdx].Location; for (int idxY = 0; idxY < 10; idxY++) { for (int idxX = 0; idxX < 10; idxX++) { FastPixelHSV pixel = bitmap.GetPixel(slotPos.X + rectActionIcon.X + idxX, slotPos.Y + rectActionIcon.Y + idxY); int monoV = pixel.GetMonochrome() / (256 / monoSteps); values[idxX + (idxY * 10)] = monoV * monoScale; } } return(values); }
public float[] ExtractButtonData(FastBitmapHSV bitmap, int slotIdx) { // scan area: 16x8 (rectButtonText scaled down) float[] values = new float[16 * 8]; for (int idx = 0; idx < values.Length; idx++) { values[idx] = 0.0f; } const int monoSteps = 16; const float monoScale = 1.0f / monoSteps; Point slotPos = rectButtonPos[slotIdx].Location; slotPos.X += rectButtonText.Location.X; slotPos.Y += rectButtonText.Location.Y; for (int idxY = 0; idxY < 16; idxY++) { for (int idxX = 0; idxX < 32; idxX++) { FastPixelHSV pixel = bitmap.GetPixel(slotPos.X + idxX, slotPos.Y + idxY); int monoV = pixel.GetMonochrome() / (256 / monoSteps); values[(idxX / 2) + ((idxY / 2) * 16)] += monoV * monoScale * 0.25f; } } return(values); }
public float[] ExtractDemonTypeData(FastBitmapHSV bitmap) { // scan area: 10x10 (rectActionIcon) float[] values = new float[10 * 10]; for (int idx = 0; idx < values.Length; idx++) { values[idx] = 0.0f; } const int monoSteps = 16; const float monoScale = 1.0f / monoSteps; for (int idxY = 0; idxY < 10; idxY++) { for (int idxX = 0; idxX < 10; idxX++) { FastPixelHSV pixel = bitmap.GetPixel(rectDemonType.X + idxX, rectDemonType.Y + idxY); int monoV = pixel.GetMonochrome() / (256 / monoSteps); values[idxX + (idxY * 10)] = monoV * monoScale; } } return(values); }
protected bool HasMatchingSamples(FastBitmapHSV bitmap, Point[] points, int offsetX, int offsetY, FastPixelMatch match, string debugName) { if (DebugLevel == EDebugLevel.Verbose) { string desc = ""; for (int idx = 0; idx < points.Length; idx++) { if (idx > 0) { desc += ", "; } var testPx = bitmap.GetPixel(points[idx].X + offsetX, points[idx].Y + offsetY); var matching = match.IsMatching(testPx); desc += "(" + testPx + "):" + matching; } Console.WriteLine("HasMatchingSamples: {2}> filter({0}) vs {1}", match, desc, debugName); } for (int idx = 0; idx < points.Length; idx++) { FastPixelHSV testPx = bitmap.GetPixel(points[idx].X + offsetX, points[idx].Y + offsetY); bool isMatch = match.IsMatching(testPx); if (!isMatch) { return(false); } } return(true); }
public float[] ExtractHeaderPatternData(FastBitmapHSV bitmap, int patternIdx) { // scan area: 20x8 float[] values = new float[20 * 8]; for (int idx = 0; idx < values.Length; idx++) { values[idx] = 0.0f; } const int monoSteps = 16; const float monoScale = 1.0f / monoSteps; for (int idxY = 0; idxY < 8; idxY++) { for (int idxX = 0; idxX < 20; idxX++) { FastPixelHSV pixel = bitmap.GetPixel(posHeaderPattern[patternIdx].X + idxX, posHeaderPattern[patternIdx].Y + idxY); int monoV = pixel.GetMonochrome() / (256 / monoSteps); values[idxX + (idxY * 20)] = monoV * monoScale; } } return(values); }
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) { Console.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) { Console.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) { Console.WriteLine(">> adding span: " + lastX + ", size:" + spanSize); } result.Add(new Point(lastX, spanSize)); } } return(result); }
private void ScanBurst(FastBitmapHSV bitmap, ScreenData screenData) { float monoAcc = 0.0f; for (int idxY = 0; idxY < rectBurstActive.Height; idxY++) { for (int idxX = 0; idxX < rectBurstActive.Width; idxX++) { FastPixelHSV testPx = bitmap.GetPixel(rectBurstActive.X + idxX, rectBurstActive.Y + idxY); monoAcc += testPx.GetMonochrome(); } } float monoAvg = monoAcc / (rectBurstActive.Width * rectBurstActive.Height); float centerFillPct = 0; if (monoAvg < 15) { screenData.BurstState = EBurstState.Active; } else { centerFillPct = ScreenshotUtilities.CountFillPct(bitmap, rectBurstCenter, matchBurstCenter); if (centerFillPct > 0.75f) { screenData.BurstState = EBurstState.ReadyAndCenter; screenData.BurstMarkerPctX = 0.5f; screenData.BurstMarkerPctY = 0.5f; if (DebugLevel >= EDebugLevel.Verbose) { Rectangle box = GetSpecialActionBox((int)ESpecialBox.BurstCenter); DrawRectangle(bitmap, box.X, box.Y, box.Width, box.Height, 255); } } else { ScanBurstPosition(bitmap, screenData); if (DebugLevel >= EDebugLevel.Verbose && screenData.BurstState == EBurstState.Ready) { Rectangle box = GetSpecialActionBox((int)ESpecialBox.BurstReady); DrawRectangle(bitmap, box.X, box.Y, box.Width, box.Height, 255); } } } if (DebugLevel >= EDebugLevel.Simple) { Console.WriteLine("{0} ScanBurst: {1}", ScannerName, screenData.BurstState); } if (DebugLevel >= EDebugLevel.Verbose) { Console.WriteLine(">> monoAvg: {0}, centerFillPct: {1}", monoAvg, centerFillPct); } }
public override bool IsMatching(FastPixelHSV pixel) { if ((pixel.Monochrome >= MonoMin) && (pixel.Monochrome <= MonoMax)) { int Hue = pixel.GetHue(); return((Hue >= HueMin) && (Hue <= HueMax)); } return(false); }
protected void ScanActionSlot(FastBitmapHSV bitmap, Rectangle bounds, ActionData actionData, int slotIdx) { for (int idxY = 0; idxY < rectActionAvail.Height; idxY++) { for (int idxX = 0; idxX < rectActionAvail.Width; idxX++) { FastPixelHSV testPx = bitmap.GetPixel(bounds.X + rectActionAvail.X + idxX, bounds.Y + rectActionAvail.Y + idxY); bool match = matchActionAvail.IsMatching(testPx); if (match) { actionData.isValid = true; break; } } } if (actionData.isValid) { float[] pixelInput = ExtractActionSlotWeaponData(bitmap, slotIdx); actionData.weaponClass = (EWeaponType)classifierWeapon.Calculate(pixelInput, out float dummyPct); actionData.element = ScanElementType(bitmap, bounds); actionData.hasBoost = HasElemBoost(bitmap, slotIdx); } if (DebugLevel >= EDebugLevel.Simple) { Console.WriteLine("{0} Action[{1}]: valid:{2}, class:{3}, elem: {4}", ScannerName, slotIdx, actionData.isValid, actionData.weaponClass, actionData.element); } if (DebugLevel >= EDebugLevel.Verbose) { var minMono = 255; var maxMono = 0; for (int idxY = 0; idxY < rectActionAvail.Height; idxY++) { for (int idxX = 0; idxX < rectActionAvail.Width; idxX++) { FastPixelHSV testPx = bitmap.GetPixel(bounds.X + rectActionAvail.X + idxX, bounds.Y + rectActionAvail.Y + idxY); minMono = Math.Min(minMono, testPx.GetMonochrome()); maxMono = Math.Max(maxMono, testPx.GetMonochrome()); } } Console.WriteLine(">> avail M:{0}..{1} (x:{2},y:{3},w:{4},h:{5})", minMono, maxMono, bounds.X + rectActionAvail.X, bounds.Y + rectActionAvail.Y, rectActionAvail.Width, rectActionAvail.Height); } }
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); } } }
private float GetActionSlotPixelValue(FastPixelHSV pixel) { const int hueSteps = 16; const int monoSteps = 16; const float monoScale = 1.0f / monoSteps; const float hueScale = monoScale / hueSteps; int hueV = pixel.GetHue() / (360 / hueSteps); int monoV = pixel.GetMonochrome() / (256 / monoSteps); float pixelV = (hueV * hueScale) + (monoV * monoScale); return(pixelV); }
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); }
protected void DrawRectangle(FastBitmapHSV bitmap, int posX, int posY, int width, int height, byte color, int border = 1) { FastPixelHSV pixelOb = new FastPixelHSV(color, color, color); for (int idxX = 0; idxX < width; idxX++) { bitmap.SetPixel(posX + idxX, posY - border, pixelOb); bitmap.SetPixel(posX + idxX, posY + height + border, pixelOb); } for (int idxY = 0; idxY < height; idxY++) { bitmap.SetPixel(posX - border, posY + idxY, pixelOb); bitmap.SetPixel(posX + width + border, posY + idxY, pixelOb); } }
protected void GetAverageChestColor(FastBitmapHSV bitmap, Point chestPos, out int avgHue, out int avgSat) { float scale = 1.0f / (rectChestArea.Width * rectChestArea.Height); float accHue = 0; float accSat = 0; for (int idxX = 0; idxX < rectChestArea.Width; idxX++) { for (int idxY = 0; idxY < rectChestArea.Height; idxY++) { FastPixelHSV testPx = bitmap.GetPixel(chestPos.X + rectChestArea.X + idxX, chestPos.Y + rectChestArea.Y + idxY); accHue += testPx.GetHue(); accSat += testPx.GetSaturation(); } } avgHue = (int)(accHue * scale); avgSat = (int)(accSat * scale); }
public override bool IsMatching(FastPixelHSV pixel) { int Saturation = pixel.GetSaturation(); if ((Saturation < SaturationMin) || (Saturation > SaturationMax) || (pixel.Value < ValueMin) || (pixel.Value > ValueMax)) { return(false); } int Hue = pixel.GetHue(); if (HueMin < 0 && Hue > 200) { Hue -= 360; } return((Hue >= HueMin) && (Hue <= HueMax)); }
public static FastPixelHSV GetAverageColor(FastBitmapHSV bitmap, Rectangle bounds) { float hueAcc = 0.0f; float satAcc = 0.0f; float valAcc = 0.0f; float scale = 1.0f / bounds.Width; for (int idx = 0; idx < bounds.Width; idx++) { FastPixelHSV testPx = bitmap.GetPixel(bounds.X + idx, bounds.Y); hueAcc += testPx.GetHue(); satAcc += testPx.GetSaturation(); valAcc += testPx.GetValue(); } FastPixelHSV avgPx = new FastPixelHSV(); avgPx.SetHSV((int)(hueAcc * scale), (int)(satAcc * scale), (int)(valAcc * scale)); return(avgPx); }
private void ScanBurstPosition(FastBitmapHSV bitmap, ScreenData screenData) { bool hasMarker = false; for (int idxY = 0; idxY < rectBurstArea.Height; idxY++) { for (int idxX = 0; idxX < rectBurstArea.Width; idxX++) { FastPixelHSV testPx = bitmap.GetPixel(rectBurstArea.X + idxX, rectBurstArea.Y + idxY); bool isMatch = matchBurstMarker.IsMatching(testPx); if (isMatch) { hasMarker = HasBurstMarker(bitmap, rectBurstArea.X + idxX, rectBurstArea.Y + idxY); if (hasMarker) { screenData.BurstState = EBurstState.Ready; screenData.BurstMarkerPctX = idxX * 1.0f / rectBurstArea.Width; screenData.BurstMarkerPctY = idxY * 1.0f / rectBurstArea.Height; cachedBurstPos = new Point(rectBurstArea.X + idxX, rectBurstArea.Y + idxY); DrawRectangle(bitmap, rectBurstArea.X + idxX - 15, rectBurstArea.Y + idxY - 15, 30, 30, 255); break; } } } if (hasMarker) { break; } } if (DebugLevel >= EDebugLevel.Simple) { Console.WriteLine("{0} ScanBurstPosition: {1}", ScannerName, screenData.BurstState); } if (DebugLevel >= EDebugLevel.Verbose) { Console.WriteLine(">> marker.X:{0:P2}, marker.Y:{1:P2}", screenData.BurstMarkerPctX, screenData.BurstMarkerPctY); } }
protected FastPixelHSV[] FindSpecialActionButton(FastBitmapHSV bitmap) { FastPixelHSV[] samples = new FastPixelHSV[posBigButton.Length]; samples[0] = bitmap.GetPixel(posBigButton[0].X, posBigButton[0].Y); int maxHDiff = 0; for (int idx = 1; idx < samples.Length; idx++) { samples[idx] = bitmap.GetPixel(posBigButton[idx].X, posBigButton[idx].Y); int hDiff = Math.Abs(samples[idx].GetHue() - samples[0].GetHue()); if (maxHDiff < hDiff) { maxHDiff = hDiff; } } var hasSpecialAction = (maxHDiff < 20); return(hasSpecialAction ? samples : null); }
public float[] ExtractDemonCounterData(FastBitmapHSV bitmap, int side) { // scan area: 50x10 float[] values = new float[50 * 10]; for (int idx = 0; idx < values.Length; idx++) { values[idx] = 0.0f; } Rectangle bounds = (side == 0) ? rectDemonL : rectDemonR; for (int idxY = 0; idxY < 10; idxY++) { for (int idxX = 0; idxX < 50; idxX++) { FastPixelHSV pixel = bitmap.GetPixel(bounds.X + idxX, bounds.Y + idxY); values[idxX + (idxY * 50)] = GetDemonPixelValue(pixel); } } return(values); }
public static Bitmap CreateBitmapWithShapes(FastBitmapHSV bitmap, List <Rectangle> listBounds) { 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); //Color writeColor = GetColorFromHSV(writePx); 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()); } } return(bmp); }
protected float[] ExtractStatData(FastBitmapHSV bitmap, Point[] playerPos, int playerIdx, int statIdx) { // scan area: (9+1)x7 float[] values = new float[(11 + 1) * 9]; int writeIdx = 0; for (int idxY = 0; idxY < 9; idxY++) { float accHueLine = 0.0f; for (int idxX = 0; idxX < 11; idxX++) { FastPixelHSV pixel = bitmap.GetPixel(playerPos[playerIdx].X + posStatOffset[statIdx].X + idxX - 1, playerPos[playerIdx].Y + posStatOffset[statIdx].Y + idxY - 1); values[writeIdx] = pixel.GetMonochrome() / 255.0f; accHueLine += pixel.GetHue() / 360.0f; writeIdx++; } values[writeIdx] = accHueLine / 11; writeIdx++; } return(values); }
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) { Console.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) { floodBitmap = new FastBitmapHSV(floodBounds.Width, floodBounds.Height); int numPx = floodBounds.Width * floodBounds.Height; for (int Idx = 0; Idx < numPx; Idx++) { floodBitmap.SetPixel(Idx, new FastPixelHSV(false)); } foreach (Point p in floodPoints) { int Idx = (p.X - minX) + ((p.Y - minY) * floodBounds.Width); floodBitmap.SetPixel(Idx, new FastPixelHSV(true)); } } else { floodBitmap = null; } return(floodBitmap != null); }
protected bool HasElemBoostMarker(FastBitmapHSV bitmap, int posX, int posY, int slotIdx) { // samplesIn: hue: 20 +- 30, higher Y = lower hue, first 3 (center column) can be a super bright wildcard // samplesOut: similar hue, low V (dark) FastPixelHSV[] samplesIn = new FastPixelHSV[posBoostIn.Length]; int numHueDec = 0; int numWildCards = 0; int numMatching = 0; for (int idx = 0; idx < samplesIn.Length; idx++) { samplesIn[idx] = bitmap.GetPixel(posX + posBoostIn[idx].X, posY + posBoostIn[idx].Y); bool isMatching = matchBoostIn.IsMatching(samplesIn[idx]); numMatching += isMatching ? 1 : 0; if ((idx > 0) && (posBoostIn[idx - 1].Y < posBoostIn[idx].Y)) { numHueDec += (samplesIn[idx - 1].GetHue() >= samplesIn[idx].GetHue()) ? 1 : 0; } if (idx < 3 && !isMatching) { numWildCards += matchBoostInW.IsMatching(samplesIn[idx]) ? 1 : 0; } } bool matchIn = ((numMatching + numWildCards) == samplesIn.Length) && (numHueDec == 3) && (numWildCards < 2); FastPixelHSV[] samplesOut = new FastPixelHSV[posBoostOut.Length]; bool matchOut = true; for (int idx = 0; idx < samplesOut.Length; idx++) { samplesOut[idx] = bitmap.GetPixel(posX + posBoostOut[idx].X, posY + posBoostOut[idx].Y); matchOut = matchOut && matchBoostOut.IsMatching(samplesOut[idx]); } var showLogs = //(slotIdx == 2) && (posY == 501); //((slotIdx == 1) || (slotIdx == 3)) && (matchIn && matchOut); false; if (DebugLevel >= EDebugLevel.Verbose && showLogs) { Console.WriteLine("HasElemBoostMarker[{0}], Y:{1}, In.HueDec:{2}, matchIn:{3}, matchOut:{4} => {5}", slotIdx, posY, numHueDec, matchIn, matchOut, matchIn && matchOut); string desc = ""; for (int idx = 0; idx < samplesIn.Length; idx++) { if (idx > 0) { desc += ", "; } desc += string.Format("({0},{1} = {2}):{3}", posX + posBoostIn[idx].X, posY + posBoostIn[idx].Y, samplesIn[idx], matchBoostIn.IsMatching(samplesIn[idx]) ? "Yes" : matchBoostInW.IsMatching(samplesIn[idx]) ? "Maybe" : "No"); } Console.WriteLine(" IN({0}): {1}", matchBoostIn, desc); desc = ""; for (int idx = 0; idx < samplesOut.Length; idx++) { if (idx > 0) { desc += ", "; } desc += string.Format("({0},{1} = {2}):{3}", posX + posBoostOut[idx].X, posY + posBoostOut[idx].Y, samplesOut[idx], matchBoostOut.IsMatching(samplesOut[idx])); } Console.WriteLine(" OUT({0}): {1}", matchBoostOut, desc); } return(matchIn && matchOut); }
protected EElementType ScanElementType(FastBitmapHSV bitmap, Rectangle bounds) { EElementType element = EElementType.Unknown; int countElemR = 0; int countElemG = 0; int countElemB = 0; int countTotal = 0; const int hueDrift = 30; const int hueB = 180; const int hueG = 130; const int hueR = 15; foreach (var sampleBounds in rectActionElements) { for (int idxY = 0; idxY < sampleBounds.Height; idxY++) { for (int idxX = 0; idxX < sampleBounds.Width; idxX++) { FastPixelHSV testPx = bitmap.GetPixel(bounds.X + sampleBounds.X + idxX, bounds.Y + sampleBounds.Y + idxY); countTotal++; int testMono = testPx.GetMonochrome(); if (testMono < 210) { int testHue = testPx.GetHue(); countElemR += ((testHue > (hueR + 360 - hueDrift)) || (testHue < (hueR + hueDrift))) ? 1 : 0; countElemG += ((testHue > (hueG - hueDrift)) && (testHue < (hueG + hueDrift))) ? 1 : 0; countElemB += ((testHue > (hueB - hueDrift)) && (testHue < (hueB + hueDrift))) ? 1 : 0; } } } } int minThr = countTotal * 30 / 100; if ((countElemR > minThr) && (countElemR > countElemG) && (countElemR > countElemB)) { element = EElementType.Fire; } else if ((countElemG > minThr) && (countElemG > countElemR) && (countElemG > countElemB)) { element = EElementType.Wind; } else if ((countElemB > minThr) && (countElemB > countElemR) && (countElemB > countElemG)) { element = EElementType.Water; } if (element == EElementType.Unknown) { countElemR = 0; countElemG = 0; countElemB = 0; for (int idxY = 0; idxY < bounds.Height; idxY++) { for (int idxX = 0; idxX < bounds.Width; idxX++) { FastPixelHSV testPx = bitmap.GetPixel(bounds.X + idxX, bounds.Y + idxY); int testMono = testPx.GetMonochrome(); if (testMono < 210) { int testHue = testPx.GetHue(); countElemR += ((testHue > (hueR + 360 - hueDrift)) || (testHue < (hueR + hueDrift))) ? 1 : 0; countElemG += ((testHue > (hueG - hueDrift)) && (testHue < (hueG + hueDrift))) ? 1 : 0; countElemB += ((testHue > (hueB - hueDrift)) && (testHue < (hueB + hueDrift))) ? 1 : 0; } } } countTotal = bounds.Width * bounds.Height; minThr = countTotal * 30 / 100; if ((countElemR > minThr) && (countElemR > countElemG) && (countElemR > countElemB)) { element = EElementType.Fire; } else if ((countElemG > minThr) && (countElemG > countElemR) && (countElemG > countElemB)) { element = EElementType.Wind; } else if ((countElemB > minThr) && (countElemB > countElemR) && (countElemB > countElemG)) { element = EElementType.Water; } } if (DebugLevel >= EDebugLevel.Verbose) { Console.WriteLine(">> elem counters: R:{0}, G:{1}, B:{2} => {3}", countElemR, countElemG, countElemB, element); } return(element); }
protected bool HasOkButtonArea(FastBitmapHSV bitmap, ScreenData screenData) { FastPixelHSV[] avgPx = new FastPixelHSV[rectButtonPos.Length]; for (int idx = 1; idx < avgPx.Length; idx++) { avgPx[idx] = ScreenshotUtilities.GetAverageColor(bitmap, rectButtonPos[idx]); var scanOb = new ActionData(); scanOb.buttonColor = matchAvgRed.IsMatching(avgPx[idx]) ? EButtonColor.Red : matchAvgWhite.IsMatching(avgPx[idx]) ? EButtonColor.White : matchAvgSpec.IsMatching(avgPx[idx]) ? EButtonColor.Spec : EButtonColor.Unknown; if (scanOb.buttonColor != EButtonColor.Unknown) { float[] values = ExtractButtonData(bitmap, idx); scanOb.buttonType = (EButtonType)classifierButtons.Calculate(values, out float DummyPct); switch (scanOb.buttonColor) { case EButtonColor.Red: scanOb.isDisabled = avgPx[idx].GetValue() < 40; break; case EButtonColor.White: scanOb.isDisabled = avgPx[idx].GetValue() < 70; break; default: break; } } screenData.actions[idx] = scanOb; } if (screenData.actions[(int)EButtonPos.CombatReportOk].buttonColor == EButtonColor.Red && screenData.actions[(int)EButtonPos.CombatReportOk].buttonType == EButtonType.Ok && screenData.actions[(int)EButtonPos.CombatReportRetry].buttonColor == EButtonColor.White && (screenData.actions[(int)EButtonPos.CombatReportRetry].buttonType == EButtonType.Retry || screenData.actions[(int)EButtonPos.CombatReportRetry].buttonType == EButtonType.Next)) { screenData.mode = EMessageType.CombatReport; } else if (screenData.actions[(int)EButtonPos.CombatStart].buttonColor == EButtonColor.Red && screenData.actions[(int)EButtonPos.CombatStart].buttonType == EButtonType.Start && screenData.actions[(int)EButtonPos.CombatDetails].buttonColor == EButtonColor.Spec && (screenData.actions[(int)EButtonPos.CombatDetails].buttonType == EButtonType.Details)) { screenData.mode = EMessageType.CombatStart; } else if (screenData.actions[(int)EButtonPos.Center].buttonColor == EButtonColor.Red && screenData.actions[(int)EButtonPos.Center].buttonType == EButtonType.Ok) { screenData.mode = EMessageType.Ok; } else if (screenData.actions[(int)EButtonPos.CenterTwoLeft].buttonColor == EButtonColor.White && screenData.actions[(int)EButtonPos.CenterTwoLeft].buttonType == EButtonType.Cancel && screenData.actions[(int)EButtonPos.CenterTwoRight].buttonColor == EButtonColor.Red && screenData.actions[(int)EButtonPos.CenterTwoRight].buttonType == EButtonType.Ok) { screenData.mode = EMessageType.OkCancel; } else if (screenData.actions[(int)EButtonPos.Center].buttonColor == EButtonColor.White && screenData.actions[(int)EButtonPos.Center].buttonType == EButtonType.Close) { screenData.mode = EMessageType.Close; } if (DebugLevel >= EDebugLevel.Simple) { Console.WriteLine("{0} Mode: {1}", ScannerName, screenData.mode); } if (DebugLevel >= EDebugLevel.Verbose) { Console.WriteLine(" filterRed:({0}), filterWhite:({1}), filterSpec({2})", matchAvgRed, matchAvgWhite, matchAvgSpec); for (int idx = 1; idx < avgPx.Length; idx++) { Console.WriteLine(" [{0}]:({1}), color:{2}, class:{3}", (EButtonPos)idx, avgPx[idx], screenData.actions[idx].buttonColor, screenData.actions[idx].buttonType); } } return(screenData.mode != EMessageType.Unknown); }
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) { Console.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) { Console.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) { Console.WriteLine(" >> mark segment:" + segPos); } if (result.Count >= segLimit && segLimit > 0) { break; } } } return(result); }
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) { Console.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) { Console.WriteLine(">> gapSize:" + gapSize + ", gapStart:" + gapStart + ", bPrevMatch:" + bPrevMatch + " => minX:" + minX); } } else { if (bPrevMatch) { gapStart = IdxX; if (bDebugMode) { Console.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) { Console.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) { Console.WriteLine(">> gapSize:" + gapSize + ", gapStart:" + gapStart + ", bPrevMatch:" + bPrevMatch + " => maxX:" + maxX); } } else { if (bPrevMatch) { gapStart = IdxX; if (bDebugMode) { Console.WriteLine(">> gapStart:" + gapStart); } } } bPrevMatch = bHasMatch; } if (maxX > minX) { return(new Point(minX, maxX - minX)); } else { if (bDebugMode) { Console.WriteLine(">> TraceBoundsH: no match on right side!"); } } } else { if (bDebugMode) { Console.WriteLine(">> TraceBoundsH: no match on left side!"); } } return(new Point()); }