見えたら天才
そんな画像があります。

ステレオグラムと言う
立体視画像です。

今回はそれを作っていきます。
解説動画はこちら



さてまずこの立体視というものですが
立体的な視覚を得る方法のことで
画像を立体的に見ることになります。

この立体的に見える画像のことを
ステレオグラム(英: stereogram)
立体画、立体図と呼んでいます。

立体的な印象をもつように描かれた
平面に描かれた図や絵あるいは写真
のことです。

こんなドット絵を見たことないでしょうか?
4つのドットの中二つが重ね合わさるように見ると
立体的に浮かび上がるように見えると思います。
download


コツとしては
右目で左側を見て、左目で右側を見るイメージ
うまく行くと点が浮かび上がってくると思います。

スマホだと厳しいかもしれないので
タブレットやPCで見てみると良いでしょう。


それではここからステレオグラムを
作っていきましょう。

今回作るやつは
ランダム・ドット・ステレオグラム
(英: Random dot stereogram, RDS)

一見ノイズのようにしか見えない画像が
うまく焦点を合わせると
立体が浮かび上がってくる画像です。

レーダー技術者から知覚研究に転じた
ユレス・ベーラさんによって
考案された手法だそうです。

今回はこちらのサイトの手法をそのまま
お借りしています。

参考



まずは背景となるドット画像の用意です。

ライブラリはopencvなどを使用します。
インストールしていないと動かないので
無い方はインストールしてください。
import numpy as np
import matplotlib.pyplot as plt
import cv2
%matplotlib inline

numpyを用いて背景ドット画像を作る関数です。
def make_dots(shape=(16, 16), levels=64):
    return np.random.randint(0, levels - 1, shape) / levels

dots = make_dots(shape=(64, 64))
plt.figure(figsize=(8,8))
plt.imshow(dots, cmap='gray')
plt.show()
dots

最初は円形の画像を浮かび上がらせる
ステレオグラムを作りましょう。

円形画像を作ります。
def make_img(shape=(400, 600)):
    img = np.zeros(shape, dtype=np.float)
    cv2.circle(img, (int(shape[1]/2), int(shape[0]/2)), 100, (255 ,255, 255), -1)
    return img

img = make_img()
plt.figure(figsize=(8,8))
plt.imshow(img, cmap='gray')
plt.show()

dotimg

ステレオグラムを作成する関数です。
こちらは参考サイトのものをそのまま転記しています。
def normalize(depthmap):
    "Normalizes values of depthmap to [0, 1] range."
    if depthmap.max() > depthmap.min():
        return (depthmap - depthmap.min()) / (depthmap.max() - depthmap.min())
    else:
        return depthmap

def make_autostereogram(depthmap, pattern, shift_amplitude=0.1, invert=False):
    "Creates an autostereogram from depthmap and pattern."
    depthmap = normalize(depthmap)
    if invert:
        depthmap = 1 - depthmap
    autostereogram = np.zeros_like(depthmap, dtype=pattern.dtype)
    for r in np.arange(autostereogram.shape[0]):
        for c in np.arange(autostereogram.shape[1]):
            if c < pattern.shape[1]:
                autostereogram[r, c] = pattern[r % pattern.shape[0], c]
            else:
                shift = int(depthmap[r, c] * shift_amplitude * pattern.shape[1])
                autostereogram[r, c] = autostereogram[r, c - pattern.shape[1] + shift]
    return autostereogram

最後に実行です。
このコードで円形ステレオグラムが
作成できると思います。
img = make_img()
autostereogram = make_autostereogram(img, dots)
plt.figure(figsize=(8,8))
plt.imshow(autostereogram, cmap='gray')
plt.show()
en

さて、注視すると円が浮かび上がってきませんでしょうか?

目安が無いので難易度は高いですが
見えない方は4つのドットで練習すると
見えるようになるかもしれません。

続いて文字を立体画像にしてみましょう。
まずは文字です。

text=の部分
引数で指定して変えれば他の文字にできます。
def make_text_img(shape=(400, 600), text='p y'):
    img = np.zeros(shape, dtype=np.float)
    font = cv2.FONT_HERSHEY_SIMPLEX
    cv2.putText(img, text, (100, 250), font, 5, (255,255,255), 30, cv2.LINE_AA)
    return img

text_img = make_text_img()
plt.figure(figsize=(8,8))
plt.imshow(text_img, cmap='gray')
plt.show()
py_text

これをステレオグラムにします。
autostereogram = make_autostereogram(text_img, dots)
plt.figure(figsize=(8,8))
plt.imshow(autostereogram, cmap='gray')
plt.show()
py

さてPYの文字が浮かび上がってきませんでしょうか?


最後にクイズです。
これは何と書いてあるでしょうか?

心が汚れている方は読めるはずですwwwwwww
sex


見えた方は動画のコメント欄にでも
コメントしていただけると嬉しいです。

見えたときは興奮、感動すること
間違いない!!!

気合と根性と集中力があれば
見えます。

頑張ってくださいね。
それでは。