Giter Club home page Giter Club logo

libpillowfight's Introduction

libpillowfight / pypillowfight

Really simple C Library containing various image processing algorithms. It includes Python 3 bindings designed to operate on Pillow images (PIL.Image).

The C library depends only on the libc. The Python bindings depend only on Pillow.

APIs are designed to be as simple to use as possible. Default values are provided for every parameters.

Python 2.x is not supported.

Available algorithms are listed below.

Available algorithms

  • Unpaper's algorithms
    • Blackfilter
    • Noisefilter
    • Blurfilter
    • Masks
    • Grayfilter
    • Border
  • Canny edge detection
  • Sobel operator
  • Gaussian blur
  • ACE (Automatic Color Equalization ; Parallelized implementation)
  • SWT (Stroke Width Transformation)
  • Compare : Compare two images (grayscale) and makes the pixels that are different really visible (red).

Python API

The Python API can be compiled, installed and used without installing the C library.

Installation

Latest release :

$ sudo pip3 install pypillowfight

Development version :

$ git clone https://github.com/jflesch/libpillowfight.git
$ cd libpillowfight
$ sudo python3 ./setup.py install

Usage

For each algorithm, a function is available. It takes a PIL.Image instance as parameter. It may take other optionnal parameters. The return value is another PIL.Image instance.

Example:

import pillowfight

input_img = PIL.Image.open("tests/data/brightness_problem.jpg")
output_img = pillowfight.ace(input_img)

Tests

$ python3 ./setup.py nosetests

C library

Installation

$ mkdir cbuild
$ cd cbuild
$ cmake ..
$ make -j4
$ sudo make install

Usage

C code

For each algorithm, a function is available. It takes a struct pf_bitmap as input. As output, it fills in another struct pf_bitmap.

struct pf_bitmap is a really simple structure:

struct pf_bitmap {
	struct {
		int x;
		int y;
	} size;
	union pf_pixel *pixels;
};

(struct pf_bitmap).size.x is the width of the image.

(struct pf_bitmap).size.y is the height of the image.

union pf_pixel are basically 32 bits integers, defined in a manner convenient to retrieve each color independantly (RGB). Each color is on one byte. 4th byte is unused (no alpha channel taken into account).

(struct pf_bitmap).pixels must points to a memory area containing the image. The image must contains x * y * union pf_pixel.

Compilation with GCC

$ gcc -Wall -Werror -lpillowfight -o test test.c

Note regarding Unpaper's algorithms

Many algorithms in this library are re-implementations of algorithms used by Unpaper. To make the API simpler to use (.. and implement), a lot of settings have been hard-coded.

Unpaper applies them in the following order:

  • Blackfilter
  • Noisefilter
  • Blurfilter
  • Masks
  • Grayfilter
  • Border

I would advise applying automatic color equalization (ACE) first.

A basic documentation for some of the algorithms can be found in Unpaper's documentation.

Input Output
Black border problem ACE + Unpapered
Brightness problem ACE + Unpapered

Available algorithms

Automatic Color Equalization (ACE)

Input Output
Brightness problem Corrected

This algorithm is quite slow (~40s for one big image with one thread on my machine). So this version is parallelized (down to ~15s on a 4 cores computer).

Python API

out_img = pillowfight.ace(img_in,
	slope=10,
	limit=1000,
	samples=100,
	seed=None)

Use as many threads as there are cores on the computer (up to 32).

This algorithm uses random number. If you need consistent results (for unit tests for instance), you can specify a seed for the random number generator. Otherwise, time.time() will be used.

C API

#define PF_DEFAULT_ACE_SLOPE 10
#define PF_DEFAULT_ACE_LIMIT 1000
#define PF_DEFAULT_ACE_NB_SAMPLES 100
#define PF_DEFAULT_ACE_NB_THREADS 2
extern void pf_ace(const struct pf_bitmap *in, struct pf_bitmap *out,
		int nb_samples, double slope, double limit,
		int nb_threads);

This function uses random numbers coming (rand()). You should call srand() before calling this function.

Sources

Canny's edge detection

Input Output
Crappy background Canny output

Python API

img_out = pillowfight.canny(img_in)

C API

extern void pf_canny(const struct pf_bitmap *in, struct pf_bitmap *out);

Sources

Compare

Simple algorithm showing the difference between two images. Note that it converts the images to grayscale first.

It accepts a parameter 'tolerance': For each pixel, the difference with the corresponding pixel from the other image is computed. If the difference is between 0 and 'tolerance', it is ignored (pixels are considered equal).

Input Input2 Output
Black border problem Black border problem + blackfilter Diff

Python API

(nb_diff, out_img) = pillowfight.compare(img_in, img_in2, tolerance=10)

C API

extern int pf_compare(const struct pf_bitmap *in, const struct pf_bitmap *in2,
		struct pf_bitmap *out, int tolerance);

Returns the number of pixels that are different between both images.

Gaussian

Input Output
Crappy background Gaussed

One of the parameters is sigma. If it is equals to 0.0, it will be computed automatically using the following formula (same as OpenCV):

sigma = 0.3 * ((nb_stddev - 1) * 0.5 - 1) + 0.8;

Python API

img_out = pillowfight.gaussian(img_in, sigma=2.0, nb_stddev=5)

C API

extern void pf_gaussian(const struct pf_bitmap *in, struct pf_bitmap *out,
	double sigma, int nb_stddev);

Sources

Sobel operator

Input Output
Crappy background Sobel

Python API

img_out = pillowfight.sobel(img_in)

C API

extern void pf_sobel(const struct pf_bitmap *in_img, struct pf_bitmap *out_img);

Sources

Stroke Width Transformation

This algorithm extracts text from natural scenes images.

To find text, it looks for strokes. Note that it doesn't appear to work well on scanned documents because strokes are too small.

This implementation can provide the output in 3 different ways:

  • Black & White : Detected text is black. Background is white.
  • Grayscale : Detected text is gray. Its exact color is proportional to the stroke width detected.
  • Original boxes : The rectangle around the detected is copied as is in the output image. Rest of the image is white.

(following examples are with original boxes)

Input Output
Black border problen SWT (SWT_OUTPUT_ORIGINAL_BOXES)
Crappy background SWT (SWT_OUTPUT_ORIGINAL_BOXES)
Black border problen SWT (SWT_OUTPUT_BW_TEXT)
Crappy background SWT (SWT_OUTPUT_BW_TEXT)

Python API

# SWT_OUTPUT_BW_TEXT = 0  # default
# SWT_OUTPUT_GRAYSCALE_TEXT = 1
# SWT_OUTPUT_ORIGINAL_BOXES = 2

img_out = pillowfight.swt(img_in, output_type=pillowfight.SWT_OUTPUT_ORIGINAL_BOXES)

C API

enum pf_swt_output
{
	PF_SWT_OUTPUT_BW_TEXT = 0,
	PF_SWT_OUTPUT_GRAYSCALE_TEXT,
	PF_SWT_OUTPUT_ORIGINAL_BOXES,
};
#define PF_DEFAULT_SWT_OUTPUT PF_SWT_OUTPUT_BW_TEXT

extern void pf_swt(const struct pf_bitmap *in_img, struct pf_bitmap *out_img,
		enum pf_swt_output output_type);

Sources

Unpaper's Blackfilter

Input Output Diff
Black border problem Filtered Diff

Python API

img_out = pillowfight.unpaper_blackfilter(img_in)

C API

extern void pf_unpaper_blackfilter(const struct pf_bitmap *in, struct pf_bitmap *out);

Sources

Unpaper's Blurfilter

Input Output Diff
Black border problem Filtered Diff

Python API

img_out = pillowfight.unpaper_blurfilter(img_in)

C API

extern void pf_unpaper_blurfilter(const struct pf_bitmap *in, struct pf_bitmap *out);

Sources

Unpaper's Border

Input Output Diff
Black border problem 3 Border Diff

Python API

img_out = pillowfight.unpaper_border(img_in)

C API

extern void pf_unpaper_border(const struct pf_bitmap *in, struct pf_bitmap *out);

Sources

Unpaper's Grayfilter

Input Output Diff
Black border problem 3 Filterd Diff

Python API

img_out = pillowfight.unpaper_grayfilter(img_in)

C API

extern void pf_unpaper_grayfilter(const struct pf_bitmap *in, struct pf_bitmap *out);

Sources

Unpaper's Masks

Input Output Diff
Black border problem 2 Masks Diff

Python API

img_out = pillowfight.unpaper_masks(img_in)

C API

extern void pf_unpaper_masks(const struct pf_bitmap *in, struct pf_bitmap *out);

Sources

Unpaper's Noisefilter

Input Output Diff
Black border problem Filtered Diff

Python API

img_out = pillowfight.unpaper_noisefilter(img_in)

C API

extern void pf_unpaper_noisefilter(const struct pf_bitmap *in, struct pf_bitmap *out);

Contact

Sources

libpillowfight's People

Contributors

jflesch avatar jfleschwyplay avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.