디지몬 사진에서 16*16 도트를 만든 이야기

소개



저는 프로그래밍 초보자(취미로 씹는 정도, 비엔지니어)입니다.
공부하면서 만드는 것입니다.
다음 페이지를 참고로 해 주셨습니다. 정말 고마워요.

htps: //포std. ㄷ/이마게-p 로세신 g-101/

환경



Windows10
파이썬 3.8
OpenCV 4.0.1
노트북

동기와 착수까지의 흐름



나는 취미로 디지몬 앱을 만들고 있습니다.
(↓이런 것)


앱에 내장 된 디지몬은 디지몬 펜듀럼 Z
1. 육성
2. 사진 찍기
3. 도트 그림을 수타로 만든다
라는 흐름으로 준비하고 있었습니다.

이 3의 도트 그림을 만드는 부분이 매우 번거로워진 것입니다.

그렇다고 하는 것도, 실기의 디지몬 자체는 16×16으로 그려져 있습니다만
그대로 그려도 늘리면 흐릿해진다
(왼쪽:실기의 아그몬 오른쪽:32×32로 그려진 아그몬)


게다가 나는 실기의 도트간의 선도 표현하고 싶기 때문에 1도트 7px(도트간 1px)로서 8배척의 128×128로 그려 있었습니다.


이 쓸데없는 조건에 의한 도트 치기가 매우 번거로워졌기 때문에,
사진에서 도트 그림을 만들 수 없을까 생각했던 것입니다.

착수



흐름적으로는
원본 이미지 → 임계값으로 이진화 → 재생성
라는 것을 생각해 시작.
(거의 참고로 한 페이지를 추적하는 것뿐입니다)

1. 이미지 준비




이번에 준비한 것은 아포카리몬 (apocaly_0.jpg)입니다.
만들고 싶은 16×16의 범위에서 트리밍하고 있습니다.
#各種インポート
import cv2, matplotlib
import numpy as np
import matplotlib.pyplot as plt

# 画像の読み込み
img = cv2.imread('images/apocaly_0.jpg')

2. 임계치 처리


# グレースケール化
gray_img = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)

# 閾値 128 で二値化
_, threshold_img = cv2.threshold(gray_img, 128, 255, cv2.THRESH_BINARY)

# グレースケールをRGBに戻して画像の表示
threshold_img = cv2.cvtColor(threshold_img, cv2.COLOR_GRAY2RGB)
plt.imshow(threshold_img)



좋은 느낌으로 흑백으로 나뉘어졌습니다.

이미지를 16x16으로 분할하여 영역 값을 계산합니다.


#画像自体の高さと幅を16分割
h, w, _ = img.shape
cell_width = w/16
cell_height = h/16

#区切りの位置を配列にする
col_cell = list(range(17))
row_cell = list(range(17))

for i in range(17):
    col_cell[i] = round(cellWidth * col_cell[i])
    row_cell[i] = round(cellHeight * row_cell[i])

로 구분된 위치의 배열을 만들었습니다.
print(col_cell)
#結果 [0, 26, 53, 79, 106, 132, 159, 185, 212, 238, 264, 291, 317, 344, 370, 397, 423]
print(row_cell)
#結果 [0, 28, 56, 84, 112, 139, 167, 195, 223, 251, 279, 307, 334, 362, 390, 418, 446]

16×16의 영역의 격자는 준비할 수 있었으므로 드디어 계산
# [i行目 ,j列目] の要素取得    
for i in range(16):
    for j in range(16):
        #領域cellとして切り取る
        cell = threshold_img[row_cell[i]:row_cell[i+1]-1, col_cell[j]:col_cell[j+1]-1]

        #cell内の行平均
        ave_per_row = np.average(cell,axis=0)

        #行平均の平均 = 全体の平均
        ave_color = np.average(ave_per_row, axis=0)
        ave_value = np.average(ave_color)

        # 白→0 黒→1 で格納
        if ave_value >= 220:
            dot[i][j] = 0
        else:
            dot[i][j] = 1

평균치의 ave_value 가 255에 가까우면 흰→ 0 를 대입, 그렇지 않으면 검정에 가깝기 때문에 1 를 대입했습니다
print(dot)
#結果
[[0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0], 
 [0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0], 
 [1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1], 
 [0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0], 
 [1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 1], 
 [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0], 
 [0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0], 
 [0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0],
 [0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0],
 [0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0],
 [0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]

아포카리몬을 무사히 01로 표현할 수 있었습니다.
여기 굉장히 디지몬 같다고 생각했습니다.

재생성



드디어 재생성
#128×128の領域を作る
width = 128
height = 128
dot_img = np.zeros((height,width,3), dtype=np.uint8)

for i in range(16):
    for j in range(16):
        if dot[i][j] == 0:
            #白→255
            dot_img[i*8:i*8+8,j*8:j*8+8] = 255
        else:
       #黒→0
            dot_img[i*8:i*8+8,j*8:j*8+8] = 0

plt.imshow(dot_img)



안전하게 할 수 있었습니다!

도트간의 1px선이나 흰색 부분은 투과해 png로 하거나 등 아직 도중이지만 일단의 목표는 달성입니다.

사이고에게



여기까지 읽어 주셔서 감사합니다.

이 기사를 쓰고
도중에 흰색 → 0 검은 → 1로 했지만 흰색 → 1 검정 → 0으로 재생성시에 dot[i][j] * 255로하는 것이 스마트하다고 생각하기도했습니다.
보상하는 것은 중요합니다.

좋은 웹페이지 즐겨찾기