182
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

Python+OpenCVでサイゼの間違い探しをしてみた話

はじめに

はじめまして、ぱそきいろと申します。
初めて技術ブログを書くので生暖かい目で見守ってください。
「いいね」いただけるとモチベーションに繋がるので、良いと思っていただけた方はお願いします。

こちらでブログもやってますので、よかったらご覧になってください。
ぱそきいろのIT日記

間違い探しをしてみた

みなさん、サイゼリヤの間違い探しが難し過ぎると度々話題になるのは知っていますか?
子供が解くレベルを軽く超えてると思いますよね。
これをプログラミングを使って解こうと思ったのがきっかけです。
(ただ、全く同じ技術で先にやっている人がいるんですよね。。。リンク参照

まぁ見た目が違うんで何かの参考になればと思います。
body.jpg
result.jpg

使った技術

MacBook Air
Python 3.6
OpenCV 3.4.3.18
Matplotlib 2.1.2

やったこと

具体的にやったことの流れとしては
1.pythonで間違い探しの画像を読み込む
2.OpenCVで画像の差分をとる
3.領域を切り分けて差分が多い部分を抽出
4.Matplotlibを使ってヒートマップを作成、画像にまとめて出力

1.pythonで画像を読み込む

まずはここから間違い探しの画像を持ってくる。
この画像は2枚が1セットになっているので真ん中で分ける必要があります。
ただ、中心が画像によって微妙に異なっているのでここは手動で分ける必要がありました。
非常にダサい。。。
どこかで、画像差分が一番小さくなるような中心を選ぶコードを書いた方が良いと思います。。。

def separate():
    body=cv2.imread("body.jpg")
    body1=np.empty([570,570,3])
    body2=np.empty([570,570,3])

    for i in range(560-1):
        for j in range(570):
            body1[j][i]=body[j][i+38]#ここの38は手動です。。。

    for i in range(560-1):
        for j in range(570):
            body2[j][i]=body[j][i+600]

    cv2.imwrite("body1.jpg",body1)
    cv2.imwrite("body2.jpg",body2)

2.OpenCVで画像の差分をとる

これはOpenCVを使えば一発ですよね。

 diff = cv2.absdiff(img0, img1)

これでできた差分の画像が以下です。
もうなんとなく間違いが分かりそうな気がしますが。。。
diff2.jpg

3.領域を切り分けて差分が多い部分を抽出

ここら辺がポイントですかね。
画像を10×10の領域に分けて各領域である一定の明るさ以下のところは切り捨てます。
ある程度差分があるところだけを残して、それらの和を取ります。
この配列を元にヒートマップを作成し、解いていきます。

def mkheatdata(img):
    N=10
    M=10
    y=int(np.shape(img)[1]/N)
    x=int(np.shape(img)[0]/M)
    array=np.zeros((N,M))
    for i in range(np.shape(img)[0]):
        for j in range(np.shape(img)[1]):
            if img[i][j]<70:
                img[i][j]=0
    for n in range(N):
        for m in range(M):
            array[n][m]=np.sum(img[x*n:x*(n+1)-1,y*m:y*(m+1)-1])
    array=array[::-1][::1]
    return array

4.Matplotlibを使ってヒートマップを作成、画像にまとめて出力

この配列の値が大きい上位10個を間違いとしています。
上位10個の抽出は割愛します。
ヒートマップの出力のところだけ。
ポイントは、画像を重ねるために軸や余白を無くしたところですね。

def heatmap(heatdata):
    fig,ax=plt.subplots()
    fig=plt.figure(figsize=(57,57),dpi=10)
    ax.tick_params(labelbottom="off", bottom="off")  # x軸の削除
    ax.tick_params(labelleft="off", left="off")  # y軸の削除
    ax.set_xticklabels([])
    box("off")  # 枠線の削除
    fig.subplots_adjust(left=0,bottom=0,right= 1,top=1)

    plt.pcolor(heatdata,cmap=plt.cm.Reds)
    plt.savefig('heatmap.png')

これでできた画像が以下です。
これを重ねると正解ができます。
heatmap.png
result.jpg

まとめ

サイゼ.jpg

結局正解が6/10
全部当てることはできなかったのですよね。。。
画像差分をとるから、位置がずれる、形が変わるには強いけど、点や線が増えるという間違いには弱いみたいです。。。
まぁ、研究に活かせそうですし、良い暇つぶしになったのかなと思います。

初投稿、読んでいただきありがとうございました。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
182
Help us understand the problem. What are the problem?