{"id":19256802,"url":"https://github.com/markmohr/handwriting-number-classification","last_synced_at":"2025-07-27T04:05:20.324Z","repository":{"id":110991214,"uuid":"93976164","full_name":"MarkMoHR/Handwriting-Number-Classification","owner":"MarkMoHR","description":"A computer vision project, based on cimg library and svm training, to classify handwriting number.","archived":false,"fork":false,"pushed_at":"2017-07-22T02:00:18.000Z","size":2672,"stargazers_count":30,"open_issues_count":1,"forks_count":18,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-21T15:40:44.465Z","etag":null,"topics":["cimg","handwriting-numbers","handwritten-digit-recognition","handwritten-text-recognition","svm"],"latest_commit_sha":null,"homepage":"https://blog.csdn.net/qq_33000225/article/details/73123880","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MarkMoHR.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2017-06-11T02:08:01.000Z","updated_at":"2024-11-13T07:17:07.000Z","dependencies_parsed_at":null,"dependency_job_id":"56c9a243-9a69-49fa-a91e-1aeb95b6538b","html_url":"https://github.com/MarkMoHR/Handwriting-Number-Classification","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/MarkMoHR/Handwriting-Number-Classification","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MarkMoHR%2FHandwriting-Number-Classification","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MarkMoHR%2FHandwriting-Number-Classification/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MarkMoHR%2FHandwriting-Number-Classification/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MarkMoHR%2FHandwriting-Number-Classification/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MarkMoHR","download_url":"https://codeload.github.com/MarkMoHR/Handwriting-Number-Classification/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MarkMoHR%2FHandwriting-Number-Classification/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267298467,"owners_count":24065881,"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","status":"online","status_checked_at":"2025-07-27T02:00:11.917Z","response_time":82,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["cimg","handwriting-numbers","handwritten-digit-recognition","handwritten-text-recognition","svm"],"created_at":"2024-11-09T19:07:13.333Z","updated_at":"2025-07-27T04:05:20.318Z","avatar_url":"https://github.com/MarkMoHR.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Handwriting Number Classification\nAn computer vision project, based on cimg library and svm training, to classify handwriting number.\n\n\n## 1. Project Requirement\n### 1.1 Input\n- A photo in which an A4 paper is placed on the desk, with some handwriting numbers on\n### 1.2 Output\n- A string of the numbers written on the paper, like \"70026548853\"\n### 1.3 Intermediate Processes\n- Modify the paper in the photo into a standard A4 paper\n- Implement the segmentation of the numbers, dividing them into single number\n- Use _Adaboost_ or _SVM_ to train a classifier of the handwriting numbers\n- Classify the handwriting numbers with the trained classifier\n\n---\n\n## 2. Coding Environment \u0026 3rd Party Library\n- Windows10 + VS2015\n- C++\n- cimg library : http://www.cimg.eu/\n- opencv (For extracting features of images)\n- libsvm (for training, testing and predicting) : http://www.csie.ntu.edu.tw/~cjlin/libsvm/\n\n---\n\n## 3. Implementation Procedure\n1. Find the 4 vertices of the paper\n1. Modify the paper into a standard A4 paper\n1. Segmentation of the numbers in order:\n    - Convert into binary image\n    - Use vertical histogram to divide the source image into sub-image (each sub-image contains a line of numbers)\n    - Use horizontal histogram to divide the line-sub-image into several row-sub-images\n    - Foreach sub-image, implement dilation to thicken the number (and join the broken ones)\n    - Foreach sub-image, use connected-component_labeling algorithm to divide the single number: \n    https://en.wikipedia.org/wiki/Connected-component_labeling\n    - Foreach sub-image, save all single number images and a list of their name in .txt\n\n1. Use libsvm to train model and test, and predict the number finally\n    - Data prepairing: \n        - convert the mnist(http://yann.lecun.com/exdb/mnist/) binary data into .jpg as well as their labels\n    - Model training: \n        - extract the HOG features of each image and construct them into svm format (in **.txt)\n        - Scale the features(in **.txt) with `svm-scale.exe` (search the _windows/_ folder)\n        - Train the model with `svm-train.exe`, and get **.model\n        - (Optional) Test the data with `svm-predict.exe` and see the accuracy (modify the training parameter to get the highest accuracy)\n    - Number predicting: \n        - read the number images you segmented just now and do prediction with the trained model\n        \n\n---\n\n## 4. Result Screenshots\n- 4 vertices of the paper \u0026 A4 paper modification\n\n![Image text](https://github.com/MarkMoHR/HandwritingNumberClassification/raw/master/ResultScreenshots/1.png)\n- Segmentation of the numbers:\n\n    - Binary image with dilation \u0026 Divided Image \u0026 Circled single number\n    \n    ![Image text](https://github.com/MarkMoHR/HandwritingNumberClassification/raw/master/ResultScreenshots/2.png)\n    ![Image text](https://github.com/MarkMoHR/HandwritingNumberClassification/raw/master/ResultScreenshots/4-DividingImg.png)\n    - Divided into single numbers in order as well as an image list in .txt\n    \n    ![Image text](https://github.com/MarkMoHR/HandwritingNumberClassification/raw/master/ResultScreenshots/imageList.png)\n    - Prediction:\n    \n    ![Image text](https://github.com/MarkMoHR/HandwritingNumberClassification/raw/master/ResultScreenshots/predict.png)\n\n---\n\n## 5. Some key points\n### 5.1 Broken numbers joining\n- Comparison (Before joining \u0026 After joining)\n    \n    ![Image text](https://github.com/MarkMoHR/HandwritingNumberClassification/raw/master/ResultScreenshots/joinTheBrokens.png)\n    \n- Implements : use the filters below when doing the __dilation__ during the number segmentation\n    ![Image text](https://github.com/MarkMoHR/HandwritingNumberClassification/raw/master/ResultScreenshots/filter1.png) (filterA) \n    ![Image text](https://github.com/MarkMoHR/HandwritingNumberClassification/raw/master/ResultScreenshots/filter2.png) (filterB)\n\n    - Do the dilation with filterA __twice__ at first, and then filterB __once__.\n    - _filterB_ means: when at the white pixel, search up/down one pixel and left/right __one__ pixel. If meeting a black pixel, set the current position to black.\n    - _filterA_ means: when at the white pixel, search up/down one pixel and left/right __two__ pixel. Count the blacks with the coefficient, -1 or 1 (-1 means subtract one black when meeting a black at left/right side). At last, only if the blacks more than 0, set the current position to black.\n    - Obviously, _filterB_ is to thicken the number in all directions, leading to the cons that the holes in number 0, 6, 8, 9 with be filled. So I propose another simple but useful filter, the _filterA_, to deal with such problem. It can be seen that the intensity of a white pixel is much relevant to its horizontal neighbors, which prevent hole filling to some extent. Luckily it works well in my experiments.\n    \n---\n\n## 6. Code and Algorithm Explanation\n1. Segmentation of the numbers \u0026 Broken numbers joining : \n    \n    http://blog.csdn.net/qq_33000225/article/details/73123880  (Chinese version)\n1. Prediction: (Waiting......)\n\n---\n\n## 7. Problems left\n1. Some numbers are connected to each other and are segmented together into one image......\n1. From the predict result above, we see that most of the 7s and 9s are classified into 1......\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarkmohr%2Fhandwriting-number-classification","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarkmohr%2Fhandwriting-number-classification","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarkmohr%2Fhandwriting-number-classification/lists"}