123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 |
- Tutorial: Histogram
- ===================
- .. contents::
- :local:
- :depth: 1
- This is a short tutorial presenting an example of a very simple sample of code
- from an existing code base that calculates histogram of an image.
- Next, the program is rewritten using GIL featres.
- Original implementation
- -----------------------
- Actual code from a commercial software product that computes the luminosity
- histogram (variable names have been changed and unrelated parts removed):
- .. code-block:: cpp
- void luminosity_hist(
- std::uint8_t const* r, std::uint8_t const* g, std::uint8_t const* b,
- int rows, int cols, int sRowBytes, Histogram* hist)
- {
- for (int r = 0; r < rows; r++)
- {
- for (int c = 0; c < cols; c++)
- {
- int v = RGBToGray(r[c], g[c], b[c]); // call internal function or macro
- (*hist)[v]++;
- }
- r += sRowBytes;
- g += sRowBytes;
- b += sRowBytes;
- }
- }
- Let's consider the following issues of the implementation above:
- - Works only for RGB (duplicate versions exist for other color spaces)
- - Works only for 8-bit images (duplicate versions exist)
- - Works only for planar images
- GIL implementation
- ------------------
- .. code-block:: cpp
- template <typename GrayView, typename R>
- void grayimage_histogram(GrayView& img, R& hist)
- {
- for (typename GrayView::iterator it=img.begin(); it!=img.end(); ++it)
- ++hist[*it];
- }
- template <typename View, typename R>
- void luminosity8bit_hist(View& img, R& hist)
- {
- grayimage_histogram(color_converted_view<gray8_pixel_t>(img),hist);
- }
- Using the Boost.Lambda library (or C++11 lambda) features it can written
- even simpler:
- .. code-block:: cpp
- using boost::lambda;
- template <typename GrayView, typename R>
- void grayimage_histogram(GrayView& img, R& hist)
- {
- for_each_pixel(img, ++var(hist)[_1]);
- }
- Let's consider the following advantages of the GIL version:
- - Works with any supported channel depth, color space, channel ordering
- (RGB vs BGR), and row alignment policy.
- - Works for both planar and interleaved images.
- - Works with new color spaces, channel depths and image types that can be
- provided in future extensions of GIL
- - The second version is as efficient as the hand-coded version
- Shortly, it is also very flexible.
- For example, to compute the histogram of the second channel of the top left
- quadrant of the image, taking every other row and column, call:
- .. code-block:: cpp
- grayimage_histogram(
- nth_channel_view(
- subsampled_view(
- subimage_view(img,
- 0,0, img.width() / 2, img.height() / 2), // upper left quadrant
- 2, 2 // skip every other row and column
- ),
- 1 // index of the second channel (for example, green for RGB)
- ),
- hist
- );
- Since GIL operates on the source pixels of ``img`` object directly, no extra
- memory is allocated and no images are copied.
|