# 还原挤地铁的参赛作品

下图左边的参赛作品（图片来自网络）掉到地上，重新做太麻烦了，据说改了个《挤地铁》的名字获奖了。

![](./rust_face_origin.jpeg)

我们可以通过 OpenCV 单应性变换的方式帮助挤地铁的人脸还原。

把没挤扁和挤扁的图的坐标标注出来

![](./rust_face_rule.jpg)

可以看到还原后的侧脸

![](./rust_face_homography.jpeg)

以下正确的实现是

## 答案

```python
import cv2
import numpy as np

if __name__ == '__main__':
    img_src = cv2.imread('rust_face_src.jpeg')
    pts_src = np.array([[0, 0], [570, 0], [570, 1078], [0, 1078]])

    img_dst = cv2.imread('rust_face_dest.jpeg')
    pts_dst = np.array([[63, 285], [378, 224], [427, 689], [84, 820]])

    dw, dh = img_dst.shape[1], img_dst.shape[0]

    h, status = cv2.findHomography(pts_src, pts_dst)
    img_out = cv2.warpPerspective(img_src, h, (dw, dh))

    images = np.concatenate((img_src[0: dh, 0:dw, 0:3], img_dst, img_out), axis=1)
    cv2.imshow('homography', images)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
```

## 选项

### 映射位置不匹配

```python
import cv2
import numpy as np

if __name__ == '__main__':
    img_src = cv2.imread('rust_face_src.jpeg')
    pts_src = np.array([[0, 0], [0, 1078], [570, 0], [570, 1078]])

    img_dst = cv2.imread('rust_face_dest.jpeg')
    pts_dst = np.array([[63, 285], [378, 224], [427, 689], [84, 820]])

    dw, dh = img_dst.shape[1], img_dst.shape[0]

    h, status = cv2.findHomography(pts_src, pts_dst)
    img_out = cv2.warpPerspective(img_src, h, (dw, dh))

    images = np.concatenate((img_src[0: dh, 0:dw, 0:3], img_dst, img_out), axis=1)
    cv2.imshow('homography', images)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
```

### 源图和目标图片错位

```python
import cv2
import numpy as np

if __name__ == '__main__':
    img_src = cv2.imread('rust_face_src.jpeg')
    pts_src = np.array([[0, 0], [0, 1078], [570, 0], [570, 1078]])

    img_dst = cv2.imread('rust_face_dest.jpeg')
    pts_dst = np.array([[63, 285], [378, 224], [427, 689], [84, 820]])

    dw, dh = img_dst.shape[1], img_dst.shape[0]

    h, status = cv2.findHomography(pts_dst, pts_src)
    img_out = cv2.warpPerspective(img_src, h, (dw, dh))

    images = np.concatenate((img_src[0: dh, 0:dw, 0:3], img_dst, img_out), axis=1)
    cv2.imshow('homography', images)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
```

### 目标长宽用错

```python
import cv2
import numpy as np

if __name__ == '__main__':
    img_src = cv2.imread('rust_face_src.jpeg')
    pts_src = np.array([[0, 0], [0, 1078], [570, 0], [570, 1078]])

    img_dst = cv2.imread('rust_face_dest.jpeg')
    pts_dst = np.array([[63, 285], [378, 224], [427, 689], [84, 820]])

    dw, dh = img_dst.shape[1], img_dst.shape[0]

    h, status = cv2.findHomography(pts_dst, pts_src)
    img_out = cv2.warpPerspective(img_src, h, (dh, dw))

    images = np.concatenate((img_src[0: dh, 0:dw, 0:3], img_dst, img_out), axis=1)
    cv2.imshow('homography', images)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
```
