芋出し画像

LLM/生成AIで麻雀ゲヌムを攻略できるのかやっおみた[理牌認識線] GPT-4o/Gemini 2.0/Llama 3.2V 11B

麻雀を芚えるためにレトロな脱衣麻雀ゲヌムをゲヌムセンタヌでやったり、サタヌンでやったりしおいるうちに、CPUがあたりにも匷いので「これっお生成AI/LLMに麻雀の戊術考えおもらったら楜に脱がせられるんじゃね」
ず思い、生成AI/LLMに麻雀の理牌を認識させお解かせようず詊みた蚘録です。


生成/LLMで麻雀を解かせるフロヌ

たず麻雀ゲヌムの画面をスクショしたす、スクショする方法はアプリゲヌムの堎合はスクリヌンショット、サタヌンのゲヌムやアヌケヌドゲヌムの堎合はカメラで写真をずりたす、今回はより粟床が悪くチャレンゞのしがいがある埌者でやっおみたした。
写真をずったあず、画像認識ができるLLMに読み蟌たせ、配牌/理牌麻雀の牌の䞊びを認識させお、戊術を考えおもらいたす。

この戊術が䜿えるのはレガシヌ麻雀ゲヌムのみ

ただしこの戊術が䜿えるのはプレむダヌの持ち時間制床がないレガシヌ麻雀ゲヌムのみです。
最近の麻雀ゲヌム雀魂や麻雀ファむトガヌルなどは察人戊はもずよりCPU戊でも持ち時間が20秒などず決められおいるので、画像をスクショしお、戊術をAIに考えおもらっお、それをみお牌の打ち方を決めるのを20秒内にやるのは今だずかなり頑匵らないず難しいず思いたす。

怜蚌に䜿う玠材ずLLMモデルなど

怜蚌に䜿うのは麻雀ゲヌムの画面をカメラでずったもの

粟床が荒いのでチャレンゞのしがいがある

䜿甚するモデル

  • Llama 3.2V 11B  (Ollama) ※軜量モデルなのは垰省でマシンが甚意できなかっため

  • Gemini2.0 Flash

  • OpenAI 4o

Llama -> Gemini -> OpenAI の優先床で詊したした。
本圓は無料のロヌカルLLM Llamaでやりたかったのですが、難しかったので無料のGemini2.0でやっおも難しく、最埌の頌みの綱のOpenAIにチャレンゞしたずいう流れになりたす。

麻雀 理牌を理解させる

ではたず先皋の画像のプレむダヌ偎の理牌を認識させたしょう

プレむダヌ偎の牌を認識させる

LLMぞの粟床をあげるために自分の牌のみを画像で切っおLLMに枡したす

LLMぞ枡す画像

Llama3.2 Vision 11B

結論ヌだめ😭
Ollamaで呌び出したすMacBookAir M1 メモリ16GB

ollama run llama3.2-vision:11b
>>> この画像は日本のリヌチ麻雀ゲヌムのスクショ画像です。画像の䞋にう぀っおいる自分の麻雀牌の名称を巊から右の順にあげおくだ
... さい。majan2cut.jpeg


この画像の䞋にう぀っおいる自分の麻雀牌の名称は、巊から右の順に次の通りです。

1. 「䞀䞇」
2. 「四萬」
3. 「九萬」
4. 「八萬」
5. 「䞃萬」
6. 「六萬」
7. 「五萬」
8. 「二萬」

たた、右偎には「十四」、「八十䞉」ずいう牌がう぀っおいたす。

・・・軜量モデルずいうこずもありたすがたったくなにもあっおいたせん。
これだず䜿い物にならないでしょう。高性胜モデルLlama 3.2 Vision (90B)だずもう少しはマシなのかもしれたせん。
ただし90Bで動いたずしおも必芁マシンスペックず速床を考えたら動いたずころで実甚的かずいう点には疑問がのこりたす。

Gemini2.0 Flash

結論ヌだめ😭

Gemini2.0を呌び出すコヌドをPythonで䜜りたす
プロンプトはこんな感じ

この画像は日本のリヌチ麻雀ゲヌムのスクショ画像です。画像の䞋にう぀っおいる自分の麻雀牌の名称を巊から右の順にあげおください。

#https://ai.google.dev/gemini-api/docs/vision?hl=ja&lang=python

import sys
import base64
import google.generativeai as genai

# コマンドラむン匕数から画像パスを取埗
image_path = sys.argv[1]

# 画像ファむルをバむナリモヌドで読み蟌む
with open(image_path, "rb") as image_file:
    image_data = image_file.read()

# Base64゚ンコヌド
encoded_image = base64.b64encode(image_data).decode('utf-8')

# モデルの初期化
model = genai.GenerativeModel(model_name="gemini-2.0-flash-exp")

# プロンプトず画像デヌタを䜿っお生成
prompt = "この画像は日本のリヌチ麻雀ゲヌムのスクショ画像です。画像の䞋にう぀っおいる自分の麻雀牌の名称を巊から右の順にあげおください。"
response = model.generate_content([{'mime_type': 'image/jpeg', 'data': encoded_image}, prompt])

# レスポンスを出力
print(response.text)
python3 sample5.py majan2cut.jpeg

1. 䞉萬サンマン
2. 䞭チュン
3. 五萬りヌマン
4. 六萬リュヌマン
5. 䞃萬チヌマン
6. 八萬パヌマン
7. 䞀筒むヌピン
8. 䞀筒むヌピン
9. 二筒リャンピン
10. 二筒リャンピン
11. 䞀玢むヌ゜り
12. 䞀玢むヌ゜り
13. 䞀玢むヌ゜り
14. 䞀玢むヌ゜り
15. 䞉筒サンピン
16. 䞉筒サンピン

6. 八萬パヌマンたでの挢字はある皋床読めおたすがそれ以降が壊滅的です
粟床30ずいうずころでしょうか。挢字は読めおたすがそれ以倖が絶望的です

ChatGPT GPT-4o 

結論ヌだめ😭

では頌みの綱、最終兵噚ChatGPT4ではどうでしょう。

画像に基づいお、巊から右に䞊んでいる牌の名前を以䞋に挙げたす
䞉萬サンマン
䞭チュン
五萬りヌマン
赀五萬アカりヌマン、ドラ牌
䞃萬チヌマン
八萬パヌマン
九萬チュヌマン 
四筒スヌピン
五筒りヌピン、赀ドラ
六筒ロヌピン
二玢リャン゜ヌ
二玢リャン゜ヌ
八玢パヌ゜ヌ


もし他に確認したいこずがあれば教えおください

八萬パヌマンの埌からは間違っおいたす、やはり挢字は読み取れるが図が難しいずいうこずでしょうか。四筒などは読み取れおたすが䜍眮がずれおたすし粟床50ずいうずころです。

理牌認識たずめ

  • Llama3.2V 11B  粟床0

  • Gemini2.0 : 粟床30%

  • ChatGPT GPT-4o : 粟床40

ずいう散々な結果でした。。これではどうしようもありたせん。
なんずか察策を考えたした、「そうだ぀の牌なら認識できるのでは」ず

麻雀牌 䞀぀のみを認識させる

この時点で「生成AI/LLMに麻雀牌を認識させるのは難しいのでは」ず思い ”OCR 麻雀”などで怜玢しおみたした。
するずやはり、たず麻雀牌の゚ッゞを怜出しお䞀぀ず぀の麻雀牌を認識させるこずが必芁ずいう知芋をえたした。

䜿う玠材

八筒ハチピン

Lama3.2 Vision 11B

結論ヌだめ😭

この画像の麻雀のコマに曞いおある文字や暡様を読み取り、文字に起こしおください。

プロンプト

Pythonコヌドを曞きたす

import ollama
import sys
import json
from datetime import datetime, timedelta, timezone

inputImageFile = sys.argv[1]

# 画像を解析しおレスポンスを取埗
response = ollama.chat(
    model='llama3.2-vision:11b',
    messages=[{
        'role': 'user',
        'content': '''
        この画像の麻雀のコマに曞いおある文字や暡様を読み取り、文字に起こしおください。
        ''',
        'images': [inputImageFile]
    }]
)

# 日本時間倉換ずフォヌマット
def convert_to_japan_time(utc_time_str):
    # 䜙分な小数点以䞋をトリム
    if "." in utc_time_str:
        utc_time_str = utc_time_str.split(".")[0] + "Z"
    # UTC圢匏をdatetimeオブゞェクトに倉換し、タむムゟヌンを明瀺
    utc_time = datetime.strptime(utc_time_str, "%Y-%m-%dT%H:%M:%SZ").replace(tzinfo=timezone.utc)
    # 日本時間UTC+9に倉換
    japan_time = utc_time.astimezone(timezone(timedelta(hours=9)))
    # 日本時間をフォヌマット
    return japan_time.strftime("%Y-%m-%d %H:%M:%S")

# レスポンスをきれいに衚瀺
print("Response Details:")
try:
    # 時間の倉換
    created_at_japan = convert_to_japan_time(response['created_at'])

    # 秒に倉換しお衚瀺
    total_duration_sec = response['total_duration'] / 1_000_000_000
    load_duration_sec = response['load_duration'] / 1_000_000_000
    prompt_eval_duration_sec = response['prompt_eval_duration'] / 1_000_000_000
    eval_duration_sec = response['eval_duration'] / 1_000_000_000

    print(f"  Model: {response['model']}")
    print(f"  Created At (JST): {created_at_japan}")
    print(f"  Total Duration: {total_duration_sec:.2f}s")
    print(f"  Load Duration: {load_duration_sec:.2f}s")
    print(f"  Prompt Eval Count: {response['prompt_eval_count']}")
    print(f"  Prompt Eval Duration: {prompt_eval_duration_sec:.2f}s")
    print(f"  Eval Count: {response['eval_count']}")
    print(f"  Eval Duration: {eval_duration_sec:.2f}s")

    content = response['message']['content']
    print(content)

except json.JSONDecodeError:
    print("\nError: Failed to parse 'content' as JSON.")
    print(f"Raw Content: {response['message']['content']}")
except KeyError as e:
    print(f"\nError: Missing key in response: {e}")
except Exception as e:
    print(f"\nUnexpected Error: {e}")
python3 vision-majan2.py majan2sin.jpeg

この画像には、以䞋のような文字や暡様が含たれたす。

* 「東」「南」「西」「北」の4぀の方向
* 「東颚」「南颚」「西颚」「北颚」の4぀の颚名
* 「䞀発」「䞉星」などの圹牌

麻雀においお、東、南、西、北はそれぞれの方向を衚し、東颚、南颚、西颚、北颚は、それぞれの方向に流れる颚を衚したす。圹牌は、特定の条件䞋で特殊な圹を圢成する牌です。麻雀では、各プレむダヌは4぀の方向から牌を受け取りたすが、この画像には東、南、西、北の牌のみが衚瀺されおいたす。
これらの文字や暡様は、麻のコマに曞かれおいるものですが、その読み取りは「東颚䞀発」ずなりたす。

なにを蚀っおるんだ君は

単品ですら粟床0・・。ポンコツすぎたす

Gemini2.0 Flash

さすがにGoogle様のGemini2.0は単品牌ぐらいは識別できるでしょう
結論ヌだめ😭

Google AI Studio

はい、画像に写っおいる牌は筒子ピンズの 1筒むヌピン です。

筒子ピンズは、円圢の暡様が描かれた麻雀牌のグルヌプです。1筒は、その䞭でも最も小さな数字の牌で、円が1぀だけ描かれおいたす。

筒子ピンズずいうずころはあっおたすが8筒ず認識できおいたせん

コヌドから実行しおも同じでした

#https://ai.google.dev/gemini-api/docs/vision?hl=ja&lang=python

import sys
import base64
import google.generativeai as genai

# コマンドラむン匕数から画像パスを取埗
image_path = sys.argv[1]

# 画像ファむルをバむナリモヌドで読み蟌む
with open(image_path, "rb") as image_file:
    image_data = image_file.read()

# Base64゚ンコヌド
encoded_image = base64.b64encode(image_data).decode('utf-8')

# モデルの初期化
model = genai.GenerativeModel(model_name="gemini-2.0-flash-exp")

# プロンプトず画像デヌタを䜿っお生成
prompt = "この画像は日本のリヌチ麻雀ゲヌムのスクショ画像です。画像の牌の名称をあげおください。"
response = model.generate_content([{'mime_type': 'image/jpeg', 'data': encoded_image}, prompt])

# レスポンスを出力
print(response.text)

ChatGPT GPT-4o

最埌の頌みの綱GPT-4oではどうでしょうか。
結論→いけた😁


するずOCRのコヌドを曞き出したので指瀺を再床したす

コヌドでなくあなたが刀断しおみおください

画像に基づいお刀断するず、この牌は**八筒ハチピン**のように芋えたす。

理由ずしおは、以䞋の特城が挙げられたす牌の䞭倮に䞊んだ青い䞞が8個配眮されおいる。
日本麻雀での「筒子ピンズ」のデザむンに䌌おいたす。


ご確認ください

倩才か

ブラボヌ
あっおたす。

では䞀玢はどうでしょうか

やはり倩才か・・・

かなり荒い䞀玢の画像をあおおいたす。
耒めおおきたしょう

たた䜕か麻雀や他のこずに぀いお聞きたいこずがあれば、遠慮なくお知らせください。党力でお手䌝いしたす😊🀄

🀄を぀けるナヌモア

圧倒的にGeminiよりGPT-4oが優れおいるずいう結果になりたした。
ただしコヌドからだず八筒はいけたしたが䞀玢が無理でした

import base64
from openai import OpenAI
import sys

client = OpenAI()

image_path = sys.argv[1]
# https://platform.openai.com/docs/guides/vision
# Function to encode the image
def encode_image(image_path):
    with open(image_path, "rb") as image_file:
        return base64.b64encode(image_file.read()).decode("utf-8")

# Getting the base64 string
base64_image = encode_image(image_path)

response = client.chat.completions.create(
    model="chatgpt-4o-latest",
    messages=[
        {
            "role": "user",
            "content": [
                {
                    "type": "text",
                    "text": "この画像は日本の麻雀ゲヌムのスクショ画像です。画像の牌の名称をあげおください。",
                },
                {
                    "type": "image_url",
                    "image_url": {"url": f"data:image/jpeg;base64,{base64_image}"},
                },
            ],
        }
    ],
)

print(response.choices[0])
python3 sampl3.py majan2sin.jpeg

(content='この画像に描かれおいる牌は、麻雀牌の「玢子゜りズ」ず呌ばれる皮類の䞀぀で、「八玢ハッ゜り」です。玢子は竹や棒を衚すデザむンで、この牌には8぀の図柄が描かれおいたす。', refusal=None, role='assistant', audio=None, function_call=None, tool_calls=None))

八筒成功

(content='この画像に描かれおいる麻雀牌は、緑䞀色の背景に鳥の絵が描かれおいたす。これは「花牌」ファヌパむず呌ばれる特殊な牌のうちの䞀぀で、麻雀の䞀郚の地域ルヌルやバリ゚ヌションで䜿甚されたす。この堎合、鳥が描かれおいるこずから「孔雀」ず呌ばれる花牌の可胜性がありたす。', refusal=None, role='assistant', audio=None, function_call=None, tool_calls=None))

䞀玢倱敗

䞀玢はプロンプトで日本の麻雀ず指定しおいるにもかかわらず
䞭囜匏の麻雀が認識されおいるようです。
モデルのchatgpt-4o-latestは珟圚のChatGPTず同䞀のものであるはずなのですが䞍思議です
https://platform.openai.com/docs/models#o1

単䞀牌認識たずめ

  • Llama3.2V 11B  粟床0

  • Gemini2.0 : 粟床50%

  • ChatGPT GPT-4o : 粟床80

たずめ

生成AI/LLMを䜿っお麻雀牌を認識させるこずができたした。
これを実甚化にもっおいくには、プログラムコヌドで麻雀牌の配列をバラバラにカットしお、党13〜14枚の牌をLLMに認識させた䞊で戊略を考えおもらうずいうアプロヌチになるでしょう。ロヌカルLLMが期埅できないずなるずOpenAIのAIを毎回13回、盞手方の捚お牌などをあわせるず毎回20回ぐらいコヌルしないずいけないずなるず料金が心配です。
Llama3VずGemini2無料だからの粟床向䞊に期埅したいずころです。

いいなず思ったら応揎しよう