ステーキ定食の画像から物体を選別できないかやってみた - ③類似画像ヒートマップ検出編

# はじめに

[ステーキ定食の画像から物体を選別できないかやってみた - オーバーラップ数編](http://qiita.com/neriai/items/e718290e8b14b0594008)に引き続き、今回はヒストグラム比較をして類似画像の検出を行ってみました。

# 参考

- [Python + OpenCVで画像の類似度を求める](http://qiita.com/best_not_best/items/c9497ffb5240622ede01)

# ソースコード

※ ちょっとリファクタリングしてない箇所ございますが、一旦無視していただければとおもいます。

ちなみに、今回はほぼ同じ画像サイズの矩形を纏めるので、あえて画像のリサイズはしておりません。

```py:group_image.py
# -*- coding: utf-8 -*-

import cv2
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
import selectivesearch
import os

def main():
    # loading lena image
    img = cv2.imread("｛画像ファイル｝")

    # perform selective search
    img_lbl, regions = selectivesearch.selective_search(
        img,
        scale=500,
        sigma=0.9,
        min_size=10
    )

    candidates = set()

    for r in regions:
        # excluding same rectangle (with different segments)
        if r['rect'] in candidates:
            continue

        # excluding regions smaller than 2000 pixels
        if r['size'] < 2000:
            continue

        # distorted rects
        x, y, w, h = r['rect']

        if w / h > 1.2 or h / w > 1.2:
            continue

        candidates.add(r['rect'])

    # draw rectangles on the original image
    fig, ax = plt.subplots(ncols=1, nrows=1, figsize=(6, 6))
    ax.imshow(img)

    overlaps = {}

    # オーバーラップの数をカウントして配列に代入します。
    for x, y, w, h in candidates:
        group = x + y + w + h

        for x2, y2, w2, h2 in candidates:
            if x2 - w < x < x2 + w2 and y2 - h < y < y2 + h2:

                if not group in overlaps:
                    overlaps[group] = 0

                overlaps[group] = overlaps[group] + 1

    # オーバーラップの数が30以上のファイルを出力します（30は勝手に閾値を敷いています）。
    for key, overlap in enumerate(overlaps):
        if overlap > 30:
            for x, y, w, h in candidates:
                group = x + y + w + h

                if group in overlaps:
                    cv2.imwrite("{ファイルパス}" + str(group) + '.jpg', img[y:y + h, x:x + w])

    # ヒストグラム比較をして画像の類似度を算出する
    image_dir = "{ファイルパス}/"
    target_files = os.listdir(image_dir)
    files = os.listdir(image_dir)

    for target_file in target_files:
        if target_file == '.DS_Store':
            continue

        target_image_path = image_dir + target_file
        target_image = cv2.imread(target_image_path)
        target_hist = cv2.calcHist([target_image], [0], None, [256], [0, 256])

        for file in files:
            if file == '.DS_Store' or file == target_file:
                continue

            comparing_image_path = image_dir + file
            comparing_image = cv2.imread(comparing_image_path)
            comparing_hist = cv2.calcHist([comparing_image], [0], None, [256], [0, 256])

            ret = cv2.compareHist(target_hist, comparing_hist, 0)
            probability = ret * 100

            print("target file: " + target_file, "file: " + file, "similarity: " + str(probability) + "%")

if __name__ == "__main__":
    main()
```

# 結果

similarityが100%のものがまったく同じ画像みたいです。
※マイナスになってるのもあるけど...

```
('target file: 1018.jpg', 'file: 250.jpg', 'similarity: 24.8911807562%')
('target file: 1018.jpg', 'file: 369.jpg', 'similarity: 6.78223462382%')
('target file: 1018.jpg', 'file: 389.jpg', 'similarity: 11.1974626968%')
('target file: 1018.jpg', 'file: 432.jpg', 'similarity: 35.179639392%')
('target file: 1018.jpg', 'file: 463.jpg', 'similarity: 79.5281353144%')
('target file: 1018.jpg', 'file: 477.jpg', 'similarity: 51.5870749875%')
('target file: 1018.jpg', 'file: 480.jpg', 'similarity: 55.1832671208%')
('target file: 1018.jpg', 'file: 492.jpg', 'similarity: 88.2822944972%')
('target file: 1018.jpg', 'file: 522.jpg', 'similarity: 76.9528435542%')
('target file: 1018.jpg', 'file: 547.jpg', 'similarity: 84.9997652385%')
('target file: 1018.jpg', 'file: 559.jpg', 'similarity: 77.6441098189%')
('target file: 1018.jpg', 'file: 575.jpg', 'similarity: 76.3571281251%')
('target file: 1018.jpg', 'file: 581.jpg', 'similarity: 76.7456283874%')
('target file: 1018.jpg', 'file: 594.jpg', 'similarity: 31.9957806646%')
('target file: 1018.jpg', 'file: 603.jpg', 'similarity: 85.3813480299%')
('target file: 1018.jpg', 'file: 629.jpg', 'similarity: 88.0957855275%')
('target file: 1018.jpg', 'file: 632.jpg', 'similarity: 60.7236277665%')
('target file: 1018.jpg', 'file: 634.jpg', 'similarity: 62.3073009307%')
('target file: 1018.jpg', 'file: 635.jpg', 'similarity: 65.5935422037%')
('target file: 1018.jpg', 'file: 657.jpg', 'similarity: 56.6421422253%')
('target file: 1018.jpg', 'file: 658.jpg', 'similarity: 82.0967550779%')
('target file: 1018.jpg', 'file: 659.jpg', 'similarity: 89.7396556858%')
('target file: 1018.jpg', 'file: 754.jpg', 'similarity: 78.3236083079%')
('target file: 1018.jpg', 'file: 758.jpg', 'similarity: 79.0903410039%')
('target file: 1018.jpg', 'file: 799.jpg', 'similarity: 89.3025985059%')
('target file: 1018.jpg', 'file: 806.jpg', 'similarity: 97.2873823376%')
('target file: 1018.jpg', 'file: 815.jpg', 'similarity: 93.3345515745%')
('target file: 1018.jpg', 'file: 867.jpg', 'similarity: 81.8261095798%')
('target file: 1018.jpg', 'file: 920.jpg', 'similarity: 93.4987208053%')
('target file: 1018.jpg', 'file: 921.jpg', 'similarity: 90.3518029292%')
('target file: 1018.jpg', 'file: 932.jpg', 'similarity: 94.4258967857%')
('target file: 1018.jpg', 'file: 964.jpg', 'similarity: 10.5652113467%')
('target file: 1018.jpg', 'file: 972.jpg', 'similarity: 98.8755231495%')
----　以下略
```

## 詳細

similarityが90%以上のものはどれくらいなのかというと、

```
('target file: 1018.jpg', 'file: 972.jpg', 'similarity: 98.8755231495%')
```

![1018.jpg](https://qiita-image-store.s3.amazonaws.com/0/90598/fe44481e-3e3c-9abb-2265-95aca14c82a8.jpeg)

![972.jpg](https://qiita-image-store.s3.amazonaws.com/0/90598/e16a8388-255d-9aa8-0090-e88091893f3f.jpeg)

```
('target file: 754.jpg', 'file: 758.jpg', 'similarity: 99.8932682258%')
```
![754.jpg](https://qiita-image-store.s3.amazonaws.com/0/90598/394312ec-9935-7955-a201-5c0a340efd1f.jpeg)

![758.jpg](https://qiita-image-store.s3.amazonaws.com/0/90598/5c06abed-e58c-c844-0b69-3e5d32736301.jpeg)

結構上々な精度な気がします。

# まとめ

一旦結構良い結果がぱっと見はでたみたいなので、次回は類似度の高い画像をグループ化して纏めたいとおもいます。

# 全ページリンク
- [PythonとOpenCVを使って物体検出をやってみた](http://qiita.com/neriai/items/448a36992e308f4cabe2)
- [ステーキ定食の画像から物体を選別できないかやってみた - ①物体検出編](http://qiita.com/neriai/items/d420b78f35033408ccda)
- [ステーキ定食の画像から物体を選別できないかやってみた - ②オーバーラップ数選別編](http://qiita.com/neriai/items/e718290e8b14b0594008)
- [ステーキ定食の画像から物体を選別できないかやってみた - ③類似画像ヒートマップ検出編](http://qiita.com/neriai/items/615c9233582a91a1396a)
- [ステーキ定食の画像から物体を選別できないかやってみた - ④クラスタリング編](http://qiita.com/neriai/items/6df233918513a51a7147)
- [ステーキ定食の画像から物体を選別できないかやってみた - ⑤類似画像特徴点検出編](http://qiita.com/neriai/items/e96d70fc3b89f050daa5)