Pythonでオリジナルのランダムドットステレオグラム（RDS）を作る。

# ランダムドットステレオグラム（RDS）
>![Mh_stereogramm_sirds.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329479/c27c68eb-badc-0226-39c9-938043b29436.png)
オリジナルのアップロード者はドイツ語版ウィキペディアのLosHawlosさん - de.wikipedia からコモンズに移動されました。, CC 表示-継承 3.0, https://commons.wikimedia.org/w/index.php?curid=1966500 による

あなたには見えるだろうか？
目の焦点を前後にずらすことで絵や文字が浮かび上がる（立体に見える）やつです。
スマホから見てる人はごめんなさい。パソコンから見てね。

これを自作してみたい。

下記のサイトにPythonでの実装例があったので、参考にしてオリジナルのランダムドットステレオグラムを作ってみた。

- [Making Your Own Autostereograms using Python](https://flothesof.github.io/making-stereograms-Python.html)


# 使うもの
```python
import numpy as np
import matplotlib.pyplot as plt
import cv2
```
Notebook形式で実験していて、画像を表示させるために使い慣れている`matplotlib`を使いましたが、画像が確認できれば何でも良いです。

# 手順
## 1.ランダムパターンを作成
```python
def make_pattern(shape=(16, 16)):
    return np.random.uniform(0, 1, shape)
```


実行してみる。

```python
pattern = make_pattern((400,400))
plt.imshow(pattern, cmap='gray')
```
![pattern.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329479/ef04ae43-0576-16d2-15de-3eba2389dce7.png)

すでに何かが浮かび上がりそうである。

## 2.浮かび上がらせるパターンを作成
```python
def make_depthmap(shape=(400, 600)):
    depthmap = np.zeros(shape, dtype=np.float)
    cv2.circle(depthmap, (int(shape[1]/2), int(shape[0]/2)), 100, (255 ,255, 255), -1)
    return depthmap
```
実行してみる。

```python
depthmap = make_depthmap()
plt.imshow(depthmap, cmap='gray')
```
![depthmap.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329479/c03263e0-3d5d-91e3-be81-f55a561e969c.png)
こいつが浮かび上がるはずである。

## 3.やってみた

```python

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

def normalize(depthmap):
        return depthmap/255
```

メインの処理は冒頭に挙げた参考サイトから引用させていただきました。
実行してみる。

```python
autostereogram = make_autostereogram(depthmap, pattern, 0.3)
plt.imshow(autostereogram, cmap='gray')
```

![autostereogram.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329479/ef6b0f20-9d1f-6991-5ee0-8befb8d372e0.png)

**はっきりと丸印が浮かび上がっている。**
（交差法といって、目の焦点を近づける方法では丸印が凹んでみえます。）

# せっかくなので
テキストをランダムドットステレオグラムにしてみた。

```python
def make_text_depthmap(shape=(400, 600), text='Q i i t a'):
    font = cv2.FONT_HERSHEY_SIMPLEX
    cv2.putText(depthmap, text, (50, 250), font, 4, (255,255,255), 12, cv2.LINE_AA)
    return depthmap
```
浮かび上がらせるもの。

```python
depthmap_text = make_text_depthmap()
plt.imshow(depthmap, cmap='gray')
```
![depthmap_qiita.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329479/de914e4b-b7fd-9ad8-e357-aa811e6ffac3.png)
実行してみる。

```python

autostereogram = make_autostereogram(depthmap_text, pattern, 0.05)
plt.imshow(autostereogram, cmap='gray')
```
![autostereogram_text.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329479/692b5308-8033-b1a8-e25d-f74ceaaf9971.png)
さっきの丸印よりちょっとぼんやりしてるけど、見えるぞ。

# エンジニアのみなさんにクイズ

なんと書いてあるでしょう？？テキストです。
![autostereogram_quiz.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/329479/ead74d7b-c3c6-8ed1-8b7f-de7fc19cf060.png)

答えはコメント欄でお待ちしています^^

# 追記
続編を書きました。

- [最高のランダムドットステレオグラム(RDS)を求めて。](https://qiita.com/KR_bangkok/items/2f79c218f296f6aaf032)

さらに続編を書きました。

- [機械学習による深度推定で2Dの写真からオリジナルのランダムドットステレオグラム(RDS)を作成する](https://qiita.com/KR_bangkok/items/8fdb403733b41f67339c)