1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ぷよぷよsteam版のpuyo認識

Posted at

スクリーンショット 2024-10-09 22.05.09.png

steam版のぷよぷよeスポーツは有料です。

画像の取り扱いについては以下のサイトを参照してください。

©SEGA

library

keyboard, pyautogui, pygetwindow,numpy の4つをpipインストールする。

import keyboard as kb
import pyautogui as ag
import pygetwindow as ag
import numpy as np
from PIL import Image,ImageDraw
import cv2
im = Image.open("all1600x900.png")
im

output_3_0.png

w,h = im.size
print(w,h)
1600 900
np_image = np.array(im)
im1 = Image.fromarray(np_image[0:50,0:100])
im1

output_5_0.png

縦方向の位置、横方向の位置、RGB
この順であることが分かりました。

# 0:black 1:red 2:green 3:yellow 4:blue 5: purple 6:skyblue 7:white
def convert_rgb_8(rgb):
    res = 0
    if rgb[0] > 100:
        res += 1
    if rgb[1] > 100:
        res += 2
    if rgb[2] > 100:
        res += 4        
    return res

x1 = w//8
y1 = h//12
lx = x1
rx = x1*3
uy = y1
ly = y1*11
for i in range(x1,x1*3):
    uy1 = y1*11
    ly1 = y1 
    l_max = 0
    l = 0
    for j in range(y1,y1*11):
        rgb = np_image[j,i]
        if convert_rgb_8(rgb) == 0: # black
            l+=1
            if l > l_max:
                uy1 = j-l
                ly1 = j
                l_max = l
        else: #white
            l = 0
    if l_max > y1 * 5:
        uy = uy1
        ly = ly1
        lx = i
        break

for i in range(x1*3,x1,-1):
    uy1 = y1*11
    ly1 = y1 
    l_max = 0
    l = 0
    for j in range(y1,y1*11):
        rgb = np_image[j,i]
        if convert_rgb_8(rgb) == 0: # black
            l+=1
            if l > l_max:
                uy1 = j-l
                ly1 = j
                l_max = l
        else: #white
            l = 0
    if l_max > y1 * 5:
        rx = i
        break
puyo_w = (rx-lx) // 6
puyo_h = (ly-uy) // 12
print(lx,uy,rx,ly,puyo_w,puyo_h)
227 132 559 735 55 50
np_stage = np_image[uy:ly,lx:rx]
im_stage = Image.fromarray(np_stage)
im_stage

output_8_0.png

ある色だけを抜き出すのが、cv2.inRangeです。
そのために、RGBからHSVに変換します。
認識した部位が255で、違うのが0になります。

def cv2_mask(np_im,color_num):
# 0:0-360:white 1:0-5:red  2:50-80:green 3:100-120:blue 4:15-40:yellow 5:130-150:purple
    color_cfg =[[0,0,200,359,49,255],[0,0,50,5,255,255],[50,0,50,80,255,255],
                [100,50,50,120,255,255],[15,50,50,40,255,255],[130,0,50,150,255,255]]

    cv2_im = cv2.cvtColor(np_im, cv2.COLOR_RGB2HSV)
    cc0 = color_cfg[0]
    msk0 =  cv2.inRange(cv2_im,(cc0[0],cc0[1],cc0[2]),(cc0[3],cc0[4],cc0[5]))
    cc = color_cfg[color_num]
    mask =  cv2.inRange(cv2_im,(cc[0],cc[1],cc[2]),(cc[3],cc[4],cc[5]))
    return mask | msk0

maskデータで、ビット単位のAND処理をします。すると、認識している場所の色だけが現れます。
ぷよの中は白いので、白もぷよとして認識しています。

msk = cv2_mask(np_stage,5)
result = cv2.bitwise_and(np_stage, np_stage, mask=msk)
im_stage = Image.fromarray(result)
im_stage

output_12_0.png

全部の色をまとめて処理することにしました。

def cv2_mask2(np_im):
# 0:0-360:white 1:0-5:red  2:50-80:green 3:100-120:blue 4:15-40:yellow 5:130-150:purple
    color_cfg =[[0,0,200,359,49,255],[0,0,50,5,255,255],[50,0,50,80,255,255],
                [100,50,50,120,255,255],[15,50,50,40,255,255],[130,0,50,150,255,255]]
    masks = []
    cv2_im = cv2.cvtColor(np_im, cv2.COLOR_RGB2HSV)
    cc0 = color_cfg[0]
    msk0 =  cv2.inRange(cv2_im,(cc0[0],cc0[1],cc0[2]),(cc0[3],cc0[4],cc0[5]))
    masks.append(msk0)
    for i in range(1,6):
        cc = color_cfg[i]
        mask =  cv2.inRange(cv2_im,(cc[0],cc[1],cc[2]),(cc[3],cc[4],cc[5]))
        masks.append(mask|msk0)
    return masks

msks = cv2_mask2(np_stage)
result = cv2.bitwise_and(np_stage, np_stage, mask=(msks[5]))
im_stage = Image.fromarray(result)
im_stage

output_14_0.png

maskデータを場所ごと集計(平均化)して、半分以上があれば、その色と認識しています。

def conv_masks_stage(masks):
    result = np.zeros((12,6))
    mask_h= masks[0].shape[0]
    mask_w= masks[0].shape[1]
    puyo_w = mask_w // 6
    puyo_h = mask_h // 12
    for i in range(6):
        for j in range(12):
            for k in range(1,6):
                c_ratio = np.mean(masks[k][puyo_h*j:puyo_h*(j+1),puyo_w*i:puyo_w*(i+1)])
                if c_ratio > 255 *0.5:
                    result[j,i] = k
    return result

conv_masks_stage(cv2_mask2(np_stage))

array([[0., 0., 1., 0., 0., 0.],
       [0., 0., 0., 0., 0., 5.],
       [0., 0., 0., 0., 0., 2.],
       [0., 0., 0., 0., 0., 2.],
       [0., 0., 0., 0., 0., 1.],
       [0., 0., 0., 0., 0., 1.],
       [0., 0., 0., 0., 0., 4.],
       [0., 0., 0., 0., 0., 5.],
       [0., 0., 0., 0., 4., 5.],
       [0., 0., 0., 0., 4., 5.],
       [2., 5., 4., 0., 1., 2.],
       [1., 4., 4., 1., 4., 4.]])

認識できているようです。


puyopuyo.gif
 ぷよぷよプログラミングAI学習システムは、中高生の自己調整学習に向けて開発されました。
 どうやって、Chromebookで、10分で、素敵な人工知能を作れるのでしょうか?
 秘密は、3つ。
 1 jupyter liteで、webクライアントがpythonコードを実行
 2 超軽量な機械学習フレームワークdezeroを採用
 3 ぷよぷよのstageとactionがコンパクト

Github&X

ぷよぷよプログラミングAI学習用まとめ

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?