OpenCVをPythonで文字の場所をレシートから取得する

# 概要
　レシートに対して入力されている文字の場所を取得する。
## 環境
- OpenCV-python　Version: 4.1.0.25
- Python 3.6.8
- Windows 10

## 処理内容

1. 画像の読み取り
2. ガウシアンフィルタで画像の平滑化
3. Laplacianを使った画像の勾配検出
4. 大津の手法を使った画像の２値化
5. モルフォロジー変換(クロージング)
6. 純粋なクロージング
7. Laplacianを使った画像の勾配検出
8. 外接矩形

## 1. 画像の読み取り
![original.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247538/719e3dd0-17d3-9859-84e7-27567b570d2f.jpeg)

```text_detection.py
input_original_data = 'target_img.jpg'
img = cv2.imread(input_original_data)
h, s, gray = cv2.split(cv2.cvtColor(img, cv2.COLOR_BGR2HSV))
```

## 2. ガウシアンフィルタで画像の平滑化
```text_detection.py
size = (3, 3)
blur = cv2.GaussianBlur(gray, size, 0)
```
![1_blur.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247538/91bf8685-77a6-b7b6-516c-e3780f49baaf.jpeg)

## 3. Laplacianを使った画像の勾配検出
```text_detection.py
lap = cv2.Laplacian(blur, cv2.CV_8UC1)
```
![2_laplacian.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247538/fbb7914e-278f-8c0c-90e8-abbc9e5133de.jpeg)

※２値化で必要なためcv2.CV_8UC1にする
## 4. 大津の手法を使った画像の２値化
```text_detection.py
ret2, th2 = cv2.threshold(lap, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
```
![3_th2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247538/4797c120-388e-d20e-1748-5a162ba7fcee.jpeg)

## 5. モルフォロジー変換(クロージング)
```text_detection.py
kernel = np.ones((3, 20), np.uint8)
closing = cv2.morphologyEx(th2, cv2.MORPH_CLOSE, kernel)
```
![4_closing.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247538/e287bfd6-47d1-842d-ad0d-33e7f6d4123e.jpeg)

※縦×横の配列は扱う画像により調整する
## 6. 純粋なクロージング
```text_detection.py
kernel = np.ones((3, 3), np.uint8)
dilation = cv2.dilate(closing, kernel, iterations = 1)
erosion = cv2.erode(dilation, kernel, iterations = 1)
```
![6_erosion.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247538/99c2fd59-3e73-4491-2f9d-3635d1a55ac6.jpeg)

## 7. Laplacianを使った画像の勾配検出
```text_detection.py
lap2 = cv2.Laplacian(erosion, cv2.CV_8UC1)
```
![7_laplacian_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247538/cc76a90e-fce7-269f-1f5c-809d71a360c0.jpeg)

## 8. 外接矩形
```text_detection.py
contours, hierarchy = cv2.findContours(lap2, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
min_area = img.shape[0] * img.shape[1] * 1e-4
tmp = img.copy()
if len(contours) > 0:
    for i, contour in enumerate(contours):
        rect = cv2.boundingRect(contour)
        if rect[2] < 10 or rect[3] < 10:
            continue
        area = cv2.contourArea(contour)
        if area < min_area:
            continue
        cv2.rectangle(tmp, (rect[0], rect[1]), (rect[0]+rect[2], rect[1]+rect[3]), (0, 255, 0), 2)
```
![8_1_findContours.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/247538/ae3cbacc-f9b7-8cc5-392b-d30c4a632f57.jpeg)

## まとめ
　参考にした元のソースがpython以外で書かれていたため、アップされている画像と少し違う状態になっているが、だいたいやっていることは同じです。pythonベースで書かれているソースをgitに挙げています。　
　https://github.com/chibadai/data/blob/master/py/20190616/text_detection.py
## その他
　画像中からレシートのみを検出して最初に切り取りを行うことで検出の精度が上がったり、その後の文字検出なんかでも使えると思うので、論文の文字起こしとかで使えるかと。
## 参考URL
- http://nikoyuwono.com/2015/10/05/receipt-scanner/
- http://pongsuke.hatenadiary.jp/entry/2017/05/19/171130