47238
デジカメ画像をモニターに表示する際、固定されたカメラ方位を変更し、図のように画像の表示方位を変えた状態にするにはどうすればよいのでしょうか？[![画像のカメラ方位の変換](https://i.stack.imgur.com/auJ2s.jpg)](https://i.stack.imgur.com/auJ2s.jpg)
CC BY-SA 4.0
2018-08-04T03:49:57.617
47233
2018-08-04T11:26:25.567
2018-08-04T10:35:14.340
19110
29546
question
python python3 windows 画像
pythonで、画像のカメラ方位を変更して表示する方法
pythonで画像処理はPillowらしいです。  
<https://note.nkmk.me/python-pillow-basic/>

今回はこの辺でしょうか。  
<https://note.nkmk.me/python-pillow-concat-images/>

> 余分な部分をカットして連結（結合）  
>  PillowのImage.paste()では貼り付け先の画像の範囲外にはみ出した部分は無視される（カットされる）。

画像がつながるかは別にして、こんな感じでしょうか。

```

    from PIL import Image
    
    def pan_panorama(img, pan):
        """ pan: パンする角度、右回り（左へスライド）する
        """
        width = img.width
        pan = pan % 360 * width // 360
        dst = Image.new('RGB', img.size)
        dst.paste(img, (-pan, 0))
        dst.paste(img, (width-pan, 0))
        return dst
    
    if __name__ == '__main__':
        img = Image.open('panorama.jpg')
        new_img = pan_panorama(img, 120)
        new_img.save('panned.jpg')
    
```
CC BY-SA 4.0
2018-08-04T09:04:08.597
47238
2018-08-04T09:04:08.597
12301
47233
answer
OpenCV を使って書いてみました。

`cv2.warpAffine()` に `M = [[1, 0, dx], [0, 1, dy]]` という行列を与えることで、画像を `(dx,
dy)`
だけ[平行移動することができます](http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_imgproc/py_geometric_transformations/py_geometric_transformations.html#id5)
(参考: ["Shift image content with
OpenCV"](https://stackoverflow.com/q/19068085/5989200))。この関数を使って左と右に平行移動させた後、2つを合成することで回転させています。

```

    import cv2
    import numpy as np
    
    def circular_shift_x(img, dx):
        rows, cols = img.shape[:2]
        if dx < 0:
            dx = cols + dx
    
        m = np.array([[1.0, 0.0, dx], [0.0, 1.0, 0.0]], dtype='float32')
        right = cv2.warpAffine(img, m, (cols, rows))
    
        m = np.array([[1.0, 0.0, dx - cols], [0.0, 1.0, 0.0]], dtype='float32')
        left = cv2.warpAffine(img, m, (cols, rows))
    
        # 現状 warpAffine の fillval はデフォルトで cvScalarAll(0) なので
        # 今回の場合は単に足し合わせるだけで合成できます。
        result = left + right
        return result
    
    # 使用例
    if __name__ == '__main__':
        img = cv2.imread("test.jpg")
        shifted_img = circular_shift_x(img, -100)
    
        cv2.imshow("window", shifted_img)
        cv2.waitKey(0)
        cv2.destroyAllWindows()
    
```
CC BY-SA 4.0
2018-08-04T11:26:25.567
47244
2018-08-04T11:26:25.567
19110
47233
answer