{"id":15637618,"url":"https://github.com/karolzak/boxdetect","last_synced_at":"2025-04-07T07:03:10.760Z","repository":{"id":45101341,"uuid":"268776062","full_name":"karolzak/boxdetect","owner":"karolzak","description":"BoxDetect is a Python package based on OpenCV which allows you to easily detect rectangular shapes like character or checkbox boxes on scanned forms.","archived":false,"fork":false,"pushed_at":"2023-01-18T23:27:26.000Z","size":7789,"stargazers_count":109,"open_issues_count":7,"forks_count":20,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-03-31T06:01:36.232Z","etag":null,"topics":["bounding-boxes","box-detection","boxes","checkbox","checkboxes","computer-vision","cv2","documents","forms","handwritten-character-recognition","handwritten-characters","handwritten-documents","handwritten-forms","opencv","opencv-python","rectangle-detection","scanned-documents","scanned-image-pdfs","scanned-images"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/karolzak.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"github":["karolzak"],"patreon":"karolzak","open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2020-06-02T10:55:17.000Z","updated_at":"2025-03-12T15:52:54.000Z","dependencies_parsed_at":"2023-02-10T18:45:24.650Z","dependency_job_id":null,"html_url":"https://github.com/karolzak/boxdetect","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karolzak%2Fboxdetect","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karolzak%2Fboxdetect/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karolzak%2Fboxdetect/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/karolzak%2Fboxdetect/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/karolzak","download_url":"https://codeload.github.com/karolzak/boxdetect/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247608150,"owners_count":20965952,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bounding-boxes","box-detection","boxes","checkbox","checkboxes","computer-vision","cv2","documents","forms","handwritten-character-recognition","handwritten-characters","handwritten-documents","handwritten-forms","opencv","opencv-python","rectangle-detection","scanned-documents","scanned-image-pdfs","scanned-images"],"created_at":"2024-10-03T11:12:18.998Z","updated_at":"2025-04-07T07:03:10.714Z","avatar_url":"https://github.com/karolzak.png","language":"Python","readme":"[![CI Build](https://github.com/karolzak/boxdetect/workflows/CI%20Build/badge.svg)](https://github.com/karolzak/boxdetect/actions?query=workflow%3A%22CI+Build%22)\n[![PyPI - Version](https://img.shields.io/pypi/v/boxdetect.svg \"PyPI version\")](https://pypi.org/project/boxdetect/) \n[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/boxdetect)](https://pypi.org/project/boxdetect/)\n[![Downloads](https://pepy.tech/badge/boxdetect)](https://pepy.tech/project/boxdetect)\n[![Downloads/Month](https://pepy.tech/badge/boxdetect/month)](https://pepy.tech/project/boxdetect/month)\n[![license](https://img.shields.io/github/license/mashape/apistatus.svg?maxAge=2592000)](https://github.com/karolzak/boxdetect/blob/master/LICENSE)\n\n**Share:**  \n[![Twitter URL](https://img.shields.io/twitter/url?url=https%3A%2F%2Fgithub.com%2karolzak%2Fboxdetect)](http://twitter.com/share?text=Check%20out%20BoxDetect%20Python%20package%20which%20helps%20you%20extract%20rectangular%20boxes%20from%20images\u0026url=https://github.com/karolzak/boxdetect/\u0026hashtags=python,computervision,boxesdetection,shapesdetection,opencv)\n[![LinkedIn URL](https://raw.githubusercontent.com/karolzak/boxdetect/master/images/linkedin_share4.png)](http://www.linkedin.com/shareArticle?mini=true\u0026url=https://github.com/karolzak/boxdetect\u0026title=Boxdetect%20python%20package)\n\n\n**BoxDetect** is a Python package based on OpenCV which allows you to easily detect rectangular shapes like character or checkbox boxes on scanned forms.\n\nMain purpose of this library is to provide helpful functions for processing document images like bank forms, applications, etc. and extract regions where character boxes or tick/check boxes are present.\n\n![](https://raw.githubusercontent.com/karolzak/boxdetect/master/images/example1.png)\n\n## Features\n- `boxdetect.pipelines.get_boxes` - basic pipeline for boxes extraction\n- `boxdetect.pipelines.get_checkboxes` - pipeline which returns only the checkboxes with simple estimation of the state (checked/unchecked)\n- `boxdetect.config.PipelinesConfig` - advanced config class used to run pipelines\n- `boxdetect.config.PipelinesConfig.save_yaml/load_yaml` - allows to save and load configs into and from yaml files\n- `boxdetect.config.PipelinesConfig.autoconfigure` - simple mechanism to automatically set config based on box sizes list you're looking for\n- `boxdetect.config.PipelinesConfig.autoconfigure_from_vott` - automatically sets up config based on ground truth/annotation json files from [VoTT](https://github.com/microsoft/VoTT)\n- `boxdetect.img_proc` and `boxdetect.rect_proc` - utility functions which can be used to build custom pipelines\n\n## Getting Started\n\nCheckout [usage examples below](#Usage-examples) to get a better understanding of how it works or go to [get-started-pipelines.ipynb](https://github.com/karolzak/boxdetect/blob/master/notebooks/get-started-pipelines.ipynb) and [get-started-autoconfig.ipynb](https://github.com/karolzak/boxdetect/blob/master/notebooks/get-started-autoconfig.ipynb) notebooks which holds step by step examples for using **BoxDetect** with premade `boxdetect.pipelines` functions.\n\n## Installation\n\n**BoxDetect** can be installed directly from this repo using `pip`:\n\n```\npip install git+https://github.com/karolzak/boxdetect\n```\n\nor through [PyPI](https://pypi.org/project/boxdetect/)\n\n```\npip install boxdetect\n```\n\n# Usage examples\n\nYou can use `BoxDetect` either by leveraging one of the pre-made pipelines or by treating `BoxDetect` functions as your toolbox to compose your own pipelines that fits your needs perfectly.\n\n- [Using pre-made pipelines](#using-boxdetectpipelines)  \n    - [Detecting boxes and grouping them together with `boxdetect.pipelines.get_boxes`](#Detect-character-boxes-and-group-them-together)  \n    - [Changing `group_size_range` param to highlight checkboxes](#highlighting-just-the-checkboxes)  \n    - [Using `boxdetect.pipelines.get_checkboxes` to retrieve checkboxes and their values](#using-boxdetectpipelinesget_checkboxes-to-retrieve-and-recognize-just-the-checkboxes)  \n    - [Using `boxdetect.config.PipelinesConfig.autoconfigure` to setup a config params based on the box sizes list](#using-boxdetectconfigpipelinesconfigautoconfigure-to-quickly-and-easily-setup-a-config-params-based-on-the-box-sizes-list)  \n    - [Using `boxdetect.config.PipelinesConfig.autoconfigure_from_vott` to setup a config params based on the annotated ground truth](#using-boxdetectconfigpipelinesconfigautoconfigure_from_vott-to-quickly-and-easily-setup-a-config-params-based-on-the-annotated-ground-truth)  \n    - [Saving and loading configuration to and from `yaml` files](#Saving-and-loading-configuration-to-and-from-yaml-files)  \n\n\n## Using `boxdetect.pipelines`\n\n### Detect character boxes and group them together\n[[back to usage examples]](#usage-examples)\n\nStart with getting the default `PipelinesConfig` and adjusting it for your requirements and data:\n```python\nfrom boxdetect import config\n\nfile_name = 'form_example1.png'\n\ncfg = config.PipelinesConfig()\n\n# important to adjust these values to match the size of boxes on your image\ncfg.width_range = (30,55)\ncfg.height_range = (25,40)\n\n# the more scaling factors the more accurate the results but also it takes more time to processing\n# too small scaling factor may cause false positives\n# too big scaling factor will take a lot of processing time\ncfg.scaling_factors = [0.7]\n\n# w/h ratio range for boxes/rectangles filtering\ncfg.wh_ratio_range = (0.5, 1.7)\n\n# group_size_range starting from 2 will skip all the groups\n# with a single box detected inside (like checkboxes)\ncfg.group_size_range = (2, 100)\n\n# num of iterations when running dilation tranformation (to engance the image)\ncfg.dilation_iterations = 0\n```\n\nAs a second step simply run:\n```python\nfrom boxdetect.pipelines import get_boxes\n\nrects, grouping_rects, image, output_image = get_boxes(\n    file_name, cfg=cfg, plot=False)\n```\n\nEach of the returned elements in `grouping_rects` are rectangular bounding boxes representing grouped character boxes (x, y, w, h)\n```python\nprint(grouping_rects)\n\nOUT:\n# (x, y, w, h)\n[(276, 276, 1221, 33),\n (324, 466, 430, 33),\n (384, 884, 442, 33),\n (985, 952, 410, 32),\n (779, 1052, 156, 33),\n (253, 1256, 445, 33)]\n```\nDisplay output image with bounding rectangles drawn on it\n```python\nimport matplotlib.pyplot as plt\n\nplt.figure(figsize=(20,20))\nplt.imshow(output_image)\nplt.show()\n```\n\n![](https://raw.githubusercontent.com/karolzak/boxdetect/master/images/example1.png)\n\n### Highlighting just the checkboxes\n[[back to usage examples]](#usage-examples)\n\nAnd if you would like to highlight only the checkboxes you just need to change a single parameter:\n```python\n# limit down the grouping algorithm to just singular boxes (e.g. checkboxes)\ncfg.group_size_range = (1, 1)\n```\n\n![](https://raw.githubusercontent.com/karolzak/boxdetect/master/images/checkbox-example.jpg)\n\n### Using `boxdetect.pipelines.get_checkboxes` to retrieve and recognize just the checkboxes\n[[back to usage examples]](#usage-examples)\n\nAssuming we're using the same image and config is already adjusted ([look above](#Detect-character-boxes-and-group-them-together)) we just need to run:\n\n```python\nfrom boxdetect.pipelines import get_checkboxes\n\ncheckboxes = get_checkboxes(\n    file_path, cfg=cfg, px_threshold=0.1, plot=False, verbose=True)\n```\nIf `verbose=True` it will print out bunch of details of checkboxes being detected and estimation being made about their state:\n```\nProcessing file:  ../images/form_example1.png\n----------------------------------\nnonzero_px_count:  3\nall_px_count:  858\nnonzero_px_count / all_px_count =  0.0034965034965034965\n----------------------------------\n----------------------------------\nnonzero_px_count:  363\nall_px_count:  858\nnonzero_px_count / all_px_count =  0.4230769230769231\n----------------------------------\n```\n\nNow looking into the details of our results:\n```python\nprint(\"Output object type: \", type(checkboxes))\nfor checkbox in checkboxes:\n    print(\"Checkbox bounding rectangle (x,y,width,height): \", checkbox[0])\n    print(\"Result of `contains_pixels` for the checkbox: \", checkbox[1])\n    print(\"Display the cropout of checkbox:\")\n    plt.figure(figsize=(1,1))\n    plt.imshow(checkbox[2])\n    plt.show()\n```\nWe should see the following:\n\n![](https://raw.githubusercontent.com/karolzak/boxdetect/master/images/checkboxes-details.jpg)\n\n\n### Using `boxdetect.config.PipelinesConfig.autoconfigure` to quickly and easily setup a config params based on the box sizes list\n[[back to usage examples]](#usage-examples)\n\nBoxDetect allows you to provide a list of sizes (h, w) of boxes which you are interested in and based on that list it would automatically set up the config to detect those.\n\n```python\nfrom boxdetect import config\n\ncfg = config.PipelinesConfig()\n\n# The values I'm providing below is a list of box sizes I'm interested in and want to focus on\n# [(h, w), (h, w), ...]\ncfg.autoconfigure([(46, 46), (44, 43)])\n```\n\nAnd after doing that you can use any of the `boxdetect.pipelines` functions as bellow:\n\n```python\nfrom boxdetect.pipelines import get_checkboxes\n\ncheckboxes = get_checkboxes(file_path, cfg=cfg, plot=False)\n```\n\n### Using `boxdetect.config.PipelinesConfig.autoconfigure_from_vott` to quickly and easily setup a config params based on the annotated ground truth\n[[back to usage examples]](#usage-examples)\n\nAnother option is to use ground truth annotations from VoTT.  \nCheck VoTT repo and docs on how to create a new project and start labelling your data: https://github.com/microsoft/VoTT\n\nFor this example I used VoTT to label my input image and my VoTT project looks somewhat like that:\n\n![](https://raw.githubusercontent.com/karolzak/boxdetect/master/images/vott1.JPG)\n\nIn principle you only need to mark a single box for each different size however the more boxes you will annotate - the more accurate the results should be.\n\n```python\nfrom boxdetect import config\n\ncfg = config.PipelinesConfig()\n\ncfg.autoconfigure_from_vott(\n    vott_dir=\"../tests/data/autoconfig_simple\", class_tags=[\"box\"])\n```\n\nAnd after doing that you can use any of the `boxdetect.pipelines` functions as bellow:\n\n```python\nfrom boxdetect.pipelines import get_checkboxes\n\ncheckboxes = get_checkboxes(file_path, cfg=cfg, plot=False)\n```\n\n### Saving and loading configuration to and from `yaml` files\n[[back to usage examples]](#usage-examples)\n\nIf you want to save a specific configuration for later reusability or automation purposes you can do so by using `PipelinesConfig` functions: `save_yaml` and `load_yaml` like below:\n\n```python\nfrom boxdetect import config\n\ncfg = config.PipelinesConfig()\ncfg.morph_kernels_thickness = 10\ncfg.save_yaml('test_cfg.yaml')\n\ncfg2.load_yaml('test_cfg.yaml')\n```\n","funding_links":["https://github.com/sponsors/karolzak","https://patreon.com/karolzak"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkarolzak%2Fboxdetect","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkarolzak%2Fboxdetect","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkarolzak%2Fboxdetect/lists"}