こちらのプログラムがひとまず完成しました。
プリチケのQRコードを隠すプログラムが完成した pic.twitter.com/yBe59HMYnh
— 黒めだか (@takeshi0406) December 3, 2015
やっている事自体は簡単なので、zbarを使えれば他の言語でも可能です。そのためこんな感じで
カメラアプリが作れればいいのですが、その辺の技術はサッパリなのでどうかな…。 とりあえずコマンドラインツール化してgithubにでもアップしておこうかしら。
#!/usr/bin/env python # -*- coding: utf-8 -*- import math import zbar from PIL import Image, ImageOps class maskPritikeQRcode: def __init__(self): self.set_output_path('./output.png') def set_output_path(self, path): self.output_path = path def set_ticket_path(self, path): self.ticket_path = path def read_ticket_data(self, path): ticket = Image.open(path) # 画像合成用にカラーで読み込む self.ticket = ticket.convert('RGBA') # qrコード解析用に白黒で読み込んだ上、色を反転する(プリチケのQRコードは白黒逆らしい) self.ticket_inverted = ImageOps.invert(ticket.convert('L')) def read_stamp_data(self, path): self.stamp = Image.open(path).convert('RGBA') def mask_qrcode(self): image = self._scan_qrcode(self.ticket_inverted) for symbol in image: # symbol.locationでQRコードの範囲が取れる self._paste_stamp(symbol.location) new_image = self.ticket.convert('RGB').convert('P', palette=Image.ADAPTIVE) new_image.save(self.output_path, "PNG") def _scan_qrcode(self, ticket): scanner = self._zbar_scanner() raw = ticket.tostring() (width, height) = ticket.size image = zbar.Image(width, height, 'Y800', raw) scanner.scan(image) return image def _zbar_scanner(self): scanner = zbar.ImageScanner() return scanner def _paste_stamp(self, location): xy_coodinate = self._get_qr_location(location) shaped_stamp = self._get_shaped_stamp(location) self.ticket.paste(shaped_stamp, xy_coodinate, shaped_stamp) # 貼り付け def _get_qr_location(self, location): return tuple(min(x) for x in zip(*location)) def _get_shaped_stamp(self, location): angle = self._get_qr_angle(location) size = self._get_qr_size(location) return self.stamp.resize(size).rotate(angle) def _get_qr_angle(self, location): # TODO:: qrコードが回転している場合をテストする left_line = sorted(location, key=lambda x:x[0])[0:2] vartical = [x - y for x, y in zip(*left_line)] # zip(*args)で転置を取れる return math.atan2(*vartical[::-1]) * 180 / math.pi + 90 def _get_qr_size(self, location): return tuple(max(x) - min(x) for x in zip(*location)) if __name__ == '__main__': p = maskPritikeQRcode() p.read_ticket_data('pritike.jpg') p.read_stamp_data('stamp.png') p.mask_qrcode()