Generování 3D modelu otisku prstu documentation master file, created by
sphinx-quickstart on Fri May  5 21:01:20 2023.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.

There is an option to input the filter series as a **preset** from JSON configuration file.
Here the presets are stored and are ready to be used whenever needed. You can usehow many filters you need as long as you like the output.
It is therefore highly recommended to check the output after every preset change.

 from JSON configuration file.

Filter used in the example above is listed bellow, along with the general form of configuration file.

<style>
table {
    border-collapse: collapse;
    width: 100%;
}

th, td {
    padding: 8px;
    text-align: left;
    border-bottom: 1px solid #ddd;
}

th {
    background-color: #f2f2f2;
}

.code {
    font-family: 'Courier New', monospace;
    background-color: #f5f5f5;
}

.language-json {
    color: #333;
}
</style>

<table>
    <thead>
        <tr>
            <th>General format</th>
            <th>Working example</th>
        </tr>
    </thead>
    <tbody>
        <tr>
        <td>
            <pre><code class="language-json">
{
    "preset": [
        {
            "name": "filter_name",
            "parameter": value,
            "parameter": value
        },
        {
        }
    ],
        ...
    ]
    ...
}
            </code></pre>
        </td>
        <td>
{
    "git_example": [
        {
            "name": "denoise_tv_chambolle",
            "weight": 0.01,
            "iterations": 1
        },
        {
            "name": "median",
            "ksize": 3
        }
    ]
}

        </td>
        </tr>
    </tbody>
</table>

To avoid accidental loss of information caused by modifying presets that have been used to generate stl files,
these presets are stored inside a JSON file **db.json**.

these presets are stored inside a JSON file 

This file serves as a simple database for storing presets, stored presets are modified by adding generated hash of all the filters in that preset.There is also an option to save current command line setting as a preset using -d switch and it's new name:

This file serves as a simple database for storing presets, stored presets are modified by adding generated hash of all the filters in that preset.There is also an option to save current command line setting as a preset using -d switch and it’s new name:

Config parser for fingerprint filtering and 3d model generation application.

Parse parameters of filters. Set to None if parameter is not specified.
These are later set to default values in the filter method apply.

Overview of all implemented filters and their parameters with descriptions is listed below.

**median blur**

  * *ksize* (int) - Kernel size, determines how large of an area the filter processes.

* *ksize* (int) - Kernel size, determines how large of an area the filter processes.

*ksize* (int) - Kernel size, determines how large of an area the filter processes.

 (int) - Kernel size, determines how large of an area the filter processes.

**gaussian blur**

  * *sigma* (int) - Gaussian kernel standart deviation, determines the weight of further pixels on the currently processed pixel.

* *sigma* (int) - Gaussian kernel standart deviation, determines the weight of further pixels on the currently processed pixel.

*sigma* (int) - Gaussian kernel standart deviation, determines the weight of further pixels on the currently processed pixel.

 (int) - Gaussian kernel standart deviation, determines the weight of further pixels on the currently processed pixel.

**bilateral blur**

  * *diameter* (int) - Diameter of pixel neighborhood used for filtering.
  * *sigmaColor* (int) - Determines the weight of pixels of different color.
  * *sigmaSpace* (int) - Determines the weight of further pixels.

* *diameter* (int) - Diameter of pixel neighborhood used for filtering.
* *sigmaColor* (int) - Determines the weight of pixels of different color.
* *sigmaSpace* (int) - Determines the weight of further pixels.

*diameter* (int) - Diameter of pixel neighborhood used for filtering.

*sigmaColor* (int) - Determines the weight of pixels of different color.

**bilateral_scikit**

  * *sigmaColor* (float) - Determines the weight of pixels of different color.
  * *sigmaSpace* (float) - Determines the weight of further pixels.

* *sigmaColor* (float) - Determines the weight of pixels of different color.
* *sigmaSpace* (float) - Determines the weight of further pixels.

*sigmaColor* (float) - Determines the weight of pixels of different color.

*sigmaSpace* (float) - Determines the weight of further pixels.

**nlmeans** (non-local means)

  * *patch_size* (int) - Size of patches used for denoising.
  * *patch_distance* (int) - Distance in pixels where to search for patches.
  * *h* (float) - Cut-off distance, higher means more smoothed image.

* *patch_size* (int) - Size of patches used for denoising.
* *patch_distance* (int) - Distance in pixels where to search for patches.
* *h* (float) - Cut-off distance, higher means more smoothed image.

*patch_distance* (int) - Distance in pixels where to search for patches.

*h* (float) - Cut-off distance, higher means more smoothed image.

**total_variation**

  * *weight* (float) - Denoising weight, determines how much the image will be denoised.

* *weight* (float) - Denoising weight, determines how much the image will be denoised.

*weight* (float) - Denoising weight, determines how much the image will be denoised.

 (float) - Denoising weight, determines how much the image will be denoised.

**unsharp_mask_scikit**

  * *radius* (int) - Radius of the gaussian filter.
  * *amount* (float) - Strength of the unsharp mask, determines how much of the mask will be used for filtering.

* *radius* (int) - Radius of the gaussian filter.
* *amount* (float) - Strength of the unsharp mask, determines how much of the mask will be used for filtering.

*amount* (float) - Strength of the unsharp mask, determines how much of the mask will be used for filtering.

 (float) - Strength of the unsharp mask, determines how much of the mask will be used for filtering.

**binarize**

  * *threshold* (int) - Value to cut differentiate pixels.

**add_margin**

  * *margin* (int) - Number of pixels to add to the sides of the image.
  * *color* (int) - Color value of newly added pixels.

* *margin* (int) - Number of pixels to add to the sides of the image.
* *color* (int) - Color value of newly added pixels.

*margin* (int) - Number of pixels to add to the sides of the image.

**erode**

  * *kernel* (numpy matrix) - Shape of the kernel used to erode image.

* *kernel* (numpy matrix) - Shape of the kernel used to erode image.

*kernel* (numpy matrix) - Shape of the kernel used to erode image.

**dilate**

  * *kernel* (numpy matrix)- Shape of the kernel used to dilate image.

* *kernel* (numpy matrix)- Shape of the kernel used to dilate image.

*kernel* (numpy matrix)- Shape of the kernel used to dilate image.

Once all the requirements are installed, the application is ready to use.
Fingerprint sample is located in res/examples, its name is Palec_P4.tif.

You will need to enter the virtual enviroment every time you want to use the application.

The application requires **input** and **output filenames** including path from the root project directory, **dpi** and **filter list** as shown bellow.

manually list all filter names and their parameters on the **command line**:

(.venv)$ python3 src/main.py res/examples/Palec_P4.tif res/examples/Palec_P4_from_cline.png 600 total_variation weight=0.15 median ksize=5

load them from preset in a JSON **configuration file**, that can be used to tune and modify existing presets, or create new ones:

, that can be used to tune and modify existing presets, or create new ones:

(.venv)$ python3 src/main.py res/examples/Palec_P4.tif res/examples/Palec_P4_from_preset.png 600 --config conf/conf.json new_ridge

/home/rostik/Documents/BP_DP-xlanro00/src/filters.py:docstring of filters

Skimage denoise_bilateral filter.
Averages pixels based on their distance and color similarity.
Preserves edges while removing unwanted noise.
Much slower than opencv implementation.

This filter is very slow and should be used only on small images

/home/rostik/Documents/BP_DP-xlanro00/src/filters.py:docstring of filters.dilate

/home/rostik/Documents/BP_DP-xlanro00/src/filters.py:docstring of filters.erode

/home/rostik/Documents/BP_DP-xlanro00/src/filters.py:docstring of filters.farid

Gaussian blur filter from scikit-image.
Easier to use than opencv version.

/home/rostik/Documents/BP_DP-xlanro00/src/filters.py:docstring of filters.invert

/home/rostik/Documents/BP_DP-xlanro00/src/filters.py:docstring of filters.median

Median blur filter from scikit-image.
Using this over opencv version as that one is limited to 5x5 kernel.

Meijering filter from scikit-image filters.
Finds continuous ridges.

/home/rostik/Documents/BP_DP-xlanro00/src/filters.py:docstring of filters.sato

Exctracts continuous ridges.

Scale values of the image to use the entire range of data type.
This should remove the line height issues.

Performs total variation denoising technique based on original Chambolle paper.
This filter removes fine detail, but preserves details such as edges.

Apply blurring using gaussian filter, then subtract the blurred image from the original image.
Radius parameter is the sigma parameter of the gaussian filter.
Amount parameter regulates the strength of the unsharp mask.
Better results than using this from opencv.

It is possible to generate stl model using the `--stl` switch. This requires more parameters, first of which is the type of generated fingerprint.

 switch. This requires more parameters, first of which is the type of generated fingerprint.

If the mode is set to `c`, the output model will be a curved finger model, with optional parameters following the filename controlling its shape.

, the output model will be a curved finger model, with optional parameters following the filename controlling its shape.

First optional parameter is papilar line height `height_line`, second is thickness of the model `height_base`,
third the rate of curvature along x axis `curv_rate_x` and the third is the rate of curvature along y axis `curv_rate_y`.

$ python3 src/main.py input_file output_file dpi --config config_file preset --stl c height_line height_base curvature_x curvature_y

$ python3 src/main.py res/examples/Palec_P4.tif res/examples/Palec_P4_from_preset.png 600 --config conf/conf.json new_ridge --stl c 2 10 2 2

Using `p` mode makes the generated fingerprint model flat.
Optional parameters are height of the papilar lines and base thickness.

 mode makes the generated fingerprint model flat.

$ python3 src/main.py input_file output_file dpi --config config_file preset --stl p height_line height_base

$ python3 src/main.py res/examples/Palec_P4.tif res/examples/Palec_P4_from_preset.png 600 --config conf/conf.json new_ridge --stl p 2 10

Using `m` mode modifies the preexisting finger model to contain fingerprint.
First optional parameter is papilar line height `height_line`, second is the number of iterations `iter` to make the finger mesh denser. Higher number of itertions results in denser finger mesh and better result.
The next three parameters are axis offsets for the finger, `finger_x`, `finger_y`, `finger_z`.
These control the location of the finger. They need to be set only if the user wants to move core of the print closer to the center of the finger model. The last parameter `finger_model` allows the user to choose custom finger model.

 mode modifies the preexisting finger model to contain fingerprint.
First optional parameter is papilar line height 

 to make the finger mesh denser. Higher number of itertions results in denser finger mesh and better result.
The next three parameters are axis offsets for the finger, 

.
These control the location of the finger. They need to be set only if the user wants to move core of the print closer to the center of the finger model. The last parameter 

$ python3 src/main.py input_file output_file dpi --config config_file preset --stl m height_line iter finger_x finger_y finger_z finger_model

$ python3 src/main.py res/examples/Palec_P4.tif res/examples/Palec_P4.png 600 --config conf/conf.json new_ridge --stl m 0.2 2 0 0 0 res/finger_backup/finger.stl

This application has been developed as a part of bachelor's thesis at Brno University of Technology - Faculty of Information Technology.
The topic of this thesis was **Generating a 3D Fingerprint Model** from input fingerprint image.

This application has been developed as a part of bachelor’s thesis at Brno University of Technology - Faculty of Information Technology.
The topic of this thesis was 

This application consists of two main parts. The first part of the application uses custom filter library to apply image filters to enhance fingerprint images.
This library consists of several filters imported from image processing modules.

The second part uses the processed image to make a 3D model of the fingerprint.
The model can then be used to print an accurate representation of human fingerprint using a 3D printer.
This model can either be planar, curved or mapped to a finger model.

The application has only been tested on Ubuntu gnu/linux machines.
It should however be possible to use it in on most linux distributions, WSLs and also virtual machines of most linux distributions.

To start off, you need these to succesfully use the application.

**python** version 3.10 is a requirement might work on earlier python 3 versions:

 version 3.10 is a requirement might work on earlier python 3 versions:

**virtualenv** package for virtual enviroment creation, other packages are installed automatically later:

 package for virtual enviroment creation, other packages are installed automatically later:

This will install the application and its components into the Documents directory.
It will also install several required python packages, including venv, which is used to create a virtual enviroment.

Go to a suitable installation folder, for example **Documents**:

$ git clone ssh://git@strade.fit.vutbr.cz:3022/xlanro00/BP_DP-xlanro00.git

Now, you are all set to run the application.
 Examples of how to do this are listedin the section bellow.

Examples of how to do this are listedin the section bellow.

/home/rostik/Documents/BP_DP-xlanro00/src/log.py:docstring of log

/home/rostik/Documents/BP_DP-xlanro00/src/log.py:docstring of log.error_exit

Print given error message to stderr and exit the application.
:param message: error message to be printed to stderr

/home/rostik/Documents/BP_DP-xlanro00/src/log.py:docstring of log.print_message

Print given message to stderr.
:param message: message to be printed to stderr

Main file of the project, contains filtering and stl generation functions

Read input file, store as numpy.array, uint8, grayscale.
Call function to apply the filters and a function to save it to output file.

Return empty figure with one ax, which has dimensions of the input image.

Mirror image using opencv.
Should be used to cancel implicit mirroring.

Apply filters to image one by one.
In case none were given, pass and save original image to the output file.

Scale image values to get values from 0 to 255.
Check validity of dimension parameters.
Then compute base and papilar lines height.
Prepare meshgrid, array which later serves to store point coordinates.

Write parameter string to stl header.
This header is 80 bytes long, so the data needs to be shortened to fit.
If the parameter string is too long, a warning is printed and the data is truncated.

Get a unique ID for the model, which is used in filename and on the model backside.
Also create parameter string for stl header, which is used to create ID using hash function MD5.

Engrave text on the back of the model.
Create an empty image, fill it with color and draw text on it.

Create faces for the model.
Iterate over all vertices, append to vector and create faces from indices.

Create vertices from meshgrid, add z coordinates from processed image heightmap.
Create faces from vertex indices.

Compute curved surface offset.

Parses stl file header.
Prints command for running main.py with preformatted arguments.

<style>
    table {
        border-collapse: collapse;
        width: 100%;
    }

    th, td {
        padding: 8px;
        text-align: left;
        border-bottom: 1px solid #ddd;
    }

    th {
        background-color: #f2f2f2;
    }

    .code {
        font-family: 'Courier New', monospace;
        background-color: #f5f5f5;
    }

    .language-json {
        color: #333;
    }
</style>
<table>
    <thead>
        <tr>
        <th>Error message</th>
        <th>Solution</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                main.py: error: the following arguments are required: input_file, output_file, dpi, filters
            </td>
            <td>
                You probably forgot to include some of the required arguments.
            </td>
        </tr>
        <tr>
            <td>
                ERROR: Input file res/Palec_P14.tif does not exist
            </td>
            <td>
                The file you want to process does not exist, check the filename again.
            </td>
        </tr>
        <tr>
            <td>
                ERROR: Config file not found
            </td>
            <td>
                The config file you want to load config from does not exist, check the filename again.
            </td>
        </tr>
        <tr>
            <td>
                ERROR: Preset not found in config file
            </td>
            <td>
                The preset is not present in selected config file, check the file again or select the correct config file.
            </td>
        </tr>
        <tr>
            <td>
                ERROR: Filter undefined_filter not found
            </td>
            <td>
                One of the filters from command line is not defined in the library, check its name.
            </td>
        </tr>
        <tr>
            <td>
                ERROR: Unrecognized generation mode
            </td>
            <td>
                The first parameter of stl generation should be p, c or m, check it again.
            </td>
        </tr>
        <tr>
            <td>
                ERROR: Line depth must be less than plate thickness
            </td>
            <td>
                When generating a cast, the depth must be less than the base plate thckness, otherwise it would have holes on the other side.
            </td>
        </tr>
        <tr>
            <td>
                ERROR: Depth of plate height must be positive
            </td>
            <td>
                Cannot generate negative base plate thickness, check order of arguments.
            </td>
        </tr>
        <tr>
            <td>
                ERROR: Base and line height must both be positive
            </td>
            <td>
                In curved generation any negative argument is an error, casts are only for planar mode.
            </td>
        </tr>
        <tr>
            <td>
                ERROR: Fingerprint image is outside of the finger model
            </td>
            <td>
                Outside of range of the finger, fingerprint cannot be mapped to nothing. Try to change finger_x, finger_y and finger_z parameters.
            </td>
        </tr>
    </tbody>
</table>

$ usage: main.py [-h] [-m | --mirror | --no-mirror] input_file
output_file dpi ([-c | --config config_file preset] |
[filters ...]) [-s | --stl_file p height_line height_base |
--stl_file c height_line height_base curv_rate_x curv_rate_y |
--stl m height_line iter finger_x finger_y finger_z finger_model]
[-d | --database database_filename]

Program for processing a 2D image into 3D fingerprint.

positional arguments:
input_file            input file path
output_file           output file path
dpi                   dpi of used scanner
filters               list of filter names and their parameters in form
                        [filter_name1 param1=value
                        param2=value filter_name2 param1=value...]

options:
-h, --help            show this help message and exit
-m, --mirror, --no-mirror
                        switch to mirror input image
-s [STL_FILE ...], --stl_file [STL_FILE ...]
                        create stl model from processed image
-c CONFIG CONFIG, --config CONFIG CONFIG
                        pair: name of the config file with presets,
                        name of the preset