EnsekiTT Blog

EnsekiTTが書くブログです。

改善を期待してHSV色空間でヒストグラム比較をしてみた話

つまりなにしたの?

前回あまりにも、残念な結果だったヒストグラム比較。
RGBでのヒストグラムを連結して比較したものから、HSV色空間でのヒストグラム比較に変更してみた。
今更OpenCVのドキュメントを読んでこっちが正攻法っぽいのでやってみることにした。
参考: OpenCV: Histogram Comparison
あと評価の仕方がよくわからないので結果に関しては感覚的なことしか言えないけど、やや改善したように見える。
f:id:ensekitt:20180814125755j:plain

前回の話

ensekitt.hatenablog.com
カラーの傾向とかもあまりなく、同じ写真同士が近くにある程度の能力

おおまかな手順

  • ベースになるイメージを読み込む
  • ベースになるイメージをHSV色空間でヒストグラム化する #ここと
  • ヒストグラムを正規化する #ここが変わった
  • フォルダ内の画像リストを作成する
  • すべての画像についてベースとの近さをパラメータ化したリストを作成する
  • パラメータでリストをソートする
  • ソート済のリストをもとに新しいフォルダに採番済の名前でコピーする

https://docs.opencv.org/3.4.2/d8/dc8/tutorial_histogram_comparison.html

環境

 % python --version
Python 3.6.4
 % pip freeze
opencv-python==3.4.0.12
matplotlib==2.1.2
numpy==1.14.1

フォルダ

.
├── base.jpg
├── img_sort.py
├── images
└── results # 実行するとできる

コード

import glob
import cv2
import numpy as np
import matplotlib.pyplot as plt
import os
import shutil

# 画像を読み込んでベクトル化する関数
h_bins = 50
s_bins = 60
histSize = [h_bins, s_bins]

h_ranges = [0, 180]
s_ranges = [0, 256]
ranges = h_ranges + s_ranges # concat lists

def img2hist(filename):
    img = cv2.imread(filename) 
    # ベースになるイメージをHSV色空間でヒストグラム化する
    img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    hist = cv2.calcHist([img], [0,1], None, histSize, ranges, accumulate=False)
    # ヒストグラムを正規化する
    cv2.normalize(hist, hist, alpha=0, beta=1, norm_type=cv2.NORM_MINMAX)
    return hist

# ベースになるイメージを読み込む
base_path = "base.jpg"

# ベースになるイメージをヒストグラム化する
basehist = img2hist(base_path)

# フォルダ内の画像リストを作成する
image_path = "images/*.jpg"
path_list = glob.glob(image_path)

# すべての画像についてベースとの近さをパラメータ化したリストを作成する
image_list = []
for path in path_list:
    targethist = img2hist(path)
    simi = cv2.compareHist(basehist, targethist, 3) #3はBhattacharyya distanceのこと
    image_list.append((simi, path))

# パラメータでリストをソートする
sorted_list = sorted(image_list, key=lambda tgt: tgt[0], reverse=True) 

# ソート済のリストをもとに新しいフォルダに採番済の名前でコピーする
result_dir = "results"
if not os.path.exists(result_dir):
    os.mkdir(result_dir)
for i, info in enumerate(sorted_list):
    new_path = os.path.join(result_dir, "{0:08d}.jpg".format(i))
    temp_path = info[1]
    shutil.copyfile(temp_path, new_path)

やってみた結果

f:id:ensekitt:20180814125731j:plain

クリエイティブ・コモンズ・ライセンス
この 作品 は クリエイティブ・コモンズ 表示 4.0 国際 ライセンスの下に提供されています。