histogram.rst.txt 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. Tutorial: Histogram
  2. ===================
  3. .. contents::
  4. :local:
  5. :depth: 1
  6. This is a short tutorial presenting an example of a very simple sample of code
  7. from an existing code base that calculates histogram of an image.
  8. Next, the program is rewritten using GIL featres.
  9. Original implementation
  10. -----------------------
  11. Actual code from a commercial software product that computes the luminosity
  12. histogram (variable names have been changed and unrelated parts removed):
  13. .. code-block:: cpp
  14. void luminosity_hist(
  15. std::uint8_t const* r, std::uint8_t const* g, std::uint8_t const* b,
  16. int rows, int cols, int sRowBytes, Histogram* hist)
  17. {
  18. for (int r = 0; r < rows; r++)
  19. {
  20. for (int c = 0; c < cols; c++)
  21. {
  22. int v = RGBToGray(r[c], g[c], b[c]); // call internal function or macro
  23. (*hist)[v]++;
  24. }
  25. r += sRowBytes;
  26. g += sRowBytes;
  27. b += sRowBytes;
  28. }
  29. }
  30. Let's consider the following issues of the implementation above:
  31. - Works only for RGB (duplicate versions exist for other color spaces)
  32. - Works only for 8-bit images (duplicate versions exist)
  33. - Works only for planar images
  34. GIL implementation
  35. ------------------
  36. .. code-block:: cpp
  37. template <typename GrayView, typename R>
  38. void grayimage_histogram(GrayView& img, R& hist)
  39. {
  40. for (typename GrayView::iterator it=img.begin(); it!=img.end(); ++it)
  41. ++hist[*it];
  42. }
  43. template <typename View, typename R>
  44. void luminosity8bit_hist(View& img, R& hist)
  45. {
  46. grayimage_histogram(color_converted_view<gray8_pixel_t>(img),hist);
  47. }
  48. Using the Boost.Lambda library (or C++11 lambda) features it can written
  49. even simpler:
  50. .. code-block:: cpp
  51. using boost::lambda;
  52. template <typename GrayView, typename R>
  53. void grayimage_histogram(GrayView& img, R& hist)
  54. {
  55. for_each_pixel(img, ++var(hist)[_1]);
  56. }
  57. Let's consider the following advantages of the GIL version:
  58. - Works with any supported channel depth, color space, channel ordering
  59. (RGB vs BGR), and row alignment policy.
  60. - Works for both planar and interleaved images.
  61. - Works with new color spaces, channel depths and image types that can be
  62. provided in future extensions of GIL
  63. - The second version is as efficient as the hand-coded version
  64. Shortly, it is also very flexible.
  65. For example, to compute the histogram of the second channel of the top left
  66. quadrant of the image, taking every other row and column, call:
  67. .. code-block:: cpp
  68. grayimage_histogram(
  69. nth_channel_view(
  70. subsampled_view(
  71. subimage_view(img,
  72. 0,0, img.width() / 2, img.height() / 2), // upper left quadrant
  73. 2, 2 // skip every other row and column
  74. ),
  75. 1 // index of the second channel (for example, green for RGB)
  76. ),
  77. hist
  78. );
  79. Since GIL operates on the source pixels of ``img`` object directly, no extra
  80. memory is allocated and no images are copied.