乙Py先生のプログラミング教室
初学者のためのプログラミング学習サイト

ステレオグラム

今回は子供の日という事で
ステレオグラムで遊んでみました。

解説動画はこちら



ステレオグラムとは(立体画)


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

目の焦点を意図的に前後にずらして合わせることで
左右の絵を別々の目で見ることにより
立体的に見ることができる画像です。


今回はドットのパターンを用意して
そこに浮かび上がらせる画像を組み合わせて作っています。

見方は、黒いドットが3つになるように
重ね合わせて目の焦点を合わしていくと
見る事ができると思います。



ステレオグラムを作成するコード

import numpy as np
import matplotlib.pyplot as plt
import cv2
import warnings
warnings.simplefilter("ignore")
%matplotlib inline

def make_dots(shape=(16, 16), levels=64):
    return np.random.randint(0, levels - 1, shape) / levels

def make_text_img(text='A', shape=(400, 600)):
    font = cv2.FONT_HERSHEY_SIMPLEX
    (text_width, text_height), _ = cv2.getTextSize(text, font, 5, 30)
    img = np.zeros((text_height + 50, text_width + 200), dtype=np.float)
    cv2.putText(img, text, (100, text_height+10), font, 5, (255, 255, 255), 30, cv2.LINE_AA)
    img_resized = cv2.resize(img, shape[::-1], interpolation=cv2.INTER_AREA)
    return img_resized

def normalize(depthmap):
    if depthmap.max() > depthmap.min():
        return (depthmap - depthmap.min()) / (depthmap.max() - depthmap.min())
    else:
        return depthmap

def make_autostereogram(text, shift_amplitude=0.1, invert=False):
    depthmap = make_text_img(text=text)
    pattern = make_dots(shape=(64, 64))
    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]
    autostereogram[48:53, 248:253] = 0
    autostereogram[48:53, 348:353] = 0
    return autostereogram

実行する際は浮かび上がらせる画像を
テキストとして文字列を変更します。
autostereogram = make_autostereogram(text='A')
plt.figure(figsize=(8,8))
plt.imshow(autostereogram, cmap='gray')
plt.axis("off")
plt.show()
download

この画像の上にある黒い点が
4つになるようにぼんやり見た後に
点が3つになるように焦点をずらします。

そうすると A という文字が
浮かび上がって見えると思います。


問題

さっきの練習を少し難しくした3文字です。
g1





新宿の掲示板に書いてある3文字です。
g2




自分の大好きな5文字です。
g3





見えましたか?


見えない方は
努力が足りていないです!!!!!!!!

見えた方は
今日の1日がとても
すこやかに過ごせるでしょう!!!

色々画像を作って遊んでみて下さい。

それでは。

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

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

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



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

この立体的に見える画像のことを
ステレオグラム(英: 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


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

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

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

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



このページのトップヘ