HistogramProcessor
Code Documentation & Explanation
This document explains the C++ source file [Link], which is part of a
computer vision processing pipeline built on top of OpenCV. The class provides tools for
computing, visualizing, equalizing, and normalizing image histograms.
1. Overview
A histogram in image processing is a graph that shows how pixel intensity values (0 = black,
255 = white) are distributed across an image. The HistogramProcessor class (inside the
processing namespace) offers five main operations:
Method Purpose
compute() Compute full histogram data for all channels of an image
computeChannel() Compute histogram for a single grayscale channel
equalize() Improve image contrast using histogram equalization
normalize() Stretch pixel values to cover the full 0-255 range
renderHistogram() Draw a line-chart histogram plot (dark background)
renderHistogramWithCurve() Draw bar histogram + Gaussian curve overlay
2. Data Structures
ChannelHistogram
Holds all computed data for one color channel (Blue, Green, Red, or Gray):
Field Type Description
label string Channel name: "Blue", "Green", "Red", or "Gray"
bins vector<float> 256 values — count of pixels at each intensity (0-255)
cdf vector<float> Cumulative Distribution Function, normalized to 0.0 - 1.0
mean double Average pixel intensity (weighted by bin counts)
stddev double Standard deviation of pixel intensities
HistogramResult
The top-level return value of compute(). It contains:
- channels: a list of ChannelHistogram objects (1 for grayscale, 3 for BGR)
- plotImage: an OpenCV Mat image of the line-chart histogram
- plotImageWithCurve: an OpenCV Mat image of bars + Gaussian overlay
3. Method-by-Method Breakdown
3.1 compute(const cv::Mat& input)
This is the main entry point. It accepts an OpenCV image (Mat) and returns a complete
HistogramResult. The steps are:
1. Validate input — throws an exception if the image is empty.
2. Split channels — for a 3-channel BGR image it splits into Blue, Green, Red mats; a
grayscale image is kept as-is.
3. Compute per-channel data — calls computeChannel() for each channel and stores results.
4. Render plots — generates both histogram images and attaches them to the result.
3.2 computeChannel(channel, label)
The workhorse of the class. For a single 8-bit grayscale Mat it:
1. Calls cv::calcHist() to count how many pixels fall into each of the 256 intensity buckets.
2. Builds the CDF: runs a cumulative sum over the bins, then divides by total pixel count so
every value is in [0, 1].
3. Computes the mean: weighted average of intensity values using bin counts as weights.
4. Computes the standard deviation (stddev): measures how spread out the intensities are
around the mean. A high stddev means the image has high contrast.
Math used:
Mean: mean = sum(i * bins[i]) / totalPixels for i in 0..255
Variance: var = sum(bins[i] * (i - mean)^2) / totalPixels
StdDev: stddev = sqrt(variance)
3.3 equalize(const cv::Mat& input)
Histogram equalization redistributes pixel intensities so that the image uses the full 0-255
range more evenly. This typically makes dark images brighter and increases overall contrast.
- For grayscale images: directly calls cv::equalizeHist().
- For color (BGR) images: converts to YCrCb color space, equalizes only the Y (luminance)
channel, then converts back. This avoids shifting colors — only brightness is adjusted.
3.4 normalize(const cv::Mat& input)
Calls cv::normalize() with NORM_MINMAX so the darkest pixel becomes 0 and the brightest
becomes 255. Unlike equalization, this is a simple linear stretch — it does not change the
shape of the histogram, only its scale.
3.5 renderHistogram() — Line Chart
Produces a 512 x 400 pixel image (black background) showing the histogram of each channel
as a colored line:
- Blue channel → blue line
- Green channel → green line
- Red channel → red line
Each bin's line segment connects the (scaled) count of the current bin to the next. The height
of each point is proportional to the bin count divided by the maximum bin count.
3.6 renderHistogramWithCurve() — Bars + Gaussian Overlay
A more detailed visualization on a dark (#141414) background with two layers:
Layer 1 — Histogram bars: each of the 256 bins is drawn as a filled rectangle. Colors are
muted (dark blue / green / red) so they don't overpower the curve.
Layer 2 — Gaussian curve: a smooth bell-curve overlay is drawn using the channel's mean
and stddev. The formula is:
gaussVal(x) = maxBinCount * exp( -0.5 * ((x - mean) / stddev)^2 )
This curve peaks at the mean and has width proportional to stddev. It lets you visually
compare the actual distribution against an ideal Gaussian. A subtle horizontal baseline is also
drawn at the bottom of the plot.
4. Color Mapping Summary
Channel Bar Color (BGR) Curve Color (BGR)
Blue (130, 60, 60) — dark blue-ish (255, 120, 120) — bright blue
Green (60, 130, 60) — dark green (120, 255, 120) — bright green
Red (60, 60, 130) — dark red-ish (120, 120, 255) — bright red
Gray (90, 90, 90) — mid-gray (255, 255, 255) — white
Note: OpenCV uses BGR (Blue-Green-Red) channel order, not the more familiar RGB.
5. Edge Cases & Safety Checks
- Empty image: all public methods throw std::runtime_error immediately.
- Zero pixel sum: division by zero is guarded; mean, stddev, and CDF remain 0.
- Flat image (constant color): stddev < 1e-6 causes the Gaussian curve to be skipped in
renderHistogramWithCurve() to avoid a degenerate spike.
- maxValue == 0 histogram: render functions return a blank image immediately.
6. Quick Usage Example (C++)
cv::Mat img = cv::imread("[Link]"); processing::HistogramProcessor proc; //
Compute histogram auto result = [Link](img); // Access stats for the Blue
channel std::cout << [Link][0].mean << std::endl; // Show the bar+curve plot
cv::imshow("Histogram", [Link]); // Equalize and normalize cv::Mat
eq = [Link](img); cv::Mat nrm = [Link](img);
Generated by Claude | [Link] Documentation