OpenCVのcalcHist()
は任意の**数の画像/チャンネルのヒストグラムを計算できます。返されるヒストグラムは、入力画像内のチャンネル数と同数の軸を持ち、各軸は、そのチャンネル用に指定されたビンと同数の値を持ちます。たとえば、RGBDイメージがあるとします。つまり、赤、青、緑、深度の4つのチャンネルがあります。あなたは、このような画像のヒストグラムを計算何らかの理由したい場合は、OpenCVのは、次のことができます。
import cv2
import numpy as np
img = cv2.imread('lane.jpg')
img = np.dstack([img, img[:, :, 0]])
print('Input image shape:', img.shape)
n_channels = img.shape[2]
channels = list(range(n_channels))
sizes = [8,]*n_channels
ranges = [0, 255]*n_channels
hist = cv2.calcHist(img, channels, None, sizes, ranges)
print('Output histogram shape: ', hist.shape)
入力画像形状:(540、960、4)
出力ヒストグラムの形状:(8、 8,8,8)
np.dstack([img, img[:, :, 0]])
私は、単に画像の最後に4番目のチャンネルとして最初のチャンネルを追加しています。あなたは9のチャネルの深さで画像上で実行するようにプログラムを変更し、出力9Dヒストグラムを得ることができます:
img = cv2.imread('lane.jpg')
img = np.dstack([img, img, img])
print('Input image shape:', img.shape)
n_channels = img.shape[2]
channels = list(range(n_channels))
sizes = [8,]*n_channels
ranges = [0, 255]*n_channels
hist = cv2.calcHist(img, channels, None, sizes, ranges)
print('Output histogram shape: ', hist.shape)
入力画像形状:(540、960、9)
出力ヒストグラムを形状:(8,8、8,8、8,8、8,8、8)ここ
のみ変形Iは単純で画像を作成する画像を3回積層dstack
ラインに再度ました9チャンネル。
マルチチャンネル配列の場合、軸が少し違うと思っています。 x
、y
などと呼ぶのではなく、ch1bins, ch2bins, ...
というように、それぞれのチャネルからbins
と考える必要があります。単一チャンネルの画像のヒストグラムを取る場合は、確かめてください。 プロットの場合、x
軸にはビンがあり、y
軸にはカウントがありますが、これはプロットする方法です。実際には、ビンの配列と数の配列を持っています。 2チャンネル画像のヒストグラムをプロットして3D棒グラフで視覚化した場合、x
軸にはビンがありますが、y
軸にも同様の軸があり、その場合はz
軸にカウントがあります。 x
軸には最初のチャネルのビンがあり、y
軸には2番目のチャネルのビンがあります。 3チャンネルの画像を持っていて、プロットで視覚化するには、3つの軸すべてが各チャンネルに対応するビンであるため、各ビンの数量を他のもので視覚化する必要があります。そのビン、または強度や何かに基づいてマーカーを色付けする必要があります。
OpenCV docs for calcHist()
には、色相と彩度のヒストグラムを分析できる2Dヒストグラム(つまり、2チャネル)の例があります。つまり、ある色相と彩度の範囲(0〜32の色相、および144と176の彩度)に対して、その範囲内のピクセル数を確認できます。
3Dヒストグラムの例については、check out some I've plottedとすることができます。ヒストグラムにOpenCVを使用しなかったのは...あなたがこの質問をするまで3Dヒストグラムを行うことができたのは実際にはわかりませんでした。しかし、numpy
はOpenCVのようにD次元のヒストグラムをすべて同じにすることができます。これらのプロットでは、マーカーの色はbinが表す実際の色に対応し、マーカーのサイズは各ビンの値の数にいくらか対応します。
3Dヒストグラムを取って、各チャンネルの暗くて明るいカウントを知りたいとしましょう。だから各チャンネルの2つのビンだけでヒストグラムを取る。その後、私のビンは次のようになります。
- チャンネル0:
[0, 127], [128, 255]
- チャンネル1:
[0, 127], [128, 255]
- チャンネル2:
[0, 127], [128, 255]
は値[0, 255, 0]
でピクセルを取ります。これは、チャネル0のビン0、チャネル1のビン1、チャネル3のビン0に対応します。そこにはどれだけの可能性がありますか?画素がビンであり得る:
- 0、0、0
- 0、0、1
- 0、1、0
- 0、1、1
- 1,0,0
- 1、0、1
- 1、1、0
- 1、1、1
8つの可能性があります。すべてのRGB値を3空間にプロットすると、これらの軸のそれぞれを2つに分割すると、8つのヒストグラムビンが得られます。次に、これらの8つのビンのそれぞれの数を単純に数えます。これがヒストグラムです。上記のリストを見ると、この単純なヒストグラムは、ビン0、0、0に対応するダークピクセルの数、ライトピクセルの数(1,1,1に対応する)、ほとんど緑の数ピクセルには(0,1,0)などがあります。そして実際これは、OpenCVのは与えるものである:
img = cv2.imread('lane.jpg')
print('Input image shape:', img.shape)
n_channels = img.shape[2]
channels = list(range(n_channels))
sizes = [2, 2, 2]
ranges = [0, 255]*n_channels
hist = cv2.calcHist(img, channels, None, sizes, ranges)
print('Output histogram shape: ', hist.shape)
入力画像形状:(540、960、3)
出力ヒストグラムの形状:(2、2、2)
マルチチャネルヒストグラムの全体的なポイントは、各チャネルごとにいくつかの値の範囲内にいくつのピクセルがあるか把握することです。うまくいけば、このポストはそれをいくつかクリアしました!
**注:チャンネル数が多い小さなビンサイズを使用しないでください。メモリが不足している場合はすぐに使い果たします。