読者です 読者をやめる 読者になる 読者になる

しょぼちむをExcel方眼紙で表現してみる

これはしょぼちむアドベントカレンダー23日目の記事です。


しょぼちむ Advent Calendar 2014 - Adventar


昨日は、ばふぁさんの「しょぼちむ!スクラムチームの外側の話をちょっと書いてみたよ!」でした!


今日は特にこれといって決めてないので、しょぼちむをExcel方眼紙にしようと思います。

以下の手順で行います。

  1. Twitterからしょぼちむのアイコンをダウンロードする
  2. 画像を適当に小さくする(リサイズ)
  3. 画像を2値化する
  4. 画像を 0 と 1 でマッピングして文字列を取り出す
  5. Excel方眼紙に貼付ける


以上です。


画像のリサイズおよび2値化には OpenCVを使います。
OpenCVのインストール(Mac)はこちらを参考にしました。

Mac - OS X に OpenCV を Homebrew で入れて python で動画入出力をする - Qiita


では早速ソースコードです。

まず vim を起動します。

$ vim syobochim.py
import cv2

img = cv2.imread('syobochim.jpg', cv2.IMREAD_GRAYSCALE)

# 2. 画像を適当に小さくする(リサイズ)
thumb = cv2.resize(img,(160, 128)) 

# 3. 画像を2値化する
thresh = 120
img_bin = cv2.threshold(thumb, thresh, 255, cv2.THRESH_BINARY)[1]

# 4. 画像を 0 と 1 でマッピングして文字列を取り出す
for y in range(0, 127):
  for x in range(0, 159):
    px = img_bin[y, x]
    if px != 0:
      print '1',
    else:
      print '0',
  print ''

そしてこれを
( ^ω^)
⊃ syobochim.py ⊂


こうして…
( ^ω^)
≡⊃⊂≡

$ python syobochim.py > syobochim.txt


こうじゃ
( ^ω^)
Excel方眼紙 ⊂
f:id:tan_go238:20141223054317p:plain





本当はここから Arduinoにシリアル通信で画像を送り、LCDディスプレイで表示しようと思ったんだけど、送信データ量が多くて送れませんでした。
バイナリデータで送ろうとしたけどpySerialでは文字列でしか送れないことと、Arduinoは128byteのread bufferしかないのが原因っぽい。多分頑張ればできるはず。
とりあえず時間があったら後でやろうかなと思うので上記ソースをちょっと修正したPythonソースコードを備忘録で残しておく。

※動いたので追記
Arduinoのバッファを消費するタイミングをうまくスリープで調整すればできた。
けどスリープのタイミングがなかなか難しいし遅い。
バッファサイズをみてやればいいような気がするけどこのへんの知識ないので難しい・・。

# convert image to 160 x 128 pixel resolution.
import array
import cv2
import serial
import time

# resize
img = cv2.imread('syobochim.jpg', cv2.IMREAD_GRAYSCALE)
thumb = cv2.resize(img,(160, 128))

# binary
thresh = 120
img_bin = cv2.threshold(thumb, thresh, 255, cv2.THRESH_BINARY)[1]

# serial
ser = serial.Serial()
ser.port = '/dev/tty.usbmodemfa131'
ser.baudrate = 9600

ser.open()
time.sleep(5)

for y in range(0, 128):
  data = ""
  for x in range(0, 160):
    px = img_bin[y, x]
    if px != 0:
      data += "1"
    else:
      data += "0"
  ret = ser.write(data)
  time.sleep(0.5)

time.sleep(1)
ser.close()
#include <SPI.h>
#include <SD.h>
#include <TFT.h>  // Arduino LCD library

// pin definition for the Uno
#define sd_cs  4
#define lcd_cs 10
#define dc     9
#define rst    8

TFT tft = TFT(lcd_cs, dc, rst);
int x,y = 0;
int rcv = 0;
  
void setup() {
  tft.begin();
  tft.background(0, 0, 0);
  Serial.begin(9600);
}

void loop() {
  while((rcv = Serial.available()) > 0){
    for(int i=0; i<rcv; i++) {
      int val = Serial.read();
      if (val == 48) {
        tft.drawPixel(x, y, 0x0000);
        x++;
      } else if(val == 49){
        tft.drawPixel(x, y, 0xFFFF); // 0xFFFF
        x++;
      }      
      if(x>=160) {
        x = 0;
        y++;
      } 
    }
  }  
}

f:id:tan_go238:20141227172325j:plain