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); }
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); }
protected void ScanSP(FastBitmapHSV bitmap, ScreenDataBase screenData) { int numMatchFull = 0; int numMatchEmpty = 0; int numChanges = 0; bool wasFull = false; bool wasEmpty = false; int lastPosFull = 0; for (int idx = 0; idx <= rectSPBar.Width; idx++) { var testPx = bitmap.GetPixel(rectSPBar.X + idx, rectSPBar.Y); var isFull = matchSPFull.IsMatching(testPx); var isEmpty = matchSPEmpty.IsMatching(testPx); if (isFull) { lastPosFull = idx; } numChanges += (idx > 0 && isFull != wasFull) ? 1 : 0; numChanges += (idx > 0 && isEmpty != wasEmpty) ? 1 : 0; numMatchFull += isFull ? 1 : 0; numMatchEmpty += isEmpty ? 1 : 0; wasFull = isFull; wasEmpty = isEmpty; } float matchedPct = (numMatchEmpty + numMatchFull) / (float)rectSPBar.Width; screenData.SPIsValid = (matchedPct > 0.75); screenData.SPFillPct = lastPosFull / (float)rectSPBar.Width; screenData.SPIsObstructed = (matchedPct < 0.95); if (DebugLevel >= EDebugLevel.Simple) { Console.WriteLine("{0} HasSP: {1}, isObstructed:{2}, fillPct:{3}", ScannerName, screenData.SPIsValid, screenData.SPIsObstructed, screenData.SPFillPct); } if (DebugLevel >= EDebugLevel.Verbose) { for (int idx = 0; idx < rectSPBar.Width; idx++) { var testPx = bitmap.GetPixel(rectSPBar.X + idx, rectSPBar.Y); Console.WriteLine(" X:{0},Y:{1} = {2} => Full:{3}, Empty:{4}", rectSPBar.X + idx, rectSPBar.Y, testPx, matchSPFull.IsMatching(testPx), matchSPEmpty.IsMatching(testPx)); } Console.WriteLine(" filterFull({0}), filterEmpty({1})", matchSPFull, matchSPEmpty); Console.WriteLine(" numMatchFull: {0}, numMatchEmpty: {1}, matchedPct: {2}, numChanges:{3}", numMatchFull, numMatchEmpty, matchedPct, numChanges); } }
protected bool HasOpenedChatLine(FastBitmapHSV bitmap, out int mode) { mode = 0; for (int posX = 0; posX < bitmap.Width; posX++) { var testPx = bitmap.GetPixel(posX, posChatBackY); bool isMatching = matchChatLineBack.IsMatching(testPx); if (!isMatching) { if (DebugLevel >= EDebugLevel.Verbose) { Console.WriteLine("{0} HasOpenedChatLine: failed match! ({1},{2})=({3}) vs filter({4})", ScannerName, posX, posChatBackY, testPx, matchChatLineBack); } return(false); } testPx = bitmap.GetPixel(posX, posNoChatBackY); isMatching = matchChatLineBack.IsMatching(testPx); if (isMatching) { if (DebugLevel >= EDebugLevel.Verbose) { Console.WriteLine("{0} HasOpenedChatLine: failed no match! ({1},{2})=({3}) vs filter({4})", ScannerName, posX, posNoChatBackY, testPx, matchChatLineBack); } return(false); } } for (int testMode = 1; testMode < posChatLineModeY.Length; testMode++) { var avgPx = ScreenshotUtilities.GetAverageColor(bitmap, new Rectangle(rectChatLine.X, posChatLineModeY[testMode], rectChatLine.Width, rectChatLine.Height)); bool isMatching = matchChatLine.IsMatching(avgPx) && !matchChatLineBack.IsMatching(avgPx); if (!isMatching) { if (DebugLevel >= EDebugLevel.Verbose) { Console.WriteLine("{0} HasOpenedChatLine: failed mode:{1}... ({2}) vs filter({3})", ScannerName, testMode, avgPx, matchChatLine); } } else { mode = testMode; return(true); } } 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); } }
protected bool HasLifeforceMeter(FastBitmapHSV bitmap) { int numMatching = 0; int numChanges = 0; bool wasMatchingR = false; bool wasMatchingG = false; for (int idx = 0; idx < posLifeforceMeter.Length; idx++) { var testPx = bitmap.GetPixel(posLifeforceMeter[idx].X, posLifeforceMeter[idx].Y); var isMatchingR = matchLifeforceR.IsMatching(testPx); var isMatchingG = isMatchingR ? false : matchLifeforceG.IsMatching(testPx); numChanges += (idx > 0 && isMatchingR != wasMatchingR) ? 1 : 0; numChanges += (idx > 0 && isMatchingG != wasMatchingG) ? 1 : 0; numMatching += (isMatchingR || isMatchingG) ? 1 : 0; wasMatchingR = isMatchingR; wasMatchingG = isMatchingG; } bool hasMatch = (numMatching >= 5) && (numChanges < 4); if (DebugLevel >= EDebugLevel.Simple) { Console.WriteLine("{0} HasLifeforceMeter: {1}", ScannerName, hasMatch); } if (DebugLevel >= EDebugLevel.Verbose) { string debugDesc = " "; for (int idx = 0; idx < posLifeforceMeter.Length; idx++) { var testPx = bitmap.GetPixel(posLifeforceMeter[idx].X, posLifeforceMeter[idx].Y); if (idx > 0) { debugDesc += ", "; } debugDesc += "(" + testPx + ")"; } Console.WriteLine(debugDesc); Console.WriteLine(" filterGreen({0}), filterRed({1})", matchLifeforceG, matchLifeforceR); Console.WriteLine(" numMatching: {0}, numChanges: {1}", numMatching, numChanges); } return(hasMatch); }
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); }
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 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); }
protected void ScanPauseButton(FastBitmapHSV bitmap, ScreenData screenData) { var testPx1 = bitmap.GetPixel(posPauseI[0].X, posPauseI[0].Y); var testPx2 = bitmap.GetPixel(posPauseI[1].X, posPauseI[1].Y); screenData.isActive = matchPause.IsMatching(testPx1) && matchPause.IsMatching(testPx2); if (DebugLevel >= EDebugLevel.Simple) { Console.WriteLine("{0} ScanPauseButton: active:{1}", ScannerName, screenData.isActive); } if (DebugLevel >= EDebugLevel.Verbose) { Console.WriteLine(">> px1:({0}), px2:({1}) vs ({2})", testPx1, testPx2, matchPause); } }
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); } }
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 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); } } }
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 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 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); } }
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); }
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); }
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); }
protected bool HasTimerMarkers(FastBitmapHSV bitmap) { foreach (var pos in posLabelI) { var isMatching = matchLabelI.IsMatching(bitmap.GetPixel(pos.X, pos.Y)); if (!isMatching) { if (DebugLevel >= EDebugLevel.Verbose) { Console.WriteLine("{0} HasTimerMarkers: failed LabelI => ({1},{2}) = ({3}) vs ({4})", ScannerName, pos.X, pos.Y, bitmap.GetPixel(pos.X, pos.Y), matchLabelI); } return(false); } } foreach (var pos in posLabelO) { var isMatching = matchLabelO.IsMatching(bitmap.GetPixel(pos.X, pos.Y)); if (!isMatching) { if (DebugLevel >= EDebugLevel.Verbose) { Console.WriteLine("{0} HasTimerMarkers: failed LabelO => ({1},{2}) = ({3}) vs ({4})", ScannerName, pos.X, pos.Y, bitmap.GetPixel(pos.X, pos.Y), matchLabelO); } return(false); } } foreach (var pos in posTimeI) { var isMatching = matchTimerI.IsMatching(bitmap.GetPixel(pos.X, pos.Y)); if (!isMatching) { if (DebugLevel >= EDebugLevel.Verbose) { Console.WriteLine("{0} HasTimerMarkers: failed TimerI => ({1},{2}) = ({3}) vs ({4})", ScannerName, pos.X, pos.Y, bitmap.GetPixel(pos.X, pos.Y), matchTimerI); } return(false); } } foreach (var pos in posTimeO) { var isMatching = matchTimerO.IsMatching(bitmap.GetPixel(pos.X, pos.Y)); if (!isMatching) { if (DebugLevel >= EDebugLevel.Verbose) { Console.WriteLine("{0} HasTimerMarkers: failed TimerO => ({1},{2}) = ({3}) vs ({4})", ScannerName, pos.X, pos.Y, bitmap.GetPixel(pos.X, pos.Y), matchTimerO); } return(false); } } return(true); }
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); }
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 HasPurifyPlate(FastBitmapHSV bitmap) { var hasMatch = true; for (int idx = 0; idx < posPurifyPlateI.Length; idx++) { var testPx = bitmap.GetPixel(posPurifyPlateI[idx].X, posPurifyPlateI[idx].Y); var isMatch = matchPlateShiny.IsMatching(testPx); if (!isMatch) { hasMatch = false; break; } } for (int idx = 0; idx < posPurifyPlateO.Length; idx++) { var testPx = bitmap.GetPixel(posPurifyPlateO[idx].X, posPurifyPlateO[idx].Y); var isMatch = matchPlateBack.IsMatching(testPx); if (!isMatch) { hasMatch = false; break; } } var rectSample0 = bitmap.GetPixel(rectPurifyPlate.X, rectPurifyPlate.Y); int maxHDiff = 0; int maxMDiff = 0; for (int idx = 1; idx < rectPurifyPlate.Width; idx++) { var testPx = bitmap.GetPixel(rectPurifyPlate.X + idx, rectPurifyPlate.Y); int hDiff = Math.Abs(testPx.GetHue() - rectSample0.GetHue()); int mDiff = Math.Abs(testPx.GetMonochrome() - rectSample0.GetMonochrome()); if (maxHDiff < hDiff) { maxHDiff = hDiff; } if (maxMDiff < mDiff) { maxMDiff = mDiff; } } if (maxHDiff > 35 || maxMDiff > 25) { hasMatch = false; } if (DebugLevel >= EDebugLevel.Simple) { Console.WriteLine("{0} HasPurifyPlate: {1}", ScannerName, hasMatch); } if (DebugLevel >= EDebugLevel.Verbose) { string debugDesc = " in: "; for (int idx = 0; idx < posPurifyPlateI.Length; idx++) { var testPx = bitmap.GetPixel(posPurifyPlateI[idx].X, posPurifyPlateI[idx].Y); if (idx > 0) { debugDesc += ", "; } debugDesc += "(" + testPx + ")"; } Console.WriteLine(debugDesc); debugDesc = " out: "; for (int idx = 0; idx < posPurifyPlateO.Length; idx++) { var testPx = bitmap.GetPixel(posPurifyPlateO[idx].X, posPurifyPlateO[idx].Y); if (idx > 0) { debugDesc += ", "; } debugDesc += "(" + testPx + ")"; } Console.WriteLine(debugDesc); Console.WriteLine(" filterIn({0}), filterOut({1})", matchPlateShiny, matchPlateBack); Console.WriteLine(" maxHDiff:{0}, maxMDiff:{1}", maxHDiff, maxMDiff); } return(hasMatch); }
public float[] ExtractActionSlotData(FastBitmapHSV bitmap, int slotIdx) { // scan area: 48x64, downsample to 16x16 float[] values = new float[16 * 16]; for (int idx = 0; idx < values.Length; idx++) { values[idx] = 0.0f; } Point slotPos = posActionSlots[slotIdx]; const float scaleV = 1.0f / 12; bool shouldMirror = slotIdx < 4; if (shouldMirror) { for (int idxY = 0; idxY < 64; idxY++) { for (int idxX = 0; idxX < 48; idxX++) { values[(idxX / 3) + ((idxY / 4) * 16)] += GetActionSlotPixelValue(bitmap.GetPixel(slotPos.X + 47 - idxX, slotPos.Y + idxY)) * scaleV; } } } else { for (int idxY = 0; idxY < 64; idxY++) { for (int idxX = 0; idxX < 48; idxX++) { values[(idxX / 3) + ((idxY / 4) * 16)] += GetActionSlotPixelValue(bitmap.GetPixel(slotPos.X + idxX, slotPos.Y + idxY)) * scaleV; } } } return(values); }
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 HasLogoMarkers(FastBitmapHSV bitmap) { foreach (var pos in posLogoWhite) { var isMatching = matchLogoWhite.IsMatching(bitmap.GetPixel(pos.X, pos.Y)); if (!isMatching) { if (DebugLevel >= EDebugLevel.Verbose) { Console.WriteLine("{0} HasLogoMarkers: failed WHITE => ({1},{2}) = ({3}) vs ({4})", ScannerName, pos.X, pos.Y, bitmap.GetPixel(pos.X, pos.Y), matchLogoWhite); } return(false); } } foreach (var pos in posLogoBlack) { var isMatching = matchLogoBlack.IsMatching(bitmap.GetPixel(pos.X, pos.Y)); if (!isMatching) { if (DebugLevel >= EDebugLevel.Verbose) { Console.WriteLine("{0} HasLogoMarkers: failed BLACK => ({1},{2}) = ({3}) vs ({4})", ScannerName, pos.X, pos.Y, bitmap.GetPixel(pos.X, pos.Y), matchLogoBlack); } return(false); } } foreach (var pos in posLogoBlue) { var isMatching = matchLogoBlue.IsMatching(bitmap.GetPixel(pos.X, pos.Y)); if (!isMatching) { if (DebugLevel >= EDebugLevel.Verbose) { Console.WriteLine("{0} HasLogoMarkers: failed BLUE => ({1},{2}) = ({3}) vs ({4})", ScannerName, pos.X, pos.Y, bitmap.GetPixel(pos.X, pos.Y), matchLogoBlue); } return(false); } } foreach (var pos in posLogoRed) { var isMatching = matchLogoRed.IsMatching(bitmap.GetPixel(pos.X, pos.Y)); if (!isMatching) { if (DebugLevel >= EDebugLevel.Verbose) { Console.WriteLine("{0} HasLogoMarkers: failed RED => ({1},{2}) = ({3}) vs ({4})", ScannerName, pos.X, pos.Y, bitmap.GetPixel(pos.X, pos.Y), matchLogoRed); } return(false); } } return(true); }