<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>emre şahin's digital garden 🍃 - Image Processing</title>
    <link>https://emresahin.net/tags/image-processing/</link>
    <description>Posts in the Image Processing tag</description>
    <language>en</language>
    <managingEditor>contact@emresahin.net (Emre Şahin)</managingEditor>
    <lastBuildDate>Tue, 15 Sep 2026 19:46:32 +0000</lastBuildDate>
    <atom:link href="https://emresahin.net/tags/image-processing/rss.xml" rel="self" type="application/rss+xml"/>
    <item>
      <title>How to convert NumPy image to QImage?</title>
      <published>2018-11-06T20:11:46+00:00</published>
      <updated>2018-11-06T20:11:46+00:00</updated>
      <author>Emre Şahin</author>
      <pubDate>Tue, 06 Nov 2018 20:11:46 +0000</pubDate>
      <link>https://emresahin.net/converting-numpy-image-to-qimage-14359-22392/</link>
      <guid isPermaLink="true">https://emresahin.net/converting-numpy-image-to-qimage-14359-22392/</guid>
      <description>When writing Qt GUI code for a deep learning system, a common task is converting an image (read from disk or camera using OpenCV) from a NumPy array to a QImage for display in a widget. There are basically two problems to address: NumPy arrays often have data types with more than 8 bits, and Open...</description>
      <category>Python</category>
      <category>Qt</category>
      <category>NumPy</category>
      <category>QImage</category>
      <category>PySide2</category>
      <category>OpenCV</category>
      <category>Image Processing</category>
      <content:encoded><![CDATA[<p>When writing Qt GUI code for a deep learning system, a common task is converting an image (read from disk or camera using OpenCV) from a NumPy array to a QImage for display in a widget.</p>
<p>There are basically two problems to address: NumPy arrays often have data types with more than 8 bits, and OpenCV reads images in BGR format rather than the more common RGB.</p>
<p>The following Python (3.5+) code demonstrates the solution:</p>
<pre><code class="language-python">import PySide2.QtGui as qtg
import numpy as np

def get_qimage(image: np.ndarray):
    assert (np.max(image) &lt;= 255)
    image8 = image.astype(np.uint8, order='C', casting='unsafe')
    height, width, colors = image8.shape
    bytesPerLine = 3 * width

    image = qtg.QImage(image8.data, width, height, bytesPerLine,
                       qtg.QImage.Format_RGB888)

    image = image.rgbSwapped()
    return image
</code></pre>]]></content:encoded>
    </item>
    <item>
      <title>Patch Histogram Feature</title>
      <published>2014-04-10T14:00:00+00:00</published>
      <updated>2014-04-10T14:00:00+00:00</updated>
      <author>Emre Şahin</author>
      <pubDate>Thu, 10 Apr 2014 14:00:00 +0000</pubDate>
      <link>https://emresahin.net/patch-histogram/</link>
      <guid isPermaLink="true">https://emresahin.net/patch-histogram/</guid>
      <description>This post introduces a new feature for binary blobs, such as connected components in text. The feature is called patch histogram , and it represents the histogram of 3x3 patches of black and white pixels. We collect all 3x3 patches and count their frequencies. A 3x3 patch for a binary image conta...</description>
      <category>Computer Vision</category>
      <category>Image Processing</category>
      <category>Histogram</category>
      <category>Python</category>
      <category>Feature Extraction</category>
      <content:encoded><![CDATA[<p>This post introduces a new feature for binary blobs, such as connected components in text.</p>
<p>The feature is called <em>patch histogram</em>, and it represents the histogram of 3x3 patches of black and white pixels. We collect all 3x3 patches and count their frequencies.</p>
<p>A 3x3 patch for a binary image contains $2^9 = 512$ different combinations. For each of these combinations, we assign a unique ID. I wrote the implementation in Python; here is a lookup table that converts all possible 3x3 patches to their IDs.</p>
<pre><code class="language-python">patch_histogram_dict = {}
for f in range(0, 512):
    i22 = f &amp; 1
    i21 = (f &gt;&gt; 1) &amp; 1
    i20 = (f &gt;&gt; 2) &amp; 1
    i12 = (f &gt;&gt; 3) &amp; 1
    i11 = (f &gt;&gt; 4) &amp; 1
    i10 = (f &gt;&gt; 5) &amp; 1
    i02 = (f &gt;&gt; 6) &amp; 1
    i01 = (f &gt;&gt; 7) &amp; 1
    i00 = (f &gt;&gt; 8) &amp; 1
    patch_histogram_dict[ma(i00, i01, i02, i10, i11, i12, i20, i21, i22)] = f
</code></pre>
<p>I was looking for a <em>skeleton feature</em> that can be applied to components after a medial axis transform. However, in this version, we will use binarized connected component images directly and explore the skeletal version later.</p>
<p>Above, we used a function <code>ma</code> to convert a set of numbers to a tuple of tuples. It’s as simple as:</p>
<pre><code class="language-python">def ma(i00, i01, i02, i10, i11, i12, i20, i21, i22):
    return ((i00, i01, i02),
            (i10, i11, i12),
            (i20, i21, i22))
</code></pre>
<p>The first step in feature generation is marking each pixel of the image with its ID. Then, a simple <code>np.histogram</code> call generates the histogram.</p>
<pre><code class="language-python">for i in range(1, rows - 1):
    for j in range(1, cols - 1):
        s = framed[(i-1):(i+2), (j-1):(j+2)]
        marks[i-1, j-1] = patch_dict[ma(s[0, 0], s[0, 1], s[0, 2],
                                        s[1, 0], s[1, 1], s[1, 2],
                                        s[2, 0], s[2, 1], s[2, 2])]
</code></pre>
<p><code>framed</code> is a copy of the original image with a 1-pixel frame, so that boundary pixels are also counted without much boundary checking. <code>patch_dict</code> is a parameter that the function receives. Its default value is the dictionary that we created above, but any kind of patch dictionary can be used.</p>
<p>The feature is generated using a call to <code>numpy.histogram</code> as follows:</p>
<pre><code class="language-python">histogram = numpy.histogram(marked_points,
                            hist_range,
                            density=True,
                            bins=bins)
</code></pre>
<p><code>marked_points</code> are the results of the pixel counting loop above. <code>hist_range</code> is the minimum and maximum value for the patch dictionary. The <code>density</code> parameter is set to <code>True</code> so that the histogram is normalized to 1, making the feature size-invariant. <code>bins</code> is a parameter we can set freely, but by default, it’s equal to the range of elements.</p>
<p>Comparisons can be performed using standard histogram comparison methods, such as EMD (Earth Mover’s Distance) or Chi-Square distance metrics.</p>]]></content:encoded>
    </item>
    <item>
      <title>Paper Review: Shape Classification Using Zernike Moments</title>
      <published>2014-04-04T00:00:00+00:00</published>
      <updated>2014-04-04T00:00:00+00:00</updated>
      <author>Emre Şahin</author>
      <pubDate>Fri, 04 Apr 2014 00:00:00 +0000</pubDate>
      <link>https://emresahin.net/shape-classification-using-zernike-moments/</link>
      <guid isPermaLink="true">https://emresahin.net/shape-classification-using-zernike-moments/</guid>
      <description>Q: What is a moment? A moment is defined as: $$m_{p,q}(x,y) = \int_{-\infty}^{+\infty} \int_{-\infty}^{+\infty} x^p y^q f(x,y) dxdy$$ In other words, it is the summation of the figure with respect to the function $f$ for both axes. Q: What are Zernike moments? Zernike moments are complex polynomi...</description>
      <category>Computer Vision</category>
      <category>Research</category>
      <category>Zernike moments</category>
      <category>Hu moments</category>
      <category>Shape classification</category>
      <category>Paper review</category>
      <category>Mathematics</category>
      <category>Image Processing</category>
      <content:encoded><![CDATA[<h1 id="q-what-is-a-moment">Q: What is a moment?</h1>
<p>A moment is defined as:</p>
<p>$$m_{p,q}(x,y) = \int_{-\infty}^{+\infty} \int_{-\infty}^{+\infty} x^p y^q f(x,y) dxdy$$</p>
<p>In other words, it is the summation of the figure with respect to the function $f$ for both axes.</p>
<h1 id="q-what-are-zernike-moments">Q: What are Zernike moments?</h1>
<p>Zernike moments are complex polynomial functions used to sum the elements of a shape. They were first introduced in the 1930s. The higher the order, the more complex the shape that can be represented. Order 1 Zernike moments (ZMs) are ellipsoid planes where one side is higher than the other.</p>
<h1 id="q-what-is-the-difference-between-hu-moments-and-zernike-moments">Q: What is the difference between Hu moments and Zernike moments?</h1>
<p>The importance of Zernike moments lies in their rotational invariance. However, Hu moments are also said to have these properties. Thus, Hu moments appear to be simpler alternatives to Zernike moments.</p>
<h1 id="q-what-are-their-properties">Q: What are their properties?</h1>
<p>Zernike moments use polar coordinates, making it easy to describe rotational invariance.</p>]]></content:encoded>
    </item>
    <item>
      <title>Dervaze: A Transliteration System for Ottoman</title>
      <published>2014-01-07T22:00:00+00:00</published>
      <updated>2014-01-07T22:00:00+00:00</updated>
      <author>Emre Şahin</author>
      <pubDate>Tue, 07 Jan 2014 22:00:00 +0000</pubDate>
      <link>https://emresahin.net/transliteration-pipeline/</link>
      <guid isPermaLink="true">https://emresahin.net/transliteration-pipeline/</guid>
      <description>Dervaze (meaning “the portal”) is a set of tools that aims to transliterate historical Ottoman documents to Modern Turkish. Here, I describe the transliteration system. The system is organized as a pipeline in which the tools at a stage produce the input for the next stage. The input to the syste...</description>
      <category>Development</category>
      <category>Ottoman Turkish</category>
      <category>Language Processing</category>
      <category>Dervaze</category>
      <category>Transliteration</category>
      <category>Binarization</category>
      <category>OCR</category>
      <category>Image Processing</category>
      <content:encoded><![CDATA[<p><em>Dervaze</em> (meaning “the portal”) is a set of tools that aims to
transliterate historical Ottoman documents to Modern Turkish.</p>
<p>Here, I describe the transliteration system.
The system is organized as a pipeline in which the tools at a stage produce the input
for the next stage.
The input to the system is a set of historical document images.
The output is either a search result or a textual representation of these documents.</p>
<p>The sections below describe these stages briefly.</p>
<h2 id="binarize-color-images-to-binary-images">Binarize Color Images to Binary Images</h2>
<p>Binarization is the process of converting color or grayscale images to black-and-white binary images.
Document images come in various flavors, mostly as color images.
Color information is mostly noise for further stages.
It is better to remove the color while keeping the textual representation intact.</p>
<p>Although seemingly easy at first, this stage includes challenges like determining the ink color or removing ink stains from images.</p>
<p>In the literature, the standard idea is to use a mathematical model, like <em>Otsu’s method</em>, to convert color to binary.
We approach this problem differently, as a classification problem.
The idea is briefly as follows:</p>
<p>Color images consist of 3 channels.
The <em>ink color</em> of a region should be persistently <em>present</em> or <em>absent</em> in these channels.
For example, a dark blue ink should be represented within similar numeric ranges in each of these channels, and a red ink should be represented more in the red channel than others.
A standard binarization approach tries to come up with a cumulative ink color value using all three channels.
We do it differently.</p>
<p>Instead of trying to find a cumulative threshold for binarization, we detect edges in each channel, considering each channel as a separate binary image.
When components in each channel are found, they are evaluated by various features (like size, presence in other channels) and classified as <em>text</em> or <em>non-text</em>.</p>
<p>After classification, the <em>text</em> elements are drawn to a canvas in black, and the document hence becomes binarized.</p>
<h2 id="extract-components-convert-binary-images-to-components">Extract Components: Convert Binary Images to Components</h2>
<p>Although the components are extracted during the <em>binarization stage</em>, we extract them in an independent stage to have a definite input and output.
The primary reason for this is to evaluate the performance of different binarization options.
This stage works even if the binarization part uses another (standard) approach.</p>
<p>Binarized document images are converted to sets of components by finding their edges.
Each component is recorded with its location and binary image.</p>
<h2 id="extract-features-find-features-of-components-for-comparison">Extract Features: Find Features of Components for Comparison</h2>
<p>Each component can have several different features, such as height, width, number of holes, number of ascenders and descenders, etc.
Some of these features work better than others in classification.
However, we don’t know beforehand which ones work better than others.</p>
<p>In order to find a set of good features, we extract all the features we can think of and run a Principal Component Analysis (PCA) on them.
Previously, since we lacked classifications for these components, it was impossible to find good features, and we had to check the outputs manually.
However, now that we have labeled around 11,000 components from 50 handwritten pages, we can
determine which features are better than others.</p>
<p><code>extract-features</code> extracts a large set of features from the component set.
These features are stored in CSV files and analyzed for their classification value.</p>]]></content:encoded>
    </item>
    <item>
      <title>Paper Review: Polygonal Approximation of Digital Curves to Preserve Original Shapes</title>
      <published>2012-09-18T14:00:00+00:00</published>
      <updated>2012-09-18T14:00:00+00:00</updated>
      <author>Emre Şahin</author>
      <pubDate>Tue, 18 Sep 2012 14:00:00 +0000</pubDate>
      <link>https://emresahin.net/polygonal-approximation-of-digital-curves-lee-lee/</link>
      <guid isPermaLink="true">https://emresahin.net/polygonal-approximation-of-digital-curves-lee-lee/</guid>
      <description>Authors: Daeho Lee, Seung Gwan Lee Keywords: dominant points consecutive vectors toothbrush shape distance metric smallest perpendicular distance Q1: How usual calculation of distance is done? Minor DPs are deleted in approximation. A minor DP is a DP where the perpendicular distance between the ...</description>
      <category>Computer Science</category>
      <category>Paper Review</category>
      <category>image processing</category>
      <category>polygonal approximation</category>
      <category>digital curves</category>
      <category>shape preservation</category>
      <content:encoded><![CDATA[<h1 id="authors-daeho-lee-seung-gwan-lee">Authors: Daeho Lee, Seung Gwan Lee</h1>
<h1 id="keywords">Keywords:</h1>
<ul>
<li>dominant points</li>
<li>consecutive vectors</li>
<li>toothbrush shape</li>
<li>distance metric</li>
<li>smallest perpendicular distance</li>
</ul>
<h1 id="q1-how-usual-calculation-of-distance-is-done">Q1: How usual calculation of distance is done?</h1>
<p>Minor DPs are deleted in approximation. A minor DP is a DP where the
perpendicular distance between the point and the straight line is
minimum.</p>
<pre><code>a a
 b
</code></pre>
<p>Here <code>b</code> is deleted when its distance to the line <code>a-a</code> is minimum.</p>
<p>The perpendicular distance is calculated using</p>
<p>[ d_i = \sqrt{\frac{((x_i - x_a) (y_b - y_a) - (y_i - y_a)
(x_b -x_a))^2}{(x_a - x_b)^2 + (y_a - y_b)^2}} ]</p>
<p>for lines between points $p_a$ and $p_b$ and the point $p_i$.</p>
<h1 id="q2-what-is-a-toothbrush-shape">Q2: What is a toothbrush shape?</h1>
<p>It’s something like</p>
<pre><code>aaaaaa
bbbbbbbbbbbbbbbbbbbbbb
</code></pre>
<p>Hence the toothbrush.</p>
<p>Though I don’t get why is this particularly important.</p>
<h1 id="q3-which-information-is-included-in-distance-metric">Q3: Which information is included in distance metric?</h1>
<p>Angle acuteness is added to the information described above.</p>
<h1 id="q4-how-the-distance-metric-differs-from-others">Q4: How the distance metric differs from others?</h1>
<p>It includes angle acuteness in the metric and the more acute the angle,
the less likely it’s removed from DP set.</p>
<h1 id="q5-whats-baseline-for-performance-and-how-does-this-improve-it">Q5: What’s baseline for performance and how does this improve it?</h1>
<p>As the number of DPs decrease, RMSE of the new metric decreases. For
large number of DPs it doesn’t matter much. (So performance penalty may
not pay off)</p>]]></content:encoded>
    </item>
    <item>
      <title>Paper Review: Text Line Segmentation of Historical Documents: A Survey</title>
      <published>2012-07-27T14:00:00+00:00</published>
      <updated>2012-07-27T14:00:00+00:00</updated>
      <author>Emre Şahin</author>
      <pubDate>Fri, 27 Jul 2012 14:00:00 +0000</pubDate>
      <link>https://emresahin.net/text-line-segmentation-of-historical-documents/</link>
      <guid isPermaLink="true">https://emresahin.net/text-line-segmentation-of-historical-documents/</guid>
      <description>Authors: Laurance Likforman-Sulem, Abderrezak Sahour, Bruno Taconet URL: http://arxiv.org/pdf/0704.1267.pdf Keywords: page segmentation overlapping components image quality document complexity preprocessing projection based smearing based grouping based hough transform based repulsive attractive ...</description>
      <category>Paper Review</category>
      <category>text line segmentation</category>
      <category>historical documents</category>
      <category>Hough transform</category>
      <category>document analysis</category>
      <category>image processing</category>
      <content:encoded><![CDATA[<h1 id="authors-laurance-likforman-sulem-abderrezak-sahour-bruno-taconet">Authors: Laurance Likforman-Sulem, Abderrezak Sahour, Bruno Taconet</h1>
<h1 id="url-httparxivorgpdf07041267pdf">URL: <a href="http://arxiv.org/pdf/0704.1267.pdf">http://arxiv.org/pdf/0704.1267.pdf</a></h1>
<h1 id="keywords">Keywords:</h1>
<ul>
<li>page segmentation</li>
<li>overlapping components</li>
<li>image quality</li>
<li>document complexity</li>
<li>preprocessing</li>
<li>projection based</li>
<li>smearing based</li>
<li>grouping based</li>
<li>hough transform based</li>
<li>repulsive attractive</li>
<li>stochastic</li>
<li>touching components</li>
</ul>
<h1 id="q1-what-are-the-most-usable-techniques-for-ottoman-divans">Q1: What are the most usable techniques for Ottoman divans?</h1>
<p>Likforman-Sulem and Faure’s technique, which uses Gestalt criteria to associate text elements, might be of use. Feldbach and Tennies’ work, which was tested on Church Registers, may also be helpful. The Hough transform can be used. The Repulsive-Attractive method of Öztop et al. is also applicable. Stochastic methods by Tseng and Lee, which use a probabilistic Viterbi algorithm, can also be utilized.</p>
<h1 id="q2-how-are-touching-components-successfully-delimited">Q2: How are touching components successfully delimited?</h1>
<p>A touching component can be detected by its size. Subsequently, it should either be assigned to a lower or upper line, or be separated. Successful separation requires letter images or skeletons (which we lack).</p>
<h1 id="q3-how-is-the-hough-transform-used">Q3: How is the Hough transform used?</h1>
<p>Centroids of the connected components (CCs) are used as units of the Hough transform. Line hypotheses are developed in the Hough domain and verified in the image domain.</p>
<h1 id="q4-what-are-the-problems-specific-to-non-latin-texts">Q4: What are the problems specific to non-Latin texts?</h1>
<p>The baseline of Hebrew is at the upper part of the letters because of their box shape. Devanagari and similar scripts also have a headline on top of them. Diacritics and inter-letter shapes pose problems for Arabic.</p>]]></content:encoded>
    </item>
  </channel>
</rss>
