Upgrade to Pro — share decks privately, control downloads, hide ads and more …

OCRを使ってゲームのアイテムをデータ化する

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

 OCRを使ってゲームのアイテムをデータ化する

プロトタイプを製品にする技術
OCRを使ってゲームのアイテムをデータ化する

Avatar for Kishikawa Katsumi

Kishikawa Katsumi

May 22, 2026

More Decks by Kishikawa Katsumi

Other Decks in Programming

Transcript

  1. 4UFQ3BX0$3 actor OCRRunner { private var busy = false func

    process(_ cgImage: CGImage) async -> [RecognizedTextObservation]? { guard !busy else { return nil } busy = true defer { busy = false } var request = RecognizeTextRequest() request.recognitionLanguages = [ Locale.Language(identifier: "ja-JP"), Locale.Language(identifier: "en-US"), ] request.recognitionLevel = .accurate request.usesLanguageCorrection = false return try? await request.perform(on: cgImage) } }
  2. let windowSize: Int = 5 let minHits: Int = 3

    func updateStability(with results: [RecognizedTextObservation]) { let textsThisFrame = Set( results.compactMap { (observation) -> String? in let raw = observation.topCandidates(1).first?.string ?? "" let t = raw.trimmingCharacters(in: .whitespacesAndNewlines) return t.isEmpty ? nil : t } ) recentTextSets.append(textsThisFrame) if recentTextSets.count > windowSize { recentTextSets.removeFirst(recentTextSets.count - windowSize) } var counts: [String: Int] = [:] for set in recentTextSets { for t in set { counts[t, default: 0] += 1 } } let stable = counts.filter { $0.value >= minHits } stableTexts = Set(stable.keys) stableLines = stable .map { StableLine(text: $0.key, hits: $0.value) } .sorted { $0.hits == $1.hits ? $0.text < $1.text : $0.hits > $1.hits } } ϑϨʔϜ಺ͰճҎ্ग़ݱͨ͠ ςΩετΛ࠾༻͢Δɻ
  3. Ԍ߈ܸྗ্ঢ Ԍ߈ܸྗ্ঢ ཕ߈ܸྗ্ঢ Ԍ߈ܸྗ্ঢ ཕ߈ܸྗ্ঢ ग़ܸ࣌ͷ෢ثʹ ੟߈ܸྗΛ෇Ճ ग़ܸ࣌ͷ෢ثʹ ੟߈ܸྗΛ෇Ճ ग़ܸ࣌ͷ෢ثʹ

    ཕ߈ܸྗΛ෇Ճ ग़ܸ࣌ͷ෢ثʹ ཕ߈ܸྗΛ෇Ճ ग़ܸ࣌ͷ෢ثʹ ཕ߈ܸྗΛ෇Ճ ϦϯάόοϑΝʹΑΔ҆ఆੑͷ޲্ /ϑϨʔϜத.ճҎ্ग़ͨςΩετΛ࠾༻͢Δ
  4. Ԍ߈ܸྗ্ঢ Ԍ߈ܸྗ্ঢ ཕ߈ܸྗ্ঢ Ԍ߈ܸྗ্ঢ ཕ߈ܸྗ্ঢ ग़ܸ࣌ͷ෢ثʹ ੟߈ܸྗΛ෇Ճ ग़ܸ࣌ͷ෢ثʹ ੟߈ܸྗΛ෇Ճ ग़ܸ࣌ͷ෢ثʹ

    ཕ߈ܸྗΛ෇Ճ ग़ܸ࣌ͷ෢ثʹ ཕ߈ܸྗΛ෇Ճ ग़ܸ࣌ͷ෢ثʹ ཕ߈ܸྗΛ෇Ճ ϦϯάόοϑΝʹΑΔ҆ఆੑͷ޲্ /ϑϨʔϜத.ճҎ্ग़ͨςΩετΛ࠾༻͢Δ
  5. static let roiOnScreen = CGRect(x: 0.08, y: 0.30, width: 0.84,

    height: 0.32) static let visionROI: NormalizedRect = { let r = roiOnScreen return NormalizedRect(x: r.minX, y: 1 - r.maxY, width: r.width, height: r.height) }() func process( _ cgImage: CGImage, roi: NormalizedRect ) async -> [RecognizedTextObservation]? { ... request.regionOfInterest = roi ... } 6*ͷ࠲ඪͷ7JTJPOGSBNFXPSLͷ ࠲ඪʹม׵ͯ͠ηοτ ΨΠυ࿮ͷൣғ͚ͩಡΈऔΔ ؔ܎ͳ͍ςΩετΛಡ·ͳ͍ɾ଎౓޲্
  6. func bestMatch(for input: String) -> (master: Master, distance: Int)? {

    let n = normalize(input) var best: (Master, Int)? for (key, master) in normalizedKeys { if abs(key.count - n.count) > 5 { continue } let d = levenshtein(n, key) if best == nil || d < best!.1 { best = (master, d) } } return best } // डཧ: ڑ཭ ≤ max(1, |master| × 0.3) ≒ score ≥ 0.70 let threshold = max(1, Int(Double(master.textJa.count) * 0.3)) guard match.distance <= threshold else { return nil } ฤूڑ཭ -FWFOTIUFJO%JTUBODF ͰҰக౓Λ൑ఆ Ϛελʔσʔλͱর߹
  7. ΞϧΰϦζϜ )BNNJOHڑ཭ ܭࢉྔ଎౓ͱ࢓૊Έ ࠷଎ 903 QPQDPVOU ɻಉ͡௕͞ͷจࣈྻͰʮҟͳΔҐஔͷ਺ʯΛ਺͑Δ ࠾༻͠ͳ͔ͬͨཧ༝ 0$3ͷจࣈ௕͸GSBNF͝ͱʹ༳ΕΔͨΊద༻ෆՄɻจࣈͰ΋௕͕͞ҧ͏ͱ࢖͑ͳ͍ ΞϧΰϦζϜ

    OHSBN+BDDBSEྨࣅ౓ ܭࢉྔ଎౓ͱ࢓૊Έ ଎͍ ू߹ԋࢉ ɻจࣈ/HSBNू߹Λ࡞Γc"ˬ#cc"˫#cΛܭࢉ ࠾༻͠ͳ͔ͬͨཧ༝ จࣈॱংΛࣺͯΔͨΊʮ߈ܸྗ্ঢʯͱʮ্ঢ߈ܸྗʯΛ۠ผͰ͖ͳ͍ ΞϧΰϦζϜ %BNFSBV-FWFOTIUFJO ܭࢉྔ଎౓ͱ࢓૊Έ -FWFOTIUFJOͱ΄΅ಉ౳ Θ͔ͣʹ஗͍ ɻ-FWFOTIUFJO ྡ઀จࣈͷೖΕସ͑ΛίετͰڐ༰ ࠾༻͠ͳ͔ͬͨཧ༝ 0$3Ͱ͸USBOTQPTJUJPOΑΓ७ਮͳஔ׵ޡΓ͕େ൒ͰɺԸܙ͕ബ͍ ΞϧΰϦζϜ +BSP8JOLMFS ܭࢉྔ଎౓ͱ࢓૊Έ -FWFOTIUFJOΑΓఆ਺͕খ͍͞ɻҰகจࣈ਺ USBOTQPTJUJPO ڞ௨QSF fi YՃ఺Ͱྨࣅ౓Λग़͢ ࠾༻͠ͳ͔ͬͨཧ༝ ୹͍ਓ໊ɾॅॴ޲͚ʹ࠷దԽ͞Εͨؔ਺ͰɺʙจࣈͷFGGFDUจͰ͸-FWFOTIUFJOͱͷ͕ࠩग़ʹ͍͘ ͦͷଞͷর߹ΞϧΰϦζϜ
  8. ͦͷଞͷর߹ΞϧΰϦζϜ ΞϧΰϦζϜ 4ZN4QFMM ܭࢉྔ଎౓ͱ࢓૊Έ ࣄલܭࢉͰ࣮࣭0  MPPLVQɻNBTUFSΛʮFEJU≤Lͷશมܗʯʹల։ͨࣙ͠ॻΛQSFCVJME͠ɺೖྗ΋ల։ͯ͠IBTIিಥΛݕग़ ࠾༻͠ͳ͔ͬͨཧ༝ ڑ཭≤·Ͱ͔͠Ҿ͚ͣ௕͞มಈʹऑ͍ɻࣙॻల։Ͱ0 -

    ͷϝϞϦ๲ு͕͋Γɺ݅ن໛Ͱ͸Ըܙ͕๡͍͠ ΞϧΰϦζϜ #,USFF ܭࢉྔ଎౓ͱ࢓૊Έ ฏۉ0 MPH/ ఔ౓ͷۙ๣୳ࡧɻจࣈྻۭؒʹNFUSJDUSFFΛߏங͠ɺڑ཭EҎ಺ͷ΋ͷΛ໦ͰߜΔ ࠾༻͠ͳ͔ͬͨཧ༝ ಺෦Ͱ݁ہ-FWFOTIUFJOΛݺͿɻ݅ن໛Ͱ͸ΠϯσοΫεߏஙίετ͕ԸܙΛ্ճΔ ΞϧΰϦζϜ 4PVOEFY.FUBQIPOF ԻӆIBTI ܭࢉྔ଎౓ͱ࢓૊Έ ଎͍ ఆ਺࣌ؒ ɻൃԻྨࣅੑͰಉ஋ΫϥεΛ࡞ΓɺϋογϡҰகͰൺֱ ࠾༻͠ͳ͔ͬͨཧ༝ ӳޠԻӆ޲͚ͷࢉ๏Ͱ͋Γɺ೔ຊޠ$+,ʹ͸ద༻Ͱ͖ͳ͍ ΞϧΰϦζϜ จ຺ϞσϧຒΊࠐΈڑ཭ #&35౳ ܭࢉྔ଎౓ͱ࢓૊Έ େ෯ʹ஗͍ ਺ेNTΫΤϦ ɻจࣈྻΛߴ࣍ݩϕΫτϧʹຒΊࠐΈɺDPTJOFڑ཭Ͱྨࣅ౓Λܭࢉ ࠾༻͠ͳ͔ͬͨཧ༝ ϦΞϧλΠϜಈըʹ͸ॏ͗͢ΔɻϞσϧ͕NBTUFSͷEPNBJOޠኮɺಛʹήʔϜ଄ޠΛ஌Βͳ͍
  9. ·ͱΊ r Ϛελʔσʔλʢਖ਼ղͷఆٛʣΛ੔͑Δ r ϑϨʔϜ୯ҐͰޡೝࣝΛϑΟϧλʔ͢Δ ‣ .VMUJGSBNF$POTFOTVT r ࣄલʹೖྗΛΫϦʔϯʹ͢Δ ‣

    ςΩετͷਖ਼نԽ ‣ Α͋͘ΔޡೝࣝΛஔ׵ r ڍಈΛܾఆ࿦తɾ؍ଌՄೳʹ͢Δ ߴ͍඼࣭Ͱ࠶ݱੑͷ͋Δ݁ՌΛग़ྗ͢ΔͨΊͷ޻෉