// BitmapについてOCRした結果を表示する public static void ShowOcrInfo(Bitmap bitmap) { // シーン判定を行う string scene = SceneRecognition.JudgeGameScene(bitmap); string output = $"シーン判定結果:{scene}\n"; // 資材関係のシーンだった場合、資材量を読み取って表示内容に追記する if (SupplyStore.SupplyListEachScene.ContainsKey(scene)) { output += "読み取った資材量:\n"; foreach (string supplyName in SupplyStore.SupplyListEachScene[scene]) { int supplyValue = CharacterRecognition.GetValueOCR(bitmap, supplyName, SettingsStore.PutCharacterRecognitionFlg); output += $" {supplyName}→{supplyValue}\n"; } } // その他のシーンの場合の処理 switch (scene) { case "戦闘中": { var gauge = SceneRecognition.GetBattleBombGauge(bitmap); output += "読み取ったゲージ量:\n"; output += $" 空撃→{Math.Round(gauge[0] * 100.0, 1)}%\n"; output += $" 雷撃→{Math.Round(gauge[1] * 100.0, 1)}%\n"; output += $" 砲撃→{Math.Round(gauge[2] * 100.0, 1)}%\n"; } break; case "委託": { output += "読み取った秒数:\n"; for (int i = 1; i <= 4; ++i) { long time = CharacterRecognition.GetTimeOCR(bitmap, $"委託{i}", SettingsStore.PutCharacterRecognitionFlg); output += $" {i}つ目→{time}\n"; } } break; case "戦術教室": { output += "読み取った秒数:\n"; for (int i = 1; i <= 2; ++i) { long time = CharacterRecognition.GetTimeOCR(bitmap, $"戦術教室{i}", SettingsStore.PutCharacterRecognitionFlg); output += $" {i}つ目→{time}\n"; } } break; case "寮舎": { output += "読み取った秒数:\n"; long time = CharacterRecognition.GetTimeOCR(bitmap, "食糧", SettingsStore.PutCharacterRecognitionFlg); output += $" 食糧→{time}\n"; } break; } MessageBox.Show(output, Utility.SoftwareName, MessageBoxButton.OK, MessageBoxImage.Information); }
// 戦闘中におけるタイマー調整 public static void SetBattleBombTimer(Bitmap screenShot, ref double[] oldGauge, ref double[] remainTime) { // 読み取ったゲージから、フルチャージに必要な秒数を計算する var gauge = SceneRecognition.GetBattleBombGauge(screenShot); // 各種のゲージ毎に判定を行う for (int ti = 0; ti < SceneRecognition.GaugeTypeCount; ++ti) { if (gauge[ti] >= 0.0) { if (oldGauge[ti] >= 0.0) { // 前回のゲージ量が残っているので、チャージ完了に要する時間が計算できる // ただしゲージが変化していないようにみえる場合は無視する if (gauge[ti] > oldGauge[ti]) { remainTime[ti] = (1.0 - gauge[ti]) / (gauge[ti] - oldGauge[ti]); // switch (ti) { case 0: SettingsStore.BombChageTime1 = DateTime.Now.AddSeconds(remainTime[ti]); break; case 1: SettingsStore.BombChageTime2 = DateTime.Now.AddSeconds(remainTime[ti]); break; case 2: SettingsStore.BombChageTime3 = DateTime.Now.AddSeconds(remainTime[ti]); break; } } else { // 読み取り失敗した祭の処理 if (remainTime[ti] > 0.0) { remainTime[ti] -= 1.0; } } } else { // 読み取り失敗した祭の処理 if (remainTime[ti] > 0.0) { remainTime[ti] -= 1.0; } } // oldGaugeに今回読み取った量を上書きする oldGauge[ti] = gauge[ti]; } else { // 読み取り失敗した祭の処理 if (remainTime[ti] > 0.0) { remainTime[ti] -= 1.0; } oldGauge[ti] = -1.0; } } }
// 時間(秒数)を読み取る(-1=読み取り不可) public static long GetTimeOCR(Bitmap bitmap, string timeType, bool debugFlg = false) { // 対応している時刻名ではない場合は無視する if (!TimeParameters.ContainsKey(timeType)) { return(-1); } var timeParameter = TimeParameters[timeType]; // 時刻に対応した「マーク」が確認できない場合は無視する ulong markHash = SceneRecognition.GetDifferenceHash(bitmap, timeParameter.MarkRect); if (SceneRecognition.GetHummingDistance(markHash, timeParameter.MarkHash) >= 20) { return(-1); } // 画像を必要な部分だけクロップし、同時に認識しやすいサイズまで拡大する var canvas = CropZoomBitmap(bitmap, timeParameter.TimeRect); if (debugFlg) { canvas.Save($"debug\\digit-{timeType}-step1.png"); } // 食糧残時間を勘定する時だけ、緑部分以外を白く塗りつぶす処理を行う if (timeType == "食糧") { for (int y = 0; y < canvas.Height; ++y) { for (int x = 0; x < canvas.Width; ++x) { var color = canvas.GetPixel(x, y); if (SceneRecognition.GetColorDistance(color, Color.FromArgb(172, 246, 74)) >= 500) { canvas.SetPixel(x, y, Color.FromArgb(0, 0, 0)); } } } } // 色の反転処理・二値化処理を行う canvas = BinarizeBitmap(canvas, timeParameter.Threshold, timeParameter.InverseFlg); if (debugFlg) { canvas.Save($"debug\\digit-{timeType}-step3.png"); } // 境界部分を認識させる var splitRectList = GetSplitRectList(canvas); // 各カット毎に数値認識を行う var digit = GetDigit(canvas, splitRectList, templateSource2, debugFlg, timeType); // 結果を数値化する if (digit.Count != 8) { return(-1); } int hour = (digit[0] > 5 ? 0 : digit[0]) * 10 + (digit[1] > 9 ? 0 : digit[1]); int minute = (digit[3] > 5 ? 0 : digit[3]) * 10 + (digit[4] > 9 ? 0 : digit[4]); int second = (digit[6] > 5 ? 0 : digit[6]) * 10 + (digit[7] > 9 ? 0 : digit[7]); if (debugFlg) { Console.WriteLine($"{timeType} {digit[0]}{digit[1]}:{digit[3]}{digit[4]}:{digit[6]}{digit[7]}"); } return((hour * 60 + minute) * 60 + second); }