/// <summary> /// スクリーンショットを撮影し、最も近い選択肢画面を返す /// </summary> /// <returns> /// 閾値より距離の小さい選択肢画面が見つかった場合、その <see cref="SelectionInfo"/> と、距離を返します。 /// 見つからなかった場合、 null と、見つかった中での最短距離を返します。 /// </returns> private async Task <(SelectionInfo, int)> GetMostSimilarSelectionAsync() { // ハミング距離の閾値 // 各々の最短距離より十分に小さいので、距離がこれ以下のものがあれば、それを返す const int threshold = 10; var arrayPool = ArrayPool <byte> .Shared; var hashArray = arrayPool.Rent(32); var hash = new ArraySegment <byte>(hashArray, 0, 32); var minDistance = int.MaxValue; try { using (var screenshot = await this._wagahighOperator.CaptureContentAsync().ConfigureAwait(false)) { Blockhash.ComputeHash(new Bgr2432InputImage(screenshot), hash); } foreach (var si in SelectionInfo.Selections) { var distance = Blockhash.GetDistance(hash, si.ScreenshotHash); if (distance <= threshold) { return(si, distance); } if (distance < minDistance) { minDistance = distance; } } } finally { arrayPool.Return(hashArray); } return(null, minDistance); }
private int OnExecute() { var hashLength = this.Bits * this.Bits / 8; var inputLength = this.InputFiles.Length; var results = new byte[hashLength * inputLength]; // 順番にハッシュを計算 var successAll = true; for (var i = 0; i < this.InputFiles.Length; i++) { try { var span = new Span <byte>(results, hashLength * i, hashLength); using (var image = Image.Load(this.InputFiles[i])) { Blockhash.ComputeHash(new Rgba32InputImage(image), span, this.Bits); } Console.WriteLine("{0}: {1}", i, ToHashString(span)); } catch (Exception ex) { if (Debugger.IsAttached) { Debugger.Break(); } Console.Error.WriteLine("{0}: {1}", i, ex); successAll = false; } } if (!successAll) { return(1); } // 最短距離を計算 if (inputLength > 1) { var minDistance = int.MaxValue; for (var i = 0; i < inputLength; i++) { for (var j = 0; j < inputLength; j++) { if (i == j) { continue; } var bs1 = new ArraySegment <byte>(results, hashLength * i, hashLength); var bs2 = new ArraySegment <byte>(results, hashLength * j, hashLength); var distance = Blockhash.GetDistance(bs1, bs2); if (distance < minDistance) { minDistance = distance; } } } Console.WriteLine("Min Distance: {0}", minDistance); } return(0); }