<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <title>FairScan Blog</title>
  <subtitle>A personal logbook about building FairScan, a simple and respectful document scanner for Android.</subtitle>
  <link href="https://fairscan.org/feed.xml" rel="self" />
  <link href="https://fairscan.org/" />
  <updated>2026-08-30T00:00:00Z</updated>
  <id>https://fairscan.org/</id>
  <author>
    <name>Pierre-Yves Nicolas</name>
    <email>contact@fairscan.org</email>
  </author>
  <entry>
    <title>Why I made FairScan open source (and chose the GPL)</title>
    <link href="https://fairscan.org/blog/open-source-and-gpl/" />
    <updated>2026-08-30T00:00:00Z</updated>
    <id>https://fairscan.org/blog/open-source-and-gpl/</id>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://fairscan.org/blog/open-source-and-gpl/github.webp&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;When I started FairScan, it was the first time I was publishing software on my own. Previously, almost all the code I wrote was on behalf of my employer, and the rest was just for me, with no intention of being published. From day one, it was obvious to me that FairScan would be open source, and the GNU General Public License (GPL) felt like the natural choice. I knew what it meant and didn&#39;t give it much thought, because my attention was on all the technical topics I had to learn to reach my goal.&lt;/p&gt;
&lt;p&gt;What did give me pause was something else: once the code is out there, I have no real control over what happens to it. Someone can fork it, rebrand it, build a product on top of it. The GPL legally requires derivative works to stay open source, but I can&#39;t enforce that in practice: if a company somewhere quietly used my code in a closed product, I would probably never even know. That&#39;s a risk I knew I was taking, and I had to be at peace with it before I clicked to make my repository public.&lt;/p&gt;
&lt;p&gt;Why was it obvious to me that FairScan should be open-source and use the GPL? I believe it&#39;s the combination of several points of view I have on the project.&lt;/p&gt;
&lt;h2&gt;As a user&lt;/h2&gt;
&lt;p&gt;As a user, I want an app that keeps my data strictly private, that doesn&#39;t track me and doesn&#39;t force me to see ads. More generally I don&#39;t want it to have any behavior that is against my own interest, and that&#39;s what I call &lt;a href=&quot;https://fairscan.org/blog/a-respectful-app/&quot;&gt;a respectful app&lt;/a&gt;. Some of those behaviors are quite visible (for example: ads) and some are hidden. App publishers make a lot of claims on how much they care about privacy and other things but there&#39;s no external control. Those claims may be phrased vaguely (&amp;quot;Your privacy is our strongest concern&amp;quot;, &amp;quot;we use data to improve our service&amp;quot;) and they rarely explicitly mention topics where you may not like the truth: how often did you read &amp;quot;we train our models with your data&amp;quot;?&lt;/p&gt;
&lt;p&gt;How an app actually behaves is defined by its source code: the code is not a claim, it&#39;s what&#39;s executed. Most often, the source code is not publicly available because it&#39;s considered a trade secret. Except for open-source apps. If an app is open source, a developer can inspect its code, and check its actual behavior. A developer may also modify the code and distribute a new application based on that. That gives users a form of control, even if they don&#39;t understand code themselves. If an open source app behaves in a way that many people don&#39;t like, it&#39;s quite likely that someone knowledgeable will distribute an alternate version of it. This is one of the most important freedoms I believe software can give its users.&lt;/p&gt;
&lt;p&gt;I personally use open source apps as much as possible, whether on my computer or my phone. Of course, that can&#39;t be the only criterion: an app should first help me get the job done, and in a way that&#39;s easy and efficient for me. Still, the fact that an app is open source means I&#39;m in control of the software I use, and that&#39;s crucial to me.&lt;/p&gt;
&lt;h2&gt;As a developer&lt;/h2&gt;
&lt;p&gt;As a developer, I prefer to develop apps that I use myself. That&#39;s rarely the case when working for an employer: my job could be to work on software whose purpose is unfamiliar to me, and to make it behave in ways that I don&#39;t agree with. As an independent developer, I can decide what I work on. FairScan started with a need I had and a solution I wanted to build. I&#39;m not FairScan&#39;s only user, but I&#39;m its first user.&lt;/p&gt;
&lt;p&gt;Why share it, though? Maybe I could have developed an app just for me: it would fill my need and I would be in control of it. I must say I never really considered that option: I would probably not have started FairScan if it was just for myself. The main reason is that I want my work to be useful. There&#39;s a real satisfaction in knowing that thousands of people use FairScan. Making it open source was the only way to share FairScan along with the freedom I want to get as a user.&lt;/p&gt;
&lt;p&gt;One question everyone publishing open source code has to answer is which license to use. In fact, there&#39;s a major difference among the most common open source licenses. On one side, permissive licenses such as the &lt;a href=&quot;https://en.wikipedia.org/wiki/Apache_License&quot;&gt;Apache License&lt;/a&gt; and the &lt;a href=&quot;https://en.wikipedia.org/wiki/MIT_License&quot;&gt;MIT license&lt;/a&gt; allow users to do almost anything with the source code. On the other side, the &lt;a href=&quot;https://en.wikipedia.org/wiki/GNU_General_Public_License&quot;&gt;GNU General Public License&lt;/a&gt; gives mostly the same rights but requires derivative works (apps that re-use the code) to be also open source and use an equivalent license.&lt;/p&gt;
&lt;p&gt;For FairScan, the choice seemed easy to me. I chose the GPL because I don&#39;t want my work to be re-used in an app that gives less freedom to its users. In a way, it&#39;s about being consistent: if, as a developer, I build software that provides the freedom I want to get as a user, then all users of derivative works should get the same. I know it can be a significant constraint for developers who want to re-use my code but I&#39;m fine with that: I believe it&#39;s a constraint worth accepting for developers who share my views.&lt;/p&gt;
&lt;p&gt;Open source is not incompatible with making money, it can even be a business strategy. For example, Google open sourced Android&#39;s core and it provides open source libraries for Android apps (FairScan uses several of them). And companies such as &lt;a href=&quot;https://proton.me/community/open-source&quot;&gt;Proton&lt;/a&gt; publish open-source apps as part of their business model. On my side, I don&#39;t see how I could build a business around FairScan and I have no intention to go that way. I started &lt;a href=&quot;https://fairscan.org/blog/donations-without-expectations/&quot;&gt;accepting donations&lt;/a&gt; a few months ago: that&#39;s a model I&#39;m more comfortable with. Thank you to all the people who donated!&lt;/p&gt;
&lt;h2&gt;As a citizen&lt;/h2&gt;
&lt;p&gt;As a citizen, there are quite a few things I don&#39;t like in the world I live in. Complaining doesn&#39;t help me feel better. Acting does, at least a little. I guess it started by paying attention to the &lt;a href=&quot;https://en.wikipedia.org/wiki/Sustainability&quot;&gt;sustainability&lt;/a&gt; of the things I consume, and that includes the software I use.&lt;/p&gt;
&lt;p&gt;But being a software engineer, I&#39;m not just a consumer of software, I&#39;m also in a position to produce it. Software has a huge impact on our lives, from personal communication to public services. But to what extent do users get to decide how software should behave? I believe that &lt;a href=&quot;https://en.wikipedia.org/wiki/Free_and_open-source_software&quot;&gt;free and open-source software (FOSS)&lt;/a&gt; can help people take back some control over it. For me, joining &lt;a href=&quot;https://www.april.org/en/&quot;&gt;April&lt;/a&gt;, a French association promoting free software, was one way to put that into practice. But building FairScan the way I did is another, more direct one.&lt;/p&gt;
&lt;p&gt;And when I think about what to build, I come back to the same question: which software do people actually need? I believe that scanning a document is a basic need today: it&#39;s required for all kinds of administrative tasks, for people who don&#39;t necessarily know or care about tech. Should getting that done require paying, watching ads, or giving away private data? I don&#39;t think so, and yet this is so often the model for &amp;quot;free&amp;quot; apps.&lt;/p&gt;
&lt;p&gt;By publishing FairScan&#39;s code, and also &lt;a href=&quot;https://fairscan.org/blog/building_a_public_dataset/&quot;&gt;the dataset I built&lt;/a&gt; to train its detection model, I hope to contribute a small piece to what&#39;s sometimes called the digital commons: things that exist for everyone to use and build upon. It&#39;s a modest contribution and it can continue to exist beyond whatever I personally decide to do with the project. As a user wrote on the Play store:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It&#39;s FOSS!! So I know it will still be around in ten years without ad nor paywall nor nonsense nor malice.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Today, I still have that doubt: if someone violates the GPL, I will most likely never know. But that&#39;s a risk I accept to move forward.&lt;/p&gt;
&lt;p&gt;In the end, I see FairScan less as an &amp;quot;open source app&amp;quot; than as a respectful app, but making it open source, with the GPL specifically, is what makes that possible.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Keeping FairScan simple isn&#39;t simple</title>
    <link href="https://fairscan.org/blog/keeping-fairscan-simple/" />
    <updated>2026-07-31T00:00:00Z</updated>
    <id>https://fairscan.org/blog/keeping-fairscan-simple/</id>
    <content type="html">&lt;p&gt;I present FairScan as a &lt;strong&gt;&amp;quot;simple and respectful&amp;quot;&lt;/strong&gt; app. But those are not just words to talk about FairScan, they are key values that drive development. I dedicated one of my first blog posts to explain what I see as a &amp;quot;respectful&amp;quot; app and I think that &amp;quot;simple&amp;quot; also deserves a few explanations.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://fairscan.org/blog/keeping-fairscan-simple/simple.webp&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2&gt;What I mean by &amp;quot;simple&amp;quot;&lt;/h2&gt;
&lt;p&gt;Let&#39;s first clarify what I mean when I describe FairScan as a &amp;quot;simple&amp;quot; app.&lt;/p&gt;
&lt;p&gt;Essentially, I&#39;m trying to make an app that&#39;s as &lt;strong&gt;easy to use&lt;/strong&gt; as possible. For an app like FairScan, the scanning process should be straightforward and require a minimal number of actions from users. I believe that an app with few buttons and options makes it easier for users to get the job done.&lt;/p&gt;
&lt;p&gt;That&#39;s more likely to happen for an app that &lt;strong&gt;focuses on doing one thing&lt;/strong&gt;. FairScan is about scanning documents. It&#39;s not about storing them or editing them. Storing user data implies some responsibility and I think it&#39;s better handled by a dedicated app. Users can combine apps that have a small but well-defined scope: the Android system provides an infrastructure to make that fluid.&lt;/p&gt;
&lt;p&gt;I should also make it clear that what I mean by &lt;strong&gt;&amp;quot;simple&amp;quot; is definitely not &amp;quot;basic&amp;quot;&lt;/strong&gt;. I put a lot of effort in automatic processing so that users can get a good scan without any manual adjustment. The app takes care of document detection, perspective correction, color detection, brightness and contrast enhancements... What you see today took me a lot of research and testing so that users can &amp;quot;get a scan&amp;quot; without having to think about what it involves behind the scenes. So the fact that FairScan is simple for users certainly does not mean that it&#39;s simple to develop.&lt;/p&gt;
&lt;p&gt;Overall, I think that my goal for a simple app is to &lt;strong&gt;reduce the mental load for users&lt;/strong&gt; as much as possible.&lt;/p&gt;
&lt;h2&gt;Why building a simple app&lt;/h2&gt;
&lt;p&gt;The main reason for me to build a simple app is that I&#39;d like it to be &lt;strong&gt;usable by everyone&lt;/strong&gt;. My goal is that FairScan is not only used by advanced users who know where to find respectful apps. It&#39;s therefore crucial that it&#39;s easy to use.&lt;/p&gt;
&lt;p&gt;It&#39;s also because that&#39;s the kind of app I want to use. When I have to scan a document, it&#39;s often for administrative purposes and I don&#39;t want to think about it, I just want to get a result fast. I&#39;m sure many people feel the same: they don&#39;t enjoy scanning documents, they just want to get the job done with &lt;strong&gt;a tool that stays out of the way&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;I also enjoy looking deeply at a problem, understanding its essence, and figuring out how to present it as clearly as possible.&lt;/p&gt;
&lt;p&gt;For all those reasons, I think a simple app is the only kind I could build.&lt;/p&gt;
&lt;p&gt;It&#39;s a deliberate choice that has been driving FairScan&#39;s development since its inception. It&#39;s a major driver for every decision and it&#39;s really about favoring clarity and ease of use over PDF perfection and manual control.&lt;/p&gt;
&lt;p&gt;Let&#39;s look at how that drives FairScan&#39;s development.&lt;/p&gt;
&lt;h2&gt;A continuous quest for simplicity&lt;/h2&gt;
&lt;p&gt;The app evolved a lot since its first public version. At the time, FairScan&#39;s workflow required users to go through 4 screens to get a scan. At some point, I received a request from someone who was using the app to scan many documents one after another and would have liked a specialized workflow requiring less clicks. I was reluctant to add an option for that and I started to think about how to make the workflow simpler for everyone.&lt;/p&gt;
&lt;p&gt;I made changes in that direction in several steps.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The screen to preview the result and adjust it looked like a questionable step of the workflow. It&#39;s useful in some cases but the app is supposed to give a good result without adjustment. The screen now only appears when tapping a thumbnail and I believe that makes more sense.&lt;/li&gt;
&lt;li&gt;The app always displayed a home screen on startup, and the end of the scanning workflow also led back to that screen. It contained a list of previously saved PDFs which was raising questions. I dropped the home screen.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It&#39;s &lt;strong&gt;not a flawless process&lt;/strong&gt; though. I had to reintroduce an explicit choice on startup to resume an ongoing scan when there&#39;s one: the removal of the home screen had made that choice implicit and that prevented new users from understanding what a &amp;quot;scan&amp;quot; means in FairScan.&lt;/p&gt;
&lt;p&gt;The result is that there are now only 2 screens left in the scanning workflow. Over the past year, FairScan improved on many aspects but it&#39;s now also &lt;strong&gt;simpler for everyone&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;Adding features and keeping it simple&lt;/h2&gt;
&lt;p&gt;The app also had to provide more and more value to users, and I didn&#39;t want that to impact how simple it is.&lt;/p&gt;
&lt;p&gt;As an example, FairScan used to produce PDFs without caring for the physical dimensions of documents until recently. That was a problem, at least in some cases, and users asked for a way to force a PDF paper format such as &amp;quot;A4&amp;quot; or &amp;quot;Letter&amp;quot;. I worked on a different way to address that problem that seemed more aligned with FairScan&#39;s approach. I found technical ways for the app to detect physical dimensions in many cases. As a result, FairScan is now able to detect standard formats such as A4 and generate PDFs that include this information in a fully automated way.&lt;/p&gt;
&lt;p&gt;That raises the question of &lt;strong&gt;what&#39;s a &amp;quot;feature&amp;quot;&lt;/strong&gt;. Users asking for new features usually expect to get new buttons or new options. In the case I just described, nothing changed in FairScan&#39;s user interface, the only visible impact is the generated PDF. All users benefit from this new ability without having to do anything about it. It&#39;s a kind of feature that many people will never notice.&lt;/p&gt;
&lt;h2&gt;Simple vs. user control&lt;/h2&gt;
&lt;p&gt;Some requests don&#39;t have such a clean answer.&lt;/p&gt;
&lt;p&gt;Quite a few people came to FairScan because it&#39;s respectful, in particular it doesn&#39;t suck up user data or display ads, which is not very common. People who care for that want control over the apps they install. The problem is that it&#39;s harder to make an app that&#39;s both simple &lt;strong&gt;and&lt;/strong&gt; gives a lot of control to users. That requires additional buttons or options and it makes the user interface more complex. Of course, it also makes the app more complex to develop and maintain.&lt;/p&gt;
&lt;p&gt;I felt this tension only a few weeks after releasing version 1, when early adopters requested the ability to manually define document edges. That&#39;s something I didn&#39;t want to do. I saw automatic document detection as the basis of FairScan&#39;s value, what makes it possible to build a simple app to scan documents. I knew what I had implemented was far from perfect and I wanted to get feedback to improve it. Unlike other aspects of a scan (for example: brightness), document edges are not a question of personal preference: they&#39;re either right or wrong. For me, introducing a manual control meant giving up on that and acknowledging that FairScan can&#39;t be what I want it to be.&lt;/p&gt;
&lt;p&gt;I resisted for a long time. I worked a lot on automatic document detection: I looked for a &lt;a href=&quot;https://fairscan.org/blog/automatic-document-detection/&quot;&gt;different segmentation model&lt;/a&gt;, produced &lt;a href=&quot;https://fairscan.org/blog/building_a_public_dataset/&quot;&gt;hundreds of new images for the dataset&lt;/a&gt;, and researched &lt;a href=&quot;https://fairscan.org/blog/where-to-cut-automatic-document-cropping/&quot;&gt;a new algorithm to make a quad&lt;/a&gt; out of a segmentation mask. I believe the app got significantly better.&lt;/p&gt;
&lt;p&gt;And yet, for some users, it was still a source of frustration, and I could feel it. I received carefully written requests but also 1-star reviews on the Play store, and GitHub comments explaining to me the basic principles of software development and user experience. I can&#39;t say I&#39;m indifferent to that.&lt;/p&gt;
&lt;p&gt;I resisted up to version 1.21.0, when I received a very well-crafted contribution (thank you Philipp Hasper!) that implemented a new screen to manually define document edges. As the screen to preview and adjust the scan was now out of the main workflow, I felt it was acceptable to add a button for that.&lt;/p&gt;
&lt;p&gt;I guess that&#39;s the kind of tradeoff I have to accept if I want FairScan to reach some day a wider audience.&lt;/p&gt;
&lt;h2&gt;Standing by simplicity&lt;/h2&gt;
&lt;p&gt;A simple app is still the only kind I&#39;m interested in building and it&#39;s been a key value since I started FairScan. The result is an app that&#39;s &amp;quot;not impressive&amp;quot; (as I sometimes read), at least at first sight. I also had to say &amp;quot;no&amp;quot; to some feature requests. And I know many people associate &amp;quot;simple&amp;quot; with &amp;quot;low value&amp;quot;. The real challenge for me is to be comfortable with that. Simplicity is almost invisible. When it succeeds, people rarely notice it, they simply get their work done. That&#39;s exactly what I&#39;m aiming for. I spent a lot of effort so that users can get a good scan without thinking about what it takes. I&#39;m not sure I&#39;ll always make the right call on where to draw the line, but I want FairScan to be an app that &amp;quot;just works&amp;quot;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>When a scan becomes a searchable PDF</title>
    <link href="https://fairscan.org/blog/when-a-scan-becomes-a-searchable-pdf/" />
    <updated>2026-06-17T00:00:00Z</updated>
    <id>https://fairscan.org/blog/when-a-scan-becomes-a-searchable-pdf/</id>
    <content type="html">&lt;p&gt;Let&#39;s say that you signed a 5-page work contract. You have a paper document but no electronic version. Now you want to find a particular clause in the contract. How can you find it quickly? If you scan it with FairScan, you can now get a PDF which you can directly search for text. You may also copy any text from it, for example the paragraph you were looking for, and paste it in another application. This is the result of a text recognition system, which is often referred to as OCR (Optical Character Recognition).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://fairscan.org/blog/when-a-scan-becomes-a-searchable-pdf/ocr.webp&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2&gt;An invisible text layer&lt;/h2&gt;
&lt;p&gt;When you scan a document, what you get is basically an image of the document. It&#39;s often stored in a PDF file and your PDF viewer displays this image, containing the pixels of a signature, the pixels of a logo, or the pixels that make the characters of a word. But to your PDF viewer, it&#39;s just the pixels of an image, and you can&#39;t search for text.&lt;/p&gt;
&lt;p&gt;OCR is about identifying which pixels belong to text and reconstructing the text information they contain: which words and where they are located. The PDF file can then contain both the image and an invisible text layer. That&#39;s the recipe for a useful illusion:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;You still see the document exactly as it is in the image&lt;/li&gt;
&lt;li&gt;When you search for text, your PDF viewer highlights an area where you see a word that matches your search&lt;/li&gt;
&lt;li&gt;When you point at an area of the image where you see a word, the cursor lets you select the word and copy it&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now you know the trick! And getting searchable PDFs like that out of FairScan is what I wanted to do.&lt;/p&gt;
&lt;h2&gt;Why now?&lt;/h2&gt;
&lt;p&gt;That looks nice, so why didn&#39;t FairScan have it before? That&#39;s because FairScan wasn&#39;t ready for it: I wouldn&#39;t be comfortable if FairScan was giving you wrong text half of the time. To get good results from an OCR engine, you need to provide it a readable image. If it&#39;s hard to read for a human, it&#39;s certainly also hard to read for an OCR engine.&lt;/p&gt;
&lt;p&gt;Over the past year, I worked on different parts of FairScan&#39;s automatic processing to transform photos of documents into PDFs that are easy for humans to read:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://fairscan.org/blog/automatic-document-detection/&quot;&gt;document detection&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;perspective correction&lt;/li&gt;
&lt;li&gt;shadow reduction&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fairscan.org/blog/what-s-a-good-scan/&quot;&gt;brightness and contrast enhancement&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All this work on image processing helped FairScan produce clean PDFs and can now also contribute to making text recognition effective.&lt;/p&gt;
&lt;h2&gt;Implementing OCR in FairScan&lt;/h2&gt;
&lt;p&gt;Developing an OCR engine is quite hard. It was definitely out of the question for FairScan. I use &lt;a href=&quot;https://github.com/tesseract-ocr/tesseract&quot;&gt;Tesseract&lt;/a&gt;, an open source project that was initiated 40 years ago at HP.&lt;/p&gt;
&lt;p&gt;Tesseract can be integrated easily into an Android app and covers about 120 languages. To avoid increasing drastically the app download size, language-specific data is not included in the app: you will have to download it separately for each language in FairScan&#39;s settings screen.&lt;/p&gt;
&lt;p&gt;Like all the other parts of FairScan&#39;s scanning process, OCR runs on your device: your data is not sent to any server to be processed. This is unlike many mobile apps that rely on cloud processing to achieve the same task. On a mobile device, OCR typically takes a few seconds per page. That&#39;s significantly more than the other processing steps in FairScan, but still fast enough to remain practical for everyday scanning.&lt;/p&gt;
&lt;h2&gt;The challenge of PDF fonts&lt;/h2&gt;
&lt;p&gt;Making Tesseract run inside FairScan wasn&#39;t particularly difficult. Generating PDFs that work reliably across different writing systems turned out to be much harder.&lt;/p&gt;
&lt;p&gt;PDF files need to know about fonts, fonts that cover the characters used in the file. Which font should FairScan use to generate PDFs? Tesseract can read many languages like English, Russian or Chinese. So we need a font for the &lt;a href=&quot;https://en.wikipedia.org/wiki/ISO_basic_Latin_alphabet&quot;&gt;latin alphabet&lt;/a&gt;, the &lt;a href=&quot;https://en.wikipedia.org/wiki/Cyrillic_alphabets&quot;&gt;cyrillic alphabet&lt;/a&gt; or &lt;a href=&quot;https://en.wikipedia.org/wiki/Chinese_characters&quot;&gt;Chinese characters&lt;/a&gt;. Fonts can be huge and that could impact both the app download size and the size of the generated PDFs. The irony is that, for invisible text, users never see the characters produced by the font. But PDF still needs a font for the text.&lt;/p&gt;
&lt;p&gt;My research led me to the &lt;a href=&quot;https://github.com/adobe-fonts/adobe-notdef&quot;&gt;Adobe NotDef&lt;/a&gt; font: it renders all &lt;a href=&quot;https://en.wikipedia.org/wiki/Unicode&quot;&gt;Unicode&lt;/a&gt; characters (covering all writing systems) the same way. As it&#39;s a tiny file, it looked like a good solution to avoid file size issues. However, because this font covers so many characters, the library I use to generate PDFs takes a couple of seconds to load it on my phone. I didn&#39;t manage to solve that and looked for another solution.&lt;/p&gt;
&lt;p&gt;In fact, Tesseract itself can render PDFs. It faces the exact same problem and found a solution for it based on a kind of fake font. I couldn&#39;t use that directly because FairScan needs direct control on the PDF, for example to feed information about the physical dimensions of the document. But I took a lot of inspiration from what Tesseract does to generate PDF files. It requires hand-crafting PDF, which I never did before, but it works: it produces PDFs for all kinds of characters very fast and with a tiny font.&lt;/p&gt;
&lt;h2&gt;Keeping it simple&lt;/h2&gt;
&lt;p&gt;The technical solution I worked on for OCR was less important to me than how OCR should impact user experience. And it was clear to me that this impact should be minimal. OCR is not FairScan&#39;s core feature, and I didn&#39;t want OCR to break FairScan&#39;s main promise: its simplicity.&lt;/p&gt;
&lt;p&gt;So the way OCR appears in FairScan&#39;s user interface is basically as an option to enable. More precisely, you choose which languages are enabled. Once it&#39;s done, OCR runs transparently, as part of the export. Nothing changes in the scanning process. The difference is in the generated output: you get a PDF where you can search and copy text.&lt;/p&gt;
&lt;p&gt;Enabling more than one language for OCR makes it possible to extract text in multilingual documents. Be aware that processing may be slower and less precise. You can also disable all languages: that effectively disables OCR.&lt;/p&gt;
&lt;h2&gt;Known limits&lt;/h2&gt;
&lt;p&gt;It&#39;s not perfect and it&#39;s not as simple as I wish it was. I like everything to be automatic in FairScan but there is no automatic language detection. You have to enable the appropriate language(s) to get good results. I guess that shouldn&#39;t be a big problem: I expect that almost all documents you scan are always in the same one or two languages.&lt;/p&gt;
&lt;p&gt;Also, let&#39;s state it clearly: you shouldn&#39;t expect to get acceptable results on handwritten text. That&#39;s a much harder problem and I believe it would go beyond FairScan&#39;s scope.&lt;/p&gt;
&lt;p&gt;I also expect OCR quality to improve gradually over time. I already noticed that detection is poor on documents with very dense text, for example dictionary pages. I hope user feedback will help identify other cases that need attention.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;A scanned document is often more useful when it can be searched, copied, and indexed like any other digital document. OCR makes that possible. FairScan&#39;s goal is still the same: turning paper documents into useful PDFs. OCR doesn&#39;t change that goal. It simply makes those PDFs more useful once they&#39;ve been created. Still, OCR is often perceived as an &amp;quot;advanced feature&amp;quot;. I hope that FairScan can contribute to bringing it to more people, in &lt;a href=&quot;https://fairscan.org/blog/fairscan-purpose/&quot;&gt;a simple and respectful way&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Donations, without expectations</title>
    <link href="https://fairscan.org/blog/donations-without-expectations/" />
    <updated>2026-04-19T00:00:00Z</updated>
    <id>https://fairscan.org/blog/donations-without-expectations/</id>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://fairscan.org/blog/donations-without-expectations/present.webp&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;I give FairScan to everyone who wants to use it. The app is free and doesn&#39;t include any behavior that goes against users&#39; interest: no ads, no tracking, no collection of your data, no premium version... That&#39;s possible because FairScan does not have to serve the interests of a business.&lt;/p&gt;
&lt;p&gt;I&#39;m an independent developer doing all kinds of tasks for FairScan:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;software development (of course)&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fairscan.org/blog/open-source-app-for-everyone/&quot;&gt;product management&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://fairscan.org/blog/where-to-cut-automatic-document-cropping/&quot;&gt;researching image processing algorithms&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;producing a dataset for the segmentation model&lt;/li&gt;
&lt;li&gt;answering e-mails and comments on GitHub issues&lt;/li&gt;
&lt;li&gt;and many other things.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I&#39;m definitely more comfortable for some of those tasks than others, but I see the project as a whole. As part of a normal job, it would be awkward for a developer to spend time on repetitive tasks that can be outsourced like &lt;a href=&quot;https://fairscan.org/blog/building_a_public_dataset/&quot;&gt;creating &amp;quot;fake&amp;quot; documents and annotating data to train a model&lt;/a&gt;. I see it differently because FairScan is &amp;quot;my&amp;quot; project: I do what it takes to make a great app for users.&lt;/p&gt;
&lt;p&gt;I spend most of my time on FairScan, and &lt;a href=&quot;https://fairscan.org/blog/working-on-fairScan-or-getting-a-real-job/&quot;&gt;I now consider it as my job&lt;/a&gt;, even if I don&#39;t make money out of it. My main interest is having a positive impact and seeing people use the software I build. I made money in my previous jobs and, for now, I can afford to work without making money.&lt;/p&gt;
&lt;p&gt;When I published FairScan, I received emails thanking me for the app, and that was quite rewarding. Some people wrote that they would like to give me money. I also appreciated those messages, but I hadn&#39;t set up a way to receive donations. I didn&#39;t see it as a priority as the app had very few users and even fewer potential donors.&lt;/p&gt;
&lt;p&gt;I also received emails asking me to implement specific features, and, even though they were always kind, that was harder to manage. &lt;a href=&quot;https://fairscan.org/blog/fairscan-purpose/&quot;&gt;What I&#39;m trying to build with FairScan&lt;/a&gt; is not the typical open source app. I&#39;m not looking for ideas of features to add and I&#39;m not trying to cover all the various needs of &amp;quot;power users&amp;quot;. I&#39;m trying to build an app that is simple and consistent. Something that can be used by everyone, even if not everyone likes it. I had to say &amp;quot;no&amp;quot; or &amp;quot;later&amp;quot; to many feature requests, and that was definitely not easy for me.&lt;/p&gt;
&lt;p&gt;Adding money into that would have made things worse. When I received an email that mentioned both giving money and features to add, I took it as a clear signal: a few days later, I added an explicit statement on my website to decline all donations. Accepting money would have led to implicit expectations that I couldn&#39;t manage. Even if that wasn&#39;t intentional, it would have put pressure on me to implement features I didn&#39;t believe in, to diverge from the direction I gave to my project.&lt;/p&gt;
&lt;p&gt;Time has passed. Little by little, feedback has helped me improve all areas of the automatic processing, which is the core of the app: document detection, cropping, color detection, brightness and contrast enhancement... This is not about &amp;quot;features&amp;quot;, it&#39;s what most people would see as the basis of a scanning app without being able to articulate it. In addition to that, I did implement a few of the requested features, and the UI is even a bit simpler than it was. Overall, FairScan got more mature and it gets closer to what I wanted to build: an app that &amp;quot;just works&amp;quot;.&lt;/p&gt;
&lt;p&gt;The reviews on the Play Store and the messages I receive also tell me that many people enjoy the app and the fact that it&#39;s simple. I still feel a bit uncomfortable saying &amp;quot;no&amp;quot; to feature requests but I&#39;m now much more confident about the direction I gave to FairScan.&lt;/p&gt;
&lt;p&gt;The app is now quite decent but I know it&#39;s still far from perfect. I see a lot of things I would like to improve or start to tackle in FairScan. And based on what I already did, I know it will take time and effort.&lt;/p&gt;
&lt;p&gt;I can continue working on FairScan without making money but I&#39;m not sure how realistic it is in the long run and I can&#39;t pretend it&#39;s a good model for open source development.&lt;/p&gt;
&lt;p&gt;I believe that donations could now help me, at least symbolically. It would help me feel some form of support and recognition for the work behind FairScan. That, in turn, could make it easier to find energy to work on tasks that are not quite enjoyable but still necessary.&lt;/p&gt;
&lt;p&gt;Let&#39;s try something new for me: I&#39;m going to update the website to now accept donations.&lt;/p&gt;
&lt;p&gt;If you&#39;re willing to donate, I will gratefully receive it provided that we agree on one thing: &lt;strong&gt;it should not lead to any kind of expectation from your side&lt;/strong&gt;. The same way I give FairScan with no expectation to every person who wants to use it. I don&#39;t want to commit on implementing any specific feature and, since life is unpredictable, I can&#39;t commit to work on FairScan for the next five years. I hope you will understand it.&lt;/p&gt;
&lt;p&gt;Working as an independent open source developer is not a typical job and I&#39;m still learning how to frame it. I&#39;m already happy to have made FairScan grow so far and I hope I can make my effort sustainable. I want to keep going as long as it makes sense.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Working on FairScan or getting a &quot;real job&quot;?</title>
    <link href="https://fairscan.org/blog/working-on-fairScan-or-getting-a-real-job/" />
    <updated>2026-04-18T00:00:00Z</updated>
    <id>https://fairscan.org/blog/working-on-fairScan-or-getting-a-real-job/</id>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://fairscan.org/blog/working-on-fairScan-or-getting-a-real-job/pict4669.webp&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;I&#39;ve been working actively on FairScan for almost a year now. Why do I spend my time working on an open source project rather than getting a &amp;quot;real job&amp;quot;? What drives me? To explain that, I have to write about myself, much more than I did so far in this blog. That feels a bit uncomfortable but it can help convey what I&#39;m trying to achieve.&lt;/p&gt;
&lt;p&gt;Over the last 25 years, I had several jobs as a software engineer. The last one was for a company producing software for developers. I worked with passionate people and I learned a lot about software engineering, product management, and team collaboration. I also found a culture that resonated strongly with my own beliefs. It was an amazing experience. However, after 10 years, my job had changed to being a manager and I wasn&#39;t happy about it. Moreover, the company had grown from 25 to 500 employees and the culture was dissolving, becoming something I no longer recognized. It was a bit heartbreaking but I had to turn that page, time had come for me to leave.&lt;/p&gt;
&lt;p&gt;What next? Life is short, and sometimes it reminds you of that. So what&#39;s important to me? When I think about this question, my head gets full of the concerns I have about where the world is going. I know I can&#39;t change the world but I just can&#39;t stay doing nothing about it. There are plenty of domains in my daily life where I try to be consistent with what I believe in, but my job is the most crucial part of it, it&#39;s where I spend a significant proportion of my time. I need sense, &lt;strong&gt;I need to feel that I contribute to something useful&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;I briefly tried working as a maths teacher but I failed. I would love being able to do that: helping other humans grow, finding ways to explain concepts, giving keys to understand the world... But I miss crucial skills: managing a group of 25 or 30 teenagers is just impossible to me and I probably knew it before trying. Even though, I tried. It was an intense experience of just a few weeks but I have no regret about it. Back to doubt.&lt;/p&gt;
&lt;p&gt;I could probably find a job as a software engineer in a bank or some other business that needs my skills. But I feel I would most likely contribute to making the world worse than it is, having an impact that is opposite to what I want. It would be easy to say that &amp;quot;I have no choice&amp;quot;, but I believe that would be wrong.&lt;/p&gt;
&lt;p&gt;Let&#39;s take a step back. &lt;strong&gt;What&#39;s a good job for me?&lt;/strong&gt; I guess it&#39;s a lot about how much I enjoy it and the sense I get out of it. I also expect to get money from it, and I need to have the required skills. It looks like an equation that is difficult to solve. Sense is what I need most. For now, &lt;a href=&quot;https://fairscan.org/blog/donations-without-expectations/&quot;&gt;I can afford to work without making money&lt;/a&gt;, so let&#39;s take it out of the equation. That&#39;s radical, but it opens new possibilities.&lt;/p&gt;
&lt;p&gt;What are my skills? Writing good software, and designing products that make sense, I believe. I can put those skills to work, not to build any kind of software, but something that makes me feel I have a modest but positive impact.&lt;/p&gt;
&lt;p&gt;My view is that, on a daily basis, we rely a lot on software that serves the interest of a business &lt;a href=&quot;https://fairscan.org/blog/a-respectful-app/&quot;&gt;rather than the interest of its users&lt;/a&gt;. Most people seem to accept the situation. I don&#39;t. My ambition is to contribute putting this situation into question by developing software that works, &lt;a href=&quot;https://fairscan.org/blog/open-source-app-for-everyone/&quot;&gt;that is usable by everyone&lt;/a&gt;, and that&#39;s respectful.&lt;/p&gt;
&lt;p&gt;I looked for ideas of software I could develop. It happened that I needed a mobile document scanning app and I couldn&#39;t find an existing one matching my criteria. So I started to develop it. Implementing a scanning app that can be used by everyone is not trivial: the main challenges are about automatic document detection, image processing and a good user interface. But, with enough motivation, it&#39;s doable by an independent developer like me. That&#39;s how FairScan was born.&lt;/p&gt;
&lt;p&gt;It turned out that this is a market that illustrates very well the problem I described: when you install a &amp;quot;free&amp;quot; app, either you give your private data (your scans) to Big Tech, or you&#39;re exposed to ads and dark patterns that try to get your money somehow. FairScan is my attempt to change that: to contribute to raise awareness, especially among people who don&#39;t know open source, that software can be both usable and respectful.&lt;/p&gt;
&lt;p&gt;Building an open source project doesn&#39;t have an impact that is as directly visible as, for example, teaching maths to kids. Still, FairScan is &lt;a href=&quot;https://forum.getodk.org/t/a-document-scanning-app-that-integrates-with-collect/57214&quot;&gt;now used&lt;/a&gt; in conjunction with &lt;a href=&quot;https://getodk.org/&quot;&gt;ODK Collect&lt;/a&gt;, an app that is used mainly by research, public health, and humanitarian organizations. I didn&#39;t expect that. I didn&#39;t think FairScan could end up contributing to efforts I actually care about.&lt;/p&gt;
&lt;p&gt;Working on FairScan is not always easy and I still have doubts. But this is what I consider my job, at least for now. At first, I wasn&#39;t quite comfortable with the idea because it doesn&#39;t fit well with what you usually call a &amp;quot;job&amp;quot;. Now, I think I am. It&#39;s the result of a deliberate choice, and it allows me to put a lot of myself in what I do every day.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Where to cut? Automatic document cropping strategies</title>
    <link href="https://fairscan.org/blog/where-to-cut-automatic-document-cropping/" />
    <updated>2026-03-14T00:00:00Z</updated>
    <id>https://fairscan.org/blog/where-to-cut-automatic-document-cropping/</id>
    <content type="html">&lt;p&gt;When you start a scan in FairScan and point your device to a document, the app detects the document and displays a quadrilateral on top of the image to show how it will crop it when you press the capture button. Two separate steps happen one after the other:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;A machine-learning segmentation model detects which pixels of the image are part of the document.&lt;/li&gt;
&lt;li&gt;An algorithm derives a quadrilateral from the outline (or contour) of the document pixels returned by step 1.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;We don&#39;t want just any polygon, we want one with four edges, because that&#39;s what can be mapped to a digital image or to a PDF page. And that&#39;s the responsibility of step 2, which could be summarized as: &lt;strong&gt;&amp;quot;where to cut?&amp;quot;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://fairscan.org/blog/where-to-cut-automatic-document-cropping/intro.webp&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;There are multiple ways to do that, and they don&#39;t all lead to the same result. The difference is subtle in many cases, but in others, that are not so rare, it&#39;s impossible to miss.&lt;/p&gt;
&lt;h2&gt;Approach 1: looking for corners&lt;/h2&gt;
&lt;p&gt;I found many examples on the web that show how to code your own &amp;quot;document scanner&amp;quot; in just a few lines of code. All of them rely on the &lt;a href=&quot;https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm&quot;&gt;Douglas-Peucker algorithm&lt;/a&gt;, that was &lt;a href=&quot;https://utppublishing.com/doi/10.3138/FM57-6770-U75U-7727&quot;&gt;published in 1973&lt;/a&gt; in the context of cartographic generalization. This algorithm simplifies a curve by removing points while ensuring that the simplified curve stays within a given distance of the original one. When applying it to the contour of the document pixels, we can check whether the resulting polygon has 4 edges: in that case, we&#39;re done.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://fairscan.org/blog/where-to-cut-automatic-document-cropping/dp.webp&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Douglas-Peucker is a simple algorithm, it&#39;s well defined and already implemented: why look further? The problem is that it gives bad results in some cases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Some documents have rounded corners (for example some identity cards). The algorithm then selects a point on the contour that is close to the corner but it has to &amp;quot;cut&amp;quot; a bit the edges of the document.&lt;/li&gt;
&lt;li&gt;When a document misses a corner (folded, stapled...), it appears as having 5 edges, not 4. To have only 4 vertices, the algorithm has, again, to cut some part of the document.&lt;/li&gt;
&lt;li&gt;When the document detection step returns a set of pixels that doesn&#39;t reflect well the reality, the algorithm may give very bad results. Among the hundreds of points in the contour, only 4 matter for the final result and any imprecision has a big impact on the resulting quadrilateral.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://fairscan.org/blog/where-to-cut-automatic-document-cropping/problems.webp&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The algorithm works by removing points from the initial contour. By design, the four corners of the resulting quadrilateral must already exist in the original contour. The algorithm cannot create new corners, and this turns out to be a major limitation.&lt;/p&gt;
&lt;h2&gt;Approach 2: looking for edges&lt;/h2&gt;
&lt;p&gt;I looked for a different kind of algorithm, that is more adapted to identifying a document. A key intuition is that edges are long and stable parts of the contour, while corners are short and often noisy. Instead of focusing on the small corner regions, we can rely on the long straight segments that make up most of the document boundary. There are well-known mathematical &lt;a href=&quot;https://en.wikipedia.org/wiki/Deming_regression&quot;&gt;ways to fit a line&lt;/a&gt; based on a set of points, so the main challenge is to split the points of the contour so that we can define a line for each edge.&lt;/p&gt;
&lt;p&gt;One way to split the contour points is to look at the &amp;quot;orientation&amp;quot; of the contour at each point: we can take the previous point and the next point and draw a line between them to get a sense of the direction (the tangent) of the contour at this precise position. Points that are part of the same edge of the document should have the same orientation. Of course, there may be some imperfections in the contour so we can use a sliding window to remove slight variations.&lt;/p&gt;
&lt;p&gt;The algorithm can then look like that:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;calculate the orientation (an angle) of the contour for each one of its points&lt;/li&gt;
&lt;li&gt;group adjacent points that have a similar orientation&lt;/li&gt;
&lt;li&gt;select the 4 largest groups of points&lt;/li&gt;
&lt;li&gt;fit a line for each group: each one is an edge of the quadrilateral&lt;/li&gt;
&lt;li&gt;corners can be calculated as the intersections of adjacent edges&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://fairscan.org/blog/where-to-cut-automatic-document-cropping/edges2.webp&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;In this algorithm, we use much more data than when focusing on the corners: a few &amp;quot;bad&amp;quot; points are therefore less likely to impact the result.&lt;/p&gt;
&lt;p&gt;This algorithm fixes the problems Douglas-Peucker had with missing or rounded corners: we can reconstruct corners that are not part of the original contour. It also handles cases better when the detected document pixels (the segmentation mask) are imperfect, because it can rely on partial edges to reconstruct them. That doesn&#39;t mean it can save the worst cases, but that&#39;s still quite valuable.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://fairscan.org/blog/where-to-cut-automatic-document-cropping/problems-fixed.webp&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;This new algorithm is slightly slower than Douglas-Peucker, but still very fast compared to the segmentation model itself, so the difference is not noticeable in the app.&lt;/p&gt;
&lt;p&gt;More importantly, it produces much more reliable quadrilaterals in difficult cases such as rounded corners, folded documents, or imperfect segmentation masks. After testing it on hundreds of images, it consistently produced better results than the previous approach.&lt;/p&gt;
&lt;p&gt;The key idea is simple: instead of trying to guess four precise corner points, the algorithm looks for the four long edges that define the document. Those edges are much more stable and carry far more information than the small, often noisy corner regions. In practice, that small change in perspective makes automatic cropping much more robust.&lt;/p&gt;
&lt;p&gt;The new edge-based detection algorithm is now available in FairScan 1.16.0.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>What&#39;s a good scan?</title>
    <link href="https://fairscan.org/blog/what-s-a-good-scan/" />
    <updated>2026-02-15T00:00:00Z</updated>
    <id>https://fairscan.org/blog/what-s-a-good-scan/</id>
    <content type="html">&lt;p&gt;In my previous post, I talked about failed scans, but what&#39;s a good scan? What does it look like? How is it different from a photo?
It&#39;s a question that comes back regularly when I work on FairScan, and I still don&#39;t have a clear answer. What I know is that this question quietly drives many of the strategic choices I make. I recently worked on improving how FairScan handles color documents, and that was a good opportunity to reflect on it with the experience I gained over the past months.&lt;/p&gt;
&lt;h2&gt;A scan is not a photo&lt;/h2&gt;
&lt;p&gt;A photo is about capturing a scene, something that happens within a given environment, with a particular atmosphere. It&#39;s largely about light: in fact, the word &lt;em&gt;photo&lt;/em&gt; &lt;a href=&quot;https://en.wikipedia.org/wiki/Photography#Etymology&quot;&gt;comes from the Greek word for light&lt;/a&gt;. Light comes from a source, either natural (the sun) or artificial (a lamp), and it has a direction. The way light falls on a scene, the way it highlights some parts and leaves others in the dark, plays a crucial role in the impression we get when looking at a photo.&lt;/p&gt;
&lt;p&gt;A scan, on the other hand, tries to capture a document and only that, as if it were isolated from the world, under light that is as uniform as the surface of a screen. A flatbed scanner is a good reference for that ideal.&lt;/p&gt;
&lt;p&gt;In comparison, a phone&#39;s camera has a major advantage: it fits in your pocket and is already connected to your digital world, making it easy to share documents instantly. But being able to take a photo of a document is very different from having a scan of that document.&lt;/p&gt;
&lt;h2&gt;What we expect from a scan&lt;/h2&gt;
&lt;p&gt;When you look at a scan, you probably have expectations that you don&#39;t consciously articulate. There is likely no absolute truth here, but working on FairScan forces me to identify what I believe are the most common ones:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Homogeneous brightness&lt;/strong&gt;: light should be uniform, shadows should be avoided&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Bright enough, but not washed out&lt;/strong&gt;: there should be enough light without losing details in the brightest areas&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Readable contrast&lt;/strong&gt;: differences in brightness are crucial for readability, especially for text&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Color only if there&#39;s color&lt;/strong&gt;: if at least one element in the document is colored, I want the scan to show it; otherwise, I expect a black-and-white scan&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Ideally, I think a good scan should look like the document appeared on a screen before it was printed. Sometimes it&#39;s more complex than that: elements can be added later on paper, like stamps or handwritten annotations. But in most cases, trying to reproduce the original digital document is a simple way to define a clear goal.&lt;/p&gt;
&lt;p&gt;As a user, I don&#39;t want to think about how to adjust a photo to get a decent scan. Which parameters should I tweak? In what order? An app like FairScan should take care of that automatically. That&#39;s how I can get a usable scan in a few seconds, without effort.&lt;/p&gt;
&lt;h2&gt;Enhancing without betraying&lt;/h2&gt;
&lt;p&gt;A document scanning application starts by cropping a photo to remove everything that is not part of the document (see &lt;a href=&quot;https://fairscan.org/blog/automatic-document-detection/&quot;&gt;this blog post&lt;/a&gt;). The goal is then to &amp;quot;enhance&amp;quot; the photo to make it look like a scan, but without damaging it in the process.&lt;/p&gt;
&lt;p&gt;When you see a document as part of a photo, as one element of the physical world, your brain tends to extrapolate what the document should look like. The surprise comes after cropping: the exact same pixels that made the document look white within a photo often don&#39;t look white anymore once everything around them is removed. What appeared to be white paper is in fact frequently composed of grey pixels (see &lt;a href=&quot;https://fairscan.org/blog/the-heart-of-fairscan-image-processing-pipeline-explained/&quot;&gt;another blog post&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://fairscan.org/blog/what-s-a-good-scan/brightness.webp&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;To mitigate this, earlier versions of FairScan processed color documents using a very basic approach: increasing the brightness of all pixels by the same factor. Unsurprisingly, the result was sometimes too dark, sometimes washed out and unreadable. FairScan 1.14 uses a more careful strategy, increasing brightness based on image content rather than an arbitrary constant.&lt;/p&gt;
&lt;p&gt;Making brightness homogeneous is also difficult. Reducing shadows involves evaluating brightness variations across the document and compensating for them. The challenge is that two things are mixed together: the lighting that reaches the document, with its direction and intensity, and the intrinsic reflectance of the document itself, which depends on its content. On a black-and-white document, how can an algorithm distinguish a shadow from an area that was intentionally printed in gray?&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://fairscan.org/blog/what-s-a-good-scan/shadows.webp&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2&gt;How I approach this in FairScan&lt;/h2&gt;
&lt;p&gt;I didn&#39;t know anything about image processing before working on FairScan. I learn techniques as I encounter concrete problems and look for ways to solve them. To compare algorithms or parameter choices, I usually test them side by side on a small set of images that cover a wide range of situations. Before shipping, I also review the results on hundreds of images from &lt;a href=&quot;https://fairscan.org/blog/building_a_public_dataset/&quot;&gt;my dataset&lt;/a&gt; to make sure the changes actually move FairScan closer to what I consider a &amp;quot;good scan&amp;quot;.&lt;/p&gt;
&lt;p&gt;It&#39;s also essential that the processing shipped in the app doesn&#39;t make it slower. FairScan should feel fast: when you capture an image, you expect to see the result almost immediately. This often means finding a trade-off between visual quality and performance on a mobile device. In practice, it&#39;s sometimes possible to gain significant performance with a loss in quality that very few people will notice.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;So what is a good scan?&lt;/p&gt;
&lt;p&gt;I still don&#39;t have a single, definitive answer. I believe it should be both readable and reasonably faithful to the original document, but I&#39;m still exploring how to translate that into FairScan. Much of it comes down to product choices, especially deciding how far the app should go when it &amp;quot;enhances&amp;quot; images.&lt;/p&gt;
&lt;p&gt;What I know for sure is that this has to remain compatible with what I&#39;m trying to build: an app that produces PDFs that don&#39;t require manual adjustments. The work I want to spare users must be handled by FairScan itself, which means carefully engineering and fine-tuning its behavior. In the end, even if the app does a lot behind the scenes, that complexity should remain invisible. To users, FairScan should feel fast and simple. Always.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Learning from failed scans</title>
    <link href="https://fairscan.org/blog/learning-from-failed-scans/" />
    <updated>2026-01-20T00:00:00Z</updated>
    <id>https://fairscan.org/blog/learning-from-failed-scans/</id>
    <content type="html">&lt;p&gt;Since version 1.0, released last September, FairScan has been updated 11 times with regular improvements. Many of those updates focus on FairScan&#39;s core, the automatic processing of captured images, with the goal of producing clean PDFs effortlessly. And yet, the result is not always what you expect. The result is sometimes not as good as what you get from a commercial app, even if it&#39;s done in a &lt;a href=&quot;https://fairscan.org/blog/a-respectful-app/&quot;&gt;much more respectful&lt;/a&gt; way.&lt;/p&gt;
&lt;p&gt;Of course, what those commercial apps produce is the result of years of work. Some of them also store all user scans in the cloud, which gives them access to massive amounts of data they can use to improve their algorithms. FairScan doesn&#39;t collect any data from its users, and its detection model is trained on a public dataset.&lt;/p&gt;
&lt;p&gt;With the latest release, however, there is now an easy way to share the images that FairScan doesn&#39;t handle well. And that can help make FairScan better.&lt;/p&gt;
&lt;h2&gt;Where the processing can fail&lt;/h2&gt;
&lt;p&gt;When you tap on the capture button in FairScan (the big round one), you get a preview of the scanned page after a fraction of a second. It&#39;s not the photo you just captured, but the result of &lt;a href=&quot;https://fairscan.org/blog/the-heart-of-fairscan-image-processing-pipeline-explained/&quot;&gt;the automatic image processing pipeline&lt;/a&gt; that the app runs behind the scenes. As the app is still far from perfect, each step of that pipeline can produce suboptimal results.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://fairscan.org/blog/learning-from-failed-scans/bad-scans.webp&quot; alt=&quot;Examples of bad scans&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here are some typical examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Document detection&lt;/strong&gt; is the most critical step. It may fail to detect edges accurately, especially in difficult conditions, for example when multiple documents appear in the frame.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Color detection&lt;/strong&gt; tries to determine automatically whether a document should be processed as grayscale or as color, but this is not always as straightforward as it sounds, particularly with low-&lt;a href=&quot;https://en.wikipedia.org/wiki/Colorfulness&quot;&gt;saturation&lt;/a&gt; colors or under dim lighting.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Brightness and contrast&lt;/strong&gt; are adjusted automatically, which can sometimes result in documents that are too bright or too dark.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When the app produces a good-looking document (which is hopefully most of the time), that&#39;s great for users. But those cases don&#39;t help improve FairScan. The real learning comes from the situations where the result is disappointing. Those &amp;quot;bad&amp;quot; cases highlight what needs to be improved and help guide future work.&lt;/p&gt;
&lt;h2&gt;How you can help&lt;/h2&gt;
&lt;p&gt;When a page is processed badly, you can now report it easily:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Open the menu at the top right and go to the &lt;em&gt;About&lt;/em&gt; screen&lt;/li&gt;
&lt;li&gt;Tap on &lt;em&gt;Report a problem with last captured image&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;https://fairscan.org/blog/learning-from-failed-scans/screenshot.webp&quot; alt=&quot;Screenshots&quot;&gt;&lt;/p&gt;
&lt;p&gt;Your system will then let you choose which app to use to send the image. The email address is prefilled with &lt;a href=&quot;mailto:contact@fairscan.org&quot;&gt;contact@fairscan.org&lt;/a&gt;. Nothing is sent directly by FairScan: the app only prepares the data and hands it over to the app you choose to actually send it. Your email app should let you see the image before sending it, and you can add a short description of the issue you noticed.&lt;/p&gt;
&lt;p&gt;Please note that the image that is sent is &lt;strong&gt;not&lt;/strong&gt; the result of FairScan&#39;s processing. It is the raw image captured by your device, which serves as the input of the processing pipeline. Also note that tapping &lt;em&gt;End scan&lt;/em&gt; on the export screen deletes all temporary images, including the last captured one.&lt;/p&gt;
&lt;h2&gt;What I will do with what you send (and what I won&#39;t do)&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;I will not share or publish your images.&lt;/strong&gt; This is probably what you would expect from an app that aims to be respectful, but it&#39;s worth stating explicitly. Please avoid sending sensitive documents, though: I would not feel comfortable receiving them. Also keep in mind that email is not encrypted.&lt;/p&gt;
&lt;p&gt;When you send an image, I reproduce locally the processing that happened on your device. That&#39;s why the FairScan version you used is automatically included in the email subject. It allows me to observe the issue myself and investigate it properly.&lt;/p&gt;
&lt;p&gt;Over time, these reports help reveal patterns: situations or document types that are not well represented in &lt;a href=&quot;https://fairscan.org/blog/building_a_public_dataset/&quot;&gt;the dataset I built&lt;/a&gt; to train the document detection model. When that happens, I do not add the received images to the dataset. Instead, I create similar images myself. This is because copyright may apply both to the photo itself and to the documents that appear in the image.&lt;/p&gt;
&lt;p&gt;The dataset currently contains over 600 images. That&#39;s already useful, but it&#39;s still a very small sample compared to the variety of documents and real-world conditions in which FairScan is used every day. Inevitably, it has biases that need to be identified and addressed. This is especially important since the same dataset is used not only for document detection, but also to evaluate other &lt;a href=&quot;https://en.wikipedia.org/wiki/Heuristic&quot;&gt;heuristics&lt;/a&gt; in the processing pipeline, such as color detection (see &lt;a href=&quot;https://fairscan.org/blog/color-detection-data-driven/&quot;&gt;this blog post&lt;/a&gt;).&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;With FairScan, you own your data. Your scans are not automatically uploaded to a cloud to be analyzed or reused by large companies.&lt;/p&gt;
&lt;p&gt;If you&#39;re willing to help improve FairScan, you can now easily share an image that the app didn&#39;t process correctly. This directly helps improve the automatic processing pipeline and make its results more reliable over time.&lt;/p&gt;
&lt;p&gt;Every report contributes to better scans, for everyone.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>FairScan can now be called from other apps</title>
    <link href="https://fairscan.org/blog/fairscan-can-now-be-called-from-other-apps/" />
    <updated>2026-01-03T00:00:00Z</updated>
    <id>https://fairscan.org/blog/fairscan-can-now-be-called-from-other-apps/</id>
    <content type="html">&lt;p&gt;FairScan was designed to make document scanning very easy. It lets you decide what to do with the resulting PDF: you can store it on your device, or share it using any app installed on your phone that declares it can handle PDF files. With FairScan 1.9.0, the latest release as of today, FairScan also makes it possible for other apps to call it directly and receive a PDF in return.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://fairscan.org/blog/fairscan-can-now-be-called-from-other-apps/intent.webp&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Making apps cooperate&lt;/h2&gt;
&lt;p&gt;Android apps can cooperate and exchange data through a mechanism called &lt;a href=&quot;https://developer.android.com/guide/components/intents-filters&quot;&gt;intents&lt;/a&gt;. The most typical example is when an app lets you &amp;quot;share&amp;quot; some data such as a picture, a contact, or a document. The Android system then shows a list of apps that can receive it, and you choose the one you want.&lt;/p&gt;
&lt;p&gt;An intent can also be used by an app to execute a task and get a result back, for example taking a picture or selecting a file. If several apps can handle the request, the system lets the user choose.&lt;/p&gt;
&lt;p&gt;This same concept could apply to document scanning: apps that occasionally need a PDF could delegate the job to a specialized app. Since there are many document scanning apps, letting the user decide which one to use would make sense. However, I didn&#39;t find any standard intent for document scanning. I&#39;m actually not aware of any scanning app that supports being called that way, either open source or closed source.&lt;/p&gt;
&lt;p&gt;So FairScan now defines its own intent, and other apps are free to use it. Instead of reinventing a scanning feature that might not work as well as a dedicated tool, other apps can now delegate that task to FairScan and focus on what they do best.&lt;/p&gt;
&lt;h2&gt;Adapting FairScan&lt;/h2&gt;
&lt;p&gt;FairScan was initially designed as a standalone app, so I had to adapt it to ensure a smooth user experience when called by another app:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The scanning flow is simplified: no home screen, and no export screen at the end, the calling app decides when to start the scan and handles the resulting PDF.&lt;/li&gt;
&lt;li&gt;The settings screen is disabled: FairScan currently has very few settings, and they would not make sense in that mode.&lt;/li&gt;
&lt;li&gt;I reworked the way FairScan stores and manages captured images so that multiple processes can run concurrently and remain isolated from each other.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;How it started&lt;/h2&gt;
&lt;p&gt;I wouldn&#39;t have built this feature without a message from Tenam Sobti, who not only suggested the idea but also provided a working prototype. Many thanks to Tenam! This is the kind of collaboration that make working in open source rewarding.&lt;/p&gt;
&lt;p&gt;The initial goal was to allow the &lt;a href=&quot;https://getodk.org/&quot;&gt;ODK Collect&lt;/a&gt; app to use FairScan. ODK Collect — as well as &lt;a href=&quot;https://www.kobotoolbox.org/&quot;&gt;KoboCollect&lt;/a&gt; — is used by research teams and humanitarian organizations to gather data using customizable forms. Since these apps are flexible, they didn&#39;t need to change their code to use this feature: users can simply configure their forms to call FairScan (see &lt;a href=&quot;https://forum.getodk.org/t/an-open-source-doc-scanner-like-microsoft-lens-camscanner-that-integrates-with-odk-collect/57214&quot;&gt;this discussion&lt;/a&gt;).&lt;/p&gt;
&lt;h2&gt;Practical impact&lt;/h2&gt;
&lt;p&gt;Being able to call FairScan from another app is not revolutionary: users could already open FairScan, scan their document, and then import the PDF somewhere else. However, an intent-based workflow brings clear advantages:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It&#39;s much easier to use: no need to switch apps or manage PDF files manually.&lt;/li&gt;
&lt;li&gt;It&#39;s less error-prone: no risk of selecting the wrong file when attaching a PDF.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Imagine a field worker filling a survey form offline for a research project, needing to attach a signed consent form. Instead of manually scanning it, saving it, switching apps and uploading it, the form app can now simply ask FairScan to scan the document and receive the PDF instantly.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;This new FairScan feature could be useful for many types of applications: cloud storage, note-taking, document management… If you&#39;re building an app and want to try it, you&#39;ll find instructions in the &lt;a href=&quot;https://github.com/pynicolas/FairScan&quot;&gt;FairScan repository&lt;/a&gt; on GitHub.&lt;/p&gt;
&lt;p&gt;I&#39;d love to hear about apps that make use of this feature: feel free to reach out!&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>A data-driven approach to color detection in FairScan</title>
    <link href="https://fairscan.org/blog/color-detection-data-driven/" />
    <updated>2025-12-14T00:00:00Z</updated>
    <id>https://fairscan.org/blog/color-detection-data-driven/</id>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://fairscan.org/blog/color-detection-data-driven/main.webp&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;FairScan&#39;s goal is to make it fast and easy for users to get a PDF. To achieve that, the app handles all image processing steps automatically. As a user, you have implicit expectations about the result. One of them is simple: if you see colors on your document, you expect a color PDF. Otherwise, you expect a grayscale one.&lt;/p&gt;
&lt;p&gt;That sounds easy. But with FairScan 1.7, I could see myself that the app was not doing a great job at that. Some users&#39; comments confirmed it. I needed to improve the automatic distinction between color and grayscale documents. However, if I change anything in this processing, how can I know whether what I do is actually better, or worse, than before?&lt;/p&gt;
&lt;h2&gt;Data to the rescue&lt;/h2&gt;
&lt;p&gt;There is an approach that works really well for this kind of problem: benchmarking. The idea is to use a dataset, with inputs and expected outputs, and to measure progress against it.&lt;/p&gt;
&lt;p&gt;Getting a dataset can be a big task on its own. But I had already built a dataset to train the segmentation model, which I described in &lt;a href=&quot;https://fairscan.org/blog/building_a_public_dataset/&quot;&gt;a previous post&lt;/a&gt;. It contains more than 600 images of over 200 different documents. It did not include information about whether documents were grayscale or in color, the so-called &lt;a href=&quot;https://en.wikipedia.org/wiki/Ground_truth&quot;&gt;ground truth&lt;/a&gt;, but that was something I could complete in less than one hour.&lt;/p&gt;
&lt;p&gt;I also had to write a small script to compute a score for the current implementation. Again, that did not take long. Here is the initial result.&lt;/p&gt;
&lt;p&gt;Initial score:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Number of images: 652&lt;/li&gt;
&lt;li&gt;Accuracy: &lt;strong&gt;86.7%&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;Expected color is true and detected color is false: 38 images&lt;/li&gt;
&lt;li&gt;Expected color is false and detected color is true: 49 images&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What matters most is that getting this score is easy and fast: one click and about one minute on my computer. I could certainly make it faster, but it is already good enough to iterate quickly.&lt;/p&gt;
&lt;h2&gt;First improvement&lt;/h2&gt;
&lt;p&gt;The algorithm used in FairScan 1.7 to detect colors is simple. It counts pixels above a given chroma threshold, which measures colorfulness, and compares the proportion of such pixels against another threshold.&lt;/p&gt;
&lt;p&gt;I had already identified one low-hanging fruit. Instead of considering all pixels inside the &lt;a href=&quot;https://fairscan.org/blog/the-heart-of-fairscan-image-processing-pipeline-explained/&quot;&gt;quadrilateral of the detected document&lt;/a&gt;, the algorithm should exclude pixels that are not part of the document according to the segmentation model. This may look like a subtle change, but it improves all cases where the document appears slightly concave, which is very common, or where a corner is missing because it is torn or stapled.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://fairscan.org/blog/color-detection-data-driven/quad-vs-mask.webp&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;This change was easy to implement, and the score immediately improved to &lt;strong&gt;90.6%&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;Overall strategy&lt;/h2&gt;
&lt;p&gt;Improving the score is a good start, but it is still far from 100%. That does not mean the change was not useful, but it clearly means more work is needed. So what is the strategy to approach the problem?&lt;/p&gt;
&lt;p&gt;Here is the process I follow:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Build a benchmark&lt;/li&gt;
&lt;li&gt;Look at individual failed cases to understand why the score is low&lt;/li&gt;
&lt;li&gt;Find a way to improve some of these cases&lt;/li&gt;
&lt;li&gt;Validate the change against the benchmark&lt;/li&gt;
&lt;li&gt;Iterate, going back to step 2&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;At this point, one improvement was validated. It was time to iterate.&lt;/p&gt;
&lt;h2&gt;Iterating&lt;/h2&gt;
&lt;p&gt;When looking at documents incorrectly detected as colored, it quickly became clear that many cases were related to lighting conditions. A black-and-white document photographed under dim light often appears slightly blue. With artificial light, it can appear slightly yellow or even reddish.&lt;/p&gt;
&lt;p&gt;One possible workaround is to apply a &lt;a href=&quot;https://en.wikipedia.org/wiki/Color_balance&quot;&gt;white balance&lt;/a&gt; algorithm, such as the &lt;a href=&quot;https://en.wikipedia.org/wiki/Color_normalization#Grey_world&quot;&gt;grey world&lt;/a&gt; assumption. I first applied it to the whole image and checked the benchmark. The score dropped. In other words, validation failed.&lt;/p&gt;
&lt;p&gt;Looking at the new incorrect cases revealed a clear pattern. When the background was strongly colored, for example a red sofa taking most of the frame, the grey world algorithm compensated for it and made the document turn slightly blue. That was clearly not what I wanted.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://fairscan.org/blog/color-detection-data-driven/white-balance.webp&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The fix was to apply the white balance algorithm only to the document area. This time, the benchmark score increased to &lt;strong&gt;91.7%&lt;/strong&gt;. Validation succeeded, and the iteration could continue.&lt;/p&gt;
&lt;p&gt;For color detection, FairScan relies on the &lt;a href=&quot;https://en.wikipedia.org/wiki/CIELAB_color_space&quot;&gt;CIELAB color space&lt;/a&gt;, which was designed to better match human perception than &lt;a href=&quot;https://en.wikipedia.org/wiki/RGB_color_model&quot;&gt;RGB&lt;/a&gt;. One interesting observation is that many pixels in a document are either very dark or very bright. For such pixels, humans barely perceive any color. I therefore tried filtering out pixels with very low or very high luminance, the L component in CIELAB. This resulted in a small improvement, bringing accuracy to &lt;strong&gt;91.9%&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;When inspecting chroma &lt;a href=&quot;https://en.wikipedia.org/wiki/Heat_map&quot;&gt;heat maps&lt;/a&gt; for incorrectly processed grayscale documents, I noticed that chroma values were sometimes high near the edges of the document. This is explained by the fact that the segmentation mask is not perfect, and some background pixels are incorrectly included. Because the proportion threshold for colored pixels must be low to detect documents with only small colored areas, these few pixels can lead to false positives.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://fairscan.org/blog/color-detection-data-driven/chroma-heatmap.webp&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The fix here was straightforward. I removed a small number of pixels along the border of the detected document. Not too many, so that documents that are only colored on the border can still be detected correctly. With this change, the score rose to &lt;strong&gt;94.3%&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;Parameters&lt;/h2&gt;
&lt;p&gt;At the end of each iteration, I adjusted the algorithm parameters to maximize the benchmark score. The main parameters are the chroma threshold and the proportion threshold for colored pixels. Changing them is similar to moving a cursor that favors either color or grayscale detection.&lt;/p&gt;
&lt;p&gt;A different dataset would likely lead to slightly different values. However, I believe these values would not change significantly with another dataset that has a good variety of images.&lt;/p&gt;
&lt;h2&gt;The end of it&lt;/h2&gt;
&lt;p&gt;After implementing several improvements, I did not reach 100% accuracy. When I look at the remaining incorrect cases, I think some of them are still reachable, but I am running out of ideas that would improve them without lowering the overall score.&lt;/p&gt;
&lt;p&gt;The last few percent are clearly harder to get and are probably not where I should focus right now. For now, I decided to stop here. I know with confidence that FairScan 1.8.0 performs better than all previous versions.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;The automatic distinction between color and grayscale documents is probably the part of FairScan that fits best with a benchmark-driven approach. The expected result is binary, color or grayscale, which makes it easy to evaluate and quantify.&lt;/p&gt;
&lt;p&gt;This kind of benchmarking is also especially useful when the goal is to match human perception. Detecting whether a document should be considered colored sounds trivial, but it is not. A benchmark helps validate, or invalidate, that a given change is a real improvement. I will definitely rely on this approach again for other steps of FairScan&#39;s automatic processing, so that users can get good-looking PDFs in most cases by doing nothing more than clicking a button.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Creating an open source app for everyone: it takes more than code</title>
    <link href="https://fairscan.org/blog/open-source-app-for-everyone/" />
    <updated>2025-12-03T00:00:00Z</updated>
    <id>https://fairscan.org/blog/open-source-app-for-everyone/</id>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://fairscan.org/blog/open-source-app-for-everyone/A6301334.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;My ambition with FairScan is not just to build an open-source app: it&#39;s to make an app that everyone can use, including all the people who don&#39;t know what GitHub is. That&#39;s definitely not easy and it takes more than writing good code. Before starting FairScan, I already knew there was a big difference between good software and a good product. Now, I experience it very concretely. This is my daily reality.&lt;/p&gt;
&lt;h2&gt;It takes a good UI so that it&#39;s usable by everyone&lt;/h2&gt;
&lt;p&gt;Open source apps are started and built by developers like me, but what users see is the user interface (UI), not code. The UI of an app should enable people to use it without reading documentation, and that&#39;s not trivial. I&#39;m not a user experience (UX) designer. No UX designer worked on FairScan, and I believe that&#39;s the case for most open source apps.&lt;/p&gt;
&lt;p&gt;So I designed FairScan&#39;s UI myself and I make it evolve. Being aware of my limits, I tried to learn. I read Steve Krug&#39;s book, &lt;a href=&quot;https://sensible.com/dont-make-me-think/&quot;&gt;Don&#39;t Make Me Think&lt;/a&gt;, and it helped a lot when non-technical testers started using FairScan. Google required me to have 12 testers try the app before I could publish it on the Play Store. They were not next to me and had to figure out the app on their own. That was a revealing moment: several of them did not understand the basic workflow of the app. I had to rethink the UI and change significant parts of it. Once I did that, it became much easier for testers to understand how they could use the app. Now that some users tell me they appreciate &amp;quot;how easy it is to use&amp;quot;, I&#39;m convinced it was worth the effort.&lt;/p&gt;
&lt;p&gt;Making the UI usable for everyone is a big step, but it still leaves open a deeper question: what should the app actually do?&lt;/p&gt;
&lt;h2&gt;It takes a product strategy to define where the app should go&lt;/h2&gt;
&lt;p&gt;The UI is crucial to expose the app&#39;s features, but which features? And among those features, which ones actually matter? Among all the things that could be improved in the app, what should development focus on? Those are exactly the questions that a product strategy tries to address. In a product development team, that&#39;s the job of product managers, who are maybe as rare in open source projects as UX designers. I knew almost nothing about product management before I joined a &amp;quot;product-first&amp;quot; company. There, the CEO had no problem saying &amp;quot;no&amp;quot; to customer requests. At first, that was a bit of a shock to me. Over time, I realized that a product is the result of choices, and avoiding choices makes the project lose direction. The product vision, and the strategy derived from it, help make conscious decisions, and that&#39;s what turns an app into an intentional system rather than a loose collection of features added whenever someone happened to request them.&lt;/p&gt;
&lt;p&gt;All of that stayed with me, and it shaped how I approached FairScan from day one. What I wanted to achieve was already fairly clear early in the project: the &amp;quot;simple and respectful&amp;quot; approach that I described in &lt;a href=&quot;https://fairscan.org/blog/fairscan-purpose/&quot;&gt;my first blog post&lt;/a&gt;. And shortly after that came the first requests from users. It&#39;s open source, so they&#39;re not customers, but just like customers, users ask for specific new features. And as the developer, it&#39;s uncomfortable to push back: if I want to have users, shouldn&#39;t I say &amp;quot;yes&amp;quot;? The problem is that each new feature has a cost, not only technical (implementation and maintenance) but also functional because it becomes harder to keep the app consistent. More importantly, the requested features don&#39;t always align with the long-term vision.&lt;/p&gt;
&lt;p&gt;The typical example for FairScan is that some users want to manually adjust the detected document edges. In my view, improving the precision of the automatic document detection is the alternative that&#39;s aligned with what I want FairScan to be. The product strategy helps make such decisions. It clarifies priorities based on long-term user value, not on what looks like the easy short-term path. It&#39;s what makes it possible to invest in hard but impactful improvements. It provides a direction, and without a direction, an open source project can drift very quickly.&lt;/p&gt;
&lt;p&gt;A clear vision helps keep the app on track, but turning that vision into something that works in practice is another story.&lt;/p&gt;
&lt;h2&gt;It takes time and effort, a lot&lt;/h2&gt;
&lt;p&gt;I doubt it&#39;s possible to come up with an app that &amp;quot;just works&amp;quot; for everyone without putting a lot of effort into polishing every aspect of it. The UI is definitely part of that, but user experience goes far beyond the interface. For FairScan, &lt;a href=&quot;https://fairscan.org/blog/automatic-document-detection/&quot;&gt;I already spent a lot of time&lt;/a&gt; improving how the app behaves when multiple documents are in the frame, or when a document missing a corner seems to have 5 edges instead of 4. Because I want FairScan to rely on automation to make things easy for users, I know it&#39;s a neverending story, and I&#39;m fine with it.&lt;/p&gt;
&lt;p&gt;And beyond that, like any other app, there are countless details that don&#39;t show up immediately but still matter: how the app behaves in unexpected error cases, how it deals with different Android versions, how persistent state transitions when upgrading the app… Those are the things that make the difference between an app that works and an app that is truly reliable. All of that takes time and dedication. And it&#39;s not always fun. A developer who is paid to work on an app understands that it&#39;s part of the job. But it&#39;s not quite the same thing to work on similar tasks for an open source project in your free time. Users don&#39;t explicitely ask for any of it so there&#39;s no immediate reward. But attention to these details can bring more users over time, and that&#39;s a kind of long-term reward.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;All these aspects add up. And building an open-source app for a broad audience is definitely challenging. It requires great care for user experience, a solid product vision and a lot of hidden work that nobody asks for directly. But that&#39;s also what makes it meaningful. I know FairScan won’t fit everyone’s tastes, but my hope is that anyone can use it. And maybe one day, through FairScan, some people will realize that open-source exists. And maybe they&#39;ll raise their expectations about how respectful the software they use daily should be. That would be my biggest success.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Building a public dataset for FairScan</title>
    <link href="https://fairscan.org/blog/building_a_public_dataset/" />
    <updated>2025-11-14T00:00:00Z</updated>
    <id>https://fairscan.org/blog/building_a_public_dataset/</id>
    <content type="html">&lt;p&gt;To automatically detect documents, FairScan uses an image segmentation model. The dataset needs to reflect the situations the model should be able to handle, so the model&#39;s accuracy depends heavily on the quality and size of that data. For FairScan, I decided to build a dedicated dataset and to make it public. That turned out to be quite an experience.&lt;/p&gt;
&lt;h2&gt;Why building a public dataset?&lt;/h2&gt;
&lt;p&gt;Before starting, I looked for existing datasets. I found datasets &lt;a href=&quot;https://github.com/xinke-wang/OCRDatasets&quot;&gt;for OCR&lt;/a&gt; or for &lt;a href=&quot;https://www3.cs.stonybrook.edu/~cvl/docunet.html&quot;&gt;unwarping documents&lt;/a&gt;. I also found &lt;a href=&quot;https://data.univ-lr.fr/datasets/37&quot;&gt;a dataset for document scanning&lt;/a&gt;, but it was focused on videos and only included a few documents. I could not find anything that matched what I needed, so I had to build it myself.&lt;/p&gt;
&lt;p&gt;I could have built a private dataset, but I did not seriously consider that option. FairScan is an open source app and the spirit of open source development is to make it possible for other people to understand how an application works and to modify it. For a model, the training data is at least as important as the source code. Publishing the code without publishing the dataset would have made little sense, especially for an app that &lt;a href=&quot;https://fairscan.org/blog/a-respectful-app/&quot;&gt;aims to be respectful&lt;/a&gt;. It was clear to me I had to build a public dataset.&lt;/p&gt;
&lt;h2&gt;What the dataset contains&lt;/h2&gt;
&lt;p&gt;A dataset should contain examples of what the model is expected to produce for given inputs. For an image segmentation model that should detect documents, the input is an image and the expected output is a mask that shows which pixels correspond to a document. Here is an example:
&lt;img src=&quot;https://fairscan.org/blog/building_a_public_dataset/dataset_example.webp&quot; alt=&quot;dataset_example.webp&quot;&gt;&lt;/p&gt;
&lt;p&gt;To make the model reliable, the dataset needs to cover the situations in which people use a scanning app:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Various types of documents, for example standalone sheets, books and magazines&lt;/li&gt;
&lt;li&gt;Various supports and backgrounds, for example a busy desk, a kitchen table or a carpet&lt;/li&gt;
&lt;li&gt;Various framing and perspectives, for example close, far or low angle&lt;/li&gt;
&lt;li&gt;Various lighting conditions, for example bright sunlight or a dim lamp&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Generally speaking, models perform better when they have more data, including some difficult examples, such as a white document on a white background. For an early development version of the app, I started with a dataset of 100 images. As of today, FairScan&#39;s dataset contains &lt;a href=&quot;https://github.com/pynicolas/fairscan-dataset/releases&quot;&gt;more than 600 images&lt;/a&gt;. My family often saw me taking pictures of documents in strange situations, for example in dim light on the white background of the bathroom sink.&lt;/p&gt;
&lt;h2&gt;Annotating images&lt;/h2&gt;
&lt;p&gt;Taking pictures is only one part of the job. The other part is to annotate them, which means defining the expected output for each image. Among the multiple tools that exist for that purpose, I used &lt;a href=&quot;https://github.com/wkentaro/labelme&quot;&gt;labelme&lt;/a&gt;. It allows you to draw polygons directly on the image to create segmentation masks. For a simple sheet of paper lying very flat, it can be quick. For the curved page of a book, approximating the shape with a polygon can require many clicks.
&lt;img src=&quot;https://fairscan.org/blog/building_a_public_dataset/labelme.webp&quot; alt=&quot;labelme.webp&quot;&gt;
Since the model&#39;s precision depends on the precision of the dataset, I did this carefully, using the zoom to place polygon vertices as close as possible to the visible contours. It is certainly tedious, but it was not the only time-consuming task.&lt;/p&gt;
&lt;h2&gt;Documents for a public dataset&lt;/h2&gt;
&lt;p&gt;One problem I faced is that I cannot take pictures of any document and put them in a public dataset. That may lead to copyright issues. I take that seriously, especially since I want FairScan to be respectful not only of its users but also of other people&#39;s work.&lt;/p&gt;
&lt;p&gt;Some documents can be used without any issue. That includes everything that is in the public domain, and &lt;a href=&quot;https://commons.wikimedia.org/&quot;&gt;Wikimedia Commons&lt;/a&gt; has many such documents. I believe that forms issued by public administrations are also acceptable. I added photos of documents that I created in the past, or that were created by people I know who agreed to that usage. That was a start, but it was not enough to represent the variety of documents people scan. Think of books, magazines or color prints.&lt;/p&gt;
&lt;p&gt;So I created additional documents myself. I took inspiration from layouts I found at home or online, and recreated documents with dummy content such as &lt;a href=&quot;https://en.wikipedia.org/wiki/Lorem_ipsum&quot;&gt;Lorem ipsum&lt;/a&gt; or with photos from Unsplash, which is allowed by &lt;a href=&quot;https://unsplash.com/license&quot;&gt;their licence&lt;/a&gt;. I created business cards, flyers and textbook pages that I inserted into real books. They only need to &lt;em&gt;look like&lt;/em&gt; real documents:
&lt;img src=&quot;https://fairscan.org/blog/building_a_public_dataset/documents.webp&quot; alt=&quot;documents.webp&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Avoiding overfitting&lt;/h2&gt;
&lt;p&gt;Creating documents takes time, so the temptation is to reuse them in many images. However, this creates a risk of &lt;a href=&quot;https://en.wikipedia.org/wiki/Overfitting&quot;&gt;overfitting&lt;/a&gt;. If the dataset contains many images of the same document, the model may learn to recognize that specific document instead of learning what a document looks like in general. I tried to limit the dataset to a maximum of 5 images per document. To reach more than 600 images, I still needed over 120 different documents.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;Looking back at the process, building a public dataset clearly takes a significant amount of work. Life is easier for companies that train models without disclosing the training data. They can afford to be less careful with copyright and they can outsource the annotation to low-paid workers who label data all day long. &lt;a href=&quot;https://www.ilo.org/resource/article/artificial-intelligence-illusion-how-invisible-workers-fuel-automated&quot;&gt;That&#39;s how the AI economy works&lt;/a&gt;. I chose a different path and I have no regret. Yes, it required effort, but I feel a real satisfaction in knowing that &lt;a href=&quot;https://github.com/pynicolas/fairscan-dataset&quot;&gt;this dataset&lt;/a&gt; forms the foundation of FairScan. It is fully aligned with the goal of building a respectful app, and FairScan is a small demonstration that this approach is possible.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>Making document detection more reliable</title>
    <link href="https://fairscan.org/blog/automatic-document-detection/" />
    <updated>2025-11-12T00:00:00Z</updated>
    <id>https://fairscan.org/blog/automatic-document-detection/</id>
    <content type="html">&lt;p&gt;I released the first public version of FairScan about two months ago. &lt;a href=&quot;https://fairscan.org/blog/fairscan-purpose/&quot;&gt;It aims to be very simple&lt;/a&gt;, so that one can get a PDF in just a few seconds. To achieve that, the app relies heavily on automatic processing... but that&#39;s easier said than done. The very first review I got on the Play Store read something like: &lt;em&gt;It doesn&#39;t work, &amp;quot;no document detected&amp;quot; on every page&lt;/em&gt;. Not exactly what I had hoped, but a good reminder that automatic document detection isn&#39;t just one feature among others: it&#39;s the feature that can make or break the whole experience.
If detection fails, the app fails.&lt;/p&gt;
&lt;p&gt;When releasing FairScan, the system seemed good enough, but I knew it wasn&#39;t perfect. Some cases were particularly difficult:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Certain document types, such as textbooks or magazines&lt;/li&gt;
&lt;li&gt;Images containing multiple documents&lt;/li&gt;
&lt;li&gt;Documents with a missing corner, folded, or stapled&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In those situations, the app often displayed &amp;quot;No document detected&amp;quot;. If that happens on every page, there&#39;s only one conclusion: &lt;em&gt;the app doesn&#39;t work&lt;/em&gt;.
I had to do something.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Improving FairScan&#39;s segmentation model&lt;/h2&gt;
&lt;p&gt;In &lt;a href=&quot;https://fairscan.org/blog/the-heart-of-fairscan-image-processing-pipeline-explained&quot;&gt;a previous article&lt;/a&gt;, I explained FairScan&#39;s image processing pipeline, how it turns a photo into the image that ends up in a PDF. The very first step is the segmentation model: detecting which pixels in the photo belong to the document.&lt;/p&gt;
&lt;p&gt;That can be tricky when there&#39;s more than one document in the image. The pixels of one document look just like those of another, so the model may treat them as one big blob, either producing a strange merged shape or failing to detect any quadrilateral at all.
From the start, I worked around that limitation by training my segmentation model to identify only the &lt;em&gt;main&lt;/em&gt; document in an image. It worked in many cases, but not always.&lt;/p&gt;
&lt;p&gt;To improve this, I tried an instance segmentation model (&lt;a href=&quot;https://docs.ultralytics.com/models/yolo11/&quot;&gt;YOLO 11&lt;/a&gt;). Unlike a semantic segmentation model such as &lt;a href=&quot;https://arxiv.org/abs/1802.02611&quot;&gt;DeepLabV3+&lt;/a&gt;, instance segmentation can distinguish several separate documents within the same image. I knew it would be more complex to integrate, but I also knew it could handle those situations better.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://fairscan.org/blog/automatic-document-detection/semantic-vs-instance.webp&quot; alt=&quot;Semantic vs instance segmentation&quot;&gt;&lt;/p&gt;
&lt;p&gt;To train it properly, I had to revisit my dataset and annotate every secondary document visible in the images. That raised an interesting question: what counts as a &amp;quot;document&amp;quot;? If only half a document appears, does it qualify? What about a tiny corner, or a blank page? Those choices could affect the model&#39;s behavior, so I removed ambiguous images entirely. From roughly 400 images, I went down to about 300.&lt;/p&gt;
&lt;p&gt;I trained the YOLO model on this dataset, and the results were promising, but it was clear I needed a &lt;strong&gt;larger dataset&lt;/strong&gt;. So I added new types of documents that were underrepresented, such as textbooks and magazines. That took time (as I describe in &lt;a href=&quot;https://fairscan.org/blog/building_a_public_dataset/&quot;&gt;another post&lt;/a&gt;), but with around 600 images, both the semantic and instance segmentation models improved noticeably. The new models perform better across document types and handle multiple documents more reliably.
Still, the instance segmentation model wasn&#39;t consistently better at separating documents, and integrating it into the Android app would have required substantial work. For now, I&#39;ve chosen to keep the simpler semantic segmentation model in production.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://fairscan.org/blog/automatic-document-detection/seg-1.4-vs-1.5.webp&quot; alt=&quot;seg-1.4-vs-1.5.webp&quot;&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Making the system more robust to non-quadrilateral documents&lt;/h2&gt;
&lt;p&gt;The segmentation model is crucial, but it&#39;s not the whole story. From its output, the app must derive a quadrilateral that can be mapped to the final rectangular image. But what if a document is stapled, folded, or missing a corner? Then the segmentation output might be a polygon with 5 sides, not 4. And if the app can&#39;t handle that, the user gets another &amp;quot;No document detected&amp;quot;.&lt;/p&gt;
&lt;p&gt;I tried training a regression model to predict a quadrilateral from the segmentation mask. In theory, that could handle missing corners or imperfect masks. I extended my dataset with &amp;quot;expected&amp;quot; quadrilaterals and trained the model accordingly. The results were mixed: not bad, but not good enough. Excluding poor segmentation cases didn&#39;t help much either. After several attempts, I realized I was overcomplicating the problem and decided to move on.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://fairscan.org/blog/automatic-document-detection/quad-1.4-vs-1.5.webp&quot; alt=&quot;FairScan 1.4 vs 1.5 on a document missing a corner&quot;&gt;&lt;/p&gt;
&lt;p&gt;I switched back to more traditional image processing and designed new fallback algorithms that activate when the default detection fails. Some of the algorithms I tried are not well-known techniques. They&#39;re just my ideas for the particular problem I have to solve. One is purely geometrical: when the detected polygon has more than 4 sides, it searches for 3 consecutive angles that are almost right angles and builds a quadrilateral from them. Another, more basic one simply constructs a quadrilateral around the detected contour: it&#39;s not ideal, but less frustrating than getting an error message.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;The dreadful &amp;quot;No document detected&amp;quot; should now be much rarer.
Over the past few weeks, I&#39;ve explored several approaches: some worked, some didn&#39;t, but all contributed to a better understanding of the problem.
Expanding the dataset and adding new fallback algorithms made FairScan significantly better at detecting documents of all kinds. It&#39;s still not perfect, but it&#39;s definitely one big step closer.
&lt;a href=&quot;https://fairscan.org/&quot;&gt;Try it&lt;/a&gt; and see for yourself.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>What&#39;s a respectful app?</title>
    <link href="https://fairscan.org/blog/a-respectful-app/" />
    <updated>2025-10-02T00:00:00Z</updated>
    <id>https://fairscan.org/blog/a-respectful-app/</id>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://fairscan.org/blog/a-respectful-app/respect.webp&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;I often describe FairScan as &lt;em&gt;simple&lt;/em&gt; and &lt;em&gt;respectful&lt;/em&gt;.
But what does &amp;quot;respectful&amp;quot; really mean when we talk about apps?
We live in a world where there’s an app for everything, and we’re constantly pushed to install more. Yet almost no one talks about &amp;quot;respectful apps&amp;quot;.
A quick search online gives barely a few hundred results. In other words: it’s not even a topic.
So let me explain what I mean when I use that word.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Disrespectful behaviors in mobile apps&lt;/h2&gt;
&lt;p&gt;Before working on FairScan, I tried quite a few Android apps for scanning documents. And all of them exhibited &lt;strong&gt;behaviors that I certainly don&#39;t want&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Some of those behaviors are intended to be &lt;strong&gt;very visible&lt;/strong&gt;: ads of all kinds, but also messages to upgrade to a premium version of the app. In some apps, such messages take up the whole screen.&lt;/p&gt;
&lt;p&gt;Some others are &lt;strong&gt;hidden&lt;/strong&gt;, almost invisible to users. &lt;a href=&quot;https://tuta.com/blog/app-tracking&quot;&gt;Trackers&lt;/a&gt; are the best example: most users don&#39;t know about them, but some apps have dozens of trackers, and they collect massive amounts of data about us and send it to &lt;a href=&quot;https://epic.org/issues/consumer-privacy/data-brokers/&quot;&gt;data brokers&lt;/a&gt; and Big Tech.&lt;/p&gt;
&lt;p&gt;Most often, it&#39;s &lt;strong&gt;in between&lt;/strong&gt;. For example when the app notifies you in small characters that all your scans are stored in their cloud: you have no choice but to give them your private data. Or when the app stops working after you scanned 3 documents unless you buy the paid version. Welcome to the world of &lt;strong&gt;&lt;a href=&quot;https://www.deceptive.design/&quot;&gt;dark patterns&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;As a user, I would expect my apps to not have those behaviors. Or, at least, to be able to disable them. When we talk about relations between humans, we have words for that: &lt;strong&gt;manipulation, concealment, unfair pressure...&lt;/strong&gt; All are considered disrespectful. Why would it be different with an app? What would make it more acceptable?&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Whose interest is it about?&lt;/h2&gt;
&lt;p&gt;If those behaviors are &lt;strong&gt;against the interest of users&lt;/strong&gt;, why do they exist? That&#39;s because they serve the interest of someone else: the app&#39;s publisher, sometimes referred to as &amp;quot;developer&amp;quot; but the people who develop an application write code that their employer asks for.&lt;/p&gt;
&lt;p&gt;Who develops and publishes applications? It can be individual developers or various kinds of organizations or public institutions. But the most well-known applications are developed by companies, small or big. And we get to know those applications because the companies that produce them have marketing budgets to serve their &lt;strong&gt;business goals&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;In the end, the way an app behaves reflects a &lt;strong&gt;conflict&lt;/strong&gt;: the user wants an app that does a given task without hassle, while the company producing the app just wants profit. Most companies that distribute a &amp;quot;free&amp;quot; app do it to make money through ads or to lure users into buying a premium version. &lt;a href=&quot;https://en.wikipedia.org/wiki/Big_Tech&quot;&gt;Big tech companies&lt;/a&gt;, on the other hand, are more interested in getting user data (&amp;quot;If you’re not paying for the product, then you are the product&amp;quot;). It doesn&#39;t make a big difference in the end: those disrespectful behaviors exist only to serve the business goals of those companies.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;How can we know? What can we do?&lt;/h2&gt;
&lt;p&gt;What can we do about that as users? The first thing is to think twice before installing an app, maybe we don&#39;t really need an app for everything in our lives.
You can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Get information about who&#39;s producing the app and what their business model is&lt;/li&gt;
&lt;li&gt;Check the permissions that the app requires and the &lt;a href=&quot;https://reports.exodus-privacy.eu.org/en/reports/&quot;&gt;trackers&lt;/a&gt; included in the app&lt;/li&gt;
&lt;li&gt;Read the privacy policy and the license (when it exists) even if it&#39;s often a boring and cryptic read&lt;/li&gt;
&lt;li&gt;Check whether the app is open source&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The fact that an application is &lt;strong&gt;open source&lt;/strong&gt; doesn&#39;t make it automatically respectful but it&#39;s probably the best guarantee you can get: if it contains disrespectful code, someone can remove that code and republish the application.&lt;/p&gt;
&lt;p&gt;You may also consider paid apps: it gives the company a clear way to get money from the app, although it certainly doesn’t guarantee respectful behavior.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;To sum up, a respectful app is one that puts the user’s interest first, without tricks or hidden agendas.
I wish we saw as much creativity in building those apps as we see in inventing new dark patterns.
I hope FairScan can be an example of an app that does its job well &lt;strong&gt;and&lt;/strong&gt; respects its users.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>The Heart of FairScan: the image processing pipeline explained</title>
    <link href="https://fairscan.org/blog/the-heart-of-fairscan-image-processing-pipeline-explained/" />
    <updated>2025-09-30T00:00:00Z</updated>
    <id>https://fairscan.org/blog/the-heart-of-fairscan-image-processing-pipeline-explained/</id>
    <content type="html">&lt;p&gt;How does FairScan work at its core? How does it transform an image captured by the phone&#39;s camera into the page of a PDF document that doesn’t just look like a photo? From the user’s point of view, it feels like a single transformation that happens in less than a second. Let’s look at the different steps involved, illustrated with a visual example.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://fairscan.org/blog/the-heart-of-fairscan-image-processing-pipeline-explained/collage.webp&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2&gt;Segmentation&lt;/h2&gt;
&lt;p&gt;The first step is &lt;a href=&quot;https://en.wikipedia.org/wiki/Image_segmentation&quot;&gt;image segmentation&lt;/a&gt;, which identifies the pixels that belong to a document. I trained a &lt;a href=&quot;https://github.com/pynicolas/fairscan-segmentation-model&quot;&gt;custom model&lt;/a&gt; specifically for images containing documents.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://fairscan.org/blog/the-heart-of-fairscan-image-processing-pipeline-explained/t1.webp&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Here you can see the original image combined with the segmentation mask (the green overlay) produced by the model. Since the model was trained to identify only one &amp;quot;document&amp;quot; even if multiple are visible, you can see that only part of the second document in the picture is captured.&lt;/p&gt;
&lt;p&gt;This is the most crucial step, the one that can feel a bit “magical.” I plan to keep improving the model so it detects documents more reliably in all kinds of conditions.&lt;/p&gt;
&lt;h2&gt;Contours&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://fairscan.org/blog/the-heart-of-fairscan-image-processing-pipeline-explained/t2.webp&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The next step is to detect the edges of the document based on the segmentation output. &lt;a href=&quot;https://en.wikipedia.org/wiki/Edge_detection&quot;&gt;Edge detection&lt;/a&gt; is a well-known problem in image processing, and the &lt;a href=&quot;https://en.wikipedia.org/wiki/Canny_edge_detector&quot;&gt;Canny algorithm&lt;/a&gt; is widely used for this task.&lt;/p&gt;
&lt;p&gt;In my first attempt at FairScan, I skipped segmentation and ran Canny directly on the captured image. That worked in some cases, but segmentation produces much better results when the background and the document have similar colors or when shadows are strong.&lt;/p&gt;
&lt;h2&gt;Quadrilateral&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://fairscan.org/blog/the-heart-of-fairscan-image-processing-pipeline-explained/t3.webp&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;At this stage, the assumption is that documents are rectangles. So we want to identify a quadrilateral. Your brain probably sees the document on the photo as a rectangle, but because of perspective distortion, it isn’t. The previous step may return several contours of arbitrary shapes. We approximate these contours as polygons using the &lt;a href=&quot;https://en.wikipedia.org/wiki/Ramer%E2%80%93Douglas%E2%80%93Peucker_algorithm&quot;&gt;Ramer–Douglas–Peucker algorithm&lt;/a&gt;, then filter out those that don’t have 4 edges, and finally pick the one with the largest area.&lt;/p&gt;
&lt;h2&gt;Perspective correction&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://fairscan.org/blog/the-heart-of-fairscan-image-processing-pipeline-explained/t4.webp&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The next step is to correct the perspective and crop the image. This involves applying a perspective transformation based on the quadrilateral from the previous step and mapping it to a target rectangle.&lt;/p&gt;
&lt;p&gt;The most important part here is the aspect ratio so that the document doesn’t look distorted. For now, I use a simple heuristic based on the average of opposite edges. It gives acceptable results as long as the photo wasn’t taken from too oblique an angle.&lt;/p&gt;
&lt;h2&gt;Post-processing&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://fairscan.org/blog/the-heart-of-fairscan-image-processing-pipeline-explained/t5.webp&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Maybe you’re thinking: “the image on the left has a strange color.” That really is the color from the original photo (I promise). I guess that when looking at the photo of a document, the human brain tends to interpret the main color of the page as white, especially because it contrasts with the darker background. But it’s not actually white, and you don’t want your PDF to look like that.&lt;/p&gt;
&lt;p&gt;So the last step adjusts parameters like brightness and contrast to bring the result closer to what you expect from a digital document.&lt;/p&gt;
&lt;p&gt;This step struggles in low-light conditions and doesn’t always correctly identify when a document should be treated as grayscale. There’s definitely room for improvement here.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;That&#39;s it: all of those steps make the heart of FairScan and it all happens very quickly. In fact, the first steps already run live on the camera preview to display the quadrilateral, so the user immediately sees what FairScan detects as the document.&lt;/p&gt;
&lt;p&gt;This pipeline combines several steps, most of them relying on well-established algorithms implemented in open-source libraries. Before starting this project, I knew nothing about image processing. It took me quite some time to tune this pipeline, but I learned a lot along the way. And I know each of these steps can still be improved to automatically produce cleaner PDFs. From the user’s perspective, it will continue to feel effortless.&lt;/p&gt;
</content>
  </entry>
  <entry>
    <title>FairScan&#39;s purpose</title>
    <link href="https://fairscan.org/blog/fairscan-purpose/" />
    <updated>2025-09-28T00:00:00Z</updated>
    <id>https://fairscan.org/blog/fairscan-purpose/</id>
    <content type="html">&lt;p&gt;&lt;img src=&quot;https://fairscan.org/blog/fairscan-purpose/purpose.webp&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;I just published the first version of FairScan and I&#39;m starting this blog to share my experience developing this project. This first post is about the vision behind FairScan: what I&#39;m trying to achieve, and what I&#39;m not aiming for.&lt;/p&gt;
&lt;p&gt;I started FairScan to fill a need I have, and one that many people share: every now and then I have to turn a piece of paper into a PDF. Of course, there are many apps that do this, and a lot of them are free. But &amp;quot;free&amp;quot; often means I end up paying in other ways, by giving away my data or being exposed to ads. And most of these apps are bloated with features I don&#39;t need.&lt;/p&gt;
&lt;p&gt;FairScan is my attempt to build something different: &lt;strong&gt;simple&lt;/strong&gt; (getting a PDF in seconds, without effort) and &lt;strong&gt;respectful&lt;/strong&gt; (no ads, no account, no tricks). It doesn&#39;t try to do everything, but it focuses on doing its job well.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;A simple app to get a scan in seconds&lt;/h2&gt;
&lt;p&gt;I don&#39;t want to spend time using a document scanning app: I want to get a PDF &lt;strong&gt;quickly&lt;/strong&gt; (around 10 seconds for a single page) and &lt;strong&gt;without effort&lt;/strong&gt;. That&#39;s what I mean by &amp;quot;simple&amp;quot;.&lt;/p&gt;
&lt;h3&gt;Automatic processing&lt;/h3&gt;
&lt;p&gt;I want to use my phone as a camera, but instead of a raw photo of a document, I want a PDF that looks good enough to share. FairScan takes care of the tedious work for me:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Detect document edges&lt;/li&gt;
&lt;li&gt;Fix perspective&lt;/li&gt;
&lt;li&gt;Enhance colors, brightness and contrast&lt;/li&gt;
&lt;li&gt;Reduce shadows&lt;/li&gt;
&lt;li&gt;Compress the PDF to keep it light&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;FairScan does all this automatically. Results may not be perfect in every case, but the goal is to get PDFs that look &amp;quot;good enough&amp;quot; most of the time, with zero effort from the user. Achieving that is far from simple for the developer, but it makes the experience truly simple for the user.&lt;/p&gt;
&lt;h3&gt;Clear interface and scanning process&lt;/h3&gt;
&lt;p&gt;Of course, the user interface also plays a key role in keeping the app simple. Automation makes it possible to remove buttons for tweaking documents, which keeps the UI clean. And since there are no ads or messages pushing you to upgrade to a premium version, there&#39;s no wasted space or distraction.&lt;/p&gt;
&lt;p&gt;The scanning process itself is designed to be crystal clear, even for multi-page documents:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Scan the pages&lt;/li&gt;
&lt;li&gt;Preview the result&lt;/li&gt;
&lt;li&gt;Save or share the PDF&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The result is an interface and workflow that stay focused on one thing: getting a PDF quickly and without distraction.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;An app that respects its users&lt;/h2&gt;
&lt;p&gt;I would like all the apps I use to be respectful. I&#39;ll try to define more generally what a &amp;quot;respectful app&amp;quot; means in a dedicated post. In short, I think it&#39;s about putting users&#39; interests first.
In the context of a document scanner, it&#39;s really about what I &lt;strong&gt;don&#39;t&lt;/strong&gt; want to have.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;No account, no cloud.&lt;/strong&gt; Big companies happily offer to store my scans on their cloud. But some of the documents I scan are definitely private data and I don&#39;t want to give that to &lt;a href=&quot;https://en.wikipedia.org/wiki/Big_Tech&quot;&gt;Big Tech&lt;/a&gt;. I want to keep control of my data.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;No ads&lt;/strong&gt;. Ads have much more impact that most people realize, they shape how we behave individually and as a society. Plus, they&#39;re annoying. I hate ads.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;No trackers&lt;/strong&gt;. Almost all apps include &lt;a href=&quot;https://tuta.com/blog/app-tracking&quot;&gt;trackers&lt;/a&gt;, but I don&#39;t want to be tracked. &lt;a href=&quot;https://reports.exodus-privacy.eu.org/en/&quot;&gt;Check your apps&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;No weird permission&lt;/strong&gt;. I don&#39;t get why a scanning app would need dozens of permissions. I don&#39;t want it to access my location or to record audio with my phone.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;No artificial limitations of any kind&lt;/strong&gt;. I tried many &amp;quot;free&amp;quot; scanning apps. Sometimes, I got a message saying that I need the premium version to scan more than 3 pages. In another app, the PDF I got had &amp;quot;Scanned with FreeApp&amp;quot; on every page. In yet another one, I could share the PDF only if it was by email.&lt;/p&gt;
&lt;p&gt;All of that is code that was intentionally added to the app. So, if an app is &lt;strong&gt;open-source&lt;/strong&gt;, it&#39;s usually easy for someone to remove that kind of code and publish a similar app. That makes open-source apps much more likely to be respectful.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/pynicolas/FairScan&quot;&gt;FairScan is open-source&lt;/a&gt;: you can review its code and check that it&#39;s as respectful as it should.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;What FairScan is not&lt;/h2&gt;
&lt;p&gt;In addition to the &amp;quot;anti-features&amp;quot; I just listed, there are features that I see in a lot of document scanning apps, and that I think I don&#39;t want for FairScan. I believe it can be helpful to list them to clarify FairScan&#39;s scope.&lt;/p&gt;
&lt;h3&gt;Not a storage app&lt;/h3&gt;
&lt;p&gt;FairScan is not about storing documents and keeping them safe. I don&#39;t want FairScan to take that responsibility. FairScan keeps data only for the current document being scanned. At the end of the scanning process, the user exports a PDF by storing it in the device&#39;s Download directory or by sharing it with any app installed on the device. After a click on &amp;quot;End Scan&amp;quot;, FairScan deletes the images it captured. It&#39;s then up to the user to keep the PDF safe.&lt;/p&gt;
&lt;h3&gt;Not an app to tweak PDFs&lt;/h3&gt;
&lt;p&gt;If FairScan gets adopted by many people, some will probably ask for options to adjust the page contrast or the PDF compression level.
But that&#39;s not the direction I want to take.
Once you open the door to manual tweaks, where do you stop? It goes against the idea of a &lt;em&gt;simple&lt;/em&gt; app.
More importantly, I believe it would discourage feedback and progress on automatic processing.
Instead, I&#39;d much rather invest development time in making the automatic pipeline smarter, so that everyone gets better PDFs without extra effort.
That&#39;s the choice I make for FairScan.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;That&#39;s the idea behind FairScan: a document scanner that is simple, respectful, and focused on doing its job well. It&#39;s already available on the &lt;a href=&quot;https://play.google.com/store/apps/details?id=org.fairscan.app&quot;&gt;Play Store&lt;/a&gt; and &lt;a href=&quot;https://f-droid.org/en/packages/org.fairscan.app/&quot;&gt;F-Droid&lt;/a&gt;, and I&#39;m committed to improving it while keeping true to this vision. I hope this post helps explain why FairScan exists and what I&#39;m trying to achieve, and I look forward to sharing more about the project and its context here on the blog.&lt;/p&gt;
</content>
  </entry>
</feed>