Pynote

Python、機械学習、画像処理について

OpenCV - 2枚の画像の類似度を compareHist() で計算する。

概要

OpenCV の compareHist() を使用して画像同士の類似度を計算する方向について

pynote.hatenablog.com

compareHist()

compareHist()ヒストグラム同士の比較を行い、類似度を算出できる。
ヒストグラムが1次元、2次元、3次元ヒストグラムに対応している。

retval = cv2.compareHist(H1, H2, method)

サンプルコード

比較元画像 きつね

比較先画像1 猫

比較先画像2 比較元画像を一度拡大して元のサイズに戻したもの

比較先画像3 もち

比較する画像を読み込む。

import cv2
import matplotlib.pyplot as plt
import numpy as np

# 画像を読み込む。
base = cv2.imread('sample1.jpg')  # 画像
test1 = cv2.imread('sample2.jpg')  # 比較対象画像1
test2 = cv2.imread('sample3.jpg')  # 比較対象画像2
test3 = cv2.imread('sample4.jpg')  # 比較対象画像3

類似度の計算は次のように行う。

1. 画像を HSV 形式に変換する。
2. 各チャンネルごとに2つの画像のヒストグラムを計算し、その類似度を計算する。
3. すべてのチャンネルの類似度の平均を最終的な類似度とする。

def test_similarity(img1, img2):
    ch_names = {0: 'Hue', 1: 'Saturation', 2: 'Brightness'}

    # HSV に変換する。
    hsv1 = cv2.cvtColor(img1, cv2.COLOR_BGR2HSV)
    hsv2 = cv2.cvtColor(img2, cv2.COLOR_BGR2HSV)

    # 各チャンネルごとにヒストグラムの類似度を算出する。
    scores, hists1, hists2 = [], [], []
    for ch in ch_names:
        h1 = cv2.calcHist(
            [hsv1], [ch], None, histSize=[256], ranges=[0, 256])
        h2 = cv2.calcHist(
            [hsv2], [ch], None, histSize=[256], ranges=[0, 256])
        score = cv2.compareHist(h1, h2, cv2.HISTCMP_CORREL)
        hists1.append(h1)
        hists2.append(h2)
        scores.append(score)
    mean = np.mean(scores)
    
    fig, axes = plt.subplots(2, 2, figsize=(8, 8))
    for [axL, axR], hist, img in zip(axes, [hists1, hists2], [img1, img2]):
        # 画像を描画する。
        axL.imshow(img[..., ::-1])
        axL.axis('off')
        # ヒストグラムを作成する。
        for i in range(3):
            axR.plot(hist[i], label=ch_names[i])
        axR.legend()
    fig.suptitle('similarity={:.2f}'.format(mean))
    plt.show()

実行する。

test_similarity(base, test1)
test_similarity(base, test2)
test_similarity(base, test3)