2013-04-19[n年前へ]
■読者への挑戦状!この「暗号」を解き、名探偵になってみろ!?
アスキーPC編集部から、連載記事の最終回で使うための「暗号」が送られてきました。送られてきたのはこのPNG画像ファイル(送られてきたファイルそのもの)で、およそ下に貼り付けたような画像です。ガチで暗号解きに挑戦して、その過程・結果を記事にする、というわけです。
「暗号」解きに挑戦した結果は、1回目の推定(解読)候補には編集部から「ブブー違います!」という返事が返り、2回目の推定候補でようやく「大正解!」となりました。
1回目の推定が正解に至らなかった原因は、「(こういう候補群は)ありえない」と想像される狭い範囲で解探索を行ってしまったからです。ありがちな話ですが、作業を楽にしたいという意識が働き、「ダメとわかってるはずなのに」「目先の楽をしたいがために(矛盾を解決できない狭い範囲で作業を行ってしまって)結局は遠回り・苦労してしまう」というミスをしてしまったのです。
しかし、それらを言い換えれば、この問題が「解推定を自然に行えば、ちゃんと正解に至ることができる」という「良問」である、ということになりそうです。つまり、ちゃんと考えれば、一発で正答に辿り着く可能性が高い「問題」だというわけです。
画像解析や統計処理が好きな人は、この「暗号」解きに挑戦してみると面白いと思います。画像処理で「解くやり方を考える」のに20分程度、そして、そのやり方で解くための「解集合」を集めるコードを書いて・実行/整理する作業に15分程度、そして、その解集合から正解をスクリーニングするのにかかる時間は10分程度…トータル45分くらいの「探偵」作業をすれば(Top Coder な方々なら、おそらく15分もあれば十分でしょう)、きっと正解に辿り着くことができると思います。
本格推理小説を読むのが好きだったり、パズル好きだったり、画像解析や統計処理が好きな人は、この「暗号」解きミステリー、結構面白いのではないでしょうか。
(解答が出たら正誤確認は、こちらかこちらまで、「解答・推理」を御連絡下さい)
2018-04-28[n年前へ]
■草間彌生デザインの「水玉模様のモジモジ君ウェア」で人体の表面形状を推定してみよう!
数ヶ月前に買ったつもりのZOZOスーツ、服に取り付けられたセンサ群とスマホの間でさまざまなデータが交換され、自分の体を知ることができるという「面白さ」に惹かれて…はや数ヶ月、「大幅な性能向上」したものが届くという連絡内容を見ると、、そこには「コレジャナイ感が、超大盛りラーメン店のようにテンコ盛りされた、草間彌生デザインの「水玉模様のモジモジ君ウェア」でした。マーカー付けた衣服を使って(スマホによる)画像計測による採寸を行うデザインに変わっていた…というわけです。
ネットには、新バージョンのZOZOスーツ試着写真もtwitterにはアップロードされ始めています。そこで、そんなマーカ模様が付けられた服を着用した画像からの人体形状推定をしてみることにしました。「ネットにアップされた画像から」というわけで、多視点撮影からの3次元推定を行うZOZOスーツ正式バージョンとは違い、一枚画像からの体表面形状の推定です。
書いてみたのは、下に貼り付けたような、十数行ばかりのPython/Jupyterコードです。OpenCV でテクスチャ検出をして、その(円形マーカーの)大きさや形状の歪みを使って、模様部分の体の表面形状情報を推定する…というわけです。Pythonコードを実行した結果は、たとえば下の4 図のようになります。向かって左から、元画像・高さ(凹凸)画像・向き(180度の反対側を区別できない)画像・法線画像です。この処理例は、水玉模様の水着画像で処理を行ったものですが、新型ZOZOスーツ画像でも同様のことが行えます。
この画像を見れば、水着の模様を介して胸やお腹の3次元形状が見えてくることがわかります。全身に模様が付けられたZOZOスーツを着用した自撮り写真がアップされたら…色んな体形状を可視化できそうです。
import numpy as np import cv2 from matplotlib import pyplot as plt from math import sin, cos img = cv2.imread('zozo_polka202.jpg',2) cimg = cv2.cvtColor( cv2.imread('zozo_polka202.jpg'), cv2.COLOR_RGB2BGR) img = cv2.adaptiveThreshold(img, 128, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 15, 5) img, contours, hierarchy = cv2.findContours( img, cv2.RETR_LIST, cv2.CHAIN_APPROX_NONE) if len(contours) > 0: for i, contour in enumerate(contours): if (contour.shape)[0]>4: ellipse = cv2.fitEllipse(contour) aMax = max(ellipse[1][0],ellipse[1][1]) aDiff = abs(ellipse[1][0]-ellipse[1][1]) if aMax < 20 and aMax > 11 and aDiff < 12: xc = sin(ellipse[2]*np.pi/180)*255 yc = cos(ellipse[2]*np.pi/180)*255 cx=int(ellipse[0][0]) cy=int(ellipse[0][1]) cv2.ellipse(cimg,ellipse, (xc,yc,255-xc),-1) #cv2.circle(cimg, (cx, cy), int((aMax-11)*2.0), (xc,yc,255-xc), -1, -1) #cv2.ellipse(cimg,ellipse,(int((aMax-11)*50.0), int((aMax-11)*50.0),int((aMax-11)*50.0)),-1) #cv2.ellipse(cimg,ellipse,(int((aMax-11)*50.0), yc+xc,int((aMax-11)*50.0)),-1) plt.imshow(np.array(cimg))