ステレオグラムの作り方_基本編3 (背景画像を深度マップの画像サイズに並べる)
ステレオグラムの作り方_基本編2の続きになります。
③背景画像を深度マップの画像サイズに並べる
次はステレオグラム作成の肝の部分です。
128×64ピクセルの背景画像を600×400ピクセルの深度マップ画像と同じサイズになるように並べていきます。このとき、深度マップの画像データの白丸部分は、背景画像をずらして配置する必要があります。
Pythonでオリジナルのランダムドットステレオグラム(RDS)を作る。 - Qiita
Making Your Own Autostereograms using Python | Frolian's blog (flothesof.github.io)
def normalize(depthmap):
return depthmap/255
In[5]
def make_autostereogram(depthmap, pattern, shift_amplitude=0.1, invert=False):
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
autostereogram = make_autostereogram(depthmap, pattern, 0.3)
plt.imshow(autostereogram, cmap='gray')
いやぁ、もう何をやっているのか全然分からないけど出来てしまいました。画像の中心に〇が浮かんでいるのが見えます。
あまりの分からなさに怖気づいてしまっていますが、頑張ってコードを読んでいきます。
def normalize(depthmap):
return depthmap/255
1、17、19、20行目
def make_autostereogram(depthmap, pattern, shift_amplitude=0.1, invert=False):
…
return autostereogram
autostereogram = make_autostereogram(depthmap, pattern, 0.3)
plt.imshow(autostereogram, cmap='gray')
”make_autostereogram”という名前で何かしらの関数を作って、"autostereogram"で
それを実行し、その結果をpltの機能を使ってグレースケールで表示させているんですね。
2行目
depthmap = normalize(depthmap)
前に定義したnormalizeという関数で正規化を実施。
4行目、5行目:
if invert:
depthmap = 1 - depthmap
if False…?ネガポジ変換?わからないのでパス。
6行目:
autostereogram = np.zeros_like(depthmap, dtype=pattern.dtype)
”autostereogram”で深度マップと同じピクセルサイズの600×400ピクセルの画像を
作ってます。中身のデータは”0”なので、黒一色の画面になっているってことですね。
8行目:
for r in np.arange(autostereogram.shape[0]):
np.arangeは等差の数列を返す関数です。
for c in np.arange(autostereogram.shape[1]):
これも8行目と同じです。autostereogramの横のピクセル数と同じだけ繰り返すと書いてあるので、『今から以下の事を600回繰り返します』、と宣言してます。
if c < pattern.shape[1]:
これは『autostereogramの横サイズがpatternの横サイズよりも小さいうちは』ですね
12行目
autostereogram[r, c] = pattern[r % pattern.shape[0], c]
ここではrとcはそれぞれautostereogramの縦と横のピクセルの位置なので ”autostereogram[r, c]”は縦r、横cのポイントの画素の情報ということになります。
次に”pattern[r % pattern.shape[0], c]”ですがa%bは a をbで割った余りを表します。つまり”r % pattern.shape[0]”は rをpattern.shape[0]つまり128で割った余りの値が入ります。
・・・? 何してるのこれ。
例えば、
autostereogramの縦のピクセル数が65のとき
129÷128=1余り1
autostereogramの縦のピクセル数が100のとき
200÷128=1余り72
あ、なるほど!割ったときの余りが0~127に変化するのを利用して、patternを1枚貼ったら次に新しいものを貼るという繰り返しをしているんですね。すごい!頭いい!
13、14行目
else:
shift = int(depthmap[r, c] * shift_amplitude * pattern.shape[1])
ええと。
それ以外ならshiftは〇〇に設定するって感じですね。ここが一番大事なところかな。
depthmap:画像を白黒で作ってるので depthmap[r, c]の答えは"0"か"1"しかない
shift_amplitude:初期値は0.1(defの中の初期値なので後で任意の値に変えられる)
pattern.shape[1]:横のピクセル数64
ということは
depthmapの黒い背景部分
0×0.1×64=0
depthmapの白い円の部分
1×0.1×64=6.4 ⇒intなので整数部分の6
となって、白い円の部分に該当するピクセルのときだけshiftに値が入るんですね。
今は画像を白黒でしか作っていませんけど、灰色だったら灰色のシフト量になるように書かれれるから、灰色を使ったらもっとリアルな奥行き感とか影とかが出せそうです。
15行目
autostereogram[r, c] = autostereogram[r, c - pattern.shape[1] + shift]
さて、最後の難関。 問題は ”c - pattern.shape[1] + shift”の部分ですね。
●depthmapの黒い背景部分だとshift=0で
c - 64 + 0
例えばr=200,c=100なら
autostereogram[r, c]= autostereogram[200, 46]
autostereogram[200, 46]の部分には12行目のpatternの値が入っているので
それが参照されるので、patternが連続しているように見える。
●depthmapの白い円の部分だとshift=6で、
c - 64 + 6
depthmapの黒い背景部分までは連続していたパターンが+6ピクセル分ずれて
入ることになる。
ほぉぉ!
それだけで立体的に見えるものなんですね。視覚って不思議。
ともあれ、これでステレオグラムの作り方の基本をマスターしました!!
ここからはこれをベースに好きな画像で作っていきたいと思います。