Python/2.7 for fun.

아이들용 덧셈색칠퍼즐 만들기.

qkqhxla1 2015. 8. 14. 18:30

페이스북을 눈팅하다 어떤 프로그래머분의 글을 보게되었다. 어린 아들이 있는데 덧셈을 해서 색칠하는 퍼즐을 너무 좋아해서 사달라고 했다는것이었다. 퍼즐은 아래와 같다.


프로그래머인 그분은 프로그래밍의 열정이 살아나서(!) 본인이 만들어주겠다고 했고, 막상 해보려니 일반 이미지를 아래와 같은 격자 모양의 이미지로 만드는것부터가 고역이었다... 라고 글을 쓰셨었다.


http://myzone.coloringsquared.netdna-cdn.com/wp-content/uploads/2013/10/Free-Addition-Worksheet-Activities-AE4-Cute-Lion-Color-math-for-kids.pdf

요러한 이미지인데 간단한 덧셈을 해서 그 결과에 맞게 색칠하면 그림이 나오는 문제이다. 


이 글을 읽고 왠지 해보면 재미있겠다 싶어서 나도 한번 만들어보았다.

내가 생각해도 가장 어려운부분은 일반적인 이미지를 가져와서 그것을 조각조각 8비트 이미지로 변환시키는거였는데, 그럴거면 차라리 아예 처음부터 8비트로 만들어진 이미지를 가져와서 작업하면 되지않나?? 라고 생각해서 8비트 이미지인 마리오를 찾아봤다.


아래는 구글링한 마리오 이미지이다.

다운받아서 보면 알겠지만 대충 몇칸으로 나뉘어져 있는지 알수 있다. 나같은경우에는 가로 세로 둘다 15칸씩 나눠서 만들어봤다.


해야됬던점.

1. 나눠진 이미지지만 색깔이 통일되지 않았었다. (빨간색이라도 다 같은 rgb값의 빨간색이 아니었다는 말.) 그래서 차이가 일정 이하이면 같은 색으로 통일되게 했다

2. 사각형 크기가 완전 정확히 딱딱 나눠지지 않아서.. 임의로 대충 크기에 맞게 가져온 후 중앙 부분의 색을 추출해서 다시 사각형을 크기에 맞게 만드는 방식으로 만들었다. 

3. 나머지는 알고리즘적으로 잘 만들면 된다.



흰색 : 13, 살색 : 12, 검은색 : 11 ~~~~등등등등

중간에 인식 실패로 한줄이 더 늘어났지만, 그래도 나름 예쁘게 잘 만들어졌다. 

맨날 쓸때없이 뭐하는건지 모르겠다..... 그래도 재밌으니깐...


# -*- encoding: cp949 -*-
import math, random
from PIL import Image
from PIL import ImageFont
from PIL import ImageDraw 
im = Image.open('mario.png')
color_temp = []; color = []
for i in range(0,im.size[1]-im.size[1]/15,im.size[1]/15):
    for j in range(0,im.size[0]-im.size[0]/15,im.size[0]/15):
        color_temp.append(im.getpixel((j + im.size[0]/30,i + im.size[1]/30)))

for i in range(len(color_temp)): #애매한 색깔들을 다 통일한다.(빨간색 계열은 동일한 RGB값의 빨간색으로 등등등.)
    if not color: 
        color.append(color_temp[0])
        continue
    flag = True
    for j in range(len(color)):
        if abs(color[j][0] - color_temp[i][0]) < 30 and abs(color[j][1] - color_temp[i][1]) < 30 and abs(color[j][2] - color_temp[i][2]) < 30:
            color.append(color[j])
            flag = False
            break
    if flag: color.append(color_temp[i])

cal = list(set(color))
color_dic = {}
for i in range(len(cal)): #각각의 색에 대해 숫자를 배정한다.
    color_dic[cal[i]] = i+5 #5~13

Image.new('RGB',(im.size[0],im.size[1]),(255,255,255)).save('mario1.png')
im = Image.open('mario1.png')

cnt = 0
draw = ImageDraw.Draw(im)
font = ImageFont.truetype("arial.ttf",10) #폰트는 알아서 구해서 스크립트와 같은 폴더에 넣으면 된다.
for i in range(0,im.size[1]-im.size[1]/15,im.size[1]/15):
    for j in range(0,im.size[0]-im.size[0]/15,im.size[0]/15):
        for k in range(i,i+im.size[1]/15): #한칸 한칸 해당 색에 맞게 색칠하기.
            for l in range(j,j+im.size[0]/15):
                im.putpixel((l,k),(color[cnt]))
        while True:
            a = random.randint(0,9)
            b = random.randint(0,9)
            if a+b == color_dic[color[cnt]]: break
        if color[cnt][0]<50 and color[cnt][1]<50 and color[cnt][2]<50: #어두우면 흰색으로 식을쓰고
            draw.text((j+2,i+4),str(a)+'+'+str(b),(255,255,255),font=font)
        else: draw.text((j+2,i+4),str(a)+'+'+str(b),(0,0,0),font=font) #아니면 검은색으로 식을씀
        cnt += 1

for i in range(im.size[1]): #각각 칸에 맞게 라인 긋기.
    for j in range(0,im.size[0]-im.size[0]/15,im.size[0]/15):
        im.putpixel((j,i),(0,0,0))
for i in range(im.size[0]): 
    for j in range(0,im.size[1]-im.size[1]/15,im.size[1]/15):
        im.putpixel((i,j),(0,0,0))

im.save('mario1.png')