# FlatCV - Image processing and computer vision library

**URL:** <https://discourse.haskell.org/t/flatcv-image-processing-and-computer-vision-library/13561>\
**Category:** Announcements\
**Created:** [January 18, 2026, 6:49pm UTC](https://discourse.haskell.org/t/flatcv-image-processing-and-computer-vision-library/13561 "2026-01-18T18:49:03Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![ad-si](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/ad-si/32/3765_2.png) [@ad-si](https://discourse.haskell.org/u/ad-si)\
**Post date:** [January 18, 2026, 6:49pm UTC](https://discourse.haskell.org/t/flatcv-image-processing-and-computer-vision-library/13561/1 "2026-01-18T18:49:03Z")

</div>

I’m very excited to announce the first official release of the FlatCV Haskell bindings!

> **[flatcv](https://hackage.haskell.org/package/flatcv)**
>
> Haskell bindings for FlatCV image processing library

This has been a very long journey that started 9 years ago with a simple question:

> Can I build a computer vision app that extracts documents from photos?

My first iteration was a CLI app called [Perspectra](https://github.com/ad-si/perspectra), implemented with Python and [scikit-image](https://scikit-image.org/). However, I quickly realized that I absolutely do not like Python and that I needed a GUI to fix incorrectly detected document boundaries, as the CV pipeline would never get it a 100% right.

And how do you build a desktop app with a GUI? Obviously with Haskell 😝.  
_(The “desktop app” part is a whole other story I’ll save for another post, but I am making good progress on that front as well. =\> [Perspec](https://github.com/ad-si/Perspec). I’ll focus on the CV part for the rest of this post.)_

As I didn’t want to use Python any longer, my next instinct was to use ImageMagick, as I had some experience with its features and capabilities. The [existing bindings](https://hackage.haskell.org/packages/search?terms=magick) were rather lacking, so I opted to simply call `magick` as an external process. While this mostly worked, it was always a pain to get it to install and link correctly across platforms, and the performance was surprisingly bad for larger images.

Another obvious choice might be OpenCV, but I had some bad memories of using it at university (maybe it was just the C++ context…), and the Haskell bindings looked rather painful.

So, my next experiment was using [Hip](https://github.com/lehins/hip), and with the help of @lehins himself and @HanStolpo at ZuriHac, we were able to make it work! _(Thanks again!)_

However, it was still missing some features that I wanted, like binarization with Otsu’s Method. While it would certainly be possible to implement this in Hip, I (for once) felt that Haskell’s abstractions didn’t really help with the task at hand and only complicated things unnecessarily. A for loop in C, by comparison, is conceptually very simple and already as fast as the Haskell code. Luckily, C is a first-class citizen in Haskell and it’s very easy to bundle some C code and call it via Haskell’s FFI.

Unfortunately, there didn’t seem to be a straightforward C library that I could hook up to, so I started to work on [FlatCV](https://github.com/ad-si/FlatCV). I’m quite happy with the UX of using C for the image manipulation algorithms, and I was able to quickly build a fully functioning version with the necessary Haskell bindings. Just a few days ago, I released [version 0.3.0](https://github.com/ad-si/FlatCV/releases/tag/v0.3.0), and by now it has most of the basic operations you would expect from an image manipulation library. I also ported some of the higher-level CV operations, like adaptive binarization and corner detection, that I first implemented in Perspectra.

There are still plenty of opportunities to improve the performance of FlatCV: SIMD, GPU usage, [streamed processing](https://github.com/libvips/libvips/wiki/Why-is-libvips-quick), etc. However, as FlatCV isn’t used in a real-time context (i.e., 60 fps), the performance is already more than sufficient.

Hope you like it, and I’d be interested to know if you have any use cases for FlatCV!

---

<div class="post-metadata">

**Author:** ![pmidden](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/pmidden/32/2426_2.png) [@pmidden](https://discourse.haskell.org/u/pmidden)\
**Post date:** [January 19, 2026, 6:54am UTC](https://discourse.haskell.org/t/flatcv-image-processing-and-computer-vision-library/13561/2 "2026-01-19T06:54:48Z")

</div>

Heh. I was looking to “how to resize an image in Haskell” recently and only found Hip (which has problems with more recent GHC versions apparently, and seems rather unmaintained) and massiv (which isn’t about resizing and images at all but matrices, so there would have been a lot of extra work for me). So this is very interesting to me. Good choice to just implement it in C, plus bindings, instead of pure Haskell.

---

<div class="post-metadata">

**Author:** ![ocramz](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/ocramz/32/3713_2.png) [@ocramz](https://discourse.haskell.org/u/ocramz)\
**Post date:** [January 19, 2026, 8:31am UTC](https://discourse.haskell.org/t/flatcv-image-processing-and-computer-vision-library/13561/3 "2026-01-19T08:31:40Z")

</div>

There’s yak shaving and then there’s this 😃

Tbf the Python bindings to OpenCV are quirky but not that bad, once you internalise a couple idioms.

Kudos on the release !

---

<div class="post-metadata">

**Author:** ![ad-si](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/ad-si/32/3765_2.png) [@ad-si](https://discourse.haskell.org/u/ad-si)\
**Post date:** [January 29, 2026, 6:46pm UTC](https://discourse.haskell.org/t/flatcv-image-processing-and-computer-vision-library/13561/4 "2026-01-29T18:46:00Z")

</div>

Thanks! 😊

I can already tease that there’s some more yak shaving happening for the desktop GUI 😅. Announcement post coming soon …
