2
0
mirror of https://github.com/boostorg/gil.git synced 2026-01-19 16:22:14 +00:00
Files
gil/develop/doc/html/tutorial/histogram.html
github-actions[bot] 43e8aef5bd deploy: 942196bedc
2025-12-11 07:34:54 +00:00

180 lines
16 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Tutorial: Histogram - Boost.GIL documentation</title>
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<link rel="stylesheet" href="../_static/style.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '../',
VERSION: '',
COLLAPSE_MODINDEX: false,
FILE_SUFFIX: '.html'
};
</script>
<script type="text/javascript" src="../_static/documentation_options.js"></script>
<script type="text/javascript" src="../_static/doctools.js"></script>
<script type="text/javascript" src="../_static/sphinx_highlight.js"></script>
<script data-url_root="../" id="documentation_options" src="../_static/documentation_options.js"></script>
<script src="../_static/searchtools.js"></script>
<script src="../_static/language_data.js"></script>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="top" title="Boost.GIL documentation" href="../index.html" />
<link rel="next" title="Tutorial: Image Gradient" href="gradient.html" />
<link rel="prev" title="Tutorial: Video Lecture" href="video.html" />
</head>
<body>
<div class="header">
<table border="0" cellpadding="7" cellspacing="0" width="100%" summary=
"header">
<tr>
<td valign="top" width="300">
<h3><a href="../index.html"><img
alt="C++ Boost" src="../../_static/gil.png" border="0"></a></h3>
</td>
<td >
<h1 align="center"><a href="../index.html"></a></h1>
</td>
<td>
<div id="searchbox" style="display: none">
<form class="search" action="../search.html" method="get">
<input type="text" name="q" size="18" />
<input type="submit" value="Search" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
</td>
</tr>
</table>
</div>
<hr/>
<div class="content">
<div class="navbar" style="text-align:right;">
<a class="prev" title="Tutorial: Video Lecture" href="video.html"><img src="../_static/prev.png" alt="prev"/></a>
<a class="next" title="Tutorial: Image Gradient" href="gradient.html"><img src="../_static/next.png" alt="next"/></a>
</div>
<section id="tutorial-histogram">
<h1>Tutorial: Histogram<a class="headerlink" href="#tutorial-histogram" title="Link to this heading"></a></h1>
<nav class="contents local" id="contents">
<ul class="simple">
<li><p><a class="reference internal" href="#original-implementation" id="id1">Original implementation</a></p></li>
<li><p><a class="reference internal" href="#gil-implementation" id="id2">GIL implementation</a></p></li>
</ul>
</nav>
<p>This is a short tutorial presenting an example of a very simple sample of code
from an existing code base that calculates the histogram of an image.
Next, the program is rewritten using GIL features.</p>
<section id="original-implementation">
<h2><a class="toc-backref" href="#id1" role="doc-backlink">Original implementation</a><a class="headerlink" href="#original-implementation" title="Link to this heading"></a></h2>
<p>Actual code from a commercial software product that computes the luminosity
histogram (variable names have been changed and unrelated parts removed):</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="kt">void</span><span class="w"> </span><span class="nf">luminosity_hist</span><span class="p">(</span>
<span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="kt">uint8_t</span><span class="w"> </span><span class="k">const</span><span class="o">*</span><span class="w"> </span><span class="n">r</span><span class="p">,</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="kt">uint8_t</span><span class="w"> </span><span class="k">const</span><span class="o">*</span><span class="w"> </span><span class="n">g</span><span class="p">,</span><span class="w"> </span><span class="n">std</span><span class="o">::</span><span class="kt">uint8_t</span><span class="w"> </span><span class="k">const</span><span class="o">*</span><span class="w"> </span><span class="n">b</span><span class="p">,</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">rows</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">cols</span><span class="p">,</span><span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">sRowBytes</span><span class="p">,</span><span class="w"> </span><span class="n">Histogram</span><span class="o">*</span><span class="w"> </span><span class="n">hist</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">rows</span><span class="p">;</span><span class="w"> </span><span class="n">r</span><span class="o">++</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="kt">int</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="n">c</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="n">cols</span><span class="p">;</span><span class="w"> </span><span class="n">c</span><span class="o">++</span><span class="p">)</span>
<span class="w"> </span><span class="p">{</span>
<span class="w"> </span><span class="kt">int</span><span class="w"> </span><span class="n">v</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">RGBToGray</span><span class="p">(</span><span class="n">r</span><span class="p">[</span><span class="n">c</span><span class="p">],</span><span class="w"> </span><span class="n">g</span><span class="p">[</span><span class="n">c</span><span class="p">],</span><span class="w"> </span><span class="n">b</span><span class="p">[</span><span class="n">c</span><span class="p">]);</span><span class="w"> </span><span class="c1">// call internal function or macro</span>
<span class="w"> </span><span class="p">(</span><span class="o">*</span><span class="n">hist</span><span class="p">)[</span><span class="n">v</span><span class="p">]</span><span class="o">++</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="w"> </span><span class="n">r</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="n">sRowBytes</span><span class="p">;</span>
<span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="n">sRowBytes</span><span class="p">;</span>
<span class="w"> </span><span class="n">b</span><span class="w"> </span><span class="o">+=</span><span class="w"> </span><span class="n">sRowBytes</span><span class="p">;</span>
<span class="w"> </span><span class="p">}</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Lets consider the following issues of the implementation above:</p>
<ul class="simple">
<li><p>Works only for RGB (duplicate versions exist for other color spaces)</p></li>
<li><p>Works only for 8-bit images (duplicate versions exist)</p></li>
<li><p>Works only for planar images</p></li>
</ul>
</section>
<section id="gil-implementation">
<h2><a class="toc-backref" href="#id2" role="doc-backlink">GIL implementation</a><a class="headerlink" href="#gil-implementation" title="Link to this heading"></a></h2>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">GrayView</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="nc">R</span><span class="o">&gt;</span>
<span class="kt">void</span><span class="w"> </span><span class="n">grayimage_histogram</span><span class="p">(</span><span class="n">GrayView</span><span class="o">&amp;</span><span class="w"> </span><span class="n">img</span><span class="p">,</span><span class="w"> </span><span class="n">R</span><span class="o">&amp;</span><span class="w"> </span><span class="n">hist</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">typename</span><span class="w"> </span><span class="nc">GrayView</span><span class="o">::</span><span class="n">iterator</span><span class="w"> </span><span class="n">it</span><span class="o">=</span><span class="n">img</span><span class="p">.</span><span class="n">begin</span><span class="p">();</span><span class="w"> </span><span class="n">it</span><span class="o">!=</span><span class="n">img</span><span class="p">.</span><span class="n">end</span><span class="p">();</span><span class="w"> </span><span class="o">++</span><span class="n">it</span><span class="p">)</span>
<span class="w"> </span><span class="o">++</span><span class="n">hist</span><span class="p">[</span><span class="o">*</span><span class="n">it</span><span class="p">];</span>
<span class="p">}</span>
<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">View</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="nc">R</span><span class="o">&gt;</span>
<span class="kt">void</span><span class="w"> </span><span class="n">luminosity8bit_hist</span><span class="p">(</span><span class="n">View</span><span class="o">&amp;</span><span class="w"> </span><span class="n">img</span><span class="p">,</span><span class="w"> </span><span class="n">R</span><span class="o">&amp;</span><span class="w"> </span><span class="n">hist</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="n">grayimage_histogram</span><span class="p">(</span><span class="n">color_converted_view</span><span class="o">&lt;</span><span class="n">gray8_pixel_t</span><span class="o">&gt;</span><span class="p">(</span><span class="n">img</span><span class="p">),</span><span class="n">hist</span><span class="p">);</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Using the Boost.Lambda library (or C++11 lambda) features it can be written
even simpler:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="k">using</span><span class="w"> </span><span class="n">boost</span><span class="o">::</span><span class="n">lambda</span><span class="p">;</span>
<span class="k">template</span><span class="w"> </span><span class="o">&lt;</span><span class="k">typename</span><span class="w"> </span><span class="nc">GrayView</span><span class="p">,</span><span class="w"> </span><span class="k">typename</span><span class="w"> </span><span class="nc">R</span><span class="o">&gt;</span>
<span class="kt">void</span><span class="w"> </span><span class="n">grayimage_histogram</span><span class="p">(</span><span class="n">GrayView</span><span class="o">&amp;</span><span class="w"> </span><span class="n">img</span><span class="p">,</span><span class="w"> </span><span class="n">R</span><span class="o">&amp;</span><span class="w"> </span><span class="n">hist</span><span class="p">)</span>
<span class="p">{</span>
<span class="w"> </span><span class="n">for_each_pixel</span><span class="p">(</span><span class="n">img</span><span class="p">,</span><span class="w"> </span><span class="o">++</span><span class="n">var</span><span class="p">(</span><span class="n">hist</span><span class="p">)[</span><span class="n">_1</span><span class="p">]);</span>
<span class="p">}</span>
</pre></div>
</div>
<p>Lets consider the following advantages of the GIL version:</p>
<ul class="simple">
<li><p>Works with any supported channel depth, color space, channel ordering
(RGB vs BGR), and row alignment policy.</p></li>
<li><p>Works for both planar and interleaved images.</p></li>
<li><p>Works with new color spaces, channel depths and image types that can be
provided in future extensions of GIL</p></li>
<li><p>The second version is as efficient as the hand-coded version</p></li>
</ul>
<p>Shortly, it is also very flexible.</p>
<p>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:</p>
<div class="highlight-cpp notranslate"><div class="highlight"><pre><span></span><span class="n">grayimage_histogram</span><span class="p">(</span>
<span class="w"> </span><span class="n">nth_channel_view</span><span class="p">(</span>
<span class="w"> </span><span class="n">subsampled_view</span><span class="p">(</span>
<span class="w"> </span><span class="n">subimage_view</span><span class="p">(</span><span class="n">img</span><span class="p">,</span>
<span class="w"> </span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="w"> </span><span class="n">img</span><span class="p">.</span><span class="n">width</span><span class="p">()</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="n">img</span><span class="p">.</span><span class="n">height</span><span class="p">()</span><span class="w"> </span><span class="o">/</span><span class="w"> </span><span class="mi">2</span><span class="p">),</span><span class="w"> </span><span class="c1">// upper left quadrant</span>
<span class="w"> </span><span class="mi">2</span><span class="p">,</span><span class="w"> </span><span class="mi">2</span><span class="w"> </span><span class="c1">// skip every other row and column</span>
<span class="w"> </span><span class="p">),</span>
<span class="w"> </span><span class="mi">1</span><span class="w"> </span><span class="c1">// index of the second channel (for example, green for RGB)</span>
<span class="w"> </span><span class="p">),</span>
<span class="w"> </span><span class="n">hist</span>
<span class="p">);</span>
</pre></div>
</div>
<p>Since GIL operates on the source pixels of <code class="docutils literal notranslate"><span class="pre">img</span></code> object directly, no extra
memory is allocated and no images are copied.</p>
</section>
</section>
<div class="navbar" style="text-align:right;">
<a class="prev" title="Tutorial: Video Lecture" href="video.html"><img src="../_static/prev.png" alt="prev"/></a>
<a class="next" title="Tutorial: Image Gradient" href="gradient.html"><img src="../_static/next.png" alt="next"/></a>
</div>
</div>
<div class="footer" role="contentinfo">
Last updated on 2025-12-11 07:12:45.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 7.2.6.
</div>
</body>
</html>