1#!/usr/bin/env python
2
3# Calculating and displaying 2D Hue-Saturation histogram of a color image
4import sys
5import cv2.cv as cv
6
7def hs_histogram(src):
8    # Convert to HSV
9    hsv = cv.CreateImage(cv.GetSize(src), 8, 3)
10    cv.CvtColor(src, hsv, cv.CV_BGR2HSV)
11
12    # Extract the H and S planes
13    h_plane = cv.CreateMat(src.rows, src.cols, cv.CV_8UC1)
14    s_plane = cv.CreateMat(src.rows, src.cols, cv.CV_8UC1)
15    cv.Split(hsv, h_plane, s_plane, None, None)
16    planes = [h_plane, s_plane]
17
18    h_bins = 30
19    s_bins = 32
20    hist_size = [h_bins, s_bins]
21    # hue varies from 0 (~0 deg red) to 180 (~360 deg red again */
22    h_ranges = [0, 180]
23    # saturation varies from 0 (black-gray-white) to
24    # 255 (pure spectrum color)
25    s_ranges = [0, 255]
26    ranges = [h_ranges, s_ranges]
27    scale = 10
28    hist = cv.CreateHist([h_bins, s_bins], cv.CV_HIST_ARRAY, ranges, 1)
29    cv.CalcHist([cv.GetImage(i) for i in planes], hist)
30    (_, max_value, _, _) = cv.GetMinMaxHistValue(hist)
31
32    hist_img = cv.CreateImage((h_bins*scale, s_bins*scale), 8, 3)
33
34    for h in range(h_bins):
35        for s in range(s_bins):
36            bin_val = cv.QueryHistValue_2D(hist, h, s)
37            intensity = cv.Round(bin_val * 255 / max_value)
38            cv.Rectangle(hist_img,
39                         (h*scale, s*scale),
40                         ((h+1)*scale - 1, (s+1)*scale - 1),
41                         cv.RGB(intensity, intensity, intensity),
42                         cv.CV_FILLED)
43    return hist_img
44
45if __name__ == '__main__':
46    src = cv.LoadImageM(sys.argv[1])
47    cv.NamedWindow("Source", 1)
48    cv.ShowImage("Source", src)
49
50    cv.NamedWindow("H-S Histogram", 1)
51    cv.ShowImage("H-S Histogram", hs_histogram(src))
52
53    cv.WaitKey(0)
54