3#include "../_cexports/c_light_meter.h"
5#include "../global.hpp"
7#include "../exception.hpp"
9#include "../area_2d.hpp"
32namespace HistogramAnalyzer
49 : numPixels_(0), median_(0), mean_(0.0), mode_ (0.0), min_(0.0), max_(0.0), variance_(0.0), standardDeviation_(0.0), values_()
53 Histogram (CExports::LMH lmHandle,
int plane)
54 : numPixels_(0), median_(0), mean_(0.0), mode_ (0.0), min_(0.0), max_(0.0), variance_(0.0), standardDeviation_(0.0), values_()
57 size_t numEntries = 0;
58 CVB_CALL_CAPI_CHECKED (LMGetDataBufferEntries (lmHandle, plane, &numEntries));
59 values_.resize (numEntries);
60 for (
size_t i = 0; i < numEntries; ++i)
63 CVB_CALL_CAPI_CHECKED (LMGetSingleHistogramEntry(lmHandle, plane, i, &val));
64 values_[i] =
static_cast<uint64_t
> (std::llround (val));
69 CVB_CALL_CAPI_CHECKED (LMGetStatisticTotal (lmHandle, plane, &out));
70 numPixels_ =
static_cast<uint64_t
> (std::llround (out));
71 CVB_CALL_CAPI_CHECKED (LMGetStatisticMean (lmHandle, plane, &mean_));
72 CVB_CALL_CAPI_CHECKED (LMGetStatisticMode (lmHandle, plane, &mode_));
73 CVB_CALL_CAPI_CHECKED (LMGetStatisticMin (lmHandle, plane, &min_));
74 CVB_CALL_CAPI_CHECKED (LMGetStatisticMax (lmHandle, plane, &max_));
75 CVB_CALL_CAPI_CHECKED (LMGetStatisticVariance (lmHandle, plane, &variance_));
76 CVB_CALL_CAPI_CHECKED (LMGetStatisticStdDev (lmHandle, plane, &standardDeviation_));
77 median_ = CalculateMedianIndex();
82 int CalculateMedianIndex()
const noexcept
85 for (uint64_t countBelow = 0; (idx < values_.size ()) && (countBelow < (numPixels_ / 2)); ++idx)
87 countBelow += values_[idx];
89 return static_cast<int>(idx);
139 double Min () const noexcept
149 double Max () const noexcept
171 return standardDeviation_;
181 return static_cast<int>(values_.size());
202 if (
static_cast<std::size_t>(index) >= values_.size())
207 return values_[index];
218 double standardDeviation_;
224typedef HandleGuard<void, CVB_CALL_CAPI(ReleaseLMVoid)> ReleaseLMGuard;
231 CExports::LMH hLM = 0;
232 CVB_CALL_CAPI_CHECKED (LMCreate (&hLM));
233 ReleaseLMGuard hLMHolder (
reinterpret_cast<void*
>(hLM));
235 CVB_CALL_CAPI_CHECKED (LMSetImage(hLM, image.Handle()));
236 for (CExports::cvbdim_t i = 0; i < image.PlanesCount (); ++i)
238 CVB_CALL_CAPI_CHECKED (LMSetEntireImageFlag (hLM, i,
false));
239 CVB_CALL_CAPI_CHECKED (LMSetProcessFlag (hLM, i,
true));
242 for (CExports::cvbdim_t i = 0; i < image.PlanesCount(); ++i)
244 CVB_CALL_CAPI_CHECKED (LMSetDensity(hLM, i, std::lround(density * 1000.0)));
245 CVB_CALL_CAPI_CHECKED (LMSetUseCSFlag(hLM, i, !ignoreImageCs));
246 CVB_CALL_CAPI_CHECKED (LMSetArea(hLM, i,
reinterpret_cast<CExports::TArea&
>(aoi)));
248 CVB_CALL_CAPI_CHECKED (LMExecute(hLM));
250 for (CExports::cvbdim_t i = 0; i < image.PlanesCount (); ++i)
252 histograms.push_back (
Histogram (hLM, i));
273 return Private::CreateHistograms (image,
Area2D(
static_cast<Rect<double>>(aoi)), density,
true);
289 return Private::CreateHistograms (image, aoi, density,
false);
369template <
class HISTVAL>
375 auto firstValue = histogram[0];
376 for (
size_t i = 0, bckOffset = kernelSize / 2; i < bckOffset; ++i)
378 result[j++] =
static_cast<double> (firstValue);
381 for (
size_t i = 0; i < histogram.size(); ++i)
383 result[j++] =
static_cast<double> (histogram[i]);
386 auto lastValue = histogram[histogram.size() - 1];
387 for (; j < result.size (); ++j)
389 result[j] =
static_cast<double> (lastValue);
395template <
class RANGE>
396inline typename TypedRange<std::vector<double>, double, RANGE>::type ApplyKernel (
const std::vector<double> &borderedHistogram,
const RANGE &kernel)
398 auto kernelRange = MakeRangeAdapter<double> (kernel, 1);
401 for (
size_t i = 0; i < result.size(); ++i)
404 for (
size_t k = 0; k < kernelRange.Size (); ++k)
406 val += borderedHistogram[i + k] * kernel[k];
416 auto itNonZero = std::find_if (derivedHistogram.begin (), derivedHistogram.end (), [](
double val) {return val != 0.0; });
417 if (itNonZero == derivedHistogram.end())
422 size_t i = std::distance (derivedHistogram.begin(), itNonZero);
424 auto sign = [](
double val) {
return (val == 0.0) ? 0 : ((val < 0.0) ? -1 : 1); };
427 auto lastStart = i++;
428 auto lastSign = sign (derivedHistogram[lastStart]);
429 for (; i < derivedHistogram.size(); i++)
433 auto thisSign = sign (derivedHistogram[i]);
436 if (thisSign != lastSign)
438 auto peakPos = (i + lastStart) / 2;
439 positions.push_back(PeakData{
static_cast<int>(peakPos), blurredHistogram[peakPos]});
451 std::sort (descendingCrossings.begin (), descendingCrossings.end (), [](PeakData first, PeakData second) { return first.Quality > second.Quality; });
453 std::transform (descendingCrossings.begin (), descendingCrossings.end (), values.begin (), [](PeakData peak) { return peak.GrayValue; });
455 for (
size_t i = 0; i < values.size() - 1; ++i)
457 for (
size_t k = i + 1; k < values.size(); ++k)
459 auto diff = std::abs (values[i] - values[k]);
462 values.erase (values.begin() + k--);
481template <
class HISTVAL,
class RANGE>
484 auto kernelSize = std::distance(std::begin(kernel), std::end(kernel));
485 if ((kernelSize < 1) || (
static_cast<size_t>(kernelSize) > histogram.size()))
490 auto borderedHistogram = Private::MakeBorderedHistogram (histogram, kernelSize);
491 return Private::ApplyKernel (borderedHistogram, kernel);
505 if ((blurSize < 1) || (
static_cast<size_t>(blurSize) > histogram.size()) || (minDiff < 1))
510 auto blurredHistogram =
FilterHistogram (histogram, Private::MakeBlurFilter(
static_cast<int>(blurSize)));
511 auto derivedHistogram =
FilterHistogram (blurredHistogram, Private::MakeDerivationFilter());
512 auto zeroCrossings = Private::FindZeroCrossings (blurredHistogram, derivedHistogram);
513 return Private::FilterByMinDistance (zeroCrossings, minDiff);
527 if ((lowerLimit < 0) || (
static_cast<size_t>(upperLimit) >= histogram.size()))
533 for (
int i = lowerLimit; i <= upperLimit; ++i)
535 nres += histogram[i];
542using HistogramAnalyzer::Histogram;
Structure that represents an area of interest in the image.
Definition: area_2d.hpp:21
A single histogram result.
Definition: histogram_analyzer.hpp:46
double Mean() const noexcept
Get the mean value of all pixels.
Definition: histogram_analyzer.hpp:119
double Min() const noexcept
Get the minimum gray value of the histogram.
Definition: histogram_analyzer.hpp:139
uint64_t Median() const noexcept
Get the median index (index of the histogram slot, at which roughly 50% of the pixels are darker and ...
Definition: histogram_analyzer.hpp:108
int Count() const noexcept
The number of elements corresponds to the number of possible gray values.
Definition: histogram_analyzer.hpp:179
std::vector< uint64_t > Values() const
The actual histogram values.
Definition: histogram_analyzer.hpp:189
double Variance() const noexcept
Get the variance of the histogram.
Definition: histogram_analyzer.hpp:159
uint64_t operator[](int index) const
Gets the histogram value at given index.
Definition: histogram_analyzer.hpp:200
double Max() const noexcept
Get the maximum gray value of the histogram.
Definition: histogram_analyzer.hpp:149
double StandardDeviation() const noexcept
Get the standard deviation of the histogram.
Definition: histogram_analyzer.hpp:169
uint64_t NumPixels() const noexcept
Total number of pixels taken into account.
Definition: histogram_analyzer.hpp:98
double Mode() const noexcept
Get the mode (the most common gray value) of the histogram.
Definition: histogram_analyzer.hpp:129
The Common Vision Blox image.
Definition: decl_image.hpp:45
Image plane information container.
Definition: decl_image_plane.hpp:33
std::unique_ptr< Image > Map() const
Create a map from a single image plane that shares its memory with the original plane.
Definition: detail_image_plane.hpp:100
std::vector< int > FindHistogramPeaks(const std::vector< uint64_t > &histogram, int blurSize, int minDiff)
Find peaks in the histogram identified by the supplied criteria.
Definition: histogram_analyzer.hpp:503
uint64_t SumHistogramBetween(const std::vector< uint64_t > &histogram, int lowerLimit, int upperLimit)
Count the number of pixels that lie between two limits in the histogram.
Definition: histogram_analyzer.hpp:525
std::vector< Histogram > CreateImageHistograms(const Image &image, Rect< int > aoi, double density=1.0)
Creates a histogram for each plane of the aoi in the given image.
Definition: histogram_analyzer.hpp:271
TypedRange< std::vector< double >, double, RANGE >::type FilterHistogram(const std::vector< HISTVAL > &histogram, const RANGE &kernel)
Filter a histogram array with the given kernel. At the beginning and end of the histogram,...
Definition: histogram_analyzer.hpp:482
Histogram CreatePlaneHistogram(const ImagePlane &imagePlane, Rect< int > aoi, double density=1.0)
Creates a histogram for the aoi in the given plane.
Definition: histogram_analyzer.hpp:316
Root namespace for the Image Manager interface.
Definition: c_barcode.h:24
std::vector< int > Histogram(const ImagePlane &plane, Area2D aoi, double density=1.0)
Gather and return the histogram from an 8 bits per pixel unsigned image.
Definition: analyze.hpp:31