nbis-py


Namenbis-py JSON
Version 0.1.3 PyPI version JSON
download
home_pagehttps://github.com/Seventh-Sense-Artificial-Intelligence/nbis-rs
SummaryPython bindings for NBIS fingerprint processing using Rust + UniFFI
upload_time2025-10-08 07:41:51
maintainerNone
docs_urlNone
authorNone
requires_python>=3.8
licenseNone
keywords fingerprint nbis biometrics rust uniffi
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            ## NBIS-rs

This is a Rust/Python binding to the [NIST Biometric Image Software](https://www.nist.gov/services-resources/software/nist-biometric-image-software-nbis) (NBIS) library, which is used for processing biometric images, particularly in the context of fingerprint recognition.

For convenience, this library also binds to the [NIST Fingerprint Image Quality](https://www.nist.gov/services-resources/software/nfiq-2) (NFIQ) version 2. 

## Features

- Bindings to NBIS functions for minutia extraction, matching
- Exports minutiae templates in ISO/IEC 19794-2:2005 format
- Matches minutiae templates against each other using the NBIS Bozorth3 algorithm
- Provides support for NFIQ2 quality assessment

## Installation (Rust)

To use NBIS-rs, add the following to your `Cargo.toml`:

```toml
[dependencies]
nbis-rs = { git = "https://github.com/Seventh-Sense-Artificial-Intelligence/nbis-rs", branch = "main", version = "0.1.2" }
```
Or you can run the following command on the terminal of your new rust project:

cargo add nbis-rs --git https://github.com/Seventh-Sense-Artificial-Intelligence/nbis-rs --branch main

Running the above command will add the above dependency in your Cargo.toml

Now you can use the nbis-rs rust library in your project as mentioned in next section.

## Usage (Rust)

Here's a simple example of how to use NBIS-rs in your project:

```rust
fn main() -> Result<(), Box<dyn std::error::Error>> {
    use nbis;
    use nbis::Minutiae;
    use nbis::NbisExtractorSettings;
    // Configuration for the NbisExtractor
    let settings = NbisExtractorSettings {
        // No filtering on minutiae quality (all minutiae will be included)
        min_quality: 0.0,
        // Do not compute ROI or center to save computing resources
        get_center: false,
        // Do not check if the image is a fingerprint using SIVV
        check_fingerprint: false,
        // compute the NFIQ score
        compute_nfiq2: true,
        // No specific PPI, use the default
        ppi: None,
    };

    let extractor = nbis::NbisExtractor::new(settings)?;

    // Read the bytes from a file (you could also use nbis::extract_minutiae_from_image_file)
    // but here we just load the image bytes as image paths on mobile platforms can be tricky.
    let image_bytes = std::fs::read("test_data/p1/p1_1.png")?;

    let minutiae_1 = extractor.extract_minutiae(&image_bytes)?;

    let image_bytes = std::fs::read("test_data/p1/p1_2.png")?;
    let minutiae_2 = extractor.extract_minutiae(&image_bytes)?;

    let image_bytes = std::fs::read("test_data/p1/p1_3.png")?;
    let minutiae_3 = extractor.extract_minutiae(&image_bytes)?;

    // Compare the two sets of minutiae
    let score = minutiae_1.compare(&minutiae_2);
    assert!(score > 35, "Expected a high similarity score between p1_1 and p1_2");
    let score = minutiae_1.compare(&minutiae_3);
    assert!(score > 35, "Expected a high similarity score between p1_1 and p1_3");
    let score = minutiae_2.compare(&minutiae_3);
    assert!(score > 35, "Expected a high similarity score between p1_2 and p1_3");

    // Next we will demonstrate conversion to ISO/IEC 19794-2:2005 format
    // and back to a `Minutiae` object.
    // First, convert the minutiae to ISO template bytes
    let iso_template: Vec<u8> = minutiae_1.to_iso_19794_2_2005();              
    // And load it back
    let minutiae_from_iso = extractor.load_iso_19794_2_2005(&iso_template)?;
    // Compare the original minutiae with the one loaded from ISO template
    for (a, b) in minutiae_from_iso.get().iter().zip(minutiae_1.get().iter()) {
        assert_eq!(a.x(), b.x());
        assert_eq!(a.y(), b.y());
        assert_eq!(a.angle(), b.angle());
        assert_eq!(a.kind(), b.kind());
        // Reliability is quantized in the round-trip conversion,
        // so we allow a small margin of error.
        assert!((a.reliability() - b.reliability()).abs() < 1e-1);
    }

    // Finally we demonstrate loading from a file and comparing a negative match
    let minutiae_4 = extractor.extract_minutiae_from_image_file("test_data/p2/p2_1.png")?;
    let score = minutiae_1.compare(&minutiae_4);
    assert!(score < 35, "Expected a low similarity score between p1_1 and p2_1");

    // We can access the NFIQ2 quality via:
    let nfiq2_quality = minutiae_1.quality();
    assert!(nfiq2_quality.score > 50, "Expected a positive NFIQ2 quality score");

    Ok(())
}
```

## Installation (Python)
To install the Python bindings, you can use pip:

```bash
pip install nbis-py
```

## Usage (Python)

Here's a simple example of how to use the NBIS Python bindings:

```python
import nbis
from nbis import NbisExtractor, NbisExtractorSettings

 #Configuration for the NbisExtractor
settings = NbisExtractorSettings(
    # Do not filter on minutiae quality (get all minutiae)
    min_quality=0.0,
    # Do not get the fingerprint center or ROI
    get_center=False,
    # Do not use SIVV to check if the image is a fingerprint
    check_fingerprint=False,
    # Compute the NFIQ2 quality score
    compute_nfiq2=True,
    # No specific PPI, use the default
    ppi=None,
)

extractor = nbis.new_nbis_extractor(settings)

# Read the bytes from a file
image_bytes = open("test_data/p1/p1_1.png", "rb").read()
minutiae_1 = extractor.extract_minutiae(image_bytes)
image_bytes = open("test_data/p1/p1_2.png", "rb").read()
minutiae_2 = extractor.extract_minutiae(image_bytes)
image_bytes = open("test_data/p1/p1_3.png", "rb").read()
minutiae_3 = extractor.extract_minutiae(image_bytes)

# Compare the two sets of minutiae
score = minutiae_1.compare(minutiae_2)
assert score > 50, "Expected a high similarity score between p1_1 and p1_2"
score = minutiae_1.compare(minutiae_3)
assert score > 50, "Expected a high similarity score between p1_1 and p1_3"
score = minutiae_2.compare(minutiae_3)
assert score > 50, "Expected a high similarity score between p1_2 and p1_3"

# Convert minutiae to ISO/IEC 19794-2:2005 format
iso_template = minutiae_1.to_iso_19794_2_2005()
# Load it back
minutiae_from_iso = extractor.load_iso_19794_2_2005(iso_template)
# Compare the original minutiae with the one loaded from ISO template
for a, b in zip(minutiae_from_iso.get(), minutiae_1.get()):
    assert a.x() == b.x()
    assert a.y() == b.y()
    assert a.angle() == b.angle()
    assert a.kind() == b.kind()
    # Reliability is quantized in the round-trip conversion,
    # so we allow a small margin of error.
    assert abs(a.reliability() - b.reliability()) < 0.1

# Finally we demonstrate loading from a file and comparing a negative match
minutiae_4 = extractor.extract_minutiae_from_image_file("test_data/p2/p2_1.png")
score = minutiae_1.compare(minutiae_4)
assert score < 50, "Expected a low similarity score between p1_1 and p2_1"

# We can access the NFIQ2 quality via:
nfiq2_quality = minutiae_1.quality()
assert nfiq2_quality.score > 50, "Expected a positive NFIQ2 quality score"
```

## Contributing

Contributions are welcome! Please open an issue or submit a pull request on GitHub.

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/Seventh-Sense-Artificial-Intelligence/nbis-rs",
    "name": "nbis-py",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.8",
    "maintainer_email": null,
    "keywords": "fingerprint, nbis, biometrics, rust, uniffi",
    "author": null,
    "author_email": "Varun Chatterji <varun@seventhsense.ai>",
    "download_url": null,
    "platform": null,
    "description": "## NBIS-rs\n\nThis is a Rust/Python binding to the [NIST Biometric Image Software](https://www.nist.gov/services-resources/software/nist-biometric-image-software-nbis) (NBIS) library, which is used for processing biometric images, particularly in the context of fingerprint recognition.\n\nFor convenience, this library also binds to the [NIST Fingerprint Image Quality](https://www.nist.gov/services-resources/software/nfiq-2) (NFIQ) version 2. \n\n## Features\n\n- Bindings to NBIS functions for minutia extraction, matching\n- Exports minutiae templates in ISO/IEC 19794-2:2005 format\n- Matches minutiae templates against each other using the NBIS Bozorth3 algorithm\n- Provides support for NFIQ2 quality assessment\n\n## Installation (Rust)\n\nTo use NBIS-rs, add the following to your `Cargo.toml`:\n\n```toml\n[dependencies]\nnbis-rs = { git = \"https://github.com/Seventh-Sense-Artificial-Intelligence/nbis-rs\", branch = \"main\", version = \"0.1.2\" }\n```\nOr you can run the following command on the terminal of your new rust project:\n\ncargo add nbis-rs --git https://github.com/Seventh-Sense-Artificial-Intelligence/nbis-rs --branch main\n\nRunning the above command will add the above dependency in your Cargo.toml\n\nNow you can use the nbis-rs rust library in your project as mentioned in next section.\n\n## Usage (Rust)\n\nHere's a simple example of how to use NBIS-rs in your project:\n\n```rust\nfn main() -> Result<(), Box<dyn std::error::Error>> {\n    use nbis;\n    use nbis::Minutiae;\n    use nbis::NbisExtractorSettings;\n    // Configuration for the NbisExtractor\n    let settings = NbisExtractorSettings {\n        // No filtering on minutiae quality (all minutiae will be included)\n        min_quality: 0.0,\n        // Do not compute ROI or center to save computing resources\n        get_center: false,\n        // Do not check if the image is a fingerprint using SIVV\n        check_fingerprint: false,\n        // compute the NFIQ score\n        compute_nfiq2: true,\n        // No specific PPI, use the default\n        ppi: None,\n    };\n\n    let extractor = nbis::NbisExtractor::new(settings)?;\n\n    // Read the bytes from a file (you could also use nbis::extract_minutiae_from_image_file)\n    // but here we just load the image bytes as image paths on mobile platforms can be tricky.\n    let image_bytes = std::fs::read(\"test_data/p1/p1_1.png\")?;\n\n    let minutiae_1 = extractor.extract_minutiae(&image_bytes)?;\n\n    let image_bytes = std::fs::read(\"test_data/p1/p1_2.png\")?;\n    let minutiae_2 = extractor.extract_minutiae(&image_bytes)?;\n\n    let image_bytes = std::fs::read(\"test_data/p1/p1_3.png\")?;\n    let minutiae_3 = extractor.extract_minutiae(&image_bytes)?;\n\n    // Compare the two sets of minutiae\n    let score = minutiae_1.compare(&minutiae_2);\n    assert!(score > 35, \"Expected a high similarity score between p1_1 and p1_2\");\n    let score = minutiae_1.compare(&minutiae_3);\n    assert!(score > 35, \"Expected a high similarity score between p1_1 and p1_3\");\n    let score = minutiae_2.compare(&minutiae_3);\n    assert!(score > 35, \"Expected a high similarity score between p1_2 and p1_3\");\n\n    // Next we will demonstrate conversion to ISO/IEC 19794-2:2005 format\n    // and back to a `Minutiae` object.\n    // First, convert the minutiae to ISO template bytes\n    let iso_template: Vec<u8> = minutiae_1.to_iso_19794_2_2005();              \n    // And load it back\n    let minutiae_from_iso = extractor.load_iso_19794_2_2005(&iso_template)?;\n    // Compare the original minutiae with the one loaded from ISO template\n    for (a, b) in minutiae_from_iso.get().iter().zip(minutiae_1.get().iter()) {\n        assert_eq!(a.x(), b.x());\n        assert_eq!(a.y(), b.y());\n        assert_eq!(a.angle(), b.angle());\n        assert_eq!(a.kind(), b.kind());\n        // Reliability is quantized in the round-trip conversion,\n        // so we allow a small margin of error.\n        assert!((a.reliability() - b.reliability()).abs() < 1e-1);\n    }\n\n    // Finally we demonstrate loading from a file and comparing a negative match\n    let minutiae_4 = extractor.extract_minutiae_from_image_file(\"test_data/p2/p2_1.png\")?;\n    let score = minutiae_1.compare(&minutiae_4);\n    assert!(score < 35, \"Expected a low similarity score between p1_1 and p2_1\");\n\n    // We can access the NFIQ2 quality via:\n    let nfiq2_quality = minutiae_1.quality();\n    assert!(nfiq2_quality.score > 50, \"Expected a positive NFIQ2 quality score\");\n\n    Ok(())\n}\n```\n\n## Installation (Python)\nTo install the Python bindings, you can use pip:\n\n```bash\npip install nbis-py\n```\n\n## Usage (Python)\n\nHere's a simple example of how to use the NBIS Python bindings:\n\n```python\nimport nbis\nfrom nbis import NbisExtractor, NbisExtractorSettings\n\n #Configuration for the NbisExtractor\nsettings = NbisExtractorSettings(\n    # Do not filter on minutiae quality (get all minutiae)\n    min_quality=0.0,\n    # Do not get the fingerprint center or ROI\n    get_center=False,\n    # Do not use SIVV to check if the image is a fingerprint\n    check_fingerprint=False,\n    # Compute the NFIQ2 quality score\n    compute_nfiq2=True,\n    # No specific PPI, use the default\n    ppi=None,\n)\n\nextractor = nbis.new_nbis_extractor(settings)\n\n# Read the bytes from a file\nimage_bytes = open(\"test_data/p1/p1_1.png\", \"rb\").read()\nminutiae_1 = extractor.extract_minutiae(image_bytes)\nimage_bytes = open(\"test_data/p1/p1_2.png\", \"rb\").read()\nminutiae_2 = extractor.extract_minutiae(image_bytes)\nimage_bytes = open(\"test_data/p1/p1_3.png\", \"rb\").read()\nminutiae_3 = extractor.extract_minutiae(image_bytes)\n\n# Compare the two sets of minutiae\nscore = minutiae_1.compare(minutiae_2)\nassert score > 50, \"Expected a high similarity score between p1_1 and p1_2\"\nscore = minutiae_1.compare(minutiae_3)\nassert score > 50, \"Expected a high similarity score between p1_1 and p1_3\"\nscore = minutiae_2.compare(minutiae_3)\nassert score > 50, \"Expected a high similarity score between p1_2 and p1_3\"\n\n# Convert minutiae to ISO/IEC 19794-2:2005 format\niso_template = minutiae_1.to_iso_19794_2_2005()\n# Load it back\nminutiae_from_iso = extractor.load_iso_19794_2_2005(iso_template)\n# Compare the original minutiae with the one loaded from ISO template\nfor a, b in zip(minutiae_from_iso.get(), minutiae_1.get()):\n    assert a.x() == b.x()\n    assert a.y() == b.y()\n    assert a.angle() == b.angle()\n    assert a.kind() == b.kind()\n    # Reliability is quantized in the round-trip conversion,\n    # so we allow a small margin of error.\n    assert abs(a.reliability() - b.reliability()) < 0.1\n\n# Finally we demonstrate loading from a file and comparing a negative match\nminutiae_4 = extractor.extract_minutiae_from_image_file(\"test_data/p2/p2_1.png\")\nscore = minutiae_1.compare(minutiae_4)\nassert score < 50, \"Expected a low similarity score between p1_1 and p2_1\"\n\n# We can access the NFIQ2 quality via:\nnfiq2_quality = minutiae_1.quality()\nassert nfiq2_quality.score > 50, \"Expected a positive NFIQ2 quality score\"\n```\n\n## Contributing\n\nContributions are welcome! Please open an issue or submit a pull request on GitHub.\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Python bindings for NBIS fingerprint processing using Rust + UniFFI",
    "version": "0.1.3",
    "project_urls": {
        "Homepage": "https://github.com/Seventh-Sense-Artificial-Intelligence/nbis-rs",
        "Repository": "https://github.com/Seventh-Sense-Artificial-Intelligence/nbis-rs"
    },
    "split_keywords": [
        "fingerprint",
        " nbis",
        " biometrics",
        " rust",
        " uniffi"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "cd725fd14657033ec5ce70e2dd160e760a9c39a12fdff119e1ec169bfef5997e",
                "md5": "199eac4626fee0a532e0dc96173bec98",
                "sha256": "4598c6b7fdabc153ad3262a91194e98845d656b9fae29739195a107d7677726c"
            },
            "downloads": -1,
            "filename": "nbis_py-0.1.3-py3-none-macosx_11_0_arm64.whl",
            "has_sig": false,
            "md5_digest": "199eac4626fee0a532e0dc96173bec98",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 4988964,
            "upload_time": "2025-10-08T07:41:51",
            "upload_time_iso_8601": "2025-10-08T07:41:51.138616Z",
            "url": "https://files.pythonhosted.org/packages/cd/72/5fd14657033ec5ce70e2dd160e760a9c39a12fdff119e1ec169bfef5997e/nbis_py-0.1.3-py3-none-macosx_11_0_arm64.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "54020cb59992a8063a9efcef4f7ceec41549948aba12365193b76ab9bd8551a6",
                "md5": "5456fba67149e9814fa6e636021d7f9b",
                "sha256": "ec934b5cfd3cacdffdee358f3c99e71fff6fcd18c21c4aa0b4d057c3ffaa184c"
            },
            "downloads": -1,
            "filename": "nbis_py-0.1.3-py3-none-manylinux_2_34_x86_64.whl",
            "has_sig": false,
            "md5_digest": "5456fba67149e9814fa6e636021d7f9b",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.8",
            "size": 6400153,
            "upload_time": "2025-10-08T07:41:53",
            "upload_time_iso_8601": "2025-10-08T07:41:53.506158Z",
            "url": "https://files.pythonhosted.org/packages/54/02/0cb59992a8063a9efcef4f7ceec41549948aba12365193b76ab9bd8551a6/nbis_py-0.1.3-py3-none-manylinux_2_34_x86_64.whl",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-10-08 07:41:51",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "Seventh-Sense-Artificial-Intelligence",
    "github_project": "nbis-rs",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "nbis-py"
}
        
Elapsed time: 2.23000s