├── images ├── cs.jpg ├── car.jpg ├── wally.jpg ├── emboss.jpg ├── kernel.png ├── retina.jpg ├── examples.png ├── gaussian.jpg ├── laplacian.jpg ├── wally_face.jpg ├── wally_mask.jpg ├── car_detection.jpg ├── face_detection.jpg ├── kernel_example.png ├── lamp_counting.png ├── peopleDetection.png └── movement_tracking.png ├── .ipynb_checkpoints ├── OpenCV I - Introduction-checkpoint.ipynb ├── OpenCV II - Image Processing-checkpoint.ipynb ├── OpenCV V - Project Suggestions-checkpoint.ipynb ├── OpenCV IV - Object Detection and Segmentation-checkpoint.ipynb └── OpenCV III - Convolutions, Histogram and Thresholding-checkpoint.ipynb ├── README.md ├── OpenCV V - Project Suggestions.ipynb ├── LICENSE ├── OpenCV IV - Object Detection and Segmentation.ipynb ├── OpenCV I - Introduction.ipynb ├── OpenCV II - Image Processing.ipynb ├── classifiers └── plates.xml └── OpenCV III - Convolutions, Histogram and Thresholding.ipynb /images/cs.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cs-ufrn/minicourse-opencv/HEAD/images/cs.jpg -------------------------------------------------------------------------------- /images/car.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cs-ufrn/minicourse-opencv/HEAD/images/car.jpg -------------------------------------------------------------------------------- /images/wally.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cs-ufrn/minicourse-opencv/HEAD/images/wally.jpg -------------------------------------------------------------------------------- /images/emboss.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cs-ufrn/minicourse-opencv/HEAD/images/emboss.jpg -------------------------------------------------------------------------------- /images/kernel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cs-ufrn/minicourse-opencv/HEAD/images/kernel.png -------------------------------------------------------------------------------- /images/retina.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cs-ufrn/minicourse-opencv/HEAD/images/retina.jpg -------------------------------------------------------------------------------- /images/examples.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cs-ufrn/minicourse-opencv/HEAD/images/examples.png -------------------------------------------------------------------------------- /images/gaussian.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cs-ufrn/minicourse-opencv/HEAD/images/gaussian.jpg -------------------------------------------------------------------------------- /images/laplacian.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cs-ufrn/minicourse-opencv/HEAD/images/laplacian.jpg -------------------------------------------------------------------------------- /images/wally_face.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cs-ufrn/minicourse-opencv/HEAD/images/wally_face.jpg -------------------------------------------------------------------------------- /images/wally_mask.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cs-ufrn/minicourse-opencv/HEAD/images/wally_mask.jpg -------------------------------------------------------------------------------- /images/car_detection.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cs-ufrn/minicourse-opencv/HEAD/images/car_detection.jpg -------------------------------------------------------------------------------- /images/face_detection.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cs-ufrn/minicourse-opencv/HEAD/images/face_detection.jpg -------------------------------------------------------------------------------- /images/kernel_example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cs-ufrn/minicourse-opencv/HEAD/images/kernel_example.png -------------------------------------------------------------------------------- /images/lamp_counting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cs-ufrn/minicourse-opencv/HEAD/images/lamp_counting.png -------------------------------------------------------------------------------- /images/peopleDetection.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cs-ufrn/minicourse-opencv/HEAD/images/peopleDetection.png -------------------------------------------------------------------------------- /images/movement_tracking.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cs-ufrn/minicourse-opencv/HEAD/images/movement_tracking.png -------------------------------------------------------------------------------- /.ipynb_checkpoints/OpenCV I - Introduction-checkpoint.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [], 3 | "metadata": {}, 4 | "nbformat": 4, 5 | "nbformat_minor": 2 6 | } 7 | -------------------------------------------------------------------------------- /.ipynb_checkpoints/OpenCV II - Image Processing-checkpoint.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [], 3 | "metadata": {}, 4 | "nbformat": 4, 5 | "nbformat_minor": 2 6 | } 7 | -------------------------------------------------------------------------------- /.ipynb_checkpoints/OpenCV V - Project Suggestions-checkpoint.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [], 3 | "metadata": {}, 4 | "nbformat": 4, 5 | "nbformat_minor": 2 6 | } 7 | -------------------------------------------------------------------------------- /.ipynb_checkpoints/OpenCV IV - Object Detection and Segmentation-checkpoint.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [], 3 | "metadata": {}, 4 | "nbformat": 4, 5 | "nbformat_minor": 2 6 | } 7 | -------------------------------------------------------------------------------- /.ipynb_checkpoints/OpenCV III - Convolutions, Histogram and Thresholding-checkpoint.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [], 3 | "metadata": {}, 4 | "nbformat": 4, 5 | "nbformat_minor": 2 6 | } 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenCV Minicourse 2 | 3 | OpenCV (Open Source Computer Vision Library) is an open source computer vision and machine learning software library. OpenCV was built to provide a common infrastructure for computer vision applications and to accelerate the use of machine perception in the commercial products. So, here is shown the basic use of OpenCV, focusing on the object recognition task. 4 | 5 | ## Lessons 6 | 7 | ### [Lesson 01 - Introduction](https://github.com/cs-ufrn/minicourse-opencv/blob/master/OpenCV%20I%20-%20Introduction.ipynb) 8 | 9 | This notebook covers the introduction of OpenCV, talking about reading and writing images, color spaces, pixels manipulation and drawing. 10 | 11 | ### [Lesson 02 - Image Processing](https://github.com/cs-ufrn/minicourse-opencv/blob/master/OpenCV%20II%20-%20Image%20Processing.ipynb) 12 | 13 | This notebook shows simple transformations, like cropping, mirroring, rotation and resizing, besides of logic and arithmetic operation and masking. 14 | 15 | ### [Lesson 03 - Intermediate Topics](https://github.com/cs-ufrn/minicourse-opencv/blob/master/OpenCV%20III%20-%20Convolutions%2C%20Histogram%20and%20Thresholding.ipynb) 16 | 17 | This lesson introduce the idea of convolution into images, histograms and thresholding. 18 | 19 | ### [Lesson 04 - Detection and Classification of Objects](https://github.com/cs-ufrn/minicourse-opencv/blob/master/OpenCV%20IV%20-%20Object%20Detection%20and%20Classification.ipynb) 20 | 21 | The last lesson addresses detection of objects using Haar Cascade and the segmentation of objects using adaptive thresholding and connected components. 22 | 23 | ### [Lesson 05 - Project Suggestions](https://github.com/cs-ufrn/minicourse-opencv/blob/master/OpenCV%20V%20-%20Project%20Suggestions.ipynb) 24 | 25 | This notebook has some suggestions of projects to practice. 26 | 27 | ## Authors 28 | 29 | [![Vinicius Campos](https://avatars.githubusercontent.com/vinihcampos?s=100)
Vinicius Campos](https://github.com/vinihcampos) | [![Vitor Greati](https://avatars.githubusercontent.com/greati?s=100)
Vitor Greati](https://github.com/greati) | [![Artur Curinga](https://avatars.githubusercontent.com/arturcuringa?s=100)
Artur Curinga](https://github.com/arturcuringa) 30 | ------------ | ------------- | ------------ 31 | 32 | 33 | ## License 34 | 35 | This project is licensed under the Apache License 2.0 - see the [LICENSE.md](LICENSE) file for details. 36 | -------------------------------------------------------------------------------- /OpenCV V - Project Suggestions.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Project Suggestions\n", 8 | "\n" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "metadata": {}, 14 | "source": [ 15 | "## 1) Face Detection\n", 16 | "\n", 17 | "Using the Haar Cascade and one of the classifiers for faces: **classifiers/haarcascade_frontalface_alt.xml, classifiers/haarcascade_frontalface_alt2.xml, ** and **classifiers/haarcascade_frontalface_default.xml**, try to detect faces of images. \n", 18 | "\n", 19 | "
\n", 20 | "
\n", 21 | " \n", 22 | "
\n", 23 | "
" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": {}, 29 | "source": [ 30 | "## 2) People Detection\n", 31 | "\n", 32 | "Using the Haar Cascade and the classifier **classifiers/haarcascade_fullbody.xml** to detect people in images.\n", 33 | "\n", 34 | "
\n", 35 | "
\n", 36 | " \n", 37 | "
\n", 38 | "
" 39 | ] 40 | }, 41 | { 42 | "cell_type": "markdown", 43 | "metadata": {}, 44 | "source": [ 45 | "## 3) Lamp Counting\n", 46 | "\n", 47 | "Using Thresholding and Connected Components, try to count the number of spots of light in images.\n", 48 | "\n", 49 | "
\n", 50 | "
\n", 51 | " \n", 52 | "
\n", 53 | "
" 54 | ] 55 | }, 56 | { 57 | "cell_type": "markdown", 58 | "metadata": {}, 59 | "source": [ 60 | "## 4) Car Detection\n", 61 | "\n", 62 | "Using the Haar Cascade and the classifier **classifiers/cars.xml** to detect cars in images.\n", 63 | "\n", 64 | "
\n", 65 | "
\n", 66 | " \n", 67 | "
\n", 68 | "
" 69 | ] 70 | }, 71 | { 72 | "cell_type": "markdown", 73 | "metadata": {}, 74 | "source": [ 75 | "## 5) Movement Detection\n", 76 | "\n", 77 | "Using an image base, try to detect some movement, using thresholding and logic operations between images to perform this operation.\n", 78 | "\n", 79 | "
\n", 80 | "
\n", 81 | " \n", 82 | "
\n", 83 | "
" 84 | ] 85 | } 86 | ], 87 | "metadata": { 88 | "kernelspec": { 89 | "display_name": "Python 3", 90 | "language": "python", 91 | "name": "python3" 92 | }, 93 | "language_info": { 94 | "codemirror_mode": { 95 | "name": "ipython", 96 | "version": 3 97 | }, 98 | "file_extension": ".py", 99 | "mimetype": "text/x-python", 100 | "name": "python", 101 | "nbconvert_exporter": "python", 102 | "pygments_lexer": "ipython3", 103 | "version": "3.6.4" 104 | } 105 | }, 106 | "nbformat": 4, 107 | "nbformat_minor": 2 108 | } 109 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /OpenCV IV - Object Detection and Segmentation.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# 1 - Object Detection\n", 8 | "## 1.1) Haar Cascade\n", 9 | "\n", 10 | "The Haar feature-based cascade classifier is an effective object detection method proposed by Viola and Jones. It is a machine learning based approach where a cascade function is trained from a lot of positive and negative images. [1]\n", 11 | "\n", 12 | "Initially, the algorithm needs a lot of positive images and negative images to train the classifier. Then we need to extract features from it. For this, Haar features shown in the below image are used. They are just like our convolutional kernel. Each feature is a single value obtained by subtracting sum of pixels under the white rectangle from sum of pixels under the black rectangle. [1]\n", 13 | "\n", 14 | "
\n", 15 | "
\n", 16 | " \n", 17 | "
Figura 1 - Kind of features [2].
\n", 18 | "
\n", 19 | "
\n", 20 | "\n", 21 | "Instead of applying all features on a window, the features are grouped into different stages of classifiers and applied one-by-one. (Normally the first few stages will contain very many fewer features). If a window fails the first stage, discard it. We don't consider the remaining features on it. If it passes, apply the second stage of features and continue the process.\n", 22 | "\n", 23 | "Now, let's discover how to use this classifier with OpenCV. " 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": null, 29 | "metadata": {}, 30 | "outputs": [], 31 | "source": [ 32 | "# Importing OpenCV library\n", 33 | "import cv2\n", 34 | "\n", 35 | "# Importing library to show our images\n", 36 | "from matplotlib import pyplot as plt\n", 37 | "\n", 38 | "# Importing library to manipulate our images\n", 39 | "import numpy as np\n", 40 | "\n", 41 | "from math import sqrt\n", 42 | "\n", 43 | "# Loading our image\n", 44 | "car = cv2.imread('images/car.jpg')\n", 45 | "car_gray = cv2.cvtColor(car, cv2.COLOR_BGR2GRAY)\n", 46 | "car = cv2.cvtColor(car, cv2.COLOR_BGR2RGB)\n", 47 | "\n", 48 | "# Showing our image\n", 49 | "plt.figure()\n", 50 | "plt.axis(\"off\")\n", 51 | "plt.imshow(car)\n", 52 | "plt.show()" 53 | ] 54 | }, 55 | { 56 | "cell_type": "markdown", 57 | "metadata": {}, 58 | "source": [ 59 | "Initially, we need to load a classifier:\n", 60 | "\n", 61 | "
\n", 62 | " cv2.CascadeClassifier([filename]) → Classifier Object \n", 63 | "
\n", 64 | "\n", 65 | "where:\n", 66 | "\n", 67 | "" 70 | ] 71 | }, 72 | { 73 | "cell_type": "code", 74 | "execution_count": null, 75 | "metadata": {}, 76 | "outputs": [], 77 | "source": [ 78 | "# Loading our classifier\n", 79 | "plates_classifier = cv2.CascadeClassifier('classifiers/plates.xml')" 80 | ] 81 | }, 82 | { 83 | "cell_type": "markdown", 84 | "metadata": {}, 85 | "source": [ 86 | "After that, we should use the following function to try to classify the object: \n", 87 | "\n", 88 | "
\n", 89 | " *name_of_classifier*.detectMultiScale(image[, scaleFactor[, minNeighbors[, flags[, minSize[, maxSize]]]]]) → objects \n", 90 | "
\n", 91 | "\n", 92 | "where:\n", 93 | "\n", 94 | "" 103 | ] 104 | }, 105 | { 106 | "cell_type": "code", 107 | "execution_count": null, 108 | "metadata": {}, 109 | "outputs": [], 110 | "source": [ 111 | "min_width = car.shape[1] * 0.045\n", 112 | "\n", 113 | "# Detecting out plates\n", 114 | "plates = plates_classifier.detectMultiScale(car_gray, 1.1, 4)" 115 | ] 116 | }, 117 | { 118 | "cell_type": "markdown", 119 | "metadata": {}, 120 | "source": [ 121 | "Now, we only need to isolate the rectangles which contain the objects." 122 | ] 123 | }, 124 | { 125 | "cell_type": "code", 126 | "execution_count": null, 127 | "metadata": {}, 128 | "outputs": [], 129 | "source": [ 130 | "# Drawing rects around detected plates\n", 131 | "car_cp = car.copy()\n", 132 | "\n", 133 | "for (x,y,w,h) in plates:\n", 134 | " cv2.rectangle(car_cp,(x,y),(x+w,y+h),(255,0,0),2)\n", 135 | "\n", 136 | "dpi = 100\n", 137 | "height, width = car.shape[:2]\n", 138 | "\n", 139 | "figsize = width / dpi, height / dpi\n", 140 | "\n", 141 | "# Create a figure of the right size with one axes that takes up the full figure\n", 142 | "fig = plt.figure(figsize=figsize)\n", 143 | "plt.axis('off')\n", 144 | "plt.imshow(car_cp)\n", 145 | "plt.show()" 146 | ] 147 | }, 148 | { 149 | "cell_type": "markdown", 150 | "metadata": {}, 151 | "source": [ 152 | "Now, as we already know our ```plates```, we will try to segment the characters of the plates. Now, we have to crop the plates from original image." 153 | ] 154 | }, 155 | { 156 | "cell_type": "code", 157 | "execution_count": null, 158 | "metadata": {}, 159 | "outputs": [], 160 | "source": [ 161 | "# Creating the list to store our plates\n", 162 | "fig_plates = []\n", 163 | "fig_plates_ngray = []\n", 164 | "\n", 165 | "# Adding plates to the list\n", 166 | "for (x,y,w,h) in plates:\n", 167 | " fig_plates.append( car_gray[y : y + h, x : x + w] )\n", 168 | " fig_plates_ngray.append( car[y : y + h, x : x + w] )\n", 169 | "\n", 170 | "# Knowing the plates\n", 171 | "for p in fig_plates:\n", 172 | " plt.figure()\n", 173 | " plt.axis(\"off\")\n", 174 | " plt.imshow(p, cmap='gray')\n", 175 | " plt.show()" 176 | ] 177 | }, 178 | { 179 | "cell_type": "markdown", 180 | "metadata": {}, 181 | "source": [ 182 | "After that, let's to *binarize* the plates using **adaptative thresholding**." 183 | ] 184 | }, 185 | { 186 | "cell_type": "code", 187 | "execution_count": null, 188 | "metadata": {}, 189 | "outputs": [], 190 | "source": [ 191 | "binary_plates = []\n", 192 | "\n", 193 | "for i in range(0, len(fig_plates)):\n", 194 | " binary_plates.append(cv2.adaptiveThreshold(fig_plates[i], 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 17, 5))\n", 195 | "\n", 196 | "for p in binary_plates:\n", 197 | " plt.figure()\n", 198 | " plt.axis(\"off\")\n", 199 | " plt.imshow(p, cmap='gray')\n", 200 | " plt.show()" 201 | ] 202 | }, 203 | { 204 | "cell_type": "markdown", 205 | "metadata": {}, 206 | "source": [ 207 | "# 2 - Segmentation\n", 208 | "## 2.1) Connected components\n", 209 | "\n", 210 | "This is the moment for we segment the letters of the plates, and this operation is possible by the use of connected components analysis. It is an algorithmic application of graph theory, where subsets of connected components are uniquely labeled based on a given heuristic and is used to detect connected regions in binary digital images. [3]\n", 211 | "\n", 212 | "With OpenCV, we can use the following function:\n", 213 | "\n", 214 | "
\n", 215 | " cv2.connectedComponentsWithStats(image, connectivity, type) \n", 216 | "
\n", 217 | "\n", 218 | "where:\n", 219 | "\n", 220 | "" 225 | ] 226 | }, 227 | { 228 | "cell_type": "code", 229 | "execution_count": null, 230 | "metadata": {}, 231 | "outputs": [], 232 | "source": [ 233 | "# Auxiliary function\n", 234 | "def euclidean(p, q):\n", 235 | " if len(p) != len (q):\n", 236 | " return -1\n", 237 | " \n", 238 | " local_sum = 0\n", 239 | " for i in range(0, len(p)):\n", 240 | " local_sum += pow(q[i] - p[i], 2)\n", 241 | " \n", 242 | " return sqrt (local_sum)\n", 243 | "\n", 244 | "# Trying to segment our plates\n", 245 | "for p in range(0, (len(binary_plates) - 1)):\n", 246 | " output = cv2.connectedComponentsWithStats(binary_plates[p], 8, cv2.CV_32S)\n", 247 | " num_labels = output[0]\n", 248 | " labels = output[1]\n", 249 | " stats = output[2]\n", 250 | " \n", 251 | " if num_labels < 7:\n", 252 | " continue\n", 253 | " \n", 254 | " # Filtering by area\n", 255 | " labels_area = []\n", 256 | " \n", 257 | " for label in range(0, num_labels - 1):\n", 258 | " labels_area.append( (stats[label, cv2.CC_STAT_AREA], label) )\n", 259 | " \n", 260 | " labels_area = sorted(labels_area)\n", 261 | " \n", 262 | " # Choosing the 10 biggest\n", 263 | " if len(labels_area) < 10:\n", 264 | " labels_area = [label[1] for label in labels_area]\n", 265 | " else:\n", 266 | " labels_area = [label[1] for label in labels_area[len(labels_area) - 10 : len(labels_area)]]\n", 267 | " \n", 268 | " # Filtering by mean of width \n", 269 | " labels_width = []\n", 270 | " mean_width = 0\n", 271 | " \n", 272 | " for label in labels_area:\n", 273 | " mean_width += stats[label, cv2.CC_STAT_WIDTH]\n", 274 | " labels_width.append( (stats[label, cv2.CC_STAT_WIDTH], label) )\n", 275 | " \n", 276 | " mean_width = mean_width / len(labels_area)\n", 277 | " \n", 278 | " for label in range(0, (len(labels_width) - 1)):\n", 279 | " labels_width[label] = (euclidean([mean_width], [labels_width[label][0]]), labels_width[label][1])\n", 280 | " \n", 281 | " labels_width = sorted(labels_width)\n", 282 | " final_labels = [label[1] for label in labels_width[:7]]\n", 283 | " \n", 284 | " # Drawing the result\n", 285 | " result = fig_plates_ngray[p].copy()\n", 286 | " \n", 287 | " for label in final_labels:\n", 288 | " width = stats[label, cv2.CC_STAT_WIDTH]\n", 289 | " height = stats[label, cv2.CC_STAT_HEIGHT]\n", 290 | " x = stats[label, cv2.CC_STAT_LEFT]\n", 291 | " y = stats[label, cv2.CC_STAT_TOP]\n", 292 | " cv2.rectangle(result,(x,y),(x+width,y+height),(255,0,0),1)\n", 293 | " \n", 294 | " plt.figure()\n", 295 | " plt.axis(\"off\")\n", 296 | " plt.imshow(result)\n", 297 | " plt.show()\n", 298 | " " 299 | ] 300 | }, 301 | { 302 | "cell_type": "markdown", 303 | "metadata": {}, 304 | "source": [ 305 | "# References\n", 306 | "\n", 307 | "[1] OpenCV: Face Detection using Haar Cascades. 2018. OpenCV: Face Detection using Haar Cascades. [ONLINE] Available at: https://docs.opencv.org/3.4.1/d7/d8b/tutorial_py_face_detection.html. [Accessed 04 May 2018].\n", 308 | "\n", 309 | "[2] Cascade Classification — OpenCV 2.4.13.6 documentation. 2018. Cascade Classification — OpenCV 2.4.13.6 documentation. [ONLINE] Available at: https://docs.opencv.org/2.4/modules/objdetect/doc/cascade_classification.html. [Accessed 04 May 2018].\n", 310 | "\n", 311 | "[3] Connected-component labeling - Wikipedia. 2018. Connected-component labeling - Wikipedia. [ONLINE] Available at: https://en.wikipedia.org/wiki/Connected-component_labeling. [Accessed 04 May 2018]." 312 | ] 313 | } 314 | ], 315 | "metadata": { 316 | "kernelspec": { 317 | "display_name": "Python 3", 318 | "language": "python", 319 | "name": "python3" 320 | }, 321 | "language_info": { 322 | "codemirror_mode": { 323 | "name": "ipython", 324 | "version": 3 325 | }, 326 | "file_extension": ".py", 327 | "mimetype": "text/x-python", 328 | "name": "python", 329 | "nbconvert_exporter": "python", 330 | "pygments_lexer": "ipython3", 331 | "version": "3.6.6" 332 | } 333 | }, 334 | "nbformat": 4, 335 | "nbformat_minor": 2 336 | } 337 | -------------------------------------------------------------------------------- /OpenCV I - Introduction.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# OpenCV - Open Source Computer Vision Library" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "OpenCV (Open Source Computer Vision Library) is an open source computer vision and machine learning software library. OpenCV was built to provide a common infrastructure for computer vision applications and to accelerate the use of machine perception in the commercial products. Being a BSD-licensed product, OpenCV makes it easy for businesses to utilize and modify the code. [1]" 15 | ] 16 | }, 17 | { 18 | "cell_type": "code", 19 | "execution_count": null, 20 | "metadata": {}, 21 | "outputs": [], 22 | "source": [ 23 | "# Importing OpenCV library\n", 24 | "import cv2\n", 25 | "\n", 26 | "# Importing library to show our images\n", 27 | "from matplotlib import pyplot as plt\n", 28 | "\n", 29 | "# Importing library to manipulate our images\n", 30 | "import numpy as np" 31 | ] 32 | }, 33 | { 34 | "cell_type": "markdown", 35 | "metadata": {}, 36 | "source": [ 37 | "## 1 - Image representation on computer\n", 38 | "\n", 39 | "
\n", 40 | "
\n", 41 | " \n", 42 | "
Figura 1 - Image representation on computer. Taken from Naushadsblog.
\n", 43 | "
\n", 44 | "
" 45 | ] 46 | }, 47 | { 48 | "cell_type": "markdown", 49 | "metadata": {}, 50 | "source": [ 51 | "## 2 - Reading and showing images" 52 | ] 53 | }, 54 | { 55 | "cell_type": "code", 56 | "execution_count": null, 57 | "metadata": {}, 58 | "outputs": [], 59 | "source": [ 60 | "# Reading our first image (in BGR)\n", 61 | "img = cv2.imread(\"images/cs.jpg\")\n", 62 | "\n", 63 | "# Showing our image\n", 64 | "plt.axis(\"off\")\n", 65 | "plt.imshow(img)\n", 66 | "plt.show()" 67 | ] 68 | }, 69 | { 70 | "cell_type": "code", 71 | "execution_count": null, 72 | "metadata": {}, 73 | "outputs": [], 74 | "source": [ 75 | "# Reading the image in gray\n", 76 | "img = cv2.imread(\"images/cs.jpg\", 0)\n", 77 | "\n", 78 | "# Showing our image\n", 79 | "plt.axis(\"off\")\n", 80 | "plt.imshow(img, cmap='gray')\n", 81 | "plt.show()" 82 | ] 83 | }, 84 | { 85 | "cell_type": "markdown", 86 | "metadata": {}, 87 | "source": [ 88 | "## 3 - Color spaces\n", 89 | "\n", 90 | "The purpose of a color model (also called color space or color system) is to facilitate the specification of colors in some standard, generally accepted way. In essence, a color model is a specification of a coordinate system and a subspace within that system where each color is represented by a single point. [4]\n", 91 | "\n", 92 | "
\n", 93 | "
\n", 94 | " \n", 95 | "
Figura 1 - RGB color space, taken from McNeel Wiki.
\n", 96 | "
\n", 97 | "
\n", 98 | " \n", 99 | "
Figura 2 - HSV color space, taken from Mathworks.
\n", 100 | "
\n", 101 | "
\n", 102 | "\n", 103 | "
\n", 104 | "A color model is an abstract mathematical model describing the way colors can be represented as tuples of numbers (e.g. triples in RGB). [5]\n", 105 | "
\n", 106 | "\n", 107 | "
\n", 108 | "
\n", 109 | " \n", 110 | "
Figura 3 - RGB decomposition of the image. The diagram is taken from Wikiwand.
\n", 111 | "
\n", 112 | "
" 113 | ] 114 | }, 115 | { 116 | "cell_type": "code", 117 | "execution_count": null, 118 | "metadata": {}, 119 | "outputs": [], 120 | "source": [ 121 | "img = cv2.imread(\"images/cs.jpg\")\n", 122 | "\n", 123 | "# Create figure to show original image\n", 124 | "plt.figure()\n", 125 | "plt.axis(\"off\")\n", 126 | "plt.imshow(img)\n", 127 | "plt.show()\n", 128 | "\n", 129 | "# Converting our BGR image to gray\n", 130 | "gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)\n", 131 | "\n", 132 | "# Create figure to show gray image\n", 133 | "plt.figure()\n", 134 | "plt.axis(\"off\")\n", 135 | "plt.imshow(gray_img, cmap='gray')\n", 136 | "plt.show()\n", 137 | "\n", 138 | "# Converting our BGR image to RGB\n", 139 | "rgb_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n", 140 | "\n", 141 | "# Create figure to show RGB image\n", 142 | "plt.figure()\n", 143 | "plt.axis(\"off\")\n", 144 | "plt.imshow(rgb_img)\n", 145 | "plt.show()\n" 146 | ] 147 | }, 148 | { 149 | "cell_type": "markdown", 150 | "metadata": {}, 151 | "source": [ 152 | "## Observation \n", 153 | "\n", 154 | "*If you aren't using jupyter notebook, you don't need use matplotlib to show your images, you may use only the OpenCV to read and show images. For more informations, look the references [2] [3].*\n", 155 | "\n" 156 | ] 157 | }, 158 | { 159 | "cell_type": "markdown", 160 | "metadata": {}, 161 | "source": [ 162 | "## 4 - Getting informations about our images\n", 163 | "### 4.1) Shape of image" 164 | ] 165 | }, 166 | { 167 | "cell_type": "code", 168 | "execution_count": null, 169 | "metadata": {}, 170 | "outputs": [], 171 | "source": [ 172 | "# Discovering the shape of our image\n", 173 | "rows,cols,channels = rgb_img.shape\n", 174 | "\n", 175 | "print(\"Number of rows: \" + str(rows))\n", 176 | "print(\"Number of cols: \" + str(cols))\n", 177 | "print(\"Number of channels: \" + str(channels))" 178 | ] 179 | }, 180 | { 181 | "cell_type": "markdown", 182 | "metadata": {}, 183 | "source": [ 184 | "## 5 - Manipulation of pixels" 185 | ] 186 | }, 187 | { 188 | "cell_type": "code", 189 | "execution_count": null, 190 | "metadata": {}, 191 | "outputs": [], 192 | "source": [ 193 | "# Discovering the values of the channels of pixel (0,0)\n", 194 | "(r, g, b) = img[0, 0]\n", 195 | "print (\"Pixel at (0, 0) - Red: %d, Green: %d, Blue: %d\" % (r, g, b))\n", 196 | "\n", 197 | "other_img = rgb_img.copy();\n", 198 | "\n", 199 | "# Changing the value of some pixels\n", 200 | "for i in range (round(rows/2)):\n", 201 | " for j in range (round(cols/2)):\n", 202 | " other_img[i, j] = (255, 0, 0)\n", 203 | " \n", 204 | "plt.figure()\n", 205 | "plt.axis(\"off\")\n", 206 | "plt.imshow(other_img)\n", 207 | "plt.show()\n", 208 | "\n", 209 | "(r, g, b) = other_img[0, 0]\n", 210 | "print (\"New value of pixel at (0, 0) - Red: %d, Green: %d, Blue: %d\" % (r, g, b))\n", 211 | "\n", 212 | "# It is possible update the values of pixels using ranges\n", 213 | "other_img = rgb_img.copy()\n", 214 | "other_img[0:round(rows/2), 0:round(cols/2) ] = (0, 255, 0)\n", 215 | "\n", 216 | "plt.figure()\n", 217 | "plt.axis(\"off\")\n", 218 | "plt.imshow(other_img)\n", 219 | "plt.show()" 220 | ] 221 | }, 222 | { 223 | "cell_type": "markdown", 224 | "metadata": {}, 225 | "source": [ 226 | "## 6 - Geometric shapes\n", 227 | "### 6.1) Line\n", 228 | "\n", 229 | "To draw a line, it's possible use the following function:\n", 230 | "\n", 231 | "
\n", 232 | "\n", 233 | "
\n", 234 | " cv2.line(img, pt1, pt2, color[, thickness[, lineType[, shift]]]) → img\n", 235 | "
\n", 236 | "\n", 237 | "where:\n", 238 | "\n", 239 | "" 254 | ] 255 | }, 256 | { 257 | "cell_type": "code", 258 | "execution_count": null, 259 | "metadata": {}, 260 | "outputs": [], 261 | "source": [ 262 | "# Create an image to draw a line\n", 263 | "line_img = np.zeros((300, 300, 3), dtype = \"uint8\")\n", 264 | "\n", 265 | "cv2.line(line_img,(0,0),(299,299),(0,255,0))\n", 266 | "\n", 267 | "plt.axis(\"off\")\n", 268 | "plt.imshow(line_img)\n", 269 | "plt.show()" 270 | ] 271 | }, 272 | { 273 | "cell_type": "markdown", 274 | "metadata": {}, 275 | "source": [ 276 | "### 6.2) Rectangle\n", 277 | "\n", 278 | "To draw a rectangle, it's possible use the following function:\n", 279 | "\n", 280 | "
\n", 281 | "\n", 282 | "
\n", 283 | " cv2.rectange(img, pt1, pt2, color[, thickness[, lineType[, shift]]]) → img\n", 284 | "
\n", 285 | "\n", 286 | "where:\n", 287 | "\n", 288 | "" 303 | ] 304 | }, 305 | { 306 | "cell_type": "code", 307 | "execution_count": null, 308 | "metadata": {}, 309 | "outputs": [], 310 | "source": [ 311 | "# Create an image to draw a rectangle\n", 312 | "rect_img = np.zeros((300, 300, 3), dtype = \"uint8\")\n", 313 | "\n", 314 | "# Draw an unfilled rectangle\n", 315 | "cv2.rectangle(rect_img,(10,10),(290,290),(0,255,0), 2)\n", 316 | "\n", 317 | "plt.figure()\n", 318 | "plt.axis(\"off\")\n", 319 | "plt.imshow(rect_img)\n", 320 | "plt.show()\n", 321 | "\n", 322 | "rect_img = np.zeros((300, 300, 3), dtype = \"uint8\")\n", 323 | "\n", 324 | "# Draw a filled rectangle\n", 325 | "cv2.rectangle(rect_img,(10,10),(290,290),(0,255,0), cv2.FILLED)\n", 326 | "\n", 327 | "plt.figure()\n", 328 | "plt.axis(\"off\")\n", 329 | "plt.imshow(rect_img)\n", 330 | "plt.show()" 331 | ] 332 | }, 333 | { 334 | "cell_type": "markdown", 335 | "metadata": {}, 336 | "source": [ 337 | "### 6.3) Circle\n", 338 | "\n", 339 | "To draw a circle, it's possible use the following function:\n", 340 | "\n", 341 | "
\n", 342 | "\n", 343 | "
\n", 344 | " cv2.circle(img, center, radius, color[, thickness[, lineType[, shift]]]) → img\n", 345 | "
\n", 346 | "\n", 347 | "where:\n", 348 | "\n", 349 | "" 364 | ] 365 | }, 366 | { 367 | "cell_type": "code", 368 | "execution_count": null, 369 | "metadata": { 370 | "scrolled": false 371 | }, 372 | "outputs": [], 373 | "source": [ 374 | "# Create an image to draw a circle\n", 375 | "circle_img = np.zeros((300, 300, 3), dtype = \"uint8\")\n", 376 | "\n", 377 | "centerX = 150\n", 378 | "centerY = 150\n", 379 | "\n", 380 | "# Drawing an unfilled circle\n", 381 | "cv2.circle(circle_img, (centerX, centerY), round(centerY/2), (0, 255, 0), 2)\n", 382 | "\n", 383 | "plt.figure()\n", 384 | "plt.axis(\"off\")\n", 385 | "plt.imshow(circle_img)\n", 386 | "plt.show()\n", 387 | "\n", 388 | "# Drawing a filled circle\n", 389 | "cv2.circle(circle_img, (centerX, centerY), round(centerY/2), (0, 255, 0), cv2.FILLED)\n", 390 | "\n", 391 | "plt.figure()\n", 392 | "plt.axis(\"off\")\n", 393 | "plt.imshow(circle_img)\n", 394 | "plt.show()" 395 | ] 396 | }, 397 | { 398 | "cell_type": "markdown", 399 | "metadata": {}, 400 | "source": [ 401 | "### 6.4) Ellipse\n", 402 | "\n", 403 | "To draw an ellipse, it's possible use the following function:\n", 404 | "\n", 405 | "
\n", 406 | "\n", 407 | "
\n", 408 | " cv2.ellipse(img, center, axes, angle, startAngle, endAngle, color[, thickness[, lineType[, shift]]]) → img\n", 409 | "
\n", 410 | "\n", 411 | "where:\n", 412 | "\n", 413 | "" 431 | ] 432 | }, 433 | { 434 | "cell_type": "code", 435 | "execution_count": null, 436 | "metadata": {}, 437 | "outputs": [], 438 | "source": [ 439 | "# Create an image to draw an ellipse\n", 440 | "ellipse_img = np.zeros((300, 300, 3), dtype = \"uint8\")\n", 441 | "\n", 442 | "# Draw an unfilled ellipse\n", 443 | "cv2.ellipse(ellipse_img,(centerX,centerY),(100,100),30,0,300,(255,255,0), 5)\n", 444 | "\n", 445 | "plt.figure()\n", 446 | "plt.axis(\"off\")\n", 447 | "plt.imshow(ellipse_img)\n", 448 | "plt.show()\n", 449 | "\n", 450 | "ellipse_img = np.zeros((300, 300, 3), dtype = \"uint8\")\n", 451 | "\n", 452 | "# Draw a filled ellipse\n", 453 | "cv2.ellipse(ellipse_img,(centerX,centerY),(100,100),30,0,300,(255,255,0), cv2.FILLED)\n", 454 | "\n", 455 | "plt.figure()\n", 456 | "plt.axis(\"off\")\n", 457 | "plt.imshow(ellipse_img)\n", 458 | "plt.show()" 459 | ] 460 | }, 461 | { 462 | "cell_type": "markdown", 463 | "metadata": {}, 464 | "source": [ 465 | "### 6.5) Text\n", 466 | "\n", 467 | "To write a text, it's possible use the following function:\n", 468 | "\n", 469 | "
\n", 470 | "\n", 471 | "
\n", 472 | " cv2.putText(img, text, org, fontFace, fontScale, color[, thickness[, lineType[, bottomLeftOrigin]]]) → img\n", 473 | "
\n", 474 | "\n", 475 | "where:\n", 476 | "\n", 477 | "" 494 | ] 495 | }, 496 | { 497 | "cell_type": "code", 498 | "execution_count": null, 499 | "metadata": {}, 500 | "outputs": [], 501 | "source": [ 502 | "# Create an image to write a text\n", 503 | "text_img = np.zeros((300, 300, 3), dtype = \"uint8\")\n", 504 | "\n", 505 | "# Draw an unfilled ellipse\n", 506 | "cv2.putText(text_img,'Computer Society',(10,160),cv2.FONT_HERSHEY_SIMPLEX,1,(0,255,0),2)\n", 507 | "\n", 508 | "plt.axis(\"off\")\n", 509 | "plt.imshow(text_img)\n", 510 | "plt.show()" 511 | ] 512 | }, 513 | { 514 | "cell_type": "markdown", 515 | "metadata": {}, 516 | "source": [ 517 | "## Referências\n", 518 | "\n", 519 | "[1] OpenCV library. 2018. OpenCV library. [ONLINE] Available at: https://opencv.org/. [Accessed 26 April 2018].\n", 520 | "\n", 521 | "[2] GitHub. 2018. GitHub - Vinihcampos/introducao-opencv: Minicurso de Introdução a Visão Computacional com OpenCV. [ONLINE] Available at: https://github.com/Vinihcampos/introducao-opencv. [Accessed 27 April 2018].\n", 522 | "\n", 523 | "[3] Getting Started with Images — OpenCV 3.0.0-dev documentation. 2018. Getting Started with Images — OpenCV 3.0.0-dev documentation. [ONLINE] Available at: https://docs.opencv.org/3.0-beta/doc/py_tutorials/py_gui/py_image_display/py_image_display.html. [Accessed 27 April 2018].\n", 524 | "\n", 525 | "[4] Gonzalez, Rafael C., and Richard E. Woods. Digital image processing. Upper Saddle River, N.J: Prentice Hall, 2008. Print.\n", 526 | "\n", 527 | "[5] Color space - Wikipedia. 2018. Color space - Wikipedia. [ONLINE] Available at: https://en.wikipedia.org/wiki/Color_space. [Accessed 27 April 2018]." 528 | ] 529 | } 530 | ], 531 | "metadata": { 532 | "kernelspec": { 533 | "display_name": "Python 3", 534 | "language": "python", 535 | "name": "python3" 536 | }, 537 | "language_info": { 538 | "codemirror_mode": { 539 | "name": "ipython", 540 | "version": 3 541 | }, 542 | "file_extension": ".py", 543 | "mimetype": "text/x-python", 544 | "name": "python", 545 | "nbconvert_exporter": "python", 546 | "pygments_lexer": "ipython3", 547 | "version": "3.6.4" 548 | } 549 | }, 550 | "nbformat": 4, 551 | "nbformat_minor": 2 552 | } 553 | -------------------------------------------------------------------------------- /OpenCV II - Image Processing.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# 1 - Image transformation\n", 8 | "\n", 9 | "A function or operator that takes an image as its input and produces an image as its output. Depending on the transform chosen, the input and output images may appear entirely different and have different interpretations [1]. Here we'll see some basic transformations, like: **cropping, flipping, rotation and resizing** [2]." 10 | ] 11 | }, 12 | { 13 | "cell_type": "code", 14 | "execution_count": null, 15 | "metadata": {}, 16 | "outputs": [], 17 | "source": [ 18 | "# Importing OpenCV library\n", 19 | "import cv2\n", 20 | "\n", 21 | "# Importing library to show our images\n", 22 | "from matplotlib import pyplot as plt\n", 23 | "\n", 24 | "# Importing library to manipulate our images\n", 25 | "import numpy as np\n", 26 | "\n", 27 | "# Reading some image\n", 28 | "img = cv2.imread('images/cs.jpg')\n", 29 | "img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n", 30 | "\n", 31 | "# Showing our image\n", 32 | "plt.axis(\"off\")\n", 33 | "plt.imshow(img)\n", 34 | "plt.show()" 35 | ] 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "metadata": {}, 40 | "source": [ 41 | "## 1.1) Cropping\n", 42 | "\n", 43 | "To crop an image in python, it is possible use ranges, like that:\n", 44 | "\n", 45 | "```python\n", 46 | "new_image = image[start_row : end_row, start_col : end_col]\n", 47 | "```" 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": null, 53 | "metadata": {}, 54 | "outputs": [], 55 | "source": [ 56 | "# Cropping our image\n", 57 | "cropped = img[100:210,20:135]\n", 58 | "\n", 59 | "plt.axis(\"off\")\n", 60 | "plt.imshow(cropped)\n", 61 | "plt.show()" 62 | ] 63 | }, 64 | { 65 | "cell_type": "markdown", 66 | "metadata": {}, 67 | "source": [ 68 | "## 1.2) Flipping\n", 69 | "\n", 70 | "The operation of flipping an image vertically is satisfied by a simple matrices multiplication between $A$ and $B$. The matrix $A$ is the image and has dimension $M \\times N$, and $B$ is an **antidiagonal** matrix of *ones*, with dimension $N \\times N$. \n", 71 | "\n", 72 | "$$A_{m,n} = \n", 73 | " \\begin{pmatrix}\n", 74 | " a_{1,1} & a_{1,2} & \\cdots & a_{1,n} \\\\\n", 75 | " a_{2,1} & a_{2,2} & \\cdots & a_{2,n} \\\\\n", 76 | " \\vdots & \\vdots & \\ddots & \\vdots \\\\\n", 77 | " a_{m,1} & a_{m,2} & \\cdots & a_{m,n} \n", 78 | " \\end{pmatrix}, \n", 79 | " B_{n,n} = \n", 80 | " \\begin{pmatrix}\n", 81 | " 0 & 0 & \\cdots & 1 \\\\\n", 82 | " 0 & 0 & \\cdots & 0 \\\\\n", 83 | " \\vdots & \\vdots & \\ddots & \\vdots \\\\\n", 84 | " 1 & 0 & \\cdots & 0 \n", 85 | " \\end{pmatrix}$$\n", 86 | " \n", 87 | " $$A_{m,n} \\times B_{n,n} = \n", 88 | " \\begin{pmatrix}\n", 89 | " a_{1,n} & \\cdots & a_{1,2} & a_{1,1} \\\\\n", 90 | " a_{2,n} & \\cdots & a_{2,2} & a_{2,1} \\\\\n", 91 | " \\vdots & \\vdots & \\ddots & \\vdots \\\\\n", 92 | " a_{m,n} & \\cdots & a_{m,2} & a_{m,1} \n", 93 | " \\end{pmatrix}$$\n", 94 | " \n", 95 | "To apply the operation of flipping an image horizontally, you should invert the position of $A$ and $B$ on multiplication. The matrix $A$ is the image and has dimension $M \\times N$, and $B$ is an **antidiagonal** matrix of *ones*, with dimension $M \\times M$.\n", 96 | "\n", 97 | "$$ B_{m,m} = \n", 98 | " \\begin{pmatrix}\n", 99 | " 0 & 0 & \\cdots & 1 \\\\\n", 100 | " 0 & 0 & \\cdots & 0 \\\\\n", 101 | " \\vdots & \\vdots & \\ddots & \\vdots \\\\\n", 102 | " 1 & 0 & \\cdots & 0 \n", 103 | " \\end{pmatrix}, A_{m,n} = \n", 104 | " \\begin{pmatrix}\n", 105 | " a_{1,1} & a_{1,2} & \\cdots & a_{1,n} \\\\\n", 106 | " a_{2,1} & a_{2,2} & \\cdots & a_{2,n} \\\\\n", 107 | " \\vdots & \\vdots & \\ddots & \\vdots \\\\\n", 108 | " a_{m,1} & a_{m,2} & \\cdots & a_{m,n} \n", 109 | " \\end{pmatrix}$$\n", 110 | " \n", 111 | " $$B_{m,m} \\times A_{m,n} = \n", 112 | " \\begin{pmatrix} \n", 113 | " a_{m,1} & a_{m,2} & \\cdots & a_{m,n} \\\\\n", 114 | " \\vdots & \\vdots & \\ddots & \\vdots \\\\\n", 115 | " a_{2,1} & a_{2,2} & \\cdots & a_{2,n} \\\\\n", 116 | " a_{1,1} & a_{1,2} & \\cdots & a_{1,n} \n", 117 | " \\end{pmatrix}$$\n", 118 | "\n", 119 | "The operation of flipping image on both directions uses three matrices. An **antidiagonal** matrix of *ones* $A$, with dimension $M \\times M$, a matrix $B$ representing the image, with dimension $M \\times N$, and a matrix $C$, also an **antidiagonal** matrix of *ones*, with dimension $N \\times N$. \n", 120 | "\n", 121 | "$$ A_{m,m} = \n", 122 | " \\begin{pmatrix}\n", 123 | " 0 & 0 & \\cdots & 1 \\\\\n", 124 | " 0 & 0 & \\cdots & 0 \\\\\n", 125 | " \\vdots & \\vdots & \\ddots & \\vdots \\\\\n", 126 | " 1 & 0 & \\cdots & 0 \n", 127 | " \\end{pmatrix}, B_{m,n} = \n", 128 | " \\begin{pmatrix}\n", 129 | " a_{1,1} & a_{1,2} & \\cdots & a_{1,n} \\\\\n", 130 | " a_{2,1} & a_{2,2} & \\cdots & a_{2,n} \\\\\n", 131 | " \\vdots & \\vdots & \\ddots & \\vdots \\\\\n", 132 | " a_{m,1} & a_{m,2} & \\cdots & a_{m,n} \n", 133 | " \\end{pmatrix}, C_{n,n} = \n", 134 | " \\begin{pmatrix}\n", 135 | " 0 & 0 & \\cdots & 1 \\\\\n", 136 | " 0 & 0 & \\cdots & 0 \\\\\n", 137 | " \\vdots & \\vdots & \\ddots & \\vdots \\\\\n", 138 | " 1 & 0 & \\cdots & 0 \n", 139 | " \\end{pmatrix}$$\n", 140 | " \n", 141 | " $$A_{m,m} \\times B_{m,n} \\times C_{n,n} = \n", 142 | " \\begin{pmatrix} \n", 143 | " a_{m,n} & \\cdots & a_{m,2} & a_{m,1} \\\\\n", 144 | " \\vdots & \\ddots & \\vdots & \\vdots \\\\\n", 145 | " a_{2,n} & \\cdots & a_{2,2} & a_{2,1} \\\\\n", 146 | " a_{1,n} & \\cdots & a_{1,2} & a_{1,1} \n", 147 | " \\end{pmatrix}$$\n", 148 | "\n", 149 | "With OpenCV, it is possoble to use the following function: \n", 150 | "\n", 151 | "
\n", 152 | " cv2.flip(img, flipCode) → img\n", 153 | "
\n", 154 | "\n", 155 | "where:\n", 156 | "\n", 157 | "" 161 | ] 162 | }, 163 | { 164 | "cell_type": "code", 165 | "execution_count": null, 166 | "metadata": {}, 167 | "outputs": [], 168 | "source": [ 169 | "# vertically inverted image\n", 170 | "v_flipped = cv2.flip(img, 1)\n", 171 | "\n", 172 | "plt.figure()\n", 173 | "plt.axis(\"off\")\n", 174 | "plt.imshow(v_flipped)\n", 175 | "plt.show()\n", 176 | "\n", 177 | "# horizontally inverted image\n", 178 | "h_flipped = cv2.flip(img, 0)\n", 179 | "\n", 180 | "plt.figure()\n", 181 | "plt.axis(\"off\")\n", 182 | "plt.imshow(h_flipped)\n", 183 | "plt.show()\n", 184 | "\n", 185 | "# vertically and horizontally inverted image\n", 186 | "flipped = cv2.flip(img, -1)\n", 187 | "\n", 188 | "plt.figure()\n", 189 | "plt.axis(\"off\")\n", 190 | "plt.imshow(flipped)\n", 191 | "plt.show()" 192 | ] 193 | }, 194 | { 195 | "cell_type": "markdown", 196 | "metadata": {}, 197 | "source": [ 198 | "## 1.3) Rotation\n", 199 | "\n", 200 | "To rotate an image, it is initially necessary to define a rotation center, like that:\n", 201 | "\n", 202 | "
\n", 203 | " cv2.getRotationMatrix2D(center, angle, scale) → retval\n", 204 | "
\n", 205 | "\n", 206 | "where:\n", 207 | "\n", 208 | "\n", 213 | "\n", 214 | "After that, the image must be applied to an affine transformation. \n", 215 | "\n", 216 | "
\n", 217 | " cv2.warpAffine(image, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) → dst\n", 218 | "
\n", 219 | "\n", 220 | "where:\n", 221 | "\n", 222 | "" 230 | ] 231 | }, 232 | { 233 | "cell_type": "code", 234 | "execution_count": null, 235 | "metadata": {}, 236 | "outputs": [], 237 | "source": [ 238 | "# Getting the shape of img\n", 239 | "rows, cols, _ = cropped.shape\n", 240 | "\n", 241 | "# Defining a pointer\n", 242 | "center = (cols / 2, rows / 2)\n", 243 | "\n", 244 | "# Rotation angle\n", 245 | "angle = 90\n", 246 | "\n", 247 | "# Defining rotation center\n", 248 | "rotation_center = cv2.getRotationMatrix2D(center, angle, 1.0)\n", 249 | "\n", 250 | "# Applying affine transformation\n", 251 | "rotated = cv2.warpAffine(cropped, rotation_center, (cols,rows))\n", 252 | "\n", 253 | "plt.axis(\"off\")\n", 254 | "plt.imshow(rotated)\n", 255 | "plt.show()" 256 | ] 257 | }, 258 | { 259 | "cell_type": "markdown", 260 | "metadata": {}, 261 | "source": [ 262 | "## 1.4) Resizing\n", 263 | "\n", 264 | "To realize the resizing of an image, it is possible use the following function:\n", 265 | "\n", 266 | "
\n", 267 | " cv2.resize(image, dsize[, dst[, fx[, fy[, interpolation]]]]) → dst\n", 268 | "
\n", 269 | "\n", 270 | "where:\n", 271 | "\n", 272 | "" 288 | ] 289 | }, 290 | { 291 | "cell_type": "code", 292 | "execution_count": null, 293 | "metadata": {}, 294 | "outputs": [], 295 | "source": [ 296 | "# Shape of image\n", 297 | "rows, cols, _ = img.shape\n", 298 | "\n", 299 | "# Scale factor\n", 300 | "scale = 2\n", 301 | "\n", 302 | "# Scaled image\n", 303 | "scaled = cv2.resize(img, (round(scale * cols), round(scale * rows)))\n", 304 | "\n", 305 | "plt.figure()\n", 306 | "plt.imshow(img)\n", 307 | "plt.show()\n", 308 | "\n", 309 | "plt.figure()\n", 310 | "plt.imshow(scaled)\n", 311 | "plt.show()" 312 | ] 313 | }, 314 | { 315 | "cell_type": "markdown", 316 | "metadata": {}, 317 | "source": [ 318 | "# 2 - Image arithmetic" 319 | ] 320 | }, 321 | { 322 | "cell_type": "code", 323 | "execution_count": null, 324 | "metadata": {}, 325 | "outputs": [], 326 | "source": [ 327 | "# Reading a new image\n", 328 | "wally = cv2.imread('images/wally.jpg')\n", 329 | "wally_gray = cv2.cvtColor(wally, cv2.COLOR_BGR2GRAY)\n", 330 | "wally = cv2.cvtColor(wally, cv2.COLOR_BGR2RGB)\n", 331 | "\n", 332 | "dpi = 100\n", 333 | "height, width, _ = wally.shape\n", 334 | "\n", 335 | "# What size does the figure need to be in inches to fit the image?\n", 336 | "figsize = width / dpi, height / dpi\n", 337 | "\n", 338 | "# Create a figure of the right size with one axes that takes up the full figure\n", 339 | "fig = plt.figure(figsize=figsize)\n", 340 | "plt.axis('off')\n", 341 | "plt.imshow(wally)\n", 342 | "plt.show()\n", 343 | "\n", 344 | "fig = plt.figure(figsize=figsize)\n", 345 | "plt.axis('off')\n", 346 | "plt.imshow(wally_gray, cmap='gray')\n", 347 | "plt.show()" 348 | ] 349 | }, 350 | { 351 | "cell_type": "markdown", 352 | "metadata": {}, 353 | "source": [ 354 | "The image arithmetic involves addition and subtraction between matrices. The OpenCV has native support for these operations, using the following functions: \n", 355 | "\n", 356 | "
\n", 357 | " cv2.add(src1, src2[, dst[, mask[, dtype]]]) → dst
\n", 358 | " cv2.subtract(src1, src2[, dst[, mask[, dtype]]]) → dst\n", 359 | "
\n", 360 | "\n", 361 | "where:\n", 362 | "\n", 363 | "" 370 | ] 371 | }, 372 | { 373 | "cell_type": "code", 374 | "execution_count": null, 375 | "metadata": {}, 376 | "outputs": [], 377 | "source": [ 378 | "# Creating a matrix with same dimension of wally's image\n", 379 | "src2 = np.ones(wally.shape, dtype = \"uint8\") * 100\n", 380 | "\n", 381 | "# Applying the operation of addition\n", 382 | "added = cv2.add(wally, src2)\n", 383 | "\n", 384 | "# Applying the operation of subtraction\n", 385 | "subt = cv2.subtract(wally, src2)\n", 386 | "\n", 387 | "fig = plt.figure(figsize=figsize)\n", 388 | "plt.axis('off')\n", 389 | "plt.imshow(added)\n", 390 | "plt.show()\n", 391 | "\n", 392 | "fig = plt.figure(figsize=figsize)\n", 393 | "plt.axis('off')\n", 394 | "plt.imshow(subt)\n", 395 | "plt.show()" 396 | ] 397 | }, 398 | { 399 | "cell_type": "code", 400 | "execution_count": null, 401 | "metadata": {}, 402 | "outputs": [], 403 | "source": [ 404 | "# Creating a matrix with same dimension of wally's image\n", 405 | "src2_gray = np.ones(wally_gray.shape, dtype = \"uint8\") * 100\n", 406 | "\n", 407 | "# Applying the operation of addition\n", 408 | "added_gray = cv2.add(wally_gray, src2_gray)\n", 409 | "\n", 410 | "# Applying the operation of subtraction\n", 411 | "subt_gray = cv2.subtract(wally_gray, src2_gray)\n", 412 | "\n", 413 | "fig = plt.figure(figsize=figsize)\n", 414 | "plt.axis('off')\n", 415 | "plt.imshow(added_gray, cmap='gray')\n", 416 | "plt.show()\n", 417 | "\n", 418 | "fig = plt.figure(figsize=figsize)\n", 419 | "plt.axis('off')\n", 420 | "plt.imshow(subt_gray, cmap='gray')\n", 421 | "plt.show()" 422 | ] 423 | }, 424 | { 425 | "cell_type": "markdown", 426 | "metadata": {}, 427 | "source": [ 428 | "# 3 - Logic Operations\n", 429 | "\n", 430 | "It is possible combine image using logic operations, and with OpenCV there is a set of functions to apply these operations. \n", 431 | "\n", 432 | "
\n", 433 | "\n", 434 | "
\n", 435 | " cv2.bitwise_and(src1, src2[, dst[, mask]]) → dst
\n", 436 | " cv2.bitwise_or(src1, src2[, dst[, mask]]) → dst
\n", 437 | " cv2.bitwise_xor(src1, src2[, dst[, mask]]) → dst
\n", 438 | " cv2.bitwise_not(src [, dst[, mask]]) → dst\n", 439 | "
\n", 440 | "\n", 441 | "where:\n", 442 | "\n", 443 | "" 450 | ] 451 | }, 452 | { 453 | "cell_type": "code", 454 | "execution_count": null, 455 | "metadata": {}, 456 | "outputs": [], 457 | "source": [ 458 | "# Applying the operation and\n", 459 | "and_image = cv2.bitwise_and(added, subt)\n", 460 | "\n", 461 | "# Applying the operation or\n", 462 | "or_image = cv2.bitwise_or(added, subt)\n", 463 | "\n", 464 | "# Applying the operation xor\n", 465 | "xor_image = cv2.bitwise_xor(added, subt)\n", 466 | "\n", 467 | "# Applying the operation and\n", 468 | "not_image = cv2.bitwise_not(added)\n", 469 | "\n", 470 | "plt.figure()\n", 471 | "plt.axis('off')\n", 472 | "plt.imshow(and_image)\n", 473 | "plt.show()\n", 474 | "\n", 475 | "plt.figure()\n", 476 | "plt.axis('off')\n", 477 | "plt.imshow(or_image)\n", 478 | "plt.show()\n", 479 | "\n", 480 | "plt.figure()\n", 481 | "plt.axis('off')\n", 482 | "plt.imshow(xor_image)\n", 483 | "plt.show()\n", 484 | "\n", 485 | "plt.figure()\n", 486 | "plt.axis('off')\n", 487 | "plt.imshow(not_image)\n", 488 | "plt.show()" 489 | ] 490 | }, 491 | { 492 | "cell_type": "markdown", 493 | "metadata": {}, 494 | "source": [ 495 | "## 3.1) Masking\n", 496 | "\n", 497 | "Masking is a powerful tool in computer vision, that makes the system \"concentrate\" only in specific part of the image. This opertation is realized by the functions showed above, with a mask *(a matrix with same width and height of image, but with only 1 channel and values between 0 and 255)*.\n", 498 | "\n", 499 | "Now, let's find **Wally**." 500 | ] 501 | }, 502 | { 503 | "cell_type": "code", 504 | "execution_count": null, 505 | "metadata": {}, 506 | "outputs": [], 507 | "source": [ 508 | "fig = plt.figure(figsize=figsize)\n", 509 | "plt.axis('off')\n", 510 | "plt.imshow(wally)\n", 511 | "plt.show()" 512 | ] 513 | }, 514 | { 515 | "cell_type": "code", 516 | "execution_count": null, 517 | "metadata": {}, 518 | "outputs": [], 519 | "source": [ 520 | "# Reading our mask\n", 521 | "wally_mask = cv2.imread('images/wally_mask.jpg', 0)\n", 522 | "\n", 523 | "# Masking\n", 524 | "wally_pos = cv2.bitwise_and(wally, wally, mask = wally_mask)\n", 525 | "\n", 526 | "# Where is Wally?\n", 527 | "fig = plt.figure(figsize=figsize)\n", 528 | "plt.axis('off')\n", 529 | "plt.imshow(wally_pos)\n", 530 | "plt.show()" 531 | ] 532 | }, 533 | { 534 | "cell_type": "markdown", 535 | "metadata": {}, 536 | "source": [ 537 | "# References\n", 538 | "\n", 539 | "[1] Ted Dejony. 2018. image transformation. [ONLINE] Available at: http://www.timbercon.com/image-transformation.shtml. [Accessed 29 April 2018].\n", 540 | "\n", 541 | "[2] Operations on Arrays — OpenCV 3.0.0-dev documentation. 2018. Operations on Arrays — OpenCV 3.0.0-dev documentation. [ONLINE] Available at: https://docs.opencv.org/3.0-beta/modules/core/doc/operations_on_arrays.html. [Accessed 30 April 2018]." 542 | ] 543 | } 544 | ], 545 | "metadata": { 546 | "kernelspec": { 547 | "display_name": "Python 3", 548 | "language": "python", 549 | "name": "python3" 550 | }, 551 | "language_info": { 552 | "codemirror_mode": { 553 | "name": "ipython", 554 | "version": 3 555 | }, 556 | "file_extension": ".py", 557 | "mimetype": "text/x-python", 558 | "name": "python", 559 | "nbconvert_exporter": "python", 560 | "pygments_lexer": "ipython3", 561 | "version": "3.6.4" 562 | } 563 | }, 564 | "nbformat": 4, 565 | "nbformat_minor": 2 566 | } 567 | -------------------------------------------------------------------------------- /classifiers/plates.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | BOOST 5 | LBP 6 | 14 7 | 42 8 | 9 | GAB 10 | 9.9500000476837158e-001 11 | 4.4999998807907104e-001 12 | 9.4999999999999996e-001 13 | 1 14 | 100 15 | 16 | 256 17 | 1 18 | 12 19 | 20 | 21 | <_> 22 | 3 23 | -8.2853245735168457e-001 24 | 25 | <_> 26 | 27 | 0 -1 37 285216984 -583724588 1359073759 -585301731 28 | -1207919366 -4685672 -1744271105 -1693972344 29 | 30 | -8.2473558187484741e-001 7.9090112447738647e-001 31 | <_> 32 | 33 | 0 -1 23 269504592 -707788396 419500415 2132086785 34 | -2138529618 -1164967776 402655407 -1960181752 35 | 36 | -7.4675083160400391e-001 7.1070402860641479e-001 37 | <_> 38 | 39 | 0 -1 39 -202378098 -251670049 -1903268086 -537928017 40 | -1263013447 -252423748 -272171121 -572523877 41 | 42 | -6.7105877399444580e-001 7.4295401573181152e-001 43 | 44 | <_> 45 | 3 46 | -8.1748569011688232e-001 47 | 48 | <_> 49 | 50 | 0 -1 17 287364601 -584025864 -720897 -537571911 -1117732865 51 | -1073948680 1069072383 -1081602328 52 | 53 | -7.6333057880401611e-001 8.1242781877517700e-001 54 | <_> 55 | 56 | 0 -1 31 -203434240 -2121399 352571791 -134749749 -3556389 57 | -360480633 -1198814209 13625999 58 | 59 | -7.8441995382308960e-001 6.5391725301742554e-001 60 | <_> 61 | 62 | 0 -1 15 285250768 -1657798636 152180093 420675585 63 | -1207926532 -8257400 419960987 -1148256087 64 | 65 | -6.5546298027038574e-001 7.3026490211486816e-001 66 | 67 | <_> 68 | 6 69 | -1.3338762521743774e+000 70 | 71 | <_> 72 | 73 | 0 -1 16 -581922373 -572703591 1025064957 -42623043 74 | -587923713 -204836 -1646481409 -1651654770 75 | 76 | -6.9488149881362915e-001 7.8489482402801514e-001 77 | <_> 78 | 79 | 0 -1 39 -100663297 -201985617 -7361009 -67108881 -138543185 80 | 1106571701 -11538609 -134221109 81 | 82 | -5.4936617612838745e-001 8.1860017776489258e-001 83 | <_> 84 | 85 | 0 -1 54 356516348 1431327064 337204735 2138898649 86 | -2004301634 -1081597799 218630399 -1196418592 87 | 88 | -7.7375411987304688e-001 5.7966601848602295e-001 89 | <_> 90 | 91 | 0 -1 55 -200875316 -209338238 139778 -249847670 -1269438517 92 | 8659008 -1572371798 -213966709 93 | 94 | -6.1659812927246094e-001 6.5415656566619873e-001 95 | <_> 96 | 97 | 0 -1 10 -6450 -122097666 -553865708 951648254 1878088704 98 | 1291608053 2147118876 -1 99 | 100 | -5.5839419364929199e-001 6.7460024356842041e-001 101 | <_> 102 | 103 | 0 -1 59 -229644094 -740913019 402653736 1595499402 104 | 1629027160 537135104 -339090710 1376477103 105 | 106 | -6.9653308391571045e-001 5.0569772720336914e-001 107 | 108 | <_> 109 | 6 110 | -1.3329070806503296e+000 111 | 112 | <_> 113 | 114 | 0 -1 38 -17 -235014145 -273698930 -1 -655361 -252578305 115 | -1048689 -1 116 | 117 | -6.2613362073898315e-001 8.3587586879730225e-001 118 | <_> 119 | 120 | 0 -1 1 -822088017 -1494220817 -286627166 -521146870 121 | -438311098 1148141431 2004874787 -452986937 122 | 123 | -6.2483572959899902e-001 7.0758932828903198e-001 124 | <_> 125 | 126 | 0 -1 19 1433731065 1567710713 -33685505 -4358209 -1073954819 127 | -745475 -409601 -1080029252 128 | 129 | -5.6460815668106079e-001 6.4405161142349243e-001 130 | <_> 131 | 132 | 0 -1 72 -289409534 572709774 -2136751520 -1605438470 133 | 1541534464 538170499 1653335808 -521666585 134 | 135 | -5.9405732154846191e-001 5.3030282258987427e-001 136 | <_> 137 | 138 | 0 -1 47 284718389 1442395637 -1181229569 -4235459 139 | -1466270465 -4196097 -71385857 -1733811012 140 | 141 | -5.5647981166839600e-001 5.8203917741775513e-001 142 | <_> 143 | 144 | 0 -1 30 1081598594 1419768706 -1017120245 -83364286 145 | -389044566 -467664864 -1068501878 -800590846 146 | 147 | -5.8518677949905396e-001 4.9468857049942017e-001 148 | 149 | <_> 150 | 6 151 | -1.2980090379714966e+000 152 | 153 | <_> 154 | 155 | 0 -1 69 -184550649 -8913025 -50331649 -201326593 -18874625 156 | -32897 -218103829 -520093713 157 | 158 | -5.9198069572448730e-001 7.8156101703643799e-001 159 | <_> 160 | 161 | 0 -1 46 -2097153 -788860673 1309495053 -974139641 -252709717 162 | -789389193 1996738051 -33 163 | 164 | -5.4641300439834595e-001 6.8572372198104858e-001 165 | <_> 166 | 167 | 0 -1 14 21242301 -539159755 -1122222113 -2280651 -36897815 168 | -73606052 -79118609 -3630132 169 | 170 | -6.3102430105209351e-001 5.3388547897338867e-001 171 | <_> 172 | 173 | 0 -1 74 -339745273 1137177294 -532159998 -2139162777 174 | -149423358 -449095354 -272110076 -218628233 175 | 176 | -5.4400163888931274e-001 5.3200685977935791e-001 177 | <_> 178 | 179 | 0 -1 42 1030755448 -1073872995 -69569291 -4501512 968236024 180 | -16486 -541393926 -1145553976 181 | 182 | -7.3628991842269897e-001 4.0775153040885925e-001 183 | <_> 184 | 185 | 0 -1 53 -521673725 -9447329 2147450855 -134217929 -457195601 186 | -671622077 -872415777 -1073233405 187 | 188 | -4.6834933757781982e-001 6.1143130064010620e-001 189 | 190 | <_> 191 | 6 192 | -1.4600841999053955e+000 193 | 194 | <_> 195 | 196 | 0 -1 40 -2 -71436289 -1081374964 -17409 -132129 -252646597 197 | -9249 -131073 198 | 199 | -7.0482200384140015e-001 6.1317390203475952e-001 200 | <_> 201 | 202 | 0 -1 27 1431568351 1977614335 2144862207 2013231039 203 | -419434578 -4370 -16848146 -67114870 204 | 205 | -5.3594231605529785e-001 6.7189788818359375e-001 206 | <_> 207 | 208 | 0 -1 3 -286265553 -288883729 -274870686 -353375034 209 | 2045506919 1690041199 2147481445 -1048761 210 | 211 | -5.9768378734588623e-001 5.4696100950241089e-001 212 | <_> 213 | 214 | 0 -1 4 -134545410 -5703686 -71540238 -1349334278 1580745724 215 | 1308117213 1202520827 1308512223 216 | 217 | -7.4109089374542236e-001 3.6831066012382507e-001 218 | <_> 219 | 220 | 0 -1 44 425729245 -8972291 -38019073 -164417 -1079459842 221 | -67200001 -1143324737 -1092082948 222 | 223 | -5.6800931692123413e-001 5.0094425678253174e-001 224 | <_> 225 | 226 | 0 -1 71 -66 990687228 -67125972 1069285308 -50332163 227 | 1044315645 -2571 -41943041 228 | 229 | -4.9089109897613525e-001 5.5790531635284424e-001 230 | 231 | <_> 232 | 8 233 | -1.3831173181533813e+000 234 | 235 | <_> 236 | 237 | 0 -1 11 -681731073 -2246209 -1208139777 -2752580 -37879809 238 | -196643 -572661761 -1075970081 239 | 240 | -5.6764817237854004e-001 7.4003648757934570e-001 241 | <_> 242 | 243 | 0 -1 43 -1057 -754982214 168807941 -1919979961 -253496143 244 | -252514096 -553126561 -68157441 245 | 246 | -5.1411336660385132e-001 6.2704712152481079e-001 247 | <_> 248 | 249 | 0 -1 29 -1349907204 -4903014 -1075574785 -5235820 -105006081 250 | -33809443 -475201 -22496840 251 | 252 | -6.5674120187759399e-001 4.4796296954154968e-001 253 | <_> 254 | 255 | 0 -1 49 -1065900489 -1052761 -268435457 -1 -10273 -2177 256 | -524289 -9181689 257 | 258 | -4.3221050500869751e-001 6.1747372150421143e-001 259 | <_> 260 | 261 | 0 -1 75 -217 -1347420177 -608282330 -487605129 1910499078 262 | 1131571950 -3179776 -523763714 263 | 264 | -5.8398228883743286e-001 4.1473022103309631e-001 265 | <_> 266 | 267 | 0 -1 51 259264536 -1149902853 -753876995 2143254457 268 | -645378568 -5314406 -1080132867 -1078428268 269 | 270 | -7.3157382011413574e-001 3.2581529021263123e-001 271 | <_> 272 | 273 | 0 -1 33 -1069030909 -905977946 -8913185 -1710847 -805331457 274 | -327790 -473968641 -1067981309 275 | 276 | -4.4401237368583679e-001 5.3910166025161743e-001 277 | <_> 278 | 279 | 0 -1 8 -421008670 -279056550 -464391041 -539758432 280 | 1303335486 -353672409 1890057173 -195561501 281 | 282 | -4.8434647917747498e-001 4.7722080349922180e-001 283 | 284 | <_> 285 | 7 286 | -1.0721565485000610e+000 287 | 288 | <_> 289 | 290 | 0 -1 15 -13041667 -294913 1060863999 1067139069 -15409924 291 | -8707 -546505217 -9761 292 | 293 | -5.3846156597137451e-001 7.8067737817764282e-001 294 | <_> 295 | 296 | 0 -1 67 -4 1058889181 -1109576068 1061024607 -630597636 297 | 990968873 -338232644 2139094975 298 | 299 | -6.1439883708953857e-001 5.0837707519531250e-001 300 | <_> 301 | 302 | 0 -1 21 1556954559 -44715049 1066999807 -34212897 -60490753 303 | -121838855 -590770181 1561712573 304 | 305 | -5.5671542882919312e-001 4.9533960223197937e-001 306 | <_> 307 | 308 | 0 -1 2 -421007634 -415770121 -15217666 -18423610 -739772201 309 | -1757702077 -138678277 2004318023 310 | 311 | -6.7898088693618774e-001 3.6057698726654053e-001 312 | <_> 313 | 314 | 0 -1 56 1084745218 -134237397 1132975563 -3672349 -133303569 315 | -84217206 -353381665 -1064833534 316 | 317 | -5.1906722784042358e-001 4.4790410995483398e-001 318 | <_> 319 | 320 | 0 -1 6 -12594 1985637327 -157620114 -386470066 -606119323 321 | 2111261223 -439408252 -168362257 322 | 323 | -5.6427675485610962e-001 4.1696536540985107e-001 324 | <_> 325 | 326 | 0 -1 18 287069429 1540717769 1504826367 -1082829027 327 | -56821761 -606297447 1049934591 -1620034247 328 | 329 | -5.8802723884582520e-001 3.9574873447418213e-001 330 | 331 | <_> 332 | 8 333 | -1.2750341892242432e+000 334 | 335 | <_> 336 | 337 | 0 -1 13 -8913413 -7012417 1060835131 2147041247 -589500419 338 | -587924228 -572588033 -536871425 339 | 340 | -5.0236552953720093e-001 7.6100629568099976e-001 341 | <_> 342 | 343 | 0 -1 41 -202381393 -242227537 -542398705 -173409041 344 | -771758709 -253364561 -80740469 -168428577 345 | 346 | -5.4317152500152588e-001 5.6954395771026611e-001 347 | <_> 348 | 349 | 0 -1 24 1087881455 2113665003 -210894853 2146828223 350 | -1140851282 -18 -890437942 -4461558 351 | 352 | -4.7311496734619141e-001 5.2226537466049194e-001 353 | <_> 354 | 355 | 0 -1 61 -16387 939276280 -1283703044 2143205076 -280183363 356 | 1034435276 1050948600 -35 357 | 358 | -4.6256715059280396e-001 4.9628910422325134e-001 359 | <_> 360 | 361 | 0 -1 26 171050035 -1221456399 -539869197 -1087169504 362 | -1922552099 -1361411 -281382437 -1410185933 363 | 364 | -5.3890913724899292e-001 3.8419398665428162e-001 365 | <_> 366 | 367 | 0 -1 73 -6137 1120918271 -1368794106 -2144358409 -83927551 368 | 1401633275 -775965916 -788529194 369 | 370 | -5.3902828693389893e-001 4.4206458330154419e-001 371 | <_> 372 | 373 | 0 -1 63 -1951234380 -1614915876 1698200827 2145161916 374 | -1355301121 -1141135941 -1145373697 -1074133536 375 | 376 | -5.5798375606536865e-001 3.4880429506301880e-001 377 | <_> 378 | 379 | 0 -1 70 -520096505 1984419111 -460858761 -1832389703 380 | -234095242 -1409595137 -366286102 -2131758089 381 | 382 | -4.5353689789772034e-001 4.7646188735961914e-001 383 | 384 | <_> 385 | 8 386 | -1.1843473911285400e+000 387 | 388 | <_> 389 | 390 | 0 -1 22 -88539393 -2622473 -67436545 -1078223497 -8694275 391 | -388 -276869121 -172161 392 | 393 | -5.0693207979202271e-001 7.3959207534790039e-001 394 | <_> 395 | 396 | 0 -1 62 1382277871 -134223894 -1093669 -789270 2012932831 397 | -10771222 -878706965 -3153270 398 | 399 | -4.2572146654129028e-001 6.5866845846176147e-001 400 | <_> 401 | 402 | 0 -1 46 -84936133 -799817490 201575681 -934553081 -730335557 403 | -1070448605 1359418891 -537919653 404 | 405 | -5.4319930076599121e-001 4.7171792387962341e-001 406 | <_> 407 | 408 | 0 -1 25 1585000699 -111330383 303305717 2078094325 409 | -1344488514 -1086581044 847298555 -215041 410 | 411 | -4.5561578869819641e-001 4.9395501613616943e-001 412 | <_> 413 | 414 | 0 -1 36 -735850437 -5548997 -170426689 -41427919 -722534981 415 | -56665225 -794167809 -637809441 416 | 417 | -3.9095941185951233e-001 6.1021536588668823e-001 418 | <_> 419 | 420 | 0 -1 65 201339189 -109363211 -131585 1601142655 -536940609 421 | -8880131 -1428402450 -1165357912 422 | 423 | -4.4847896695137024e-001 4.8076605796813965e-001 424 | <_> 425 | 426 | 0 -1 34 -1024463798 -67440058 1412853760 -1292148966 427 | -357569761 1109114946 -235150709 1395639042 428 | 429 | -5.9451353549957275e-001 3.2721316814422607e-001 430 | <_> 431 | 432 | 0 -1 66 -252447488 -686295729 -774513665 -2108929 -876294680 433 | -1888788333 -2067312392 1355546591 434 | 435 | -5.9371763467788696e-001 3.0977559089660645e-001 436 | 437 | <_> 438 | 9 439 | -1.7721819877624512e+000 440 | 441 | <_> 442 | 443 | 0 -1 52 1364590559 -6488196 2071953407 -304133 -4210689 444 | -16973858 -69222721 -318838 445 | 446 | -5.0053322315216064e-001 7.2953337430953979e-001 447 | <_> 448 | 449 | 0 -1 9 -1346390051 -1153975463 -168044545 -1073760400 450 | -603979812 -71570664 -78774824 -3146535 451 | 452 | -4.7651672363281250e-001 5.5323666334152222e-001 453 | <_> 454 | 455 | 0 -1 48 -1073492989 -624955969 -629407821 -277350569 456 | -367002093 -1881174853 -370159189 1526981123 457 | 458 | -5.3586703538894653e-001 4.3482360243797302e-001 459 | <_> 460 | 461 | 0 -1 7 -268514049 -2182498 -557921026 -1143833520 1337869053 462 | 1595298893 -6356993 -1409037 463 | 464 | -4.6753937005996704e-001 4.7871547937393188e-001 465 | <_> 466 | 467 | 0 -1 28 -4224337 -3210241 -1491399617 -177201 -1666217729 468 | -188466456 -37118977 -570621953 469 | 470 | -4.5714759826660156e-001 4.2808809876441956e-001 471 | <_> 472 | 473 | 0 -1 68 937426204 1025373468 -1189126255 2138821591 474 | -1700284228 -1216642872 -1158053604 805297404 475 | 476 | -5.4907804727554321e-001 3.8489469885826111e-001 477 | <_> 478 | 479 | 0 -1 0 -288366334 -825757274 -460792322 -291581722 480 | 1170695122 -884364 -415762442 -227019529 481 | 482 | -6.1079239845275879e-001 2.9559111595153809e-001 483 | <_> 484 | 485 | 0 -1 58 -540048250 322173639 -634957345 -679614881 -82855217 486 | -664080198 -945776257 1431534827 487 | 488 | -4.9022802710533142e-001 4.0082153677940369e-001 489 | <_> 490 | 491 | 0 -1 35 78730549 488199256 1405345655 1971282205 -1734690372 492 | -1398044024 700103675 -1735738837 493 | 494 | -4.9552637338638306e-001 3.6625802516937256e-001 495 | 496 | <_> 497 | 9 498 | -1.6782010793685913e+000 499 | 500 | <_> 501 | 502 | 0 -1 45 -218370049 -31505 -8193 -1110514 -797769730 -2049 503 | -11010053 -8433 504 | 505 | -4.4659072160720825e-001 7.9415500164031982e-001 506 | <_> 507 | 508 | 0 -1 12 -203689238 -11411516 395785395 905899519 -946933521 509 | 1479650435 1101129199 1468004095 510 | 511 | -5.4474192857742310e-001 4.7251713275909424e-001 512 | <_> 513 | 514 | 0 -1 20 -496508273 -1048657 -4097 2146957074 -553652225 515 | -65713 -17 -179837374 516 | 517 | -3.9359572529792786e-001 5.4971671104431152e-001 518 | <_> 519 | 520 | 0 -1 60 1358984660 -1210300454 404051839 -545474884 521 | 567032571 -1093952574 781125119 -5567960 522 | 523 | -4.8279407620429993e-001 4.3091443181037903e-001 524 | <_> 525 | 526 | 0 -1 57 1426068991 1601467897 992870367 2145386399 527 | 2038484222 -71778387 -341114881 -585061027 528 | 529 | -5.4100221395492554e-001 3.2671278715133667e-001 530 | <_> 531 | 532 | 0 -1 5 -35655857 1692374991 -453645532 -867243825 2042613767 533 | -467932117 -1149248511 -184552449 534 | 535 | -5.2549248933792114e-001 4.0258836746215820e-001 536 | <_> 537 | 538 | 0 -1 32 1342691326 1475291005 -1055105 1073430447 -538386740 539 | -1048577 -270038549 -68424022 540 | 541 | -3.8929802179336548e-001 4.6440866589546204e-001 542 | <_> 543 | 544 | 0 -1 50 2071425138 166474750 2007511288 1015435772 545 | -743868420 449328296 323123188 1875607550 546 | 547 | -6.6830915212631226e-001 2.5718382000923157e-001 548 | <_> 549 | 550 | 0 -1 64 -198224875 2014237438 1368741745 823456091 -9455171 551 | -268766785 -760679910 -1970341089 552 | 553 | -4.3688443303108215e-001 3.7087124586105347e-001 554 | 555 | <_> 556 | 557 | 0 2 2 2 558 | <_> 559 | 560 | 0 3 1 2 561 | <_> 562 | 563 | 0 3 3 2 564 | <_> 565 | 566 | 0 4 1 1 567 | <_> 568 | 569 | 0 5 3 3 570 | <_> 571 | 572 | 0 7 1 1 573 | <_> 574 | 575 | 0 7 1 2 576 | <_> 577 | 578 | 0 10 2 1 579 | <_> 580 | 581 | 1 1 2 3 582 | <_> 583 | 584 | 1 1 9 2 585 | <_> 586 | 587 | 1 5 1 3 588 | <_> 589 | 590 | 2 1 12 2 591 | <_> 592 | 593 | 2 2 13 1 594 | <_> 595 | 596 | 2 3 12 1 597 | <_> 598 | 599 | 3 0 12 3 600 | <_> 601 | 602 | 3 3 9 1 603 | <_> 604 | 605 | 4 1 12 2 606 | <_> 607 | 608 | 4 11 7 1 609 | <_> 610 | 611 | 6 11 4 1 612 | <_> 613 | 614 | 6 11 5 1 615 | <_> 616 | 617 | 7 1 1 3 618 | <_> 619 | 620 | 7 1 11 2 621 | <_> 622 | 623 | 7 2 6 1 624 | <_> 625 | 626 | 7 4 10 1 627 | <_> 628 | 629 | 8 2 7 3 630 | <_> 631 | 632 | 8 8 3 2 633 | <_> 634 | 635 | 9 1 5 1 636 | <_> 637 | 638 | 9 3 6 2 639 | <_> 640 | 641 | 10 7 6 2 642 | <_> 643 | 644 | 10 10 6 1 645 | <_> 646 | 647 | 11 1 1 3 648 | <_> 649 | 650 | 11 2 3 3 651 | <_> 652 | 653 | 11 4 5 1 654 | <_> 655 | 656 | 12 1 1 3 657 | <_> 658 | 659 | 12 4 1 2 660 | <_> 661 | 662 | 13 0 9 1 663 | <_> 664 | 665 | 13 1 2 2 666 | <_> 667 | 668 | 13 11 9 1 669 | <_> 670 | 671 | 14 4 3 3 672 | <_> 673 | 674 | 14 5 3 2 675 | <_> 676 | 677 | 14 5 3 3 678 | <_> 679 | 680 | 14 6 3 2 681 | <_> 682 | 683 | 14 11 6 1 684 | <_> 685 | 686 | 15 5 2 2 687 | <_> 688 | 689 | 16 0 3 1 690 | <_> 691 | 692 | 16 5 1 2 693 | <_> 694 | 695 | 16 5 2 2 696 | <_> 697 | 698 | 17 0 6 1 699 | <_> 700 | 701 | 17 1 2 2 702 | <_> 703 | 704 | 18 0 2 3 705 | <_> 706 | 707 | 19 7 2 2 708 | <_> 709 | 710 | 19 11 5 1 711 | <_> 712 | 713 | 20 4 3 1 714 | <_> 715 | 716 | 21 1 1 3 717 | <_> 718 | 719 | 21 11 6 1 720 | <_> 721 | 722 | 22 5 2 1 723 | <_> 724 | 725 | 23 0 1 4 726 | <_> 727 | 728 | 23 11 5 1 729 | <_> 730 | 731 | 24 3 2 2 732 | <_> 733 | 734 | 24 5 2 2 735 | <_> 736 | 737 | 25 4 3 1 738 | <_> 739 | 740 | 26 8 1 2 741 | <_> 742 | 743 | 27 3 2 2 744 | <_> 745 | 746 | 29 11 3 1 747 | <_> 748 | 749 | 30 2 4 2 750 | <_> 751 | 752 | 32 0 2 1 753 | <_> 754 | 755 | 33 1 3 3 756 | <_> 757 | 758 | 33 8 3 2 759 | <_> 760 | 761 | 33 11 3 1 762 | <_> 763 | 764 | 35 1 2 3 765 | <_> 766 | 767 | 36 1 2 3 768 | <_> 769 | 770 | 36 8 2 2 771 | <_> 772 | 773 | 39 2 1 3 774 | <_> 775 | 776 | 39 3 1 1 777 | <_> 778 | 779 | 39 3 1 2 780 | <_> 781 | 782 | 39 4 1 1 783 | 784 | -------------------------------------------------------------------------------- /OpenCV III - Convolutions, Histogram and Thresholding.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# 1 - What are image convolutions?\n", 8 | "\n", 9 | "Basically, the process of convolution in images is an *element-wise multiplication of two matrices followed by a sum* [1]. The main idea follows these three steps:\n", 10 | "\n", 11 | "
    \n", 12 | "
  1. Take two matrices (which both have the same dimensions).
  2. \n", 13 | "
  3. Multiply them, element-by-element (i.e., not the dot product, just a simple multiplication).
  4. \n", 14 | "
  5. Sum the elements together.
  6. \n", 15 | "
\n", 16 | "\n", 17 | "# 2 - What are these matrices? \n", 18 | "\n", 19 | "To understand the meaning of the matrices, we can make an analogy of ``Big Matrix`` and ``Tiny Matrix``, being the ``Big Matrix`` is an image and the ``Tiny Matrix`` is the kernel. The center of the kernel should be positioned at the top left of the image, also slide from left to right and top to bottom, applying a mathematical operation (i.e., a convolution) at each (x, y)-coordinate of the original image.\n", 20 | "\n", 21 | "
\n", 22 | "
\n", 23 | " \n", 24 | "
Figura 1 - Kernel sliding from left to right and up to bottom over the ``Big Matrix`` [1].
\n", 25 | "
\n", 26 | "
\n", 27 | "\n", 28 | "Now we already know the base of convolution and the meaning of kernels, some questions may appear, like: \n", 29 | "\n", 30 | "
    \n", 31 | "
  1. \n", 32 | " What is the purpose of the convolution?
    \n", 33 | " Produce a new image based on pre-defined kernel and the ``Big Matrix``, where this new image has the same dimension that ``Big Matrix``. \n", 34 | "
  2. \n", 35 | "
  3. \n", 36 | " What will we gain with that technique?
    \n", 37 | " With this tool, we win several ''filters\", as blurring and sharpening, also an important aid for edge detections, noise removal, etc. \n", 38 | "
  4. \n", 39 | "
\n", 40 | "\n", 41 | "
\n", 42 | "
\n", 43 | " \n", 44 | "
Figura 2 - Examples of convolutions [1].
\n", 45 | "
\n", 46 | "
\n", 47 | "\n", 48 | "For more informations about kernels and convolution, look the references [2] [3]. \n", 49 | "\n", 50 | "# 3 - Implementation\n", 51 | "\n", 52 | "To implement a convolution, we can follow the following steps:\n", 53 | "\n", 54 | "
    \n", 55 | "
  1. Obtain an input image.
  2. \n", 56 | "
  3. Obtain a kernel matrix that we are going to apply to the input image.
  4. \n", 57 | "
  5. Create an output image to store the output of the image convolved with the kernel.
  6. \n", 58 | "
  7. \n", 59 | " For each pixel of input image, do:\n", 60 | "
      \n", 61 | "
    1. Select an (x, y)-coordinate from the original image.
    2. \n", 62 | "
    3. Place the center of the kernel at this (x, y)-coordinate.
    4. \n", 63 | "
    5. Take the element-wise multiplication of the input image region and the kernel, then sum\n", 64 | " up the values of these multiplication operations into a single value. The sum of these\n", 65 | " multiplications is called the kernel output.
    6. \n", 66 | "
    7. Use the same (x, y)-coordinates from step A, but this time, store the kernel output at the\n", 67 | " same (x, y)-location as the output image.
    8. \n", 68 | "
    \n", 69 | "
  8. \n", 70 | "
\n", 71 | "\n", 72 | "
\n", 73 | "Let's start coding.\n", 74 | "
" 75 | ] 76 | }, 77 | { 78 | "cell_type": "code", 79 | "execution_count": null, 80 | "metadata": {}, 81 | "outputs": [], 82 | "source": [ 83 | "# Importing OpenCV, Numpy and pyplot\n", 84 | "import cv2\n", 85 | "import numpy as np\n", 86 | "from matplotlib import pyplot as plt\n", 87 | "from skimage.exposure import rescale_intensity as rescale" 88 | ] 89 | }, 90 | { 91 | "cell_type": "code", 92 | "execution_count": null, 93 | "metadata": {}, 94 | "outputs": [], 95 | "source": [ 96 | "# Defining the function to convolve images\n", 97 | "def convolve(img, kernel):\n", 98 | " # Obtaining the shape of matrices\n", 99 | " i_rows, i_cols = img.shape[:2]\n", 100 | " k_rows, k_cols = kernel.shape[:2]\n", 101 | " \n", 102 | " # Discovering how many pixels is needed to surround the image\n", 103 | " pad_r = k_rows // 2\n", 104 | " pad_c = k_cols // 2\n", 105 | " \n", 106 | " output = np.zeros((i_rows,i_cols), dtype='float')\n", 107 | " \n", 108 | " img = cv2.copyMakeBorder(img, pad_r, pad_r, pad_c, pad_c, cv2.BORDER_CONSTANT)\n", 109 | " \n", 110 | " for i in range(0, i_rows):\n", 111 | " for j in range(0, i_cols): \n", 112 | " # Creating a window of same width and height of kernel\n", 113 | " crop = img[i : i + (pad_r * 2) + 1, j : j + (pad_c * 2) + 1]\n", 114 | " \n", 115 | " # Applying product operation\n", 116 | " result = (crop * kernel).sum()\n", 117 | " \n", 118 | " # Storing the result\n", 119 | " output[i,j] = result\n", 120 | " \n", 121 | " output = rescale(output, in_range=(0, 255))\n", 122 | " output = (output * 255).astype(\"uint8\")\n", 123 | " \n", 124 | " return output" 125 | ] 126 | }, 127 | { 128 | "cell_type": "markdown", 129 | "metadata": {}, 130 | "source": [ 131 | "## 3.1) Kernels\n", 132 | "\n", 133 | "Before we start our tests, let's define some kernels:\n", 134 | "\n", 135 | "\n", 136 | " \n", 137 | " \n", 138 | " \n", 139 | " \n", 140 | " \n", 141 | " \n", 142 | " \n", 143 | " \n", 150 | " \n", 153 | " \n", 154 | " \n", 155 | " \n", 156 | " \n", 163 | " \n", 166 | " \n", 167 | " \n", 168 | " \n", 169 | " \n", 176 | " \n", 179 | " \n", 180 | " \n", 181 | " \n", 182 | " \n", 189 | " \n", 192 | " \n", 193 | "
OperationKernelImage
Identity\n", 144 | " $$\\begin{matrix}\n", 145 | " 0 & 0 & 0 \\\\\n", 146 | " 0 & 1 & 0 \\\\\n", 147 | " 0 & 0 & 0\n", 148 | " \\end{matrix}$$\n", 149 | " \n", 151 | " \n", 152 | "
Sobel X\n", 157 | " $$\\begin{matrix}\n", 158 | " -1 & 0 & 1 \\\\\n", 159 | " -2 & 0 & 2 \\\\\n", 160 | " -1 & 0 & 1\n", 161 | " \\end{matrix}$$\n", 162 | " \n", 164 | " \n", 165 | "
Sobel Y\n", 170 | " $$\\begin{matrix}\n", 171 | " -1 & -2 & -1 \\\\\n", 172 | " 0 & 0 & 0 \\\\\n", 173 | " 1 & 2 & 1\n", 174 | " \\end{matrix}$$\n", 175 | " \n", 177 | " \n", 178 | "
Laplacian\n", 183 | " $$\\begin{matrix}\n", 184 | " 0 & 1 & 0 \\\\\n", 185 | " 1 & -4 & 1 \\\\\n", 186 | " 0 & 1 & 0\n", 187 | " \\end{matrix}$$\n", 188 | " \n", 190 | " \n", 191 | "
\n", 194 | "\n", 195 | "\n", 196 | " \n", 197 | " \n", 198 | " \n", 199 | " \n", 200 | " \n", 201 | " \n", 202 | " \n", 203 | " \n", 210 | " \n", 213 | " \n", 214 | " \n", 215 | " \n", 216 | " \n", 223 | " \n", 226 | " \n", 227 | " \n", 228 | " \n", 229 | " \n", 236 | " \n", 239 | " \n", 240 | " \n", 241 | " \n", 242 | " \n", 249 | " \n", 252 | " \n", 253 | "
OperationKernelImage
Emboss\n", 204 | " $$\\begin{matrix}\n", 205 | " -2 & -1 & 0 \\\\\n", 206 | " -1 & 1 & 1 \\\\\n", 207 | " 0 & 1 & 2\n", 208 | " \\end{matrix}$$\n", 209 | " \n", 211 | " \n", 212 | "
Sharpen\n", 217 | " $$\\begin{matrix}\n", 218 | " 0 & -1 & 0 \\\\\n", 219 | " -1 & 5 & -1 \\\\\n", 220 | " 0 & -1 & 0\n", 221 | " \\end{matrix}$$\n", 222 | " \n", 224 | " \n", 225 | "
Blur\n", 230 | " $$\\begin{matrix}\n", 231 | " \\frac{1}{9} & \\frac{1}{9} & \\frac{1}{9} \\\\\n", 232 | " \\frac{1}{9} & \\frac{1}{9} & \\frac{1}{9} \\\\\n", 233 | " \\frac{1}{9} & \\frac{1}{9} & \\frac{1}{9}\n", 234 | " \\end{matrix}$$\n", 235 | " \n", 237 | " \n", 238 | "
Gaussian Blur\n", 243 | " $$\\begin{matrix}\n", 244 | " 1 & 2 & 1 \\\\\n", 245 | " 2 & 4 & 2 \\\\\n", 246 | " 1 & 2 & 1\n", 247 | " \\end{matrix}$$\n", 248 | " \n", 250 | " \n", 251 | "
" 254 | ] 255 | }, 256 | { 257 | "cell_type": "code", 258 | "execution_count": null, 259 | "metadata": {}, 260 | "outputs": [], 261 | "source": [ 262 | "identity = np.array(([0, 0, 0],\n", 263 | " [0, 1, 0],\n", 264 | " [0, 0, 0]), dtype=\"int\")\n", 265 | "\n", 266 | "sobelX = np.array(([-1, 0, 1],\n", 267 | " [-2, 0, 2],\n", 268 | " [-1, 0, 1]), dtype=\"int\")\n", 269 | "\n", 270 | "sobelY = np.array(([-1, -2, -1],\n", 271 | " [0, 0, 0],\n", 272 | " [1, 2, 1]), dtype=\"int\")\n", 273 | "\n", 274 | "sharpen = np.array(([0, -1, 0],\n", 275 | " [-1, 5, -1],\n", 276 | " [0, -1, 0]), dtype=\"int\")\n", 277 | "\n", 278 | "blur = np.ones((3,3), dtype='float') / 9\n", 279 | "\n", 280 | "laplacian = np.array(([0, 1, 0],\n", 281 | " [1, -4, 1],\n", 282 | " [0, 1, 0]), dtype=\"int\")\n", 283 | "\n", 284 | "emboss = np.array(([-2, -1, 0],\n", 285 | " [-1, 1, 1],\n", 286 | " [0, 1, 2]), dtype=\"int\")\n", 287 | "\n", 288 | "gaussian = np.array(([1, 4, 1],\n", 289 | " [2, 4, 2],\n", 290 | " [1, 2, 1]), dtype=\"float\") / 16" 291 | ] 292 | }, 293 | { 294 | "cell_type": "markdown", 295 | "metadata": {}, 296 | "source": [ 297 | "
\n", 298 | "Let's test.\n", 299 | "
" 300 | ] 301 | }, 302 | { 303 | "cell_type": "code", 304 | "execution_count": null, 305 | "metadata": {}, 306 | "outputs": [], 307 | "source": [ 308 | "retina = cv2.imread('images/retina.jpg', 0)\n", 309 | "\n", 310 | "# Shape of image\n", 311 | "rows, cols = retina.shape\n", 312 | "\n", 313 | "# Scale factor\n", 314 | "scale = 0.5\n", 315 | "\n", 316 | "# Scaled image\n", 317 | "retina = cv2.resize(retina, (round(scale * cols), round(scale * rows)))\n", 318 | "\n", 319 | "result_identity = convolve(retina, identity)\n", 320 | "result_sobelx = convolve(retina, sobelX)\n", 321 | "result_sobely = convolve(retina, sobelY)\n", 322 | "result_sharpen = convolve(retina, sharpen)\n", 323 | "result_blur = convolve(retina, blur)\n", 324 | "result_laplacian = convolve(retina, laplacian)\n", 325 | "result_emboss = convolve(retina,emboss)\n", 326 | "result_gaussian = convolve(retina,gaussian)" 327 | ] 328 | }, 329 | { 330 | "cell_type": "code", 331 | "execution_count": null, 332 | "metadata": {}, 333 | "outputs": [], 334 | "source": [ 335 | "# Showing our results\n", 336 | "f, axarr = plt.subplots(2,4, figsize=(30,10))\n", 337 | "axarr[0,0].imshow(result_identity, cmap='gray')\n", 338 | "axarr[0,1].imshow(result_sobelx, cmap='gray')\n", 339 | "axarr[0,2].imshow(result_sobely, cmap='gray')\n", 340 | "axarr[0,3].imshow(result_laplacian, cmap='gray')\n", 341 | "axarr[1,0].imshow(result_emboss, cmap='gray')\n", 342 | "axarr[1,1].imshow(result_sharpen, cmap='gray')\n", 343 | "axarr[1,2].imshow(result_blur, cmap='gray')\n", 344 | "axarr[1,3].imshow(result_gaussian, cmap='gray')\n", 345 | "plt.show()" 346 | ] 347 | }, 348 | { 349 | "cell_type": "markdown", 350 | "metadata": {}, 351 | "source": [ 352 | "## 3.2) Using OpenCV's own functions\n", 353 | "\n", 354 | "Until now, we saw how to create convolution function, but OpenCV has its own functions to perform these operations. So, it is the moment to get to know some of these functions.\n", 355 | "\n", 356 | "### 3.2.1) Filter2D\n", 357 | "\n", 358 | "This function has the responsibility of convolving images, like our convolve. \n", 359 | "\n", 360 | "
\n", 361 | " cv2.filter2D(src, ddepth, kernel[, dst[, anchor[, delta[, borderType]]]]) → dst\n", 362 | "
\n", 363 | "\n", 364 | "where:\n", 365 | "\n", 366 | "" 382 | ] 383 | }, 384 | { 385 | "cell_type": "code", 386 | "execution_count": null, 387 | "metadata": {}, 388 | "outputs": [], 389 | "source": [ 390 | "filter2D = cv2.filter2D(retina, -1, emboss)\n", 391 | "\n", 392 | "# Comparative between convolve and filter2D\n", 393 | "plt.figure()\n", 394 | "plt.title(\"Image convolved by the convolve function\")\n", 395 | "plt.axis(\"off\")\n", 396 | "plt.imshow(result_emboss, cmap='gray')\n", 397 | "plt.show()\n", 398 | "\n", 399 | "plt.figure()\n", 400 | "plt.title(\"Image convolved by the filter2D function\")\n", 401 | "plt.axis(\"off\")\n", 402 | "plt.imshow(filter2D, cmap='gray')\n", 403 | "plt.show()" 404 | ] 405 | }, 406 | { 407 | "cell_type": "markdown", 408 | "metadata": {}, 409 | "source": [ 410 | "### 3.2.2) Blur's filters\n", 411 | "\n", 412 | "Here we have 3 functions, that have the responsibility of blurring images, like our convolve with kernel *Blur* and *Gaussian Blur*. \n", 413 | "\n", 414 | "
\n", 415 | " cv2.blur(src, ksize[, dst[, anchor[, borderType]]]) → dst
\n", 416 | " cv2.GaussianBlur(src, ksize, sigmaX[, dst[, sigmaY[, borderType]]]) → dst
\n", 417 | " cv2.medianBlur(src, ksize[, dst]) → dst
\n", 418 | "
\n", 419 | "\n", 420 | "where:\n", 421 | "\n", 422 | "" 432 | ] 433 | }, 434 | { 435 | "cell_type": "code", 436 | "execution_count": null, 437 | "metadata": {}, 438 | "outputs": [], 439 | "source": [ 440 | "blurred = cv2.blur(retina, (3,3))\n", 441 | "g_blurred = cv2.GaussianBlur(retina, (3,3), 0)\n", 442 | "m_blurred = cv2.medianBlur(retina, 3)\n", 443 | "\n", 444 | "# Comparative results\n", 445 | "plt.figure()\n", 446 | "plt.title(\"Image convolved by the convolve function\")\n", 447 | "plt.axis(\"off\")\n", 448 | "plt.imshow(result_blur, cmap='gray')\n", 449 | "plt.show()\n", 450 | "\n", 451 | "plt.figure()\n", 452 | "plt.title(\"Image convolved by the blur function\")\n", 453 | "plt.axis(\"off\")\n", 454 | "plt.imshow(blurred, cmap='gray')\n", 455 | "plt.show()\n", 456 | "\n", 457 | "plt.figure()\n", 458 | "plt.title(\"Image convolved by the convolve function\")\n", 459 | "plt.axis(\"off\")\n", 460 | "plt.imshow(result_gaussian, cmap='gray')\n", 461 | "plt.show()\n", 462 | "\n", 463 | "plt.figure()\n", 464 | "plt.title(\"Image convolved by the GaussianBlur function\")\n", 465 | "plt.axis(\"off\")\n", 466 | "plt.imshow(g_blurred, cmap='gray')\n", 467 | "plt.show()\n", 468 | "\n", 469 | "plt.figure()\n", 470 | "plt.title(\"Image convolved by the medianBlur function\")\n", 471 | "plt.axis(\"off\")\n", 472 | "plt.imshow(m_blurred, cmap='gray')\n", 473 | "plt.show()" 474 | ] 475 | }, 476 | { 477 | "cell_type": "markdown", 478 | "metadata": {}, 479 | "source": [ 480 | "### 3.2.3) Laplacian filters\n", 481 | "\n", 482 | "This function calculates the laplacian of an image. \n", 483 | "\n", 484 | "
\n", 485 | " cv2.Laplacian(src, ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]]) → dst
\n", 486 | "
\n", 487 | "\n", 488 | "where:\n", 489 | "\n", 490 | "" 499 | ] 500 | }, 501 | { 502 | "cell_type": "code", 503 | "execution_count": null, 504 | "metadata": {}, 505 | "outputs": [], 506 | "source": [ 507 | "laplacian_ex = cv2.Laplacian(retina, -1)\n", 508 | "\n", 509 | "# Comparative between convolve and filter2D\n", 510 | "plt.figure()\n", 511 | "plt.title(\"Image convolved by the convolve function\")\n", 512 | "plt.axis(\"off\")\n", 513 | "plt.imshow(result_laplacian, cmap='gray')\n", 514 | "plt.show()\n", 515 | "\n", 516 | "plt.figure()\n", 517 | "plt.title(\"Image convolved by the laplacian function\")\n", 518 | "plt.axis(\"off\")\n", 519 | "plt.imshow(laplacian_ex, cmap='gray')\n", 520 | "plt.show()" 521 | ] 522 | }, 523 | { 524 | "cell_type": "markdown", 525 | "metadata": {}, 526 | "source": [ 527 | "*To see more functions of filter, look for the reference [4]*.\n", 528 | "\n", 529 | "# 4 - Histogram\n", 530 | "\n", 531 | "A histogram represents the distribution of pixel intensities (whether color or grayscale) in an image [5]. The use of histograms may help us to get know several informations about our images, like **contrast, brightness** and **intensity**.\n", 532 | "\n", 533 | "In OpenCV, we have the following function to calculate histograms: \n", 534 | "\n", 535 | "
\n", 536 | " cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]]) → hist
\n", 537 | "
\n", 538 | "\n", 539 | "where:\n", 540 | "\n", 541 | "" 550 | ] 551 | }, 552 | { 553 | "cell_type": "code", 554 | "execution_count": null, 555 | "metadata": {}, 556 | "outputs": [], 557 | "source": [ 558 | "# Creating a mask for our image\n", 559 | "mask = np.zeros(retina.shape, dtype='uint8')\n", 560 | "\n", 561 | "centerX = mask.shape[0] // 2\n", 562 | "centerY = mask.shape[1] // 2\n", 563 | "\n", 564 | "cv2.circle(mask, (centerX, centerY), round(centerY * .95), 255, cv2.FILLED)\n", 565 | "\n", 566 | "hist = cv2.calcHist([retina], [0], None, [256], [0, 256])\n", 567 | "hist_mask = cv2.calcHist([retina], [0], mask, [256], [0, 256])\n", 568 | "\n", 569 | "plt.figure()\n", 570 | "plt.title(\"Mask\")\n", 571 | "plt.axis(\"off\")\n", 572 | "plt.imshow(mask, cmap='gray')\n", 573 | "plt.show()\n", 574 | "\n", 575 | "plt.figure()\n", 576 | "plt.title(\"Retina\")\n", 577 | "plt.axis(\"off\")\n", 578 | "plt.imshow(retina, cmap='gray')\n", 579 | "plt.show()\n", 580 | "\n", 581 | "plt.figure()\n", 582 | "plt.title(\"Histogram of the Retina without mask\")\n", 583 | "plt.xlabel(\"Bins\")\n", 584 | "plt.ylabel(\"# of Pixels\")\n", 585 | "plt.plot(hist)\n", 586 | "plt.xlim([-10, 256])\n", 587 | "plt.ylim([0, 10000])\n", 588 | "plt.show()\n", 589 | "\n", 590 | "plt.figure()\n", 591 | "plt.title(\"Histogram of the Retina with mask\")\n", 592 | "plt.xlabel(\"Bins\")\n", 593 | "plt.ylabel(\"# of Pixels\")\n", 594 | "plt.plot(hist_mask)\n", 595 | "plt.xlim([-10, 256])\n", 596 | "plt.ylim([0, 10000])\n", 597 | "plt.show()" 598 | ] 599 | }, 600 | { 601 | "cell_type": "markdown", 602 | "metadata": {}, 603 | "source": [ 604 | "## 4.1) Histogram equalization\n", 605 | "\n", 606 | "The histogram equalization improves the contrast of an image by ```stretching``` the distribution of pixels.\n", 607 | "\n", 608 | "The OpenCV has the following function to help us: \n", 609 | "\n", 610 | "
\n", 611 | " cv2.equalizeHist(src[, dst]) → dst
\n", 612 | "
\n", 613 | "\n", 614 | "where:\n", 615 | "\n", 616 | "" 620 | ] 621 | }, 622 | { 623 | "cell_type": "code", 624 | "execution_count": null, 625 | "metadata": {}, 626 | "outputs": [], 627 | "source": [ 628 | "equalized = cv2.equalizeHist(retina)\n", 629 | "\n", 630 | "plt.figure()\n", 631 | "plt.title(\"Retina\")\n", 632 | "plt.imshow(retina, cmap='gray')\n", 633 | "plt.show()\n", 634 | "\n", 635 | "plt.figure()\n", 636 | "plt.title(\"Retina after histogram equalization\")\n", 637 | "plt.axis(\"off\")\n", 638 | "plt.imshow(equalized, cmap='gray')\n", 639 | "plt.show()\n", 640 | "\n", 641 | "histAfter = cv2.calcHist([equalized], [0], None, [256], [0, 256])\n", 642 | "\n", 643 | "plt.figure()\n", 644 | "plt.title(\"Histogram of the Retina after equalization\")\n", 645 | "plt.xlabel(\"Bins\")\n", 646 | "plt.ylabel(\"# of Pixels\")\n", 647 | "plt.plot(histAfter)\n", 648 | "plt.xlim([-10, 256])\n", 649 | "plt.ylim([0, 10000])\n", 650 | "plt.show()" 651 | ] 652 | }, 653 | { 654 | "cell_type": "markdown", 655 | "metadata": {}, 656 | "source": [ 657 | "# 5 - Thresholding\n", 658 | "\n", 659 | "Basically, this technique is used when you wish to binarize an image. Normally, we performs the thresholding to focus on objects or areas of particular interest in an image, and here we will see some kinds of binarizations.\n", 660 | "\n", 661 | "## 5.1) Simple Thresholding\n", 662 | "\n", 663 | "The simple thresholding uses the human intervention, who informs the pixels which will receive value 0 and 255. With OpenCV, we can do it with function *threshold*. \n", 664 | "\n", 665 | "
\n", 666 | " cv2.threshold(src, thresh, maxval, type[, dst]) → retval, dst
\n", 667 | "
\n", 668 | "\n", 669 | "where:\n", 670 | "\n", 671 | "" 678 | ] 679 | }, 680 | { 681 | "cell_type": "code", 682 | "execution_count": null, 683 | "metadata": {}, 684 | "outputs": [], 685 | "source": [ 686 | "_, binarized = cv2.threshold(retina, 60, 255, cv2.THRESH_BINARY)\n", 687 | "_, binarized_after = cv2.threshold(equalized, 155, 255, cv2.THRESH_BINARY)\n", 688 | "\n", 689 | "_, binarized_inv = cv2.threshold(retina, 60, 255, cv2.THRESH_BINARY_INV)\n", 690 | "_, binarized_after_inv = cv2.threshold(equalized, 155, 255, cv2.THRESH_BINARY_INV)\n", 691 | "\n", 692 | "plt.figure()\n", 693 | "plt.title(\"Retina\")\n", 694 | "plt.imshow(retina, cmap='gray')\n", 695 | "plt.show()\n", 696 | "\n", 697 | "plt.figure()\n", 698 | "plt.title(\"Retina after binarization\")\n", 699 | "plt.axis(\"off\")\n", 700 | "plt.imshow(binarized, cmap='gray')\n", 701 | "plt.show()\n", 702 | "\n", 703 | "plt.figure()\n", 704 | "plt.title(\"Equalized Retina after binarization\")\n", 705 | "plt.axis(\"off\")\n", 706 | "plt.imshow(binarized_after, cmap='gray')\n", 707 | "plt.show()\n", 708 | "\n", 709 | "plt.figure()\n", 710 | "plt.title(\"Retina after inverted binarization\")\n", 711 | "plt.axis(\"off\")\n", 712 | "plt.imshow(binarized_inv, cmap='gray')\n", 713 | "plt.show()\n", 714 | "\n", 715 | "plt.figure()\n", 716 | "plt.title(\"Equalized Retina after inverted binarization\")\n", 717 | "plt.axis(\"off\")\n", 718 | "plt.imshow(binarized_after_inv, cmap='gray')\n", 719 | "plt.show()" 720 | ] 721 | }, 722 | { 723 | "cell_type": "markdown", 724 | "metadata": {}, 725 | "source": [ 726 | "## 5.2) Adaptative thresholding\n", 727 | "\n", 728 | "To avoid the human intervention on which pixel should receives value 0 or 255, we can use an adaptative thresholding, that considers small neighbors of pixels and then finds an optimal threshold value T for each neighbor.\n", 729 | "\n", 730 | "
\n", 731 | " cv.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C[, dst]) → dst
\n", 732 | "
\n", 733 | "\n", 734 | "where:\n", 735 | "\n", 736 | "" 745 | ] 746 | }, 747 | { 748 | "cell_type": "code", 749 | "execution_count": null, 750 | "metadata": {}, 751 | "outputs": [], 752 | "source": [ 753 | "adaptative_mean = cv2.adaptiveThreshold(retina, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 15, 4)\n", 754 | "adaptative_gaussian = cv2.adaptiveThreshold(retina, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 15, 4)\n", 755 | "\n", 756 | "adaptative_mean_inv = cv2.adaptiveThreshold(retina, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 15, 4)\n", 757 | "adaptative_gaussian_inv = cv2.adaptiveThreshold(retina, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 15, 4)\n", 758 | "\n", 759 | "plt.figure()\n", 760 | "plt.title(\"Retina\")\n", 761 | "plt.axis(\"off\")\n", 762 | "plt.imshow(retina, cmap='gray')\n", 763 | "plt.show()\n", 764 | "\n", 765 | "plt.figure()\n", 766 | "plt.title(\"Retina after adaptative threshold with mean method\")\n", 767 | "plt.axis(\"off\")\n", 768 | "plt.imshow(adaptative_mean, cmap='gray')\n", 769 | "plt.show()\n", 770 | "\n", 771 | "plt.figure()\n", 772 | "plt.title(\"Retina after adaptative threshold with Gaussian method\")\n", 773 | "plt.axis(\"off\")\n", 774 | "plt.imshow(adaptative_gaussian, cmap='gray')\n", 775 | "plt.show()\n", 776 | "\n", 777 | "plt.figure()\n", 778 | "plt.title(\"Retina after adaptative threshold with mean method and inverted type\")\n", 779 | "plt.axis(\"off\")\n", 780 | "plt.imshow(adaptative_mean_inv, cmap='gray')\n", 781 | "plt.show()\n", 782 | "\n", 783 | "plt.figure()\n", 784 | "plt.title(\"Retina after adaptative threshold with Gaussian method and inverted type\")\n", 785 | "plt.axis(\"off\")\n", 786 | "plt.imshow(adaptative_gaussian_inv, cmap='gray')\n", 787 | "plt.show()" 788 | ] 789 | }, 790 | { 791 | "cell_type": "markdown", 792 | "metadata": {}, 793 | "source": [ 794 | "##### Besides these functions, there are other methods like Otsu’s Binarization, if you want get to know this method and other things, check this reference [6].\n", 795 | "\n", 796 | "# References\n", 797 | "\n", 798 | "[1] Rosebrock, A., 2017. Deep Learning for Computer Vision with Python. 1st ed. https://www.pyimagesearch.com: PyImageSearch.\n", 799 | "\n", 800 | "[2] Leonardo Araujo dos Santos. 2018. Convolution · Artificial Inteligence. [ONLINE] Available at: https://leonardoaraujosantos.gitbooks.io/artificial-inteligence/content/convolution.html. [Accessed 01 May 2018].\n", 801 | "\n", 802 | "[3] Explained Visually. 2018. Image Kernels explained visually. [ONLINE] Available at: http://setosa.io/ev/image-kernels/. [Accessed 01 May 2018].\n", 803 | "\n", 804 | "[4] Image Filtering — OpenCV 2.4.13.6 documentation. 2018. Image Filtering — OpenCV 2.4.13.6 documentation. [ONLINE] Available at: https://docs.opencv.org/2.4/modules/imgproc/doc/filtering.html. [Accessed 02 May 2018]. \n", 805 | "\n", 806 | "[5] Rosebrock, A., 2014. Practical Python and OpenCV: An Introductory, Example Driven Guide to Image Processing and Computer Vision. 1st ed. PyImageSearch.com.\n", 807 | "\n", 808 | "[6] OpenCV: Image Thresholding. 2018. OpenCV: Image Thresholding. [ONLINE] Available at: https://docs.opencv.org/3.4.0/d7/d4d/tutorial_py_thresholding.html. [Accessed 04 May 2018]." 809 | ] 810 | } 811 | ], 812 | "metadata": { 813 | "kernelspec": { 814 | "display_name": "Python 3", 815 | "language": "python", 816 | "name": "python3" 817 | }, 818 | "language_info": { 819 | "codemirror_mode": { 820 | "name": "ipython", 821 | "version": 3 822 | }, 823 | "file_extension": ".py", 824 | "mimetype": "text/x-python", 825 | "name": "python", 826 | "nbconvert_exporter": "python", 827 | "pygments_lexer": "ipython3", 828 | "version": "3.6.4" 829 | } 830 | }, 831 | "nbformat": 4, 832 | "nbformat_minor": 2 833 | } 834 | --------------------------------------------------------------------------------