<?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 🍃 - Dervaze</title>
    <link>https://emresahin.net/tags/dervaze/</link>
    <description>Posts in the Dervaze tag</description>
    <language>en</language>
    <managingEditor>contact@emresahin.net (Emre Şahin)</managingEditor>
    <lastBuildDate>Tue, 29 Sep 2026 14:57:43 +0000</lastBuildDate>
    <atom:link href="https://emresahin.net/tags/dervaze/rss.xml" rel="self" type="application/rss+xml"/>
    <item>
      <title>Development Journal, June 9</title>
      <published>2018-06-09T23:42:56+00:00</published>
      <updated>2018-06-09T23:42:56+00:00</updated>
      <author>Emre Şahin</author>
      <pubDate>Sat, 09 Jun 2018 23:42:56 +0000</pubDate>
      <link>https://emresahin.net/dev-journal-14209-35016/</link>
      <guid isPermaLink="true">https://emresahin.net/dev-journal-14209-35016/</guid>
      <description>I began implementing an Ottoman translator using Finite State Transducers via OpenFST . Instead of using ad-hoc algorithms to translate between Ottoman and Turkish, I’ll be creating FSTs. In the past, I have used FOMA and TRmorph as a building block and basis for Ottoman conversion. However, I sa...</description>
      <category>Development</category>
      <category>Linguistics</category>
      <category>Ottoman Turkish</category>
      <category>FST</category>
      <category>OpenFST</category>
      <category>Common Lisp</category>
      <category>mocl</category>
      <category>dervaze</category>
      <content:encoded><![CDATA[<p>I began implementing an Ottoman translator using Finite State Transducers via
<a href="http://www.openfst.org/twiki/bin/view/FST/WebHome">OpenFST</a>. Instead of using ad-hoc algorithms to translate between
Ottoman and Turkish, I’ll be creating FSTs.</p>
<p>In the past, I have used <a href="https://fomafst.github.io/">FOMA</a> and <a href="http://coltekin.net/cagri/trmorph/">TRmorph</a> as a building block
and basis for Ottoman conversion. However, I saw that writing something on top of
a morphological analyzer to convert Ottoman to Turkish requires almost another
morphological analyzer. (This is also true for Turkish to Ottoman conversion as
well, because spelling rules of Ottoman require another layer of FSTs.)</p>
<p>After that initial failure, I decided to write an ad-hoc algorithm that uses
surface-level representations of Turkish and Ottoman. The result has been running in
<a href="http://dervaze.com">dervaze</a> for two years now.</p>
<p>But as it can be observed, it’s slow. I was working to replace it with a C
library that will also be used in mobile applications. I have completed the
dictionary part that’s used to search for words. In this version of the library,
I was using trie structures.</p>
<p>I have decided, however, that using FSTs to translate may be more robust and
formal in the long run. When you use tries, it’s almost like using half of FSTs
without much thought on states. As I’m developing this solo and my main concern
is expandability, converting ad-hoc rules to states seemed easier than writing a
C library.</p>
<p>I will be writing about this experience in the coming days.</p>
<hr>
<p>I’ve learned that there is a specialized Common Lisp implementation for mobile
devices, <a href="https://wukix.com/mocl">mocl</a>.</p>
<p>It should also be possible to write C-compatible shared libraries in CL and use
them in iOS and Android. Although I began to prefer writing libraries in plain C
(instead of any other language), I may switch to CL if there is enough
motivation.</p>]]></content:encoded>
    </item>
    <item>
      <title>Progress on Ottoman Translation - Week 6, 2018</title>
      <published>2018-02-05T07:23:43+00:00</published>
      <updated>2018-02-05T07:23:43+00:00</updated>
      <author>Emre Şahin</author>
      <pubDate>Mon, 05 Feb 2018 07:23:43 +0000</pubDate>
      <link>https://emresahin.net/dervaze-progress-2018-6-14084-62774/</link>
      <guid isPermaLink="true">https://emresahin.net/dervaze-progress-2018-6-14084-62774/</guid>
      <description>Some of the upcoming posts will serve as a TODO list for the coming months, outlining my plans for Dervaze and its mobile versions. As a solo developer, I’ll share my experiences with this problem here to help those interested. The technology for Ottoman OCR was mostly ready before my family obli...</description>
      <category>NLP</category>
      <category>History</category>
      <category>Ottoman Turkish</category>
      <category>OCR</category>
      <category>C</category>
      <category>Dervaze</category>
      <category>Linguistics</category>
      <content:encoded><![CDATA[<p>Some of the upcoming posts will serve as a TODO list for the coming months, outlining my plans for <a href="http://dervaze.com">Dervaze</a> and its mobile versions. As a solo developer, I’ll share my experiences with this problem here to help those interested.</p>
<p>The technology for Ottoman OCR was mostly ready before my family obligations interrupted the project. I need to re-evaluate what is currently available, but a more pressing problem for me is the <em>speed</em> of translation; currently, it is so slow that it’s barely usable.</p>
<p>I have written the dictionary as a C library without any database dependencies and integrated it into the Android version. I’m currently updating the search functionality in the mobile app to use this library instead of a web service. It will be orders of magnitude faster than the current version because it’s offline and uses a <a href="https://en.wikipedia.org/wiki/Trie">trie</a> to store the words—making it both small and fast.</p>
<p>In my experience, having a single data structure with dedicated functions for transforming and indexing is much simpler than managing multiple data structures. In my case, the core structure is:</p>
<pre><code class="language-c">typedef struct _dervaze_lexical_item {
  int index;
  bstr latin_search_key;
  bstr latin;
  bstr visenc_search_key;
  bstr visenc_dotless_search_key;
  bstr visenc;
  bstr annotation;
  bstr meaning;
  bstr abjad;
  lexical_role role;
  int last_vowel;
  int props;
} dervaze_lexical_item;
</code></pre>
<p><code>visenc</code> is our abbreviation for <em>visual encoding</em>, which is used to represent Arabic/Ottoman/Farsi words using basic ASCII letters. It is documented on its <a href="https://emresahin.net/visual-encoding-for-ottoman/">own page</a>.</p>
<p><code>index</code> is a unique identifier assigned to each word. Search keys for Latin, Visenc, and <em>Dotless Visenc</em> (e.g., searching for ﺥ using letters like ح, چ, or ج) are used to locate these lexical items via the tries mentioned earlier.</p>
<p>I’m intentionally avoiding UTF-8 or other Unicode encodings because terminal output is often not well-suited for displaying Arabic text correctly.</p>
<p>When I began writing this software, one of my goals was to enable searching for words by their traditional numeric values (Abjad). These are often used in classical Ottoman poetry to encode a date within a verse. For example, the letter Alif corresponds to 1, Ba (ب) to 2, and so on. To search for words by these numerals—for instance, typing 246 to find words with that total value—we store the value here as well.</p>
<p>The <code>lexical_role</code> is used during translation; currently, we use two roles to distinguish between noun and verb suffixes in Turkish.</p>
<p><code>last_vowel</code>, as the name implies, represents the last vowel of the word. Since vowel harmony in Turkish is not always reflected in Ottoman spelling, we check the last vowel when converting an Ottoman word to its Latin Turkish equivalent to ensure the correct suffix is added (e.g., <em>gemiler</em> instead of <em>gemilar</em>).</p>
<p><code>props</code> is a bit field used to represent various properties of the lexical item, such as:</p>
<pre><code class="language-c">#define HAS_FINAL_VOWEL 0x01
#define HAS_SINGLE_VOWEL 0x02
#define IS_LAST_VOWEL_HARD 0x04
#define IS_FINAL_CONSONANT_HARD 0x08
#define HAS_CONSONANT_SOFTENING 0x10
</code></pre>
<p>These properties are particularly important when converting Ottoman text to modern Turkish.</p>
<p>The current version of the translation engine is written in Python, but I plan to rewrite it in C this week. As this is the third rewrite, I don’t expect it to pose a major algorithmic challenge, although debugging the C version may be more demanding.</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>
  </channel>
</rss>
