├── README.md
├── blogs.md
├── .gitignore
├── 208_canny_edge_detector.ipynb
├── 104-opencv_flipping.ipynb
├── 109_opencv_split_merge.ipynb
├── 108_opencv_masking.ipynb
├── 204_opencv_color_spaces.ipynb
├── 107_opencv_bitwise.ipynb
├── 209_auto_canny.ipynb
├── 105_opencv_cropping.ipynb
├── 206_adapative_thresholding.ipynb
├── 1104_compare_images_siamese_networks.ipynb
├── 505_opencv_guess_aruco_type.ipynb
├── 106_opencv_image_arithmetic.ipynb
├── 501_python_apriltag.ipynb
├── 103-image_resizing.ipynb
├── 205-opencv_thresholding.ipynb
├── 102-rotate_image.ipynb
├── 502-opencv_generate_aruco.ipynb
├── 207_image_gradients.ipynb
├── 203_smoothing_and_blurring.ipynb
├── 1102_siamese_image_pairs.ipynb
├── 801_perceptron_neural_network.ipynb
├── 701_gradient_descent.ipynb
└── 702_stochastic_gradient_descent.ipynb
/README.md:
--------------------------------------------------------------------------------
1 | # pyImageSearch
2 | A source of pyImageSearch university courses
3 |
--------------------------------------------------------------------------------
/blogs.md:
--------------------------------------------------------------------------------
1 |
2 | ## 801 [Introduction to Neural Networks](https://www.pyimagesearch.com/2021/05/06/introduction-to-neural-networks/)
3 | ## 804 [The 4 Key Ingredients When Training Any Neural Network](https://www.pyimagesearch.com/2021/05/06/the-four-key-ingredients-when-training-any-neural-network/)
4 | ## 805 [Understanding Weight Initialization for Neural Networks](https://www.pyimagesearch.com/2021/05/06/understanding-weight-initialization-for-neural-networks/)
5 | ## 1704 [Choosing a Face Detection Method](https://www.pyimagesearch.com/2021/04/26/face-detection-tips-suggestions-and-best-practices/)
6 |
7 | ## 1803 [Real-time Facial Landmark Detection blog](https://www.pyimagesearch.com/2017/04/17/real-time-facial-landmark-detection-opencv-python-dlib/)
8 | ## 1803 [Real-time Facial Landmark Detection source](https://s3-us-west-2.amazonaws.com/static.pyimagesearch.com/real-time-facial-landmarks/real-time-facial-landmarks.zip)
9 | ## 1901 [What Is Face Recognition?](https://www.pyimagesearch.com/2021/05/01/what-is-face-recognition/)
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | pip-wheel-metadata/
24 | share/python-wheels/
25 | *.egg-info/
26 | .installed.cfg
27 | *.egg
28 | MANIFEST
29 |
30 | # PyInstaller
31 | # Usually these files are written by a python script from a template
32 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
33 | *.manifest
34 | *.spec
35 |
36 | # Installer logs
37 | pip-log.txt
38 | pip-delete-this-directory.txt
39 |
40 | # Unit test / coverage reports
41 | htmlcov/
42 | .tox/
43 | .nox/
44 | .coverage
45 | .coverage.*
46 | .cache
47 | nosetests.xml
48 | coverage.xml
49 | *.cover
50 | *.py,cover
51 | .hypothesis/
52 | .pytest_cache/
53 |
54 | # Translations
55 | *.mo
56 | *.pot
57 |
58 | # Django stuff:
59 | *.log
60 | local_settings.py
61 | db.sqlite3
62 | db.sqlite3-journal
63 |
64 | # Flask stuff:
65 | instance/
66 | .webassets-cache
67 |
68 | # Scrapy stuff:
69 | .scrapy
70 |
71 | # Sphinx documentation
72 | docs/_build/
73 |
74 | # PyBuilder
75 | target/
76 |
77 | # Jupyter Notebook
78 | .ipynb_checkpoints
79 |
80 | # IPython
81 | profile_default/
82 | ipython_config.py
83 |
84 | # pyenv
85 | .python-version
86 |
87 | # pipenv
88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
91 | # install all needed dependencies.
92 | #Pipfile.lock
93 |
94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
95 | __pypackages__/
96 |
97 | # Celery stuff
98 | celerybeat-schedule
99 | celerybeat.pid
100 |
101 | # SageMath parsed files
102 | *.sage.py
103 |
104 | # Environments
105 | .env
106 | .venv
107 | env/
108 | venv/
109 | ENV/
110 | env.bak/
111 | venv.bak/
112 |
113 | # Spyder project settings
114 | .spyderproject
115 | .spyproject
116 |
117 | # Rope project settings
118 | .ropeproject
119 |
120 | # mkdocs documentation
121 | /site
122 |
123 | # mypy
124 | .mypy_cache/
125 | .dmypy.json
126 | dmypy.json
127 |
128 | # Pyre type checker
129 | .pyre/
130 |
--------------------------------------------------------------------------------
/208_canny_edge_detector.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "colab": {
6 | "name": "208-canny_edge_detector.ipynb",
7 | "provenance": [],
8 | "collapsed_sections": [],
9 | "toc_visible": true,
10 | "include_colab_link": true
11 | },
12 | "kernelspec": {
13 | "name": "python3",
14 | "display_name": "Python 3"
15 | },
16 | "language_info": {
17 | "name": "python"
18 | }
19 | },
20 | "cells": [
21 | {
22 | "cell_type": "markdown",
23 | "metadata": {
24 | "id": "view-in-github",
25 | "colab_type": "text"
26 | },
27 | "source": [
28 | "
"
29 | ]
30 | },
31 | {
32 | "cell_type": "markdown",
33 | "metadata": {
34 | "id": "j4RpK9pawQzP"
35 | },
36 | "source": [
37 | "# OpenCV Edge Detection ( cv2.Canny )\n"
38 | ]
39 | },
40 | {
41 | "cell_type": "markdown",
42 | "metadata": {
43 | "id": "8ntZ1AkXZIxY"
44 | },
45 | "source": [
46 | "\n",
47 | "This notebook is associated with the [OpenCV Edge Detection ( cv2.Canny )](https://www.pyimagesearch.com/2021/05/12/opencv-edge-detection-cv2-canny) blog post published on 2021-05-12.\n",
48 | "\n",
49 | "Only the code for the blog post is here. Most codeblocks have a 1:1 relationship with what you find in the blog post with two exceptions: (1) Python classes are not separate files as they are typically organized with PyImageSearch projects, and (2) Command Line Argument parsing is replaced with an `args` dictionary that you can manipulate as needed.\n",
50 | "\n",
51 | "We recommend that you execute (press ▶️) the code block-by-block, as-is, before adjusting parameters and `args` inputs. Once you've verified that the code is working, you are welcome to hack with it and learn from manipulating inputs, settings, and parameters. For more information on using Jupyter and Colab, please refer to these resources:\n",
52 | "\n",
53 | "* [Jupyter Notebook User Interface](https://jupyter-notebook.readthedocs.io/en/stable/notebook.html#notebook-user-interface)\n",
54 | "* [Overview of Google Colaboratory Features](https://colab.research.google.com/notebooks/basic_features_overview.ipynb)\n",
55 | "\n",
56 | "\n",
57 | "\n",
58 | "Happy hacking!\n",
59 | "\n",
60 | "\n",
61 | "
\n",
62 | "\n"
63 | ]
64 | },
65 | {
66 | "cell_type": "markdown",
67 | "metadata": {
68 | "id": "NFhAzQB3aNMa"
69 | },
70 | "source": [
71 | "### Download the code zip file"
72 | ]
73 | },
74 | {
75 | "cell_type": "code",
76 | "metadata": {
77 | "id": "7y0LG1EuaRlB"
78 | },
79 | "source": [
80 | "!wget https://pyimagesearch-code-downloads.s3-us-west-2.amazonaws.com/canny-edge-detector/canny-edge-detector.zip\n",
81 | "!unzip -qq canny-edge-detector.zip\n",
82 | "%cd canny-edge-detector"
83 | ],
84 | "execution_count": null,
85 | "outputs": []
86 | },
87 | {
88 | "cell_type": "markdown",
89 | "metadata": {
90 | "id": "_SgTVT3HagGZ"
91 | },
92 | "source": [
93 | "## Blog Post Code"
94 | ]
95 | },
96 | {
97 | "cell_type": "markdown",
98 | "metadata": {
99 | "id": "wcrOk6pURp50"
100 | },
101 | "source": [
102 | "### Import Packages"
103 | ]
104 | },
105 | {
106 | "cell_type": "code",
107 | "metadata": {
108 | "id": "VJaCNlDDRz6d"
109 | },
110 | "source": [
111 | "# import the necessary packages\n",
112 | "import matplotlib.pyplot as plt\n",
113 | "import cv2"
114 | ],
115 | "execution_count": null,
116 | "outputs": []
117 | },
118 | {
119 | "cell_type": "markdown",
120 | "metadata": {
121 | "id": "lBrLwCtN5kqy"
122 | },
123 | "source": [
124 | "### Function to display images in Jupyter Notebooks and Google Colab"
125 | ]
126 | },
127 | {
128 | "cell_type": "code",
129 | "metadata": {
130 | "id": "sYaD_Es9-8y6"
131 | },
132 | "source": [
133 | "def plt_imshow(title, image):\n",
134 | "\t# convert the image frame BGR to RGB color space and display it\n",
135 | "\timage = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n",
136 | "\tplt.imshow(image)\n",
137 | "\tplt.title(title)\n",
138 | "\tplt.grid(False)\n",
139 | "\tplt.show()"
140 | ],
141 | "execution_count": null,
142 | "outputs": []
143 | },
144 | {
145 | "cell_type": "markdown",
146 | "metadata": {
147 | "id": "khdPrbuL-5xD"
148 | },
149 | "source": [
150 | "### Implementing the Canny edge detector with OpenCV"
151 | ]
152 | },
153 | {
154 | "cell_type": "code",
155 | "metadata": {
156 | "id": "3hFftCsSc3A7"
157 | },
158 | "source": [
159 | "# # construct the argument parser and parse the arguments\n",
160 | "# ap = argparse.ArgumentParser()\n",
161 | "# ap.add_argument(\"-i\", \"--image\", type=str, required=True,\n",
162 | "# \thelp=\"path to input image\")\n",
163 | "# args = vars(ap.parse_args())\n",
164 | "\n",
165 | "# since we are using Jupyter Notebooks we can replace our argument\n",
166 | "# parsing code with *hard coded* arguments and values\n",
167 | "args = {\n",
168 | " \"image\": \"images/coins.png\"\n",
169 | "}"
170 | ],
171 | "execution_count": null,
172 | "outputs": []
173 | },
174 | {
175 | "cell_type": "code",
176 | "metadata": {
177 | "id": "xb65OOibebAq"
178 | },
179 | "source": [
180 | "# load the image, convert it to grayscale, and blur it slightly\n",
181 | "image = cv2.imread(args[\"image\"])\n",
182 | "gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)\n",
183 | "blurred = cv2.GaussianBlur(gray, (5, 5), 0)\n",
184 | "\n",
185 | "# show the original and blurred images\n",
186 | "plt_imshow(\"Original\", image)\n",
187 | "plt_imshow(\"Blurred\", blurred)"
188 | ],
189 | "execution_count": null,
190 | "outputs": []
191 | },
192 | {
193 | "cell_type": "code",
194 | "metadata": {
195 | "id": "P8tiXpwtef8i"
196 | },
197 | "source": [
198 | "# compute a \"wide\", \"mid-range\", and \"tight\" threshold for the edges\n",
199 | "# using the Canny edge detector\n",
200 | "wide = cv2.Canny(blurred, 10, 200)\n",
201 | "mid = cv2.Canny(blurred, 30, 150)\n",
202 | "tight = cv2.Canny(blurred, 240, 250)\n",
203 | "\n",
204 | "# show the output Canny edge maps\n",
205 | "plt_imshow(\"Wide Edge Map\", wide)\n",
206 | "plt_imshow(\"Mid Edge Map\", mid)\n",
207 | "plt_imshow(\"Tight Edge Map\", tight)"
208 | ],
209 | "execution_count": null,
210 | "outputs": []
211 | },
212 | {
213 | "cell_type": "markdown",
214 | "metadata": {
215 | "id": "4ogkNauArL6u"
216 | },
217 | "source": [
218 | "For a detailed walkthrough of the concepts and code, be sure to refer to the full tutorial, [OpenCV Edge Detection ( cv2.Canny )](https://www.pyimagesearch.com/2021/05/12/opencv-edge-detection-cv2-canny) published on 2021-05-12."
219 | ]
220 | }
221 | ]
222 | }
--------------------------------------------------------------------------------
/104-opencv_flipping.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "colab": {
6 | "name": "opencv_flipping.ipynb",
7 | "provenance": [],
8 | "collapsed_sections": [],
9 | "toc_visible": true,
10 | "include_colab_link": true
11 | },
12 | "kernelspec": {
13 | "name": "python3",
14 | "display_name": "Python 3"
15 | }
16 | },
17 | "cells": [
18 | {
19 | "cell_type": "markdown",
20 | "metadata": {
21 | "id": "view-in-github",
22 | "colab_type": "text"
23 | },
24 | "source": [
25 | "
"
26 | ]
27 | },
28 | {
29 | "cell_type": "markdown",
30 | "metadata": {
31 | "id": "j4RpK9pawQzP"
32 | },
33 | "source": [
34 | "# OpenCV Flip Image ( cv2.flip )\n"
35 | ]
36 | },
37 | {
38 | "cell_type": "markdown",
39 | "metadata": {
40 | "id": "8ntZ1AkXZIxY"
41 | },
42 | "source": [
43 | "\n",
44 | "This notebook is associated with the [OpenCV Flip Image ( cv2.flip )](https://www.pyimagesearch.com/2021/01/20/opencv-flip-image-cv2-flip/) blog post published on 01-20-2021.\n",
45 | "\n",
46 | "Only the code for the blog post is here. Most codeblocks have a 1:1 relationship with what you find in the blog post with two exceptions: (1) Python classes are not separate files as they are typically organized with PyImageSearch projects, and (2) Command Line Argument parsing is replaced with an `args` dictionary that you can manipulate as needed.\n",
47 | "\n",
48 | "We recommend that you execute (press ▶️) the code block-by-block, as-is, before adjusting parameters and `args` inputs. Once you've verified that the code is working, you are welcome to hack with it and learn from manipulating inputs, settings, and parameters. For more information on using Jupyter and Colab, please refer to these resources:\n",
49 | "\n",
50 | "* [Jupyter Notebook User Interface](https://jupyter-notebook.readthedocs.io/en/stable/notebook.html#notebook-user-interface)\n",
51 | "* [Overview of Google Colaboratory Features](https://colab.research.google.com/notebooks/basic_features_overview.ipynb)\n",
52 | "\n",
53 | "\n",
54 | "\n",
55 | "Happy hacking!\n",
56 | "\n",
57 | "\n",
58 | "
\n"
59 | ]
60 | },
61 | {
62 | "cell_type": "markdown",
63 | "metadata": {
64 | "id": "NFhAzQB3aNMa"
65 | },
66 | "source": [
67 | "### Download the code zip file"
68 | ]
69 | },
70 | {
71 | "cell_type": "code",
72 | "metadata": {
73 | "id": "7y0LG1EuaRlB"
74 | },
75 | "source": [
76 | "!wget https://pyimagesearch-code-downloads.s3-us-west-2.amazonaws.com/opencv-flipping/opencv-flipping.zip\n",
77 | "!unzip -qq opencv-flipping.zip\n",
78 | "%cd opencv-flipping"
79 | ],
80 | "execution_count": null,
81 | "outputs": []
82 | },
83 | {
84 | "cell_type": "markdown",
85 | "metadata": {
86 | "id": "_SgTVT3HagGZ"
87 | },
88 | "source": [
89 | "## Blog Post Code"
90 | ]
91 | },
92 | {
93 | "cell_type": "markdown",
94 | "metadata": {
95 | "id": "wcrOk6pURp50"
96 | },
97 | "source": [
98 | "### Import Packages"
99 | ]
100 | },
101 | {
102 | "cell_type": "code",
103 | "metadata": {
104 | "id": "VJaCNlDDRz6d"
105 | },
106 | "source": [
107 | "# import the necessary packages\n",
108 | "from matplotlib import pyplot as plt\n",
109 | "import numpy as np\n",
110 | "import argparse\n",
111 | "import cv2"
112 | ],
113 | "execution_count": null,
114 | "outputs": []
115 | },
116 | {
117 | "cell_type": "markdown",
118 | "metadata": {
119 | "id": "lBrLwCtN5kqy"
120 | },
121 | "source": [
122 | "### Function to display images in Jupyter Notebooks and Google Colab"
123 | ]
124 | },
125 | {
126 | "cell_type": "code",
127 | "metadata": {
128 | "id": "fRw969Dp5Kdm"
129 | },
130 | "source": [
131 | "def plt_imshow(title, image):\n",
132 | "\t# convert the image frame BGR to RGB color space and display it\n",
133 | "\timage = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n",
134 | "\tplt.imshow(image)\n",
135 | "\tplt.title(title)\n",
136 | "\tplt.grid(False)\n",
137 | "\tplt.show()"
138 | ],
139 | "execution_count": null,
140 | "outputs": []
141 | },
142 | {
143 | "cell_type": "markdown",
144 | "metadata": {
145 | "id": "70hAWGrBDMli"
146 | },
147 | "source": [
148 | "### Implementing image flipping with OpenCV"
149 | ]
150 | },
151 | {
152 | "cell_type": "code",
153 | "metadata": {
154 | "id": "AgdFxpQRDO9g"
155 | },
156 | "source": [
157 | "# # construct the argument parser and parse the arguments\n",
158 | "# ap = argparse.ArgumentParser()\n",
159 | "# ap.add_argument(\"-i\", \"--image\", type=str, default=\"opencv_logo.png\",\n",
160 | "# \thelp=\"path to the input image\")\n",
161 | "# args = vars(ap.parse_args())\n",
162 | "\n",
163 | "# since we are using Jupyter Notebooks we can replace our argument\n",
164 | "# parsing code with *hard coded* arguments and values\n",
165 | "args = {\n",
166 | "\t\"image\": \"opencv_logo.png\"\n",
167 | "}"
168 | ],
169 | "execution_count": null,
170 | "outputs": []
171 | },
172 | {
173 | "cell_type": "code",
174 | "metadata": {
175 | "id": "TlWdkKacDkEF"
176 | },
177 | "source": [
178 | "# load the original input image and display it to our screen\n",
179 | "image = cv2.imread(args[\"image\"])\n",
180 | "plt_imshow(\"Original\", image)\n",
181 | "\n",
182 | "# flip the image horizontally\n",
183 | "print(\"[INFO] flipping image horizontally...\")\n",
184 | "flipped = cv2.flip(image, 1)\n",
185 | "plt_imshow(\"Flipped Horizontally\", flipped)"
186 | ],
187 | "execution_count": null,
188 | "outputs": []
189 | },
190 | {
191 | "cell_type": "code",
192 | "metadata": {
193 | "id": "xra7PjakD_9M"
194 | },
195 | "source": [
196 | "# flip the image vertically\n",
197 | "flipped = cv2.flip(image, 0)\n",
198 | "print(\"[INFO] flipping image vertically...\")\n",
199 | "plt_imshow(\"Flipped Vertically\", flipped)"
200 | ],
201 | "execution_count": null,
202 | "outputs": []
203 | },
204 | {
205 | "cell_type": "code",
206 | "metadata": {
207 | "id": "DHFa-TCzEEyv"
208 | },
209 | "source": [
210 | "# flip the image along both axes\n",
211 | "flipped = cv2.flip(image, -1)\n",
212 | "print(\"[INFO] flipping image horizontally and vertically...\")\n",
213 | "plt_imshow(\"Flipped Horizontally & Vertically\", flipped)"
214 | ],
215 | "execution_count": null,
216 | "outputs": []
217 | },
218 | {
219 | "cell_type": "markdown",
220 | "metadata": {
221 | "id": "4ogkNauArL6u"
222 | },
223 | "source": [
224 | "For a detailed walkthrough of the concepts and code, be sure to refer to the full tutorial, [*OpenCV Flip Image ( cv2.flip )*](https://www.pyimagesearch.com/2021/01/20/opencv-flip-image-cv2-flip/) published on 01-20-2021."
225 | ]
226 | }
227 | ]
228 | }
--------------------------------------------------------------------------------
/109_opencv_split_merge.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "colab": {
6 | "name": "110-opencv_split_merge.ipynb",
7 | "provenance": [],
8 | "collapsed_sections": [],
9 | "toc_visible": true,
10 | "include_colab_link": true
11 | },
12 | "kernelspec": {
13 | "name": "python3",
14 | "display_name": "Python 3"
15 | }
16 | },
17 | "cells": [
18 | {
19 | "cell_type": "markdown",
20 | "metadata": {
21 | "id": "view-in-github",
22 | "colab_type": "text"
23 | },
24 | "source": [
25 | "
"
26 | ]
27 | },
28 | {
29 | "cell_type": "markdown",
30 | "metadata": {
31 | "id": "j4RpK9pawQzP"
32 | },
33 | "source": [
34 | "# Splitting and Merging Channels with OpenCV\n"
35 | ]
36 | },
37 | {
38 | "cell_type": "markdown",
39 | "metadata": {
40 | "id": "8ntZ1AkXZIxY"
41 | },
42 | "source": [
43 | "## Welcome to **[PyImageSearch Plus](http://pyimg.co/plus)** Jupyter Notebooks!\n",
44 | "\n",
45 | "This notebook is associated with the [Splitting and Merging Channels with OpenCV](https://www.pyimagesearch.com/2021/01/23/splitting-and-merging-channels-with-opencv/) blog post published on 01-23-2021.\n",
46 | "\n",
47 | "Only the code for the blog post is here. Most codeblocks have a 1:1 relationship with what you find in the blog post with two exceptions: (1) Python classes are not separate files as they are typically organized with PyImageSearch projects, and (2) Command Line Argument parsing is replaced with an `args` dictionary that you can manipulate as needed.\n",
48 | "\n",
49 | "We recommend that you execute (press ▶️) the code block-by-block, as-is, before adjusting parameters and `args` inputs. Once you've verified that the code is working, you are welcome to hack with it and learn from manipulating inputs, settings, and parameters. For more information on using Jupyter and Colab, please refer to these resources:\n",
50 | "\n",
51 | "* [Jupyter Notebook User Interface](https://jupyter-notebook.readthedocs.io/en/stable/notebook.html#notebook-user-interface)\n",
52 | "* [Overview of Google Colaboratory Features](https://colab.research.google.com/notebooks/basic_features_overview.ipynb)\n",
53 | "\n",
54 | "\n",
55 | "\n",
56 | "Happy hacking!\n",
57 | "\n",
58 | "\n",
59 | "
\n",
60 | "\n"
61 | ]
62 | },
63 | {
64 | "cell_type": "markdown",
65 | "metadata": {
66 | "id": "NFhAzQB3aNMa"
67 | },
68 | "source": [
69 | "### Download the code zip file"
70 | ]
71 | },
72 | {
73 | "cell_type": "code",
74 | "metadata": {
75 | "id": "7y0LG1EuaRlB"
76 | },
77 | "source": [
78 | "!wget https://pyimagesearch-code-downloads.s3-us-west-2.amazonaws.com/opencv-split-merge/opencv-split-merge.zip\n",
79 | "!unzip -qq opencv-split-merge.zip\n",
80 | "%cd opencv-split-merge"
81 | ],
82 | "execution_count": null,
83 | "outputs": []
84 | },
85 | {
86 | "cell_type": "markdown",
87 | "metadata": {
88 | "id": "_SgTVT3HagGZ"
89 | },
90 | "source": [
91 | "## Blog Post Code"
92 | ]
93 | },
94 | {
95 | "cell_type": "markdown",
96 | "metadata": {
97 | "id": "wcrOk6pURp50"
98 | },
99 | "source": [
100 | "### Import Packages"
101 | ]
102 | },
103 | {
104 | "cell_type": "code",
105 | "metadata": {
106 | "id": "VJaCNlDDRz6d"
107 | },
108 | "source": [
109 | "# import the necessary packages\n",
110 | "from matplotlib import pyplot as plt\n",
111 | "import numpy as np\n",
112 | "import argparse\n",
113 | "import cv2"
114 | ],
115 | "execution_count": null,
116 | "outputs": []
117 | },
118 | {
119 | "cell_type": "markdown",
120 | "metadata": {
121 | "id": "lBrLwCtN5kqy"
122 | },
123 | "source": [
124 | "### Function to display images in Jupyter Notebooks and Google Colab"
125 | ]
126 | },
127 | {
128 | "cell_type": "code",
129 | "metadata": {
130 | "id": "fRw969Dp5Kdm"
131 | },
132 | "source": [
133 | "def plt_imshow(title, image):\n",
134 | "\t# convert the image frame BGR to RGB color space and display it\n",
135 | "\timage = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n",
136 | "\tplt.imshow(image)\n",
137 | "\tplt.title(title)\n",
138 | "\tplt.grid(False)\n",
139 | "\tplt.show()"
140 | ],
141 | "execution_count": null,
142 | "outputs": []
143 | },
144 | {
145 | "cell_type": "markdown",
146 | "metadata": {
147 | "id": "70hAWGrBDMli"
148 | },
149 | "source": [
150 | "### How to split and merge channels with OpenCV\n"
151 | ]
152 | },
153 | {
154 | "cell_type": "code",
155 | "metadata": {
156 | "id": "AgdFxpQRDO9g"
157 | },
158 | "source": [
159 | "# # construct the argument parser and parse the arguments\n",
160 | "# ap = argparse.ArgumentParser()\n",
161 | "# ap.add_argument(\"-i\", \"--image\", type=str, default=\"opencv_logo.png\",\n",
162 | "# \thelp=\"path to the input image\")\n",
163 | "# args = vars(ap.parse_args())\n",
164 | "\n",
165 | "# since we are using Jupyter Notebooks we can replace our argument\n",
166 | "# parsing code with *hard coded* arguments and values\n",
167 | "args = {\n",
168 | "\t\"image\": \"opencv_logo.png\"\n",
169 | "}"
170 | ],
171 | "execution_count": null,
172 | "outputs": []
173 | },
174 | {
175 | "cell_type": "code",
176 | "metadata": {
177 | "id": "lE64rhBbMxI9"
178 | },
179 | "source": [
180 | "# load the input image and grab each channel -- note how OpenCV\n",
181 | "# represents images as NumPy arrays with channels in Blue, Green,\n",
182 | "# Red ordering rather than Red, Green Blue\n",
183 | "image = cv2.imread(args[\"image\"])\n",
184 | "(B, G, R) = cv2.split(image)\n",
185 | "\n",
186 | "# show each channel individually\n",
187 | "plt_imshow(\"Red\", R)\n",
188 | "plt_imshow(\"Green\", G)\n",
189 | "plt_imshow(\"Blue\", B)"
190 | ],
191 | "execution_count": null,
192 | "outputs": []
193 | },
194 | {
195 | "cell_type": "code",
196 | "metadata": {
197 | "id": "plY2SePZM2Nt"
198 | },
199 | "source": [
200 | "merged = cv2.merge([B, G, R])\n",
201 | "plt_imshow(\"Merged\", merged)"
202 | ],
203 | "execution_count": null,
204 | "outputs": []
205 | },
206 | {
207 | "cell_type": "code",
208 | "metadata": {
209 | "id": "MFS3mhQVNwrz"
210 | },
211 | "source": [
212 | "# visualize each channel in color\n",
213 | "zeros = np.zeros(image.shape[:2], dtype=\"uint8\")\n",
214 | "plt_imshow(\"Red\", cv2.merge([zeros, zeros, R]))\n",
215 | "plt_imshow(\"Green\", cv2.merge([zeros, G, zeros]))\n",
216 | "plt_imshow(\"Blue\", cv2.merge([B, zeros, zeros]))"
217 | ],
218 | "execution_count": null,
219 | "outputs": []
220 | },
221 | {
222 | "cell_type": "markdown",
223 | "metadata": {
224 | "id": "xPnqHE_ON8jG"
225 | },
226 | "source": [
227 | "For a detailed walkthrough of the concepts and code, be sure to refer to the full tutorial, [*Splitting and Merging Channels with OpenCV*](https://www.pyimagesearch.com/2021/01/23/splitting-and-merging-channels-with-opencv/) published on 01-23-2021."
228 | ]
229 | }
230 | ]
231 | }
232 |
--------------------------------------------------------------------------------
/108_opencv_masking.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "colab": {
6 | "name": "108-opencv_masking.ipynb",
7 | "provenance": [],
8 | "collapsed_sections": [],
9 | "toc_visible": true,
10 | "include_colab_link": true
11 | },
12 | "kernelspec": {
13 | "name": "python3",
14 | "display_name": "Python 3"
15 | }
16 | },
17 | "cells": [
18 | {
19 | "cell_type": "markdown",
20 | "metadata": {
21 | "id": "view-in-github",
22 | "colab_type": "text"
23 | },
24 | "source": [
25 | "
"
26 | ]
27 | },
28 | {
29 | "cell_type": "markdown",
30 | "metadata": {
31 | "id": "j4RpK9pawQzP"
32 | },
33 | "source": [
34 | "# Image Masking with OpenCV"
35 | ]
36 | },
37 | {
38 | "cell_type": "markdown",
39 | "metadata": {
40 | "id": "8ntZ1AkXZIxY"
41 | },
42 | "source": [
43 | "\n",
44 | "\n",
45 | "This notebook is associated with the [Image Masking with OpenCV](https://www.pyimagesearch.com/2021/01/19/image-masking-with-opencv/) blog post published on 01-19-2021.\n",
46 | "\n",
47 | "Only the code for the blog post is here. Most codeblocks have a 1:1 relationship with what you find in the blog post with two exceptions: (1) Python classes are not separate files as they are typically organized with PyImageSearch projects, and (2) Command Line Argument parsing is replaced with an `args` dictionary that you can manipulate as needed.\n",
48 | "\n",
49 | "We recommend that you execute (press ▶️) the code block-by-block, as-is, before adjusting parameters and `args` inputs. Once you've verified that the code is working, you are welcome to hack with it and learn from manipulating inputs, settings, and parameters. For more information on using Jupyter and Colab, please refer to these resources:\n",
50 | "\n",
51 | "* [Jupyter Notebook User Interface](https://jupyter-notebook.readthedocs.io/en/stable/notebook.html#notebook-user-interface)\n",
52 | "* [Overview of Google Colaboratory Features](https://colab.research.google.com/notebooks/basic_features_overview.ipynb)\n",
53 | "\n",
54 | "\n",
55 | "\n",
56 | "Happy hacking!\n",
57 | "\n",
58 | "\n",
59 | "\n",
60 | "
\n",
61 | "\n"
62 | ]
63 | },
64 | {
65 | "cell_type": "markdown",
66 | "metadata": {
67 | "id": "NFhAzQB3aNMa"
68 | },
69 | "source": [
70 | "### Download the code zip file"
71 | ]
72 | },
73 | {
74 | "cell_type": "code",
75 | "metadata": {
76 | "id": "7y0LG1EuaRlB"
77 | },
78 | "source": [
79 | "!wget https://pyimagesearch-code-downloads.s3-us-west-2.amazonaws.com/opencv-masking/opencv-masking.zip\n",
80 | "!unzip -qq opencv-masking.zip\n",
81 | "%cd opencv-masking"
82 | ],
83 | "execution_count": null,
84 | "outputs": []
85 | },
86 | {
87 | "cell_type": "markdown",
88 | "metadata": {
89 | "id": "_SgTVT3HagGZ"
90 | },
91 | "source": [
92 | "## Blog Post Code"
93 | ]
94 | },
95 | {
96 | "cell_type": "markdown",
97 | "metadata": {
98 | "id": "wcrOk6pURp50"
99 | },
100 | "source": [
101 | "### Import Packages"
102 | ]
103 | },
104 | {
105 | "cell_type": "code",
106 | "metadata": {
107 | "id": "VJaCNlDDRz6d"
108 | },
109 | "source": [
110 | "# import the necessary packages\n",
111 | "from matplotlib import pyplot as plt\n",
112 | "import numpy as np\n",
113 | "import argparse\n",
114 | "import cv2"
115 | ],
116 | "execution_count": null,
117 | "outputs": []
118 | },
119 | {
120 | "cell_type": "markdown",
121 | "metadata": {
122 | "id": "lBrLwCtN5kqy"
123 | },
124 | "source": [
125 | "### Function to display images in Jupyter Notebooks and Google Colab"
126 | ]
127 | },
128 | {
129 | "cell_type": "code",
130 | "metadata": {
131 | "id": "fRw969Dp5Kdm"
132 | },
133 | "source": [
134 | "def plt_imshow(title, image):\n",
135 | "\t# convert the image frame BGR to RGB color space and display it\n",
136 | "\timage = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n",
137 | "\tplt.imshow(image)\n",
138 | "\tplt.title(title)\n",
139 | "\tplt.grid(False)\n",
140 | "\tplt.show()"
141 | ],
142 | "execution_count": null,
143 | "outputs": []
144 | },
145 | {
146 | "cell_type": "markdown",
147 | "metadata": {
148 | "id": "RDzVnVDL7oNg"
149 | },
150 | "source": [
151 | "### Implementing image arithmetic with OpenCV"
152 | ]
153 | },
154 | {
155 | "cell_type": "code",
156 | "metadata": {
157 | "id": "C0VidOkV64nK"
158 | },
159 | "source": [
160 | "# # construct the argument parser and parse the arguments\n",
161 | "# ap = argparse.ArgumentParser()\n",
162 | "# ap.add_argument(\"-i\", \"--image\", type=str, default=\"grand_canyon.png\",\n",
163 | "# \thelp=\"path to the input image\")\n",
164 | "# args = vars(ap.parse_args())\n",
165 | "\n",
166 | "# since we are using Jupyter Notebooks we can replace our argument\n",
167 | "# parsing code with *hard coded* arguments and values\n",
168 | "args = {\n",
169 | "\t\"image\": \"adrian.png\"\n",
170 | "}"
171 | ],
172 | "execution_count": null,
173 | "outputs": []
174 | },
175 | {
176 | "cell_type": "code",
177 | "metadata": {
178 | "id": "4e3yPYPx7uU2"
179 | },
180 | "source": [
181 | "# load the original input image and display it to our screen\n",
182 | "image = cv2.imread(args[\"image\"])\n",
183 | "plt_imshow(\"Original\", image)\n",
184 | "\n",
185 | "# a mask is the same size as our image, but has only two pixel\n",
186 | "# values, 0 and 255 -- pixels with a value of 0 (background) are\n",
187 | "# ignored in the original image while mask pixels with a value of\n",
188 | "# 255 (foreground) are allowed to be kept\n",
189 | "mask = np.zeros(image.shape[:2], dtype=\"uint8\")\n",
190 | "cv2.rectangle(mask, (0, 90), (290, 450), 255, -1)\n",
191 | "plt_imshow(\"Rectangular Mask\", mask)\n",
192 | "\n",
193 | "# apply our mask -- notice how only the person in the image is\n",
194 | "# cropped out\n",
195 | "masked = cv2.bitwise_and(image, image, mask=mask)\n",
196 | "plt_imshow(\"Mask Applied to Image\", masked)"
197 | ],
198 | "execution_count": null,
199 | "outputs": []
200 | },
201 | {
202 | "cell_type": "code",
203 | "metadata": {
204 | "id": "IhjnVmLc70Iu"
205 | },
206 | "source": [
207 | "# now, let's make a circular mask with a radius of 100 pixels and\n",
208 | "# apply the mask again\n",
209 | "mask = np.zeros(image.shape[:2], dtype=\"uint8\")\n",
210 | "cv2.circle(mask, (145, 200), 100, 255, -1)\n",
211 | "masked = cv2.bitwise_and(image, image, mask=mask)\n",
212 | "\n",
213 | "# show the output images\n",
214 | "plt_imshow(\"Circular Mask\", mask)\n",
215 | "plt_imshow(\"Mask Applied to Image\", masked)"
216 | ],
217 | "execution_count": null,
218 | "outputs": []
219 | },
220 | {
221 | "cell_type": "markdown",
222 | "metadata": {
223 | "id": "4ogkNauArL6u"
224 | },
225 | "source": [
226 | "For a detailed walkthrough of the concepts and code, be sure to refer to the full tutorial, [*Image Masking with OpenCV*](https://www.pyimagesearch.com/2021/01/19/image-masking-with-opencv/) published on 01-19-2021."
227 | ]
228 | }
229 | ]
230 | }
--------------------------------------------------------------------------------
/204_opencv_color_spaces.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "colab": {
6 | "name": "204-opencv_color_spaces.ipynb",
7 | "provenance": [],
8 | "collapsed_sections": [],
9 | "toc_visible": true,
10 | "include_colab_link": true
11 | },
12 | "kernelspec": {
13 | "name": "python3",
14 | "display_name": "Python 3"
15 | },
16 | "language_info": {
17 | "name": "python"
18 | }
19 | },
20 | "cells": [
21 | {
22 | "cell_type": "markdown",
23 | "metadata": {
24 | "id": "view-in-github",
25 | "colab_type": "text"
26 | },
27 | "source": [
28 | "
"
29 | ]
30 | },
31 | {
32 | "cell_type": "markdown",
33 | "metadata": {
34 | "id": "c7uPgNc0NyO7"
35 | },
36 | "source": [
37 | "# OpenCV Color Spaces ( cv2.cvtColor )\n",
38 | "\n"
39 | ]
40 | },
41 | {
42 | "cell_type": "markdown",
43 | "metadata": {
44 | "id": "Mpthbjs-N2qJ"
45 | },
46 | "source": [
47 | "\n",
48 | "This notebook is associated with the [OpenCV Color Spaces ( cv2.cvtColor )](https://www.pyimagesearch.com/2021/04/28/opencv-color-spaces-cv2-cvtcolor/) blog post published on 04-28-21.\n",
49 | "\n",
50 | "Only the code for the blog post is here. Most codeblocks have a 1:1 relationship with what you find in the blog post with two exceptions: (1) Python classes are not separate files as they are typically organized with PyImageSearch projects, and (2) Command Line Argument parsing is replaced with an `args` dictionary that you can manipulate as needed.\n",
51 | "\n",
52 | "We recommend that you execute (press ▶️) the code block-by-block, as-is, before adjusting parameters and `args` inputs. Once you've verified that the code is working, you are welcome to hack with it and learn from manipulating inputs, settings, and parameters. For more information on using Jupyter and Colab, please refer to these resources:\n",
53 | "\n",
54 | "* [Jupyter Notebook User Interface](https://jupyter-notebook.readthedocs.io/en/stable/notebook.html#notebook-user-interface)\n",
55 | "* [Overview of Google Colaboratory Features](https://colab.research.google.com/notebooks/basic_features_overview.ipynb)\n",
56 | "\n",
57 | "\n",
58 | "Happy hacking!\n",
59 | "\n",
60 | "
\n",
61 | "\n"
62 | ]
63 | },
64 | {
65 | "cell_type": "markdown",
66 | "metadata": {
67 | "id": "0pL5rHGgOAMk"
68 | },
69 | "source": [
70 | "### Download the code zip file"
71 | ]
72 | },
73 | {
74 | "cell_type": "code",
75 | "metadata": {
76 | "id": "g1LJpLYFqhjX"
77 | },
78 | "source": [
79 | "!wget https://pyimagesearch-code-downloads.s3-us-west-2.amazonaws.com/opencv-color-spaces/opencv-color-spaces.zip\n",
80 | "!unzip -qq opencv-color-spaces.zip\n",
81 | "%cd opencv-color-spaces"
82 | ],
83 | "execution_count": null,
84 | "outputs": []
85 | },
86 | {
87 | "cell_type": "markdown",
88 | "metadata": {
89 | "id": "8yYRCnThOQXl"
90 | },
91 | "source": [
92 | "## Blog Post Code"
93 | ]
94 | },
95 | {
96 | "cell_type": "markdown",
97 | "metadata": {
98 | "id": "BcmY4DDJOSIt"
99 | },
100 | "source": [
101 | "### Import Packages"
102 | ]
103 | },
104 | {
105 | "cell_type": "code",
106 | "metadata": {
107 | "id": "BlcPho8lOOuF"
108 | },
109 | "source": [
110 | "# import the necessary packages\n",
111 | "import matplotlib.pyplot as plt\n",
112 | "import cv2"
113 | ],
114 | "execution_count": null,
115 | "outputs": []
116 | },
117 | {
118 | "cell_type": "markdown",
119 | "metadata": {
120 | "id": "uY1ceK63OuFY"
121 | },
122 | "source": [
123 | "### Function to display images in Jupyter Notebooks and Google Colab"
124 | ]
125 | },
126 | {
127 | "cell_type": "code",
128 | "metadata": {
129 | "id": "gkPDb7emOuwQ"
130 | },
131 | "source": [
132 | "def plt_imshow(title, image):\n",
133 | " # convert the image frame BGR to RGB color space and display it\n",
134 | " if len(image.shape) == 3:\n",
135 | " image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n",
136 | " plt.imshow(image)\n",
137 | " plt.title(title)\n",
138 | " plt.grid(False)\n",
139 | " plt.show()"
140 | ],
141 | "execution_count": null,
142 | "outputs": []
143 | },
144 | {
145 | "cell_type": "code",
146 | "metadata": {
147 | "id": "F9dtsgjQqqYT"
148 | },
149 | "source": [
150 | "# # construct the argument parser and parse the arguments\n",
151 | "# ap = argparse.ArgumentParser()\n",
152 | "# ap.add_argument(\"-i\", \"--image\", type=str, default=\"adrian.png\",\n",
153 | "# \thelp=\"path to input image\")\n",
154 | "# args = vars(ap.parse_args())\n",
155 | "\n",
156 | "# since we are using Jupyter Notebooks we can replace our argument\n",
157 | "# parsing code with *hard coded* arguments and values\n",
158 | "args = {\n",
159 | " \"image\": \"adrian.png\",\n",
160 | "}"
161 | ],
162 | "execution_count": null,
163 | "outputs": []
164 | },
165 | {
166 | "cell_type": "code",
167 | "metadata": {
168 | "id": "wwKrgN2FrH_U"
169 | },
170 | "source": [
171 | "# load the original image and show it\n",
172 | "image = cv2.imread(args[\"image\"])\n",
173 | "plt_imshow(\"RGB\", image)\n",
174 | "\n",
175 | "# loop over each of the individual channels and display them\n",
176 | "for (name, chan) in zip((\"B\", \"G\", \"R\"), cv2.split(image)):\n",
177 | " plt_imshow(name, chan)"
178 | ],
179 | "execution_count": null,
180 | "outputs": []
181 | },
182 | {
183 | "cell_type": "code",
184 | "metadata": {
185 | "id": "1_ajNtgSr-UL"
186 | },
187 | "source": [
188 | "# convert the image to the HSV color space and show it\n",
189 | "hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)\n",
190 | "plt_imshow(\"HSV\", hsv)\n",
191 | "\n",
192 | "# loop over each of the invidiaul channels and display them\n",
193 | "for (name, chan) in zip((\"H\", \"S\", \"V\"), cv2.split(hsv)):\n",
194 | "\tplt_imshow(name, chan)"
195 | ],
196 | "execution_count": null,
197 | "outputs": []
198 | },
199 | {
200 | "cell_type": "code",
201 | "metadata": {
202 | "id": "mH6akE2NsbdG"
203 | },
204 | "source": [
205 | "# convert the image to the L*a*b* color space and show it\n",
206 | "lab = cv2.cvtColor(image, cv2.COLOR_BGR2LAB)\n",
207 | "plt_imshow(\"L*a*b*\", lab)\n",
208 | "\n",
209 | "# loop over each of the invidiaul channels and display them\n",
210 | "for (name, chan) in zip((\"L*\", \"a*\", \"b*\"), cv2.split(lab)):\n",
211 | "\tplt_imshow(name, chan)"
212 | ],
213 | "execution_count": null,
214 | "outputs": []
215 | },
216 | {
217 | "cell_type": "code",
218 | "metadata": {
219 | "id": "o3wfUE87st8U"
220 | },
221 | "source": [
222 | "# show the original and grayscale versions of the image\n",
223 | "gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)\n",
224 | "plt_imshow(\"Original\", image)\n",
225 | "plt_imshow(\"Grayscale\", gray)"
226 | ],
227 | "execution_count": null,
228 | "outputs": []
229 | },
230 | {
231 | "cell_type": "markdown",
232 | "metadata": {
233 | "id": "iIK0y_52aETm"
234 | },
235 | "source": [
236 | "For a detailed walkthrough of the concepts and code, be sure to refer to the full tutorial, [OpenCV Color Spaces ( cv2.cvtColor )](https://www.pyimagesearch.com/2021/04/28/opencv-color-spaces-cv2-cvtcolor/) published on 04-28-21."
237 | ]
238 | }
239 | ]
240 | }
--------------------------------------------------------------------------------
/107_opencv_bitwise.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "colab": {
6 | "name": "107-opencv_bitwise.ipynb",
7 | "provenance": [],
8 | "collapsed_sections": [],
9 | "include_colab_link": true
10 | },
11 | "kernelspec": {
12 | "name": "python3",
13 | "display_name": "Python 3"
14 | }
15 | },
16 | "cells": [
17 | {
18 | "cell_type": "markdown",
19 | "metadata": {
20 | "id": "view-in-github",
21 | "colab_type": "text"
22 | },
23 | "source": [
24 | "
"
25 | ]
26 | },
27 | {
28 | "cell_type": "markdown",
29 | "metadata": {
30 | "id": "j4RpK9pawQzP"
31 | },
32 | "source": [
33 | "# OpenCV Bitwise AND, OR, XOR, and NOT\n"
34 | ]
35 | },
36 | {
37 | "cell_type": "markdown",
38 | "metadata": {
39 | "id": "8ntZ1AkXZIxY"
40 | },
41 | "source": [
42 | "## Welcome to **[PyImageSearch Plus](http://pyimg.co/plus)** Jupyter Notebooks!\n",
43 | "\n",
44 | "This notebook is associated with the [OpenCV Bitwise AND, OR, XOR, and NOT](https://www.pyimagesearch.com/2021/01/19/opencv-bitwise-and-or-xor-and-not/) blog post published on 01-19-2021.\n",
45 | "\n",
46 | "Only the code for the blog post is here. Most codeblocks have a 1:1 relationship with what you find in the blog post with two exceptions: (1) Python classes are not separate files as they are typically organized with PyImageSearch projects, and (2) Command Line Argument parsing is replaced with an `args` dictionary that you can manipulate as needed.\n",
47 | "\n",
48 | "We recommend that you execute (press ▶️) the code block-by-block, as-is, before adjusting parameters and `args` inputs. Once you've verified that the code is working, you are welcome to hack with it and learn from manipulating inputs, settings, and parameters. For more information on using Jupyter and Colab, please refer to these resources:\n",
49 | "\n",
50 | "* [Jupyter Notebook User Interface](https://jupyter-notebook.readthedocs.io/en/stable/notebook.html#notebook-user-interface)\n",
51 | "* [Overview of Google Colaboratory Features](https://colab.research.google.com/notebooks/basic_features_overview.ipynb)\n",
52 | " \n",
53 | "\n",
54 | "Happy hacking!\n",
55 | "\n",
56 | "\n",
57 | "\n",
58 | "
\n",
59 | "\n"
60 | ]
61 | },
62 | {
63 | "cell_type": "markdown",
64 | "metadata": {
65 | "id": "NFhAzQB3aNMa"
66 | },
67 | "source": [
68 | "### Download the code zip file"
69 | ]
70 | },
71 | {
72 | "cell_type": "code",
73 | "metadata": {
74 | "id": "7y0LG1EuaRlB"
75 | },
76 | "source": [
77 | "!wget https://pyimagesearch-code-downloads.s3-us-west-2.amazonaws.com/opencv-bitwise/opencv-bitwise.zip\n",
78 | "!unzip -qq opencv-bitwise.zip\n",
79 | "%cd opencv-bitwise.zip"
80 | ],
81 | "execution_count": null,
82 | "outputs": []
83 | },
84 | {
85 | "cell_type": "markdown",
86 | "metadata": {
87 | "id": "_SgTVT3HagGZ"
88 | },
89 | "source": [
90 | "## Blog Post Code"
91 | ]
92 | },
93 | {
94 | "cell_type": "markdown",
95 | "metadata": {
96 | "id": "wcrOk6pURp50"
97 | },
98 | "source": [
99 | "### Import Packages"
100 | ]
101 | },
102 | {
103 | "cell_type": "code",
104 | "metadata": {
105 | "id": "VJaCNlDDRz6d"
106 | },
107 | "source": [
108 | "# import the necessary packages\n",
109 | "from matplotlib import pyplot as plt\n",
110 | "import numpy as np\n",
111 | "import cv2"
112 | ],
113 | "execution_count": null,
114 | "outputs": []
115 | },
116 | {
117 | "cell_type": "markdown",
118 | "metadata": {
119 | "id": "lBrLwCtN5kqy"
120 | },
121 | "source": [
122 | "### Function to display images in Jupyter Notebooks and Google Colab"
123 | ]
124 | },
125 | {
126 | "cell_type": "code",
127 | "metadata": {
128 | "id": "fRw969Dp5Kdm"
129 | },
130 | "source": [
131 | "def plt_imshow(title, image):\n",
132 | "\t# convert the image frame BGR to RGB color space and display it\n",
133 | "\timage = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n",
134 | "\tplt.imshow(image)\n",
135 | "\tplt.title(title)\n",
136 | "\tplt.grid(False)\n",
137 | "\tplt.show()"
138 | ],
139 | "execution_count": null,
140 | "outputs": []
141 | },
142 | {
143 | "cell_type": "markdown",
144 | "metadata": {
145 | "id": "wqHP1MnPBCLX"
146 | },
147 | "source": [
148 | "### Implementing OpenCV AND, OR, XOR, and NOT bitwise operators"
149 | ]
150 | },
151 | {
152 | "cell_type": "code",
153 | "metadata": {
154 | "id": "-9UoHbsG_3Qv"
155 | },
156 | "source": [
157 | "# draw a rectangle\n",
158 | "rectangle = np.zeros((300, 300), dtype=\"uint8\")\n",
159 | "cv2.rectangle(rectangle, (25, 25), (275, 275), 255, -1)\n",
160 | "plt_imshow(\"Rectangle\", rectangle)\n",
161 | "\n",
162 | "# draw a circle\n",
163 | "circle = np.zeros((300, 300), dtype = \"uint8\")\n",
164 | "cv2.circle(circle, (150, 150), 150, 255, -1)\n",
165 | "plt_imshow(\"Circle\", circle)"
166 | ],
167 | "execution_count": null,
168 | "outputs": []
169 | },
170 | {
171 | "cell_type": "code",
172 | "metadata": {
173 | "id": "zDq5smbuBILh"
174 | },
175 | "source": [
176 | "# a bitwise 'AND' is only 'True' when both inputs have a value that\n",
177 | "# is \"ON' -- in this case, the cv2.bitwise_and function examines\n",
178 | "# every pixel in the rectangle and circle; if *BOTH* pixels have a\n",
179 | "# value greater than zero then the pixel is turned 'ON (i.e., 255)\n",
180 | "# in the output image; otherwise, the output value is set to\n",
181 | "# 'OFF' (i.e., 0)\n",
182 | "bitwiseAnd = cv2.bitwise_and(rectangle, circle)\n",
183 | "plt_imshow(\"AND\", bitwiseAnd)"
184 | ],
185 | "execution_count": null,
186 | "outputs": []
187 | },
188 | {
189 | "cell_type": "code",
190 | "metadata": {
191 | "id": "1s8j9h31BNYT"
192 | },
193 | "source": [
194 | "# a bitwise 'OR' examines every pixel in the two inputs, and if\n",
195 | "# *EITHER* pixel in the rectangle or circle is greater than zero,\n",
196 | "# then the output pixel has a value of 255, otherwise it is 0\n",
197 | "bitwiseOr = cv2.bitwise_or(rectangle, circle)\n",
198 | "plt_imshow(\"OR\", bitwiseOr)"
199 | ],
200 | "execution_count": null,
201 | "outputs": []
202 | },
203 | {
204 | "cell_type": "code",
205 | "metadata": {
206 | "id": "ikLIrzexBRPR"
207 | },
208 | "source": [
209 | "# the bitwise 'XOR' is identical to the 'OR' function, with one\n",
210 | "# exception: both the rectangle and circle are not allowed to *BOTH*\n",
211 | "# have values greater than 0 (only one can be 0)\n",
212 | "bitwiseXor = cv2.bitwise_xor(rectangle, circle)\n",
213 | "plt_imshow(\"XOR\", bitwiseXor)"
214 | ],
215 | "execution_count": null,
216 | "outputs": []
217 | },
218 | {
219 | "cell_type": "code",
220 | "metadata": {
221 | "id": "hDOJaJcTBT_4"
222 | },
223 | "source": [
224 | "# finally, the bitwise 'NOT' inverts the values of the pixels; pixels\n",
225 | "# with a value of 255 become 0, and pixels with a value of 0 become\n",
226 | "# 255\n",
227 | "bitwiseNot = cv2.bitwise_not(circle)\n",
228 | "plt_imshow(\"NOT\", bitwiseNot)"
229 | ],
230 | "execution_count": null,
231 | "outputs": []
232 | },
233 | {
234 | "cell_type": "markdown",
235 | "metadata": {
236 | "id": "4ogkNauArL6u"
237 | },
238 | "source": [
239 | "For a detailed walkthrough of the concepts and code, be sure to refer to the full tutorial, [*OpenCV Bitwise AND, OR, XOR, and NOT*](https://www.pyimagesearch.com/2021/01/19/opencv-bitwise-and-or-xor-and-not/) published on 01-19-2021."
240 | ]
241 | }
242 | ]
243 | }
--------------------------------------------------------------------------------
/209_auto_canny.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "colab": {
6 | "name": "208-auto_canny.ipynb",
7 | "provenance": [],
8 | "collapsed_sections": [],
9 | "include_colab_link": true
10 | },
11 | "kernelspec": {
12 | "display_name": "Python 3",
13 | "language": "python",
14 | "name": "python3"
15 | },
16 | "language_info": {
17 | "codemirror_mode": {
18 | "name": "ipython",
19 | "version": 3
20 | },
21 | "file_extension": ".py",
22 | "mimetype": "text/x-python",
23 | "name": "python",
24 | "nbconvert_exporter": "python",
25 | "pygments_lexer": "ipython3",
26 | "version": "3.8.3"
27 | }
28 | },
29 | "cells": [
30 | {
31 | "cell_type": "markdown",
32 | "metadata": {
33 | "id": "view-in-github",
34 | "colab_type": "text"
35 | },
36 | "source": [
37 | "
"
38 | ]
39 | },
40 | {
41 | "cell_type": "markdown",
42 | "metadata": {
43 | "id": "j4RpK9pawQzP"
44 | },
45 | "source": [
46 | "# Zero-parameter, automatic Canny edge detection with Python and OpenCV\n"
47 | ]
48 | },
49 | {
50 | "cell_type": "markdown",
51 | "metadata": {
52 | "id": "8ntZ1AkXZIxY"
53 | },
54 | "source": [
55 | "\n",
56 | "This notebook is associated with the [Zero-parameter, automatic Canny edge detection with Python and OpenCV](https://www.pyimagesearch.com/2015/04/06/zero-parameter-automatic-canny-edge-detection-with-python-and-opencv/) blog post published on 2015-04-06.\n",
57 | "\n",
58 | "Only the code for the blog post is here. Most codeblocks have a 1:1 relationship with what you find in the blog post with two exceptions: (1) Python classes are not separate files as they are typically organized with PyImageSearch projects, and (2) Command Line Argument parsing is replaced with an `args` dictionary that you can manipulate as needed.\n",
59 | "\n",
60 | "We recommend that you execute (press ▶️) the code block-by-block, as-is, before adjusting parameters and `args` inputs. Once you've verified that the code is working, you are welcome to hack with it and learn from manipulating inputs, settings, and parameters. For more information on using Jupyter and Colab, please refer to these resources:\n",
61 | "\n",
62 | "* [Jupyter Notebook User Interface](https://jupyter-notebook.readthedocs.io/en/stable/notebook.html#notebook-user-interface)\n",
63 | "* [Overview of Google Colaboratory Features](https://colab.research.google.com/notebooks/basic_features_overview.ipynb)\n",
64 | "\n",
65 | "\n",
66 | "\n",
67 | "Happy hacking!\n",
68 | "\n",
69 | "\n",
70 | "
\n"
71 | ]
72 | },
73 | {
74 | "cell_type": "markdown",
75 | "metadata": {
76 | "id": "NFhAzQB3aNMa"
77 | },
78 | "source": [
79 | "### Download the code zip file"
80 | ]
81 | },
82 | {
83 | "cell_type": "code",
84 | "metadata": {
85 | "id": "7y0LG1EuaRlB"
86 | },
87 | "source": [
88 | "!wget https://www.pyimagesearch.com/wp-content/uploads/2015/01/auto-canny.zip\n",
89 | "!unzip -qq auto-canny.zip\n",
90 | "%cd auto-canny"
91 | ],
92 | "execution_count": null,
93 | "outputs": []
94 | },
95 | {
96 | "cell_type": "markdown",
97 | "metadata": {
98 | "id": "_SgTVT3HagGZ"
99 | },
100 | "source": [
101 | "## Blog Post Code"
102 | ]
103 | },
104 | {
105 | "cell_type": "markdown",
106 | "metadata": {
107 | "id": "wcrOk6pURp50"
108 | },
109 | "source": [
110 | "### Import Packages"
111 | ]
112 | },
113 | {
114 | "cell_type": "code",
115 | "metadata": {
116 | "id": "VJaCNlDDRz6d"
117 | },
118 | "source": [
119 | "# import the necessary packages\n",
120 | "from matplotlib import pyplot as plt\n",
121 | "import numpy as np\n",
122 | "import argparse\n",
123 | "import glob\n",
124 | "import cv2"
125 | ],
126 | "execution_count": null,
127 | "outputs": []
128 | },
129 | {
130 | "cell_type": "markdown",
131 | "metadata": {
132 | "id": "lBrLwCtN5kqy"
133 | },
134 | "source": [
135 | "### Function to display images in Jupyter Notebooks and Google Colab"
136 | ]
137 | },
138 | {
139 | "cell_type": "code",
140 | "metadata": {
141 | "id": "fRw969Dp5Kdm"
142 | },
143 | "source": [
144 | "def plt_imshow(title, image):\n",
145 | "\t# convert the image frame BGR to RGB color space and display it\n",
146 | "\timage = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n",
147 | "\tplt.imshow(image)\n",
148 | "\tplt.title(title)\n",
149 | "\tplt.grid(False)\n",
150 | "\tplt.show()"
151 | ],
152 | "execution_count": null,
153 | "outputs": []
154 | },
155 | {
156 | "cell_type": "markdown",
157 | "metadata": {
158 | "id": "Jppw5-Bd56H-"
159 | },
160 | "source": [
161 | "### Zero-parameter, automatic Canny edge detection with Python and OpenCV"
162 | ]
163 | },
164 | {
165 | "cell_type": "code",
166 | "metadata": {
167 | "id": "puEwrYdqM4XR"
168 | },
169 | "source": [
170 | "def auto_canny(image, sigma=0.33):\n",
171 | "\t# compute the median of the single channel pixel intensities\n",
172 | "\tv = np.median(image)\n",
173 | "\n",
174 | "\t# apply automatic Canny edge detection using the computed median\n",
175 | "\tlower = int(max(0, (1.0 - sigma) * v))\n",
176 | "\tupper = int(min(255, (1.0 + sigma) * v))\n",
177 | "\tedged = cv2.Canny(image, lower, upper)\n",
178 | "\n",
179 | "\t# return the edged image\n",
180 | "\treturn edged"
181 | ],
182 | "execution_count": null,
183 | "outputs": []
184 | },
185 | {
186 | "cell_type": "code",
187 | "metadata": {
188 | "id": "okM7Bpyeq8Kc"
189 | },
190 | "source": [
191 | "# construct the argument parser and parse the arguments\n",
192 | "# ap = argparse.ArgumentParser()\n",
193 | "# ap.add_argument(\"-i\", \"--images\", required=True,\n",
194 | "# \thelp=\"path to input dataset of images\")\n",
195 | "# args = vars(ap.parse_args())\n",
196 | "\n",
197 | "# since we are using Jupyter Notebooks we can replace our argument\n",
198 | "# parsing code with *hard coded* arguments and values\n",
199 | "args = {\n",
200 | "\t\"images\": \"images\"\n",
201 | "}"
202 | ],
203 | "execution_count": null,
204 | "outputs": []
205 | },
206 | {
207 | "cell_type": "code",
208 | "metadata": {
209 | "id": "_5voxYEVNGEC"
210 | },
211 | "source": [
212 | "# loop over the images\n",
213 | "for imagePath in glob.glob(args[\"images\"] + \"/*.jpg\"):\n",
214 | "\t# load the image, convert it to grayscale, and blur it slightly\n",
215 | "\timage = cv2.imread(imagePath)\n",
216 | "\tgray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)\n",
217 | "\tblurred = cv2.GaussianBlur(gray, (3, 3), 0)\n",
218 | "\n",
219 | "\t# apply Canny edge detection using a wide threshold, tight\n",
220 | "\t# threshold, and automatically determined threshold\n",
221 | "\twide = cv2.Canny(blurred, 10, 200)\n",
222 | "\ttight = cv2.Canny(blurred, 225, 250)\n",
223 | "\tauto = auto_canny(blurred)\n",
224 | "\n",
225 | "\t# show the images\n",
226 | "\tplt_imshow(\"Original\", image)\n",
227 | "\tplt_imshow(\"Edges\", np.hstack([wide, tight, auto]))"
228 | ],
229 | "execution_count": null,
230 | "outputs": []
231 | },
232 | {
233 | "cell_type": "markdown",
234 | "metadata": {
235 | "id": "4ogkNauArL6u"
236 | },
237 | "source": [
238 | "For a detailed walkthrough of the concepts and code, be sure to refer to the full tutorial, [*Zero-parameter, automatic Canny edge detection with Python and OpenCV*](https://www.pyimagesearch.com/2015/04/06/zero-parameter-automatic-canny-edge-detection-with-python-and-opencv/) published on 2015-04-06."
239 | ]
240 | }
241 | ]
242 | }
243 |
--------------------------------------------------------------------------------
/105_opencv_cropping.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "colab": {
6 | "name": "105-opencv_cropping.ipynb",
7 | "provenance": [],
8 | "collapsed_sections": [],
9 | "toc_visible": true,
10 | "include_colab_link": true
11 | },
12 | "kernelspec": {
13 | "name": "python3",
14 | "display_name": "Python 3"
15 | }
16 | },
17 | "cells": [
18 | {
19 | "cell_type": "markdown",
20 | "metadata": {
21 | "id": "view-in-github",
22 | "colab_type": "text"
23 | },
24 | "source": [
25 | "
"
26 | ]
27 | },
28 | {
29 | "cell_type": "markdown",
30 | "metadata": {
31 | "id": "j4RpK9pawQzP"
32 | },
33 | "source": [
34 | "# Crop Image with OpenCV\n"
35 | ]
36 | },
37 | {
38 | "cell_type": "markdown",
39 | "metadata": {
40 | "id": "8ntZ1AkXZIxY"
41 | },
42 | "source": [
43 | "## Welcome to **[PyImageSearch Plus](http://pyimg.co/plus)** Jupyter Notebooks!\n",
44 | "\n",
45 | "This notebook is associated with the [Crop Image with OpenCV](https://www.pyimagesearch.com/2021/01/19/crop-image-with-opencv/) blog post published on 01-19-2021.\n",
46 | "\n",
47 | "Only the code for the blog post is here. Most codeblocks have a 1:1 relationship with what you find in the blog post with two exceptions: (1) Python classes are not separate files as they are typically organized with PyImageSearch projects, and (2) Command Line Argument parsing is replaced with an `args` dictionary that you can manipulate as needed.\n",
48 | "\n",
49 | "We recommend that you execute (press ▶️) the code block-by-block, as-is, before adjusting parameters and `args` inputs. Once you've verified that the code is working, you are welcome to hack with it and learn from manipulating inputs, settings, and parameters. For more information on using Jupyter and Colab, please refer to these resources:\n",
50 | "\n",
51 | "* [Jupyter Notebook User Interface](https://jupyter-notebook.readthedocs.io/en/stable/notebook.html#notebook-user-interface)\n",
52 | "* [Overview of Google Colaboratory Features](https://colab.research.google.com/notebooks/basic_features_overview.ipynb)\n",
53 | "\n",
54 | "\n",
55 | "Happy hacking!\n",
56 | "\n",
57 | "\n",
58 | "\n",
59 | "
\n"
60 | ]
61 | },
62 | {
63 | "cell_type": "markdown",
64 | "metadata": {
65 | "id": "NFhAzQB3aNMa"
66 | },
67 | "source": [
68 | "### Download the code zip file"
69 | ]
70 | },
71 | {
72 | "cell_type": "code",
73 | "metadata": {
74 | "id": "7y0LG1EuaRlB"
75 | },
76 | "source": [
77 | "!wget https://pyimagesearch-code-downloads.s3-us-west-2.amazonaws.com/opencv-cropping/opencv-cropping.zip\n",
78 | "!unzip -qq opencv-cropping.zip\n",
79 | "%cd opencv-cropping"
80 | ],
81 | "execution_count": null,
82 | "outputs": []
83 | },
84 | {
85 | "cell_type": "markdown",
86 | "metadata": {
87 | "id": "_SgTVT3HagGZ"
88 | },
89 | "source": [
90 | "## Blog Post Code"
91 | ]
92 | },
93 | {
94 | "cell_type": "markdown",
95 | "metadata": {
96 | "id": "wcrOk6pURp50"
97 | },
98 | "source": [
99 | "### Import Packages"
100 | ]
101 | },
102 | {
103 | "cell_type": "code",
104 | "metadata": {
105 | "id": "VJaCNlDDRz6d"
106 | },
107 | "source": [
108 | "# import the necessary packages\n",
109 | "from matplotlib import pyplot as plt\n",
110 | "import numpy as np\n",
111 | "import argparse\n",
112 | "import cv2"
113 | ],
114 | "execution_count": null,
115 | "outputs": []
116 | },
117 | {
118 | "cell_type": "markdown",
119 | "metadata": {
120 | "id": "lBrLwCtN5kqy"
121 | },
122 | "source": [
123 | "### Function to display images in Jupyter Notebooks and Google Colab"
124 | ]
125 | },
126 | {
127 | "cell_type": "code",
128 | "metadata": {
129 | "id": "fRw969Dp5Kdm"
130 | },
131 | "source": [
132 | "def plt_imshow(title, image):\n",
133 | "\t# convert the image frame BGR to RGB color space and display it\n",
134 | "\timage = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n",
135 | "\tplt.imshow(image)\n",
136 | "\tplt.title(title)\n",
137 | "\tplt.grid(False)\n",
138 | "\tplt.show()"
139 | ],
140 | "execution_count": null,
141 | "outputs": []
142 | },
143 | {
144 | "cell_type": "markdown",
145 | "metadata": {
146 | "id": "HQEOQ4VTzaf-"
147 | },
148 | "source": [
149 | "### Understanding image cropping with OpenCV and NumPy array slicing\n",
150 | "\n"
151 | ]
152 | },
153 | {
154 | "cell_type": "code",
155 | "metadata": {
156 | "id": "BCHrjTxIzO8J"
157 | },
158 | "source": [
159 | "I = np.arange(0, 25)\n",
160 | "I"
161 | ],
162 | "execution_count": null,
163 | "outputs": []
164 | },
165 | {
166 | "cell_type": "code",
167 | "metadata": {
168 | "id": "q0KpQFF3zpl4"
169 | },
170 | "source": [
171 | "I = I.reshape((5, 5))\n",
172 | "I"
173 | ],
174 | "execution_count": null,
175 | "outputs": []
176 | },
177 | {
178 | "cell_type": "code",
179 | "metadata": {
180 | "id": "e0uMnBqxzti3"
181 | },
182 | "source": [
183 | "I[0:3, 0:2]"
184 | ],
185 | "execution_count": null,
186 | "outputs": []
187 | },
188 | {
189 | "cell_type": "code",
190 | "metadata": {
191 | "id": "SerCBcbmz1km"
192 | },
193 | "source": [
194 | "I[3:5, 1:5]"
195 | ],
196 | "execution_count": null,
197 | "outputs": []
198 | },
199 | {
200 | "cell_type": "markdown",
201 | "metadata": {
202 | "id": "qmRDPisyz8wv"
203 | },
204 | "source": [
205 | "### Implementing image cropping with OpenCV\n"
206 | ]
207 | },
208 | {
209 | "cell_type": "code",
210 | "metadata": {
211 | "id": "-2ANlDU0z4C3"
212 | },
213 | "source": [
214 | "# # construct the argument parser and parse the arguments\n",
215 | "# ap = argparse.ArgumentParser()\n",
216 | "# ap.add_argument(\"-i\", \"--image\", type=str, default=\"adrian.png\",\n",
217 | "# \thelp=\"path to the input image\")\n",
218 | "# args = vars(ap.parse_args())\n",
219 | "\n",
220 | "# since we are using Jupyter Notebooks we can replace our argument\n",
221 | "# parsing code with *hard coded* arguments and values\n",
222 | "args = {\n",
223 | "\t\"image\": \"adrian.png\"\n",
224 | "}"
225 | ],
226 | "execution_count": null,
227 | "outputs": []
228 | },
229 | {
230 | "cell_type": "code",
231 | "metadata": {
232 | "id": "Qba6OkzG0Hop"
233 | },
234 | "source": [
235 | "# load the input image and display it to our screen\n",
236 | "image = cv2.imread(args[\"image\"])\n",
237 | "plt_imshow(\"Original\", image)\n",
238 | "\n",
239 | "# cropping an image with OpenCV is accomplished via simple NumPy\n",
240 | "# array slices in startY:endY, startX:endX order -- here we are\n",
241 | "# cropping the face from the image (these coordinates were\n",
242 | "# determined using photo editing software such as Photoshop,\n",
243 | "# GIMP, Paint, etc.)\n",
244 | "face = image[85:250, 85:220]\n",
245 | "plt_imshow(\"Face\", face)"
246 | ],
247 | "execution_count": null,
248 | "outputs": []
249 | },
250 | {
251 | "cell_type": "code",
252 | "metadata": {
253 | "id": "ZUQI3AzP0RLq"
254 | },
255 | "source": [
256 | "# apply another image crop, this time extracting the body\n",
257 | "body = image[90:450, 0:290]\n",
258 | "plt_imshow(\"Body\", body)"
259 | ],
260 | "execution_count": null,
261 | "outputs": []
262 | },
263 | {
264 | "cell_type": "markdown",
265 | "metadata": {
266 | "id": "4ogkNauArL6u"
267 | },
268 | "source": [
269 | "For a detailed walkthrough of the concepts and code, be sure to refer to the full tutorial, [*Crop Image with OpenCV*](https://www.pyimagesearch.com/2021/01/19/crop-image-with-opencv/) published on 01-19-2021."
270 | ]
271 | }
272 | ]
273 | }
--------------------------------------------------------------------------------
/206_adapative_thresholding.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "colab": {
6 | "name": "206-adapative_thresholding.ipynb",
7 | "provenance": [],
8 | "collapsed_sections": [],
9 | "toc_visible": true,
10 | "include_colab_link": true
11 | },
12 | "kernelspec": {
13 | "name": "python3",
14 | "display_name": "Python 3"
15 | },
16 | "language_info": {
17 | "name": "python"
18 | }
19 | },
20 | "cells": [
21 | {
22 | "cell_type": "markdown",
23 | "metadata": {
24 | "id": "view-in-github",
25 | "colab_type": "text"
26 | },
27 | "source": [
28 | "
"
29 | ]
30 | },
31 | {
32 | "cell_type": "markdown",
33 | "metadata": {
34 | "id": "j4RpK9pawQzP"
35 | },
36 | "source": [
37 | "# Adaptive Thresholding with OpenCV ( cv2.adaptiveThreshold )\n"
38 | ]
39 | },
40 | {
41 | "cell_type": "markdown",
42 | "metadata": {
43 | "id": "8ntZ1AkXZIxY"
44 | },
45 | "source": [
46 | "\n",
47 | "\n",
48 | "This notebook is associated with the [Adaptive Thresholding with OpenCV ( cv2.adaptiveThreshold )](https://www.pyimagesearch.com/2021/05/12/adaptive-thresholding-with-opencv-cv2-adaptivethreshold/) blog post published on 2021-05-12.\n",
49 | "\n",
50 | "Only the code for the blog post is here. Most codeblocks have a 1:1 relationship with what you find in the blog post with two exceptions: (1) Python classes are not separate files as they are typically organized with PyImageSearch projects, and (2) Command Line Argument parsing is replaced with an `args` dictionary that you can manipulate as needed.\n",
51 | "\n",
52 | "We recommend that you execute (press ▶️) the code block-by-block, as-is, before adjusting parameters and `args` inputs. Once you've verified that the code is working, you are welcome to hack with it and learn from manipulating inputs, settings, and parameters. For more information on using Jupyter and Colab, please refer to these resources:\n",
53 | "\n",
54 | "* [Jupyter Notebook User Interface](https://jupyter-notebook.readthedocs.io/en/stable/notebook.html#notebook-user-interface)\n",
55 | "* [Overview of Google Colaboratory Features](https://colab.research.google.com/notebooks/basic_features_overview.ipynb)\n",
56 | "\n",
57 | "\n",
58 | "Happy hacking!\n",
59 | "\n",
60 | "\n",
61 | "\n",
62 | "
\n",
63 | "\n"
64 | ]
65 | },
66 | {
67 | "cell_type": "markdown",
68 | "metadata": {
69 | "id": "NFhAzQB3aNMa"
70 | },
71 | "source": [
72 | "### Download the code zip file"
73 | ]
74 | },
75 | {
76 | "cell_type": "code",
77 | "metadata": {
78 | "id": "7y0LG1EuaRlB"
79 | },
80 | "source": [
81 | "!wget https://pyimagesearch-code-downloads.s3-us-west-2.amazonaws.com/adapative-thresholding/adapative-thresholding.zip\n",
82 | "!unzip -qq adapative-thresholding.zip\n",
83 | "%cd adapative-thresholding"
84 | ],
85 | "execution_count": null,
86 | "outputs": []
87 | },
88 | {
89 | "cell_type": "markdown",
90 | "metadata": {
91 | "id": "_SgTVT3HagGZ"
92 | },
93 | "source": [
94 | "## Blog Post Code"
95 | ]
96 | },
97 | {
98 | "cell_type": "markdown",
99 | "metadata": {
100 | "id": "wcrOk6pURp50"
101 | },
102 | "source": [
103 | "### Import Packages"
104 | ]
105 | },
106 | {
107 | "cell_type": "code",
108 | "metadata": {
109 | "id": "VJaCNlDDRz6d"
110 | },
111 | "source": [
112 | "# import the necessary packages\n",
113 | "import matplotlib.pyplot as plt\n",
114 | "import cv2"
115 | ],
116 | "execution_count": null,
117 | "outputs": []
118 | },
119 | {
120 | "cell_type": "markdown",
121 | "metadata": {
122 | "id": "lBrLwCtN5kqy"
123 | },
124 | "source": [
125 | "### Function to display images in Jupyter Notebooks and Google Colab"
126 | ]
127 | },
128 | {
129 | "cell_type": "code",
130 | "metadata": {
131 | "id": "sYaD_Es9-8y6"
132 | },
133 | "source": [
134 | "def plt_imshow(title, image):\n",
135 | "\t# convert the image frame BGR to RGB color space and display it\n",
136 | "\timage = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n",
137 | "\tplt.imshow(image)\n",
138 | "\tplt.title(title)\n",
139 | "\tplt.grid(False)\n",
140 | "\tplt.show()"
141 | ],
142 | "execution_count": null,
143 | "outputs": []
144 | },
145 | {
146 | "cell_type": "markdown",
147 | "metadata": {
148 | "id": "khdPrbuL-5xD"
149 | },
150 | "source": [
151 | "### Implementing adaptive thresholding with OpenCV"
152 | ]
153 | },
154 | {
155 | "cell_type": "code",
156 | "metadata": {
157 | "id": "vohO_FtVVMVr"
158 | },
159 | "source": [
160 | "# # construct the argument parser and parse the arguments\n",
161 | "# ap = argparse.ArgumentParser()\n",
162 | "# ap.add_argument(\"-i\", \"--image\", type=str, required=True,\n",
163 | "# \thelp=\"path to input image\")\n",
164 | "# args = vars(ap.parse_args())\n",
165 | "\n",
166 | "# since we are using Jupyter Notebooks we can replace our argument\n",
167 | "# parsing code with *hard coded* arguments and values\n",
168 | "args = {\n",
169 | "\t\"image\": \"steve_jobs.png\"\n",
170 | "}"
171 | ],
172 | "execution_count": null,
173 | "outputs": []
174 | },
175 | {
176 | "cell_type": "code",
177 | "metadata": {
178 | "id": "5NhT_pdNVYcM"
179 | },
180 | "source": [
181 | "# load the image and display it\n",
182 | "image = cv2.imread(args[\"image\"])\n",
183 | "plt_imshow(\"Image\", image)\n",
184 | "\n",
185 | "# convert the image to grayscale and blur it slightly\n",
186 | "gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)\n",
187 | "blurred = cv2.GaussianBlur(gray, (7, 7), 0)"
188 | ],
189 | "execution_count": null,
190 | "outputs": []
191 | },
192 | {
193 | "cell_type": "code",
194 | "metadata": {
195 | "id": "VShzhcOkVbeF"
196 | },
197 | "source": [
198 | "# apply simple thresholding with a hardcoded threshold value\n",
199 | "(T, threshInv) = cv2.threshold(blurred, 230, 255,\n",
200 | "\tcv2.THRESH_BINARY_INV)\n",
201 | "plt_imshow(\"Simple Thresholding\", threshInv)"
202 | ],
203 | "execution_count": null,
204 | "outputs": []
205 | },
206 | {
207 | "cell_type": "code",
208 | "metadata": {
209 | "id": "Tgv45PzLVjvQ"
210 | },
211 | "source": [
212 | "# apply Otsu's automatic thresholding\n",
213 | "(T, threshInv) = cv2.threshold(blurred, 0, 255,\n",
214 | "\tcv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)\n",
215 | "plt_imshow(\"Otsu Thresholding\", threshInv)"
216 | ],
217 | "execution_count": null,
218 | "outputs": []
219 | },
220 | {
221 | "cell_type": "code",
222 | "metadata": {
223 | "id": "AFRnbYjIV0C8"
224 | },
225 | "source": [
226 | "# instead of manually specifying the threshold value, we can use\n",
227 | "# adaptive thresholding to examine neighborhoods of pixels and\n",
228 | "# adaptively threshold each neighborhood\n",
229 | "thresh = cv2.adaptiveThreshold(blurred, 255,\n",
230 | "\tcv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 21, 10)\n",
231 | "plt_imshow(\"Mean Adaptive Thresholding\", thresh)"
232 | ],
233 | "execution_count": null,
234 | "outputs": []
235 | },
236 | {
237 | "cell_type": "code",
238 | "metadata": {
239 | "id": "BtPiIzhDV-dJ"
240 | },
241 | "source": [
242 | "# perform adaptive thresholding again, this time using a Gaussian\n",
243 | "# weighting versus a simple mean to compute our local threshold\n",
244 | "# value\n",
245 | "thresh = cv2.adaptiveThreshold(blurred, 255,\n",
246 | "\tcv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 21, 4)\n",
247 | "plt_imshow(\"Gaussian Adaptive Thresholding\", thresh)"
248 | ],
249 | "execution_count": null,
250 | "outputs": []
251 | },
252 | {
253 | "cell_type": "markdown",
254 | "metadata": {
255 | "id": "4ogkNauArL6u"
256 | },
257 | "source": [
258 | "For a detailed walkthrough of the concepts and code, be sure to refer to the full tutorial, [Adaptive Thresholding with OpenCV ( cv2.adaptiveThreshold )](https://www.pyimagesearch.com/2021/05/12/adaptive-thresholding-with-opencv-cv2-adaptivethreshold/) published on 2021-05-12."
259 | ]
260 | }
261 | ]
262 | }
--------------------------------------------------------------------------------
/1104_compare_images_siamese_networks.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "colab": {
6 | "name": "1104-compare_images_siamese_networks.ipynb",
7 | "provenance": [],
8 | "collapsed_sections": [],
9 | "include_colab_link": true
10 | },
11 | "kernelspec": {
12 | "name": "python3",
13 | "display_name": "Python 3"
14 | },
15 | "accelerator": "GPU"
16 | },
17 | "cells": [
18 | {
19 | "cell_type": "markdown",
20 | "metadata": {
21 | "id": "view-in-github",
22 | "colab_type": "text"
23 | },
24 | "source": [
25 | "
"
26 | ]
27 | },
28 | {
29 | "cell_type": "markdown",
30 | "metadata": {
31 | "id": "NS3f6TEA9YFg"
32 | },
33 | "source": [
34 | "# Comparing images for similarity using siamese networks, Keras, and TensorFlow\n",
35 | "\n"
36 | ]
37 | },
38 | {
39 | "cell_type": "markdown",
40 | "metadata": {
41 | "id": "LeP1x1yK9fjB"
42 | },
43 | "source": [
44 | "\n",
45 | "This notebook is associated with the [Comparing images for similarity using siamese networks, Keras, and TensorFlow](https://www.pyimagesearch.com/2020/12/07/comparing-images-for-similarity-using-siamese-networks-keras-and-tensorflow/) blog post published on 12-07-20.\n",
46 | "\n",
47 | "Only the code for the blog post is here. Most codeblocks have a 1:1 relationship with what you find in the blog post with two exceptions: (1) Python classes are not separate files as they are typically organized with PyImageSearch projects, and (2) Command Line Argument parsing is replaced with an `args` dictionary that you can manipulate as needed.\n",
48 | "\n",
49 | "We recommend that you execute (press ▶️) the code block-by-block, as-is, before adjusting parameters and `args` inputs. Once you've verified that the code is working, you are welcome to hack with it and learn from manipulating inputs, settings, and parameters. For more information on using Jupyter and Colab, please refer to these resources:\n",
50 | "\n",
51 | "* [Jupyter Notebook User Interface](https://jupyter-notebook.readthedocs.io/en/stable/notebook.html#notebook-user-interface)\n",
52 | "* [Overview of Google Colaboratory Features](https://colab.research.google.com/notebooks/basic_features_overview.ipynb)\n",
53 | "\n",
54 | "Happy hacking!\n",
55 | "\n",
56 | "\n",
57 | "
\n",
58 | "\n"
59 | ]
60 | },
61 | {
62 | "cell_type": "markdown",
63 | "metadata": {
64 | "id": "RpuM4JQK-ecz"
65 | },
66 | "source": [
67 | "### Install the necessary packages"
68 | ]
69 | },
70 | {
71 | "cell_type": "code",
72 | "metadata": {
73 | "id": "qdtSckfk-hua"
74 | },
75 | "source": [
76 | "!pip install tensorflow==2.3.0"
77 | ],
78 | "execution_count": null,
79 | "outputs": []
80 | },
81 | {
82 | "cell_type": "markdown",
83 | "metadata": {
84 | "id": "3_lvhD4o9oGJ"
85 | },
86 | "source": [
87 | "### Download the code zip file"
88 | ]
89 | },
90 | {
91 | "cell_type": "code",
92 | "metadata": {
93 | "id": "6byP3EAl9AY5"
94 | },
95 | "source": [
96 | "!wget https://pyimagesearch-code-downloads.s3-us-west-2.amazonaws.com/compare-images-siamese-networks/compare-images-siamese-networks.zip\n",
97 | "!unzip -qq compare-images-siamese-networks.zip\n",
98 | "%cd compare-images-siamese-networks"
99 | ],
100 | "execution_count": null,
101 | "outputs": []
102 | },
103 | {
104 | "cell_type": "markdown",
105 | "metadata": {
106 | "id": "Ch5Fu9OX9yCD"
107 | },
108 | "source": [
109 | "## Blog Post Code"
110 | ]
111 | },
112 | {
113 | "cell_type": "markdown",
114 | "metadata": {
115 | "id": "aifRe2ub91HU"
116 | },
117 | "source": [
118 | "### Import Packages"
119 | ]
120 | },
121 | {
122 | "cell_type": "code",
123 | "metadata": {
124 | "id": "kKec3zy09voQ"
125 | },
126 | "source": [
127 | "# import the necessary packages\n",
128 | "from pyimagesearch import config\n",
129 | "from tensorflow.keras.models import load_model\n",
130 | "from imutils.paths import list_images\n",
131 | "import matplotlib.pyplot as plt\n",
132 | "import numpy as np\n",
133 | "import argparse\n",
134 | "import cv2"
135 | ],
136 | "execution_count": null,
137 | "outputs": []
138 | },
139 | {
140 | "cell_type": "markdown",
141 | "metadata": {
142 | "id": "KoGHQxxeAfkH"
143 | },
144 | "source": [
145 | "### Implementing our siamese network image similarity script"
146 | ]
147 | },
148 | {
149 | "cell_type": "code",
150 | "metadata": {
151 | "id": "7SXN3orIAbCc"
152 | },
153 | "source": [
154 | "# # construct the argument parser and parse the arguments\n",
155 | "# ap = argparse.ArgumentParser()\n",
156 | "# ap.add_argument(\"-i\", \"--input\", required=True,\n",
157 | "# \thelp=\"path to input directory of testing images\")\n",
158 | "# args = vars(ap.parse_args())\n",
159 | "\n",
160 | "# since we are using Jupyter Notebooks we can replace our argument\n",
161 | "# parsing code with *hard coded* arguments and values\n",
162 | "args = {\n",
163 | "\t\"input\": \"examples\"\n",
164 | "}"
165 | ],
166 | "execution_count": null,
167 | "outputs": []
168 | },
169 | {
170 | "cell_type": "code",
171 | "metadata": {
172 | "id": "4eD9_jrpBHCa"
173 | },
174 | "source": [
175 | "# grab the test dataset image paths and then randomly generate a\n",
176 | "# total of 10 image pairs\n",
177 | "print(\"[INFO] loading test dataset...\")\n",
178 | "testImagePaths = list(list_images(args[\"input\"]))\n",
179 | "np.random.seed(42)\n",
180 | "pairs = np.random.choice(testImagePaths, size=(10, 2))\n",
181 | "\n",
182 | "# load the model from disk\n",
183 | "print(\"[INFO] loading siamese model...\")\n",
184 | "model = load_model(config.MODEL_PATH)"
185 | ],
186 | "execution_count": null,
187 | "outputs": []
188 | },
189 | {
190 | "cell_type": "code",
191 | "metadata": {
192 | "id": "HMRFqph4_nS4"
193 | },
194 | "source": [
195 | "# loop over all image pairs\n",
196 | "for (i, (pathA, pathB)) in enumerate(pairs):\n",
197 | "\t# load both the images and convert them to grayscale\n",
198 | "\timageA = cv2.imread(pathA, 0)\n",
199 | "\timageB = cv2.imread(pathB, 0)\n",
200 | "\n",
201 | "\t# create a copy of both the images for visualization purpose\n",
202 | "\torigA = imageA.copy()\n",
203 | "\torigB = imageB.copy()\n",
204 | "\n",
205 | "\t# add channel a dimension to both the images\n",
206 | "\timageA = np.expand_dims(imageA, axis=-1)\n",
207 | "\timageB = np.expand_dims(imageB, axis=-1)\n",
208 | "\n",
209 | "\t# add a batch dimension to both images\n",
210 | "\timageA = np.expand_dims(imageA, axis=0)\n",
211 | "\timageB = np.expand_dims(imageB, axis=0)\n",
212 | "\n",
213 | "\t# scale the pixel values to the range of [0, 1]\n",
214 | "\timageA = imageA / 255.0\n",
215 | "\timageB = imageB / 255.0\n",
216 | "\n",
217 | "\t# use our siamese model to make predictions on the image pair,\n",
218 | "\t# indicating whether or not the images belong to the same class\n",
219 | "\tpreds = model.predict([imageA, imageB])\n",
220 | "\tproba = preds[0][0]\n",
221 | "\n",
222 | "\t# initialize the figure\n",
223 | "\tfig = plt.figure(\"Pair #{}\".format(i + 1), figsize=(4, 2))\n",
224 | "\tplt.suptitle(\"Similarity: {:.2f}\".format(proba))\n",
225 | "\n",
226 | "\t# show first image\n",
227 | "\tax = fig.add_subplot(1, 2, 1)\n",
228 | "\tplt.imshow(origA, cmap=plt.cm.gray)\n",
229 | "\tplt.axis(\"off\")\n",
230 | "\n",
231 | "\t# show the second image\n",
232 | "\tax = fig.add_subplot(1, 2, 2)\n",
233 | "\tplt.imshow(origB, cmap=plt.cm.gray)\n",
234 | "\tplt.axis(\"off\")\n",
235 | "\n",
236 | "\t# show the plot\n",
237 | "\tplt.show()"
238 | ],
239 | "execution_count": null,
240 | "outputs": []
241 | },
242 | {
243 | "cell_type": "markdown",
244 | "metadata": {
245 | "id": "yebZ6JXU_4Ft"
246 | },
247 | "source": [
248 | "For a detailed walkthrough of the concepts and code, be sure to refer to the full tutorial, [*Comparing images for similarity using siamese networks, Keras, and TensorFlow*](https://www.pyimagesearch.com/2020/12/07/comparing-images-for-similarity-using-siamese-networks-keras-and-tensorflow/) blog post published on 12-07-20."
249 | ]
250 | }
251 | ]
252 | }
--------------------------------------------------------------------------------
/505_opencv_guess_aruco_type.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "colab": {
6 | "name": "505-opencv_guess_aruco_type.ipynb",
7 | "provenance": [],
8 | "collapsed_sections": [],
9 | "include_colab_link": true
10 | },
11 | "kernelspec": {
12 | "name": "python3",
13 | "display_name": "Python 3"
14 | }
15 | },
16 | "cells": [
17 | {
18 | "cell_type": "markdown",
19 | "metadata": {
20 | "id": "view-in-github",
21 | "colab_type": "text"
22 | },
23 | "source": [
24 | "
"
25 | ]
26 | },
27 | {
28 | "cell_type": "markdown",
29 | "metadata": {
30 | "id": "-sQ7-Wabet3d"
31 | },
32 | "source": [
33 | "# Determining ArUco marker type with OpenCV and Python\n",
34 | "\n"
35 | ]
36 | },
37 | {
38 | "cell_type": "markdown",
39 | "metadata": {
40 | "id": "cJjRCMSKe0mN"
41 | },
42 | "source": [
43 | "\n",
44 | "This notebook is associated with the [Determining ArUco marker type with OpenCV and Python](https://www.pyimagesearch.com/2020/12/28/determining-aruco-marker-type-with-opencv-and-python/) blog post published on 12-28-20.\n",
45 | "\n",
46 | "Only the code for the blog post is here. Most codeblocks have a 1:1 relationship with what you find in the blog post with two exceptions: (1) Python classes are not separate files as they are typically organized with PyImageSearch projects, and (2) Command Line Argument parsing is replaced with an `args` dictionary that you can manipulate as needed.\n",
47 | "\n",
48 | "We recommend that you execute (press ▶️) the code block-by-block, as-is, before adjusting parameters and `args` inputs. Once you've verified that the code is working, you are welcome to hack with it and learn from manipulating inputs, settings, and parameters. For more information on using Jupyter and Colab, please refer to these resources:\n",
49 | "\n",
50 | "* [Jupyter Notebook User Interface](https://jupyter-notebook.readthedocs.io/en/stable/notebook.html#notebook-user-interface)\n",
51 | "* [Overview of Google Colaboratory Features](https://colab.research.google.com/notebooks/basic_features_overview.ipynb)\n",
52 | "\n",
53 | "\n",
54 | "Happy hacking!\n",
55 | "\n",
56 | "\n",
57 | "
\n",
58 | "\n"
59 | ]
60 | },
61 | {
62 | "cell_type": "markdown",
63 | "metadata": {
64 | "id": "Ys84blvYe_J4"
65 | },
66 | "source": [
67 | "### Download the code zip file"
68 | ]
69 | },
70 | {
71 | "cell_type": "code",
72 | "metadata": {
73 | "id": "Mc3NNFBrdKu8"
74 | },
75 | "source": [
76 | "!wget https://pyimagesearch-code-downloads.s3-us-west-2.amazonaws.com/opencv-guess-aruco-type/opencv-guess-aruco-type.zip\n",
77 | "!unzip -qq opencv-guess-aruco-type.zip\n",
78 | "%cd opencv-guess-aruco-type"
79 | ],
80 | "execution_count": null,
81 | "outputs": []
82 | },
83 | {
84 | "cell_type": "markdown",
85 | "metadata": {
86 | "id": "OQe9LuwRfsZG"
87 | },
88 | "source": [
89 | "## Blog Post Code"
90 | ]
91 | },
92 | {
93 | "cell_type": "markdown",
94 | "metadata": {
95 | "id": "WxEZ_b1bfvGN"
96 | },
97 | "source": [
98 | "### Import Packages"
99 | ]
100 | },
101 | {
102 | "cell_type": "code",
103 | "metadata": {
104 | "id": "Z8MN00pxfMDQ"
105 | },
106 | "source": [
107 | "# import the necessary packages\n",
108 | "import matplotlib.pyplot as plt\n",
109 | "import argparse\n",
110 | "import imutils\n",
111 | "import cv2"
112 | ],
113 | "execution_count": null,
114 | "outputs": []
115 | },
116 | {
117 | "cell_type": "markdown",
118 | "metadata": {
119 | "id": "N_MYWq8Hf_vO"
120 | },
121 | "source": [
122 | "### Function to display images in Jupyter Notebooks and Google Colab"
123 | ]
124 | },
125 | {
126 | "cell_type": "code",
127 | "metadata": {
128 | "id": "dVEsT9UBf5xT"
129 | },
130 | "source": [
131 | "def plt_imshow(title, image):\n",
132 | " # convert the image frame BGR to RGB color space and display it\n",
133 | "\timage = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n",
134 | "\tplt.imshow(image)\n",
135 | "\tplt.title(title)\n",
136 | "\tplt.grid(False)\n",
137 | "\tplt.show()"
138 | ],
139 | "execution_count": null,
140 | "outputs": []
141 | },
142 | {
143 | "cell_type": "markdown",
144 | "metadata": {
145 | "id": "iEw7wOnAgE6g"
146 | },
147 | "source": [
148 | "### Implementing our ArUco/AprilTag marker type identifier"
149 | ]
150 | },
151 | {
152 | "cell_type": "code",
153 | "metadata": {
154 | "id": "ZTCjxuyCgB16"
155 | },
156 | "source": [
157 | "# # construct the argument parser and parse the arguments\n",
158 | "# ap = argparse.ArgumentParser()\n",
159 | "# ap.add_argument(\"-i\", \"--image\", required=True,\n",
160 | "# \thelp=\"path to input image containing ArUCo tag\")\n",
161 | "# args = vars(ap.parse_args())\n",
162 | "\n",
163 | "# since we are using Jupyter Notebooks we can replace our argument\n",
164 | "# parsing code with *hard coded* arguments and values\n",
165 | "args = {\n",
166 | "\t\"image\": \"images/example_01.png\"\n",
167 | "}"
168 | ],
169 | "execution_count": null,
170 | "outputs": []
171 | },
172 | {
173 | "cell_type": "code",
174 | "metadata": {
175 | "id": "oOqDdfaGgWNs"
176 | },
177 | "source": [
178 | "# define names of each possible ArUco tag OpenCV supports\n",
179 | "ARUCO_DICT = {\n",
180 | "\t\"DICT_4X4_50\": cv2.aruco.DICT_4X4_50,\n",
181 | "\t\"DICT_4X4_100\": cv2.aruco.DICT_4X4_100,\n",
182 | "\t\"DICT_4X4_250\": cv2.aruco.DICT_4X4_250,\n",
183 | "\t\"DICT_4X4_1000\": cv2.aruco.DICT_4X4_1000,\n",
184 | "\t\"DICT_5X5_50\": cv2.aruco.DICT_5X5_50,\n",
185 | "\t\"DICT_5X5_100\": cv2.aruco.DICT_5X5_100,\n",
186 | "\t\"DICT_5X5_250\": cv2.aruco.DICT_5X5_250,\n",
187 | "\t\"DICT_5X5_1000\": cv2.aruco.DICT_5X5_1000,\n",
188 | "\t\"DICT_6X6_50\": cv2.aruco.DICT_6X6_50,\n",
189 | "\t\"DICT_6X6_100\": cv2.aruco.DICT_6X6_100,\n",
190 | "\t\"DICT_6X6_250\": cv2.aruco.DICT_6X6_250,\n",
191 | "\t\"DICT_6X6_1000\": cv2.aruco.DICT_6X6_1000,\n",
192 | "\t\"DICT_7X7_50\": cv2.aruco.DICT_7X7_50,\n",
193 | "\t\"DICT_7X7_100\": cv2.aruco.DICT_7X7_100,\n",
194 | "\t\"DICT_7X7_250\": cv2.aruco.DICT_7X7_250,\n",
195 | "\t\"DICT_7X7_1000\": cv2.aruco.DICT_7X7_1000,\n",
196 | "\t\"DICT_ARUCO_ORIGINAL\": cv2.aruco.DICT_ARUCO_ORIGINAL,\n",
197 | "\t\"DICT_APRILTAG_16h5\": cv2.aruco.DICT_APRILTAG_16h5,\n",
198 | "\t\"DICT_APRILTAG_25h9\": cv2.aruco.DICT_APRILTAG_25h9,\n",
199 | "\t\"DICT_APRILTAG_36h10\": cv2.aruco.DICT_APRILTAG_36h10,\n",
200 | "\t\"DICT_APRILTAG_36h11\": cv2.aruco.DICT_APRILTAG_36h11\n",
201 | "}"
202 | ],
203 | "execution_count": null,
204 | "outputs": []
205 | },
206 | {
207 | "cell_type": "code",
208 | "metadata": {
209 | "id": "w7r-wQBHgbPm"
210 | },
211 | "source": [
212 | "# load the input image from disk and resize it\n",
213 | "print(\"[INFO] loading image...\")\n",
214 | "image = cv2.imread(args[\"image\"])\n",
215 | "image = imutils.resize(image, width=600)\n",
216 | "\n",
217 | "# loop over the types of ArUco dictionaries\n",
218 | "for (arucoName, arucoDict) in ARUCO_DICT.items():\n",
219 | "\t# load the ArUCo dictionary, grab the ArUCo parameters, and\n",
220 | "\t# attempt to detect the markers for the current dictionary\n",
221 | "\tarucoDict = cv2.aruco.Dictionary_get(arucoDict)\n",
222 | "\tarucoParams = cv2.aruco.DetectorParameters_create()\n",
223 | "\t(corners, ids, rejected) = cv2.aruco.detectMarkers(\n",
224 | "\t\timage, arucoDict, parameters=arucoParams)\n",
225 | "\n",
226 | "\t# if at least one ArUco marker was detected display the ArUco\n",
227 | "\t# name to our terminal\n",
228 | "\tif len(corners) > 0:\n",
229 | "\t\tprint(\"[INFO] detected {} markers for '{}'\".format(\n",
230 | "\t\t\tlen(corners), arucoName))"
231 | ],
232 | "execution_count": null,
233 | "outputs": []
234 | },
235 | {
236 | "cell_type": "markdown",
237 | "metadata": {
238 | "id": "4dayoJFLgi8B"
239 | },
240 | "source": [
241 | "For a detailed walkthrough of the concepts and code, be sure to refer to the full tutorial, [*Determining ArUco marker type with OpenCV and Python*](https://www.pyimagesearch.com/2020/12/28/determining-aruco-marker-type-with-opencv-and-python/) blog post published on 12-28-20."
242 | ]
243 | }
244 | ]
245 | }
--------------------------------------------------------------------------------
/106_opencv_image_arithmetic.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "colab": {
6 | "name": "106-opencv_image_arithmetic.ipynb",
7 | "provenance": [],
8 | "collapsed_sections": [],
9 | "toc_visible": true,
10 | "include_colab_link": true
11 | },
12 | "kernelspec": {
13 | "name": "python3",
14 | "display_name": "Python 3"
15 | }
16 | },
17 | "cells": [
18 | {
19 | "cell_type": "markdown",
20 | "metadata": {
21 | "id": "view-in-github",
22 | "colab_type": "text"
23 | },
24 | "source": [
25 | "
"
26 | ]
27 | },
28 | {
29 | "cell_type": "markdown",
30 | "metadata": {
31 | "id": "j4RpK9pawQzP"
32 | },
33 | "source": [
34 | "# Image Arithmetic OpenCV\n"
35 | ]
36 | },
37 | {
38 | "cell_type": "markdown",
39 | "metadata": {
40 | "id": "8ntZ1AkXZIxY"
41 | },
42 | "source": [
43 | "## Welcome to **[PyImageSearch Plus](http://pyimg.co/plus)** Jupyter Notebooks!\n",
44 | "\n",
45 | "This notebook is associated with the [Image Arithmetic OpenCV](https://www.pyimagesearch.com/2021/01/19/image-arithmetic-opencv/) blog post published on 01-19-2021.\n",
46 | "\n",
47 | "Only the code for the blog post is here. Most codeblocks have a 1:1 relationship with what you find in the blog post with two exceptions: (1) Python classes are not separate files as they are typically organized with PyImageSearch projects, and (2) Command Line Argument parsing is replaced with an `args` dictionary that you can manipulate as needed.\n",
48 | "\n",
49 | "We recommend that you execute (press ▶️) the code block-by-block, as-is, before adjusting parameters and `args` inputs. Once you've verified that the code is working, you are welcome to hack with it and learn from manipulating inputs, settings, and parameters. For more information on using Jupyter and Colab, please refer to these resources:\n",
50 | "\n",
51 | "* [Jupyter Notebook User Interface](https://jupyter-notebook.readthedocs.io/en/stable/notebook.html#notebook-user-interface)\n",
52 | "* [Overview of Google Colaboratory Features](https://colab.research.google.com/notebooks/basic_features_overview.ipynb)\n",
53 | "\n",
54 | "\n",
55 | "Happy hacking!\n",
56 | "\n",
57 | "\n",
58 | "
\n"
59 | ]
60 | },
61 | {
62 | "cell_type": "markdown",
63 | "metadata": {
64 | "id": "NFhAzQB3aNMa"
65 | },
66 | "source": [
67 | "### Download the code zip file"
68 | ]
69 | },
70 | {
71 | "cell_type": "code",
72 | "metadata": {
73 | "id": "7y0LG1EuaRlB"
74 | },
75 | "source": [
76 | "!wget https://pyimagesearch-code-downloads.s3-us-west-2.amazonaws.com/opencv-image-arithmetic/opencv-image-arithmetic.zip\n",
77 | "!unzip -qq opencv-image-arithmetic.zip\n",
78 | "%cd opencv-image-arithmetic"
79 | ],
80 | "execution_count": null,
81 | "outputs": []
82 | },
83 | {
84 | "cell_type": "markdown",
85 | "metadata": {
86 | "id": "_SgTVT3HagGZ"
87 | },
88 | "source": [
89 | "## Blog Post Code"
90 | ]
91 | },
92 | {
93 | "cell_type": "markdown",
94 | "metadata": {
95 | "id": "wcrOk6pURp50"
96 | },
97 | "source": [
98 | "### Import Packages"
99 | ]
100 | },
101 | {
102 | "cell_type": "code",
103 | "metadata": {
104 | "id": "VJaCNlDDRz6d"
105 | },
106 | "source": [
107 | "# import the necessary packages\n",
108 | "from matplotlib import pyplot as plt\n",
109 | "import numpy as np\n",
110 | "import argparse\n",
111 | "import cv2"
112 | ],
113 | "execution_count": null,
114 | "outputs": []
115 | },
116 | {
117 | "cell_type": "markdown",
118 | "metadata": {
119 | "id": "lBrLwCtN5kqy"
120 | },
121 | "source": [
122 | "### Function to display images in Jupyter Notebooks and Google Colab"
123 | ]
124 | },
125 | {
126 | "cell_type": "code",
127 | "metadata": {
128 | "id": "fRw969Dp5Kdm"
129 | },
130 | "source": [
131 | "def plt_imshow(title, image):\n",
132 | "\t# convert the image frame BGR to RGB color space and display it\n",
133 | "\timage = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n",
134 | "\tplt.imshow(image)\n",
135 | "\tplt.title(title)\n",
136 | "\tplt.grid(False)\n",
137 | "\tplt.show()"
138 | ],
139 | "execution_count": null,
140 | "outputs": []
141 | },
142 | {
143 | "cell_type": "markdown",
144 | "metadata": {
145 | "id": "iH8-nfqp35qq"
146 | },
147 | "source": [
148 | "### Implementing image arithmetic with OpenCV"
149 | ]
150 | },
151 | {
152 | "cell_type": "code",
153 | "metadata": {
154 | "id": "H_aj3SDjnns4"
155 | },
156 | "source": [
157 | "# # construct the argument parser and parse the arguments\n",
158 | "# ap = argparse.ArgumentParser()\n",
159 | "# ap.add_argument(\"-i\", \"--image\", type=str, default=\"grand_canyon.png\",\n",
160 | "# \thelp=\"path to the input image\")\n",
161 | "# args = vars(ap.parse_args())\n",
162 | "\n",
163 | "# since we are using Jupyter Notebooks we can replace our argument\n",
164 | "# parsing code with *hard coded* arguments and values\n",
165 | "args = {\n",
166 | "\t\"image\": \"grand_canyon.png\"\n",
167 | "}"
168 | ],
169 | "execution_count": null,
170 | "outputs": []
171 | },
172 | {
173 | "cell_type": "code",
174 | "metadata": {
175 | "id": "Xf1415LG4HaT"
176 | },
177 | "source": [
178 | "# images are NumPy arrays stored as unsigned 8-bit integers (unit8)\n",
179 | "# with values in the range [0, 255]; when using the add/subtract\n",
180 | "# functions in OpenCV, these values will be *clipped* to this range,\n",
181 | "# even if they fall outside the range [0, 255] after applying the\n",
182 | "# operation\n",
183 | "added = cv2.add(np.uint8([200]), np.uint8([100]))\n",
184 | "subtracted = cv2.subtract(np.uint8([50]), np.uint8([100]))\n",
185 | "print(\"max of 255: {}\".format(added))\n",
186 | "print(\"min of 0: {}\".format(subtracted))"
187 | ],
188 | "execution_count": null,
189 | "outputs": []
190 | },
191 | {
192 | "cell_type": "code",
193 | "metadata": {
194 | "id": "uSBLjUtU4LGj"
195 | },
196 | "source": [
197 | "# using NumPy arithmetic operations (rather than OpenCV operations)\n",
198 | "# will result in a modulo (\"wrap around\") instead of being clipped\n",
199 | "# to the range [0, 255]\n",
200 | "added = np.uint8([200]) + np.uint8([100])\n",
201 | "subtracted = np.uint8([50]) - np.uint8([100])\n",
202 | "print(\"wrap around: {}\".format(added))\n",
203 | "print(\"wrap around: {}\".format(subtracted))"
204 | ],
205 | "execution_count": null,
206 | "outputs": []
207 | },
208 | {
209 | "cell_type": "code",
210 | "metadata": {
211 | "id": "UKMIMUXN4RCT"
212 | },
213 | "source": [
214 | "# load the original input image and display it to our screen\n",
215 | "image = cv2.imread(args[\"image\"])\n",
216 | "plt_imshow(\"Original\", image)"
217 | ],
218 | "execution_count": null,
219 | "outputs": []
220 | },
221 | {
222 | "cell_type": "code",
223 | "metadata": {
224 | "id": "7MDDfXXi4U9t"
225 | },
226 | "source": [
227 | "# increasing the pixel intensities in our input image by 100 is\n",
228 | "# accomplished by constructing a NumPy array that has the *same\n",
229 | "# dimensions* as our input image, filling it with ones, multiplying\n",
230 | "# it by 100, and then adding the input image and matrix together\n",
231 | "M = np.ones(image.shape, dtype=\"uint8\") * 100\n",
232 | "added = cv2.add(image, M)\n",
233 | "plt_imshow(\"Lighter\", added)"
234 | ],
235 | "execution_count": null,
236 | "outputs": []
237 | },
238 | {
239 | "cell_type": "code",
240 | "metadata": {
241 | "id": "2xmOaNyU4Ypk"
242 | },
243 | "source": [
244 | "# similarly, we can subtract 50 from all pixels in our image and make it\n",
245 | "# darker\n",
246 | "M = np.ones(image.shape, dtype=\"uint8\") * 50\n",
247 | "subtracted = cv2.subtract(image, M)\n",
248 | "plt_imshow(\"Darker\", subtracted)"
249 | ],
250 | "execution_count": null,
251 | "outputs": []
252 | },
253 | {
254 | "cell_type": "markdown",
255 | "metadata": {
256 | "id": "4ogkNauArL6u"
257 | },
258 | "source": [
259 | "For a detailed walkthrough of the concepts and code, be sure to refer to the full tutorial, [*Image Arithmetic OpenCV*](https://www.pyimagesearch.com/2021/01/19/image-arithmetic-opencv/) published on 01-19-2021."
260 | ]
261 | }
262 | ]
263 | }
--------------------------------------------------------------------------------
/501_python_apriltag.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "colab": {
6 | "name": "501-python_apriltag.ipynb",
7 | "provenance": [],
8 | "collapsed_sections": [],
9 | "include_colab_link": true
10 | },
11 | "kernelspec": {
12 | "name": "python3",
13 | "display_name": "Python 3"
14 | }
15 | },
16 | "cells": [
17 | {
18 | "cell_type": "markdown",
19 | "metadata": {
20 | "id": "view-in-github",
21 | "colab_type": "text"
22 | },
23 | "source": [
24 | "
"
25 | ]
26 | },
27 | {
28 | "cell_type": "markdown",
29 | "metadata": {
30 | "id": "pGB7ghYeRHsA"
31 | },
32 | "source": [
33 | "# AprilTag with Python\n",
34 | "\n"
35 | ]
36 | },
37 | {
38 | "cell_type": "markdown",
39 | "metadata": {
40 | "id": "SjUC1zgNRXmw"
41 | },
42 | "source": [
43 | "\n",
44 | "This notebook is associated with the [AprilTag with Python](https://www.pyimagesearch.com/2020/11/02/apriltag-with-python/) blog post published on 11-02-20.\n",
45 | "\n",
46 | "Only the code for the blog post is here. Most codeblocks have a 1:1 relationship with what you find in the blog post with two exceptions: (1) Python classes are not separate files as they are typically organized with PyImageSearch projects, and (2) Command Line Argument parsing is replaced with an `args` dictionary that you can manipulate as needed.\n",
47 | "\n",
48 | "We recommend that you execute (press ▶️) the code block-by-block, as-is, before adjusting parameters and `args` inputs. Once you've verified that the code is working, you are welcome to hack with it and learn from manipulating inputs, settings, and parameters. For more information on using Jupyter and Colab, please refer to these resources:\n",
49 | "\n",
50 | "* [Jupyter Notebook User Interface](https://jupyter-notebook.readthedocs.io/en/stable/notebook.html#notebook-user-interface)\n",
51 | "* [Overview of Google Colaboratory Features](https://colab.research.google.com/notebooks/basic_features_overview.ipynb)\n",
52 | "\n",
53 | "\n",
54 | "Happy hacking!\n",
55 | "\n",
56 | "\n",
57 | "
\n"
58 | ]
59 | },
60 | {
61 | "cell_type": "markdown",
62 | "metadata": {
63 | "id": "ZY4l5Bs8RwO6"
64 | },
65 | "source": [
66 | "### Install the necessary packages"
67 | ]
68 | },
69 | {
70 | "cell_type": "code",
71 | "metadata": {
72 | "id": "qh6_ChdSR19_"
73 | },
74 | "source": [
75 | "!pip install apriltag"
76 | ],
77 | "execution_count": null,
78 | "outputs": []
79 | },
80 | {
81 | "cell_type": "markdown",
82 | "metadata": {
83 | "id": "8Rllb5HER6mI"
84 | },
85 | "source": [
86 | "### Download the code zip file"
87 | ]
88 | },
89 | {
90 | "cell_type": "code",
91 | "metadata": {
92 | "id": "7riYwdhjPc6a"
93 | },
94 | "source": [
95 | "!wget https://pyimagesearch-code-downloads.s3-us-west-2.amazonaws.com/python-apriltag/python-apriltag.zip\n",
96 | "!unzip -qq python-apriltag.zip\n",
97 | "%cd python-apriltag"
98 | ],
99 | "execution_count": null,
100 | "outputs": []
101 | },
102 | {
103 | "cell_type": "markdown",
104 | "metadata": {
105 | "id": "mAXMOkb2SELL"
106 | },
107 | "source": [
108 | "## Blog Post Code"
109 | ]
110 | },
111 | {
112 | "cell_type": "markdown",
113 | "metadata": {
114 | "id": "arlbRe__SGoU"
115 | },
116 | "source": [
117 | "### Import Packages"
118 | ]
119 | },
120 | {
121 | "cell_type": "code",
122 | "metadata": {
123 | "id": "xhkI9oGsSOBh"
124 | },
125 | "source": [
126 | "# import the necessary packages\n",
127 | "import matplotlib.pyplot as plt\n",
128 | "import apriltag\n",
129 | "import argparse\n",
130 | "import cv2"
131 | ],
132 | "execution_count": null,
133 | "outputs": []
134 | },
135 | {
136 | "cell_type": "markdown",
137 | "metadata": {
138 | "id": "5Sl-xfCoSU44"
139 | },
140 | "source": [
141 | "### Function to display images in Jupyter Notebooks and Google Colab"
142 | ]
143 | },
144 | {
145 | "cell_type": "code",
146 | "metadata": {
147 | "id": "fmxGKmZDSOk3"
148 | },
149 | "source": [
150 | "def plt_imshow(title, image):\n",
151 | "\t# convert the image frame BGR to RGB color space and display it\n",
152 | "\timage = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n",
153 | "\tplt.imshow(image)\n",
154 | "\tplt.title(title)\n",
155 | "\tplt.grid(False)\n",
156 | "\tplt.show()"
157 | ],
158 | "execution_count": null,
159 | "outputs": []
160 | },
161 | {
162 | "cell_type": "markdown",
163 | "metadata": {
164 | "id": "fmQQbEHwSkkk"
165 | },
166 | "source": [
167 | "### Implementing AprilTag detection with Python"
168 | ]
169 | },
170 | {
171 | "cell_type": "code",
172 | "metadata": {
173 | "id": "Y6Qe0ITHSbH5"
174 | },
175 | "source": [
176 | "# # construct the argument parser and parse the arguments\n",
177 | "# ap = argparse.ArgumentParser()\n",
178 | "# ap.add_argument(\"-i\", \"--image\", required=True,\n",
179 | "# \thelp=\"path to input image containing AprilTag\")\n",
180 | "# args = vars(ap.parse_args())\n",
181 | "\n",
182 | "# since we are using Jupyter Notebooks we can replace our argument\n",
183 | "# parsing code with *hard coded* arguments and values\n",
184 | "args = {\n",
185 | "\t\"image\": \"images/example_02.png\"\n",
186 | "}"
187 | ],
188 | "execution_count": null,
189 | "outputs": []
190 | },
191 | {
192 | "cell_type": "code",
193 | "metadata": {
194 | "id": "Ie7oMtK8Sxzk"
195 | },
196 | "source": [
197 | "# load the input image and convert it to grayscale\n",
198 | "print(\"[INFO] loading image...\")\n",
199 | "image = cv2.imread(args[\"image\"])\n",
200 | "gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)"
201 | ],
202 | "execution_count": null,
203 | "outputs": []
204 | },
205 | {
206 | "cell_type": "code",
207 | "metadata": {
208 | "id": "gZVuAkycS1K0"
209 | },
210 | "source": [
211 | "# define the AprilTags detector options and then detect the AprilTags\n",
212 | "# in the input image\n",
213 | "print(\"[INFO] detecting AprilTags...\")\n",
214 | "options = apriltag.DetectorOptions(families=\"tag36h11\")\n",
215 | "detector = apriltag.Detector(options)\n",
216 | "results = detector.detect(gray)\n",
217 | "print(\"[INFO] {} total AprilTags detected\".format(len(results)))"
218 | ],
219 | "execution_count": null,
220 | "outputs": []
221 | },
222 | {
223 | "cell_type": "code",
224 | "metadata": {
225 | "id": "z5pEbtvpS8c1"
226 | },
227 | "source": [
228 | "# loop over the AprilTag detection results\n",
229 | "for r in results:\n",
230 | "\t# extract the bounding box (x, y)-coordinates for the AprilTag\n",
231 | "\t# and convert each of the (x, y)-coordinate pairs to integers\n",
232 | "\t(ptA, ptB, ptC, ptD) = r.corners\n",
233 | "\tptB = (int(ptB[0]), int(ptB[1]))\n",
234 | "\tptC = (int(ptC[0]), int(ptC[1]))\n",
235 | "\tptD = (int(ptD[0]), int(ptD[1]))\n",
236 | "\tptA = (int(ptA[0]), int(ptA[1]))\n",
237 | "\n",
238 | "\t# draw the bounding box of the AprilTag detection\n",
239 | "\tcv2.line(image, ptA, ptB, (0, 255, 0), 2)\n",
240 | "\tcv2.line(image, ptB, ptC, (0, 255, 0), 2)\n",
241 | "\tcv2.line(image, ptC, ptD, (0, 255, 0), 2)\n",
242 | "\tcv2.line(image, ptD, ptA, (0, 255, 0), 2)\n",
243 | "\n",
244 | "\t# draw the center (x, y)-coordinates of the AprilTag\n",
245 | "\t(cX, cY) = (int(r.center[0]), int(r.center[1]))\n",
246 | "\tcv2.circle(image, (cX, cY), 5, (0, 0, 255), -1)\n",
247 | "\n",
248 | "\t# draw the tag family on the image\n",
249 | "\ttagFamily = r.tag_family.decode(\"utf-8\")\n",
250 | "\tcv2.putText(image, tagFamily, (ptA[0], ptA[1] - 15),\n",
251 | "\t\tcv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)\n",
252 | "\tprint(\"[INFO] tag family: {}\".format(tagFamily))\n",
253 | " \n",
254 | " # show the output image after AprilTag detection\n",
255 | "plt_imshow(\"Image\", image)"
256 | ],
257 | "execution_count": null,
258 | "outputs": []
259 | },
260 | {
261 | "cell_type": "markdown",
262 | "metadata": {
263 | "id": "D0SwqbOHTq6l"
264 | },
265 | "source": [
266 | "For a detailed walkthrough of the concepts and code, be sure to refer to the full tutorial, [*AprilTag with Python*](https://www.pyimagesearch.com/2020/11/02/apriltag-with-python/) blog post published on 11-02-20."
267 | ]
268 | }
269 | ]
270 | }
--------------------------------------------------------------------------------
/103-image_resizing.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "colab": {
6 | "name": "Copy of opencv_resizing.ipynb",
7 | "provenance": [],
8 | "collapsed_sections": [],
9 | "toc_visible": true,
10 | "include_colab_link": true
11 | },
12 | "kernelspec": {
13 | "name": "python3",
14 | "display_name": "Python 3"
15 | }
16 | },
17 | "cells": [
18 | {
19 | "cell_type": "markdown",
20 | "metadata": {
21 | "id": "view-in-github",
22 | "colab_type": "text"
23 | },
24 | "source": [
25 | "
"
26 | ]
27 | },
28 | {
29 | "cell_type": "markdown",
30 | "metadata": {
31 | "id": "c7uPgNc0NyO7"
32 | },
33 | "source": [
34 | "# OpenCV Resize Image ( cv2.resize )\n",
35 | "\n"
36 | ]
37 | },
38 | {
39 | "cell_type": "markdown",
40 | "metadata": {
41 | "id": "Mpthbjs-N2qJ"
42 | },
43 | "source": [
44 | "\n",
45 | "This notebook is associated with the [OpenCV Resize Image ( cv2.resize )](https://www.pyimagesearch.com/2021/01/20/opencv-resize-image-cv2-resize/) blog post published on 01-20-2021.\n",
46 | "\n",
47 | "Only the code for the blog post is here. Most codeblocks have a 1:1 relationship with what you find in the blog post with two exceptions: (1) Python classes are not separate files as they are typically organized with PyImageSearch projects, and (2) Command Line Argument parsing is replaced with an `args` dictionary that you can manipulate as needed.\n",
48 | "\n",
49 | "We recommend that you execute (press ▶️) the code block-by-block, as-is, before adjusting parameters and `args` inputs. Once you've verified that the code is working, you are welcome to hack with it and learn from manipulating inputs, settings, and parameters. For more information on using Jupyter and Colab, please refer to these resources:\n",
50 | "\n",
51 | "* [Jupyter Notebook User Interface](https://jupyter-notebook.readthedocs.io/en/stable/notebook.html#notebook-user-interface)\n",
52 | "* [Overview of Google Colaboratory Features](https://colab.research.google.com/notebooks/basic_features_overview.ipynb)\n",
53 | "\n",
54 | "\n",
55 | "Happy hacking!\n",
56 | "\n",
57 | "*Akhil*"
58 | ]
59 | },
60 | {
61 | "cell_type": "markdown",
62 | "metadata": {
63 | "id": "0pL5rHGgOAMk"
64 | },
65 | "source": [
66 | "### Download the code zip file"
67 | ]
68 | },
69 | {
70 | "cell_type": "code",
71 | "metadata": {
72 | "id": "uEZbwcwepI9V"
73 | },
74 | "source": [
75 | "!wget https://pyimagesearch-code-downloads.s3-us-west-2.amazonaws.com/opencv-resizing/opencv-resizing.zip\n",
76 | "!unzip -qq opencv-resizing.zip\n",
77 | "%cd opencv-resizing"
78 | ],
79 | "execution_count": null,
80 | "outputs": []
81 | },
82 | {
83 | "cell_type": "markdown",
84 | "metadata": {
85 | "id": "8yYRCnThOQXl"
86 | },
87 | "source": [
88 | "## Blog Post Code"
89 | ]
90 | },
91 | {
92 | "cell_type": "markdown",
93 | "metadata": {
94 | "id": "BcmY4DDJOSIt"
95 | },
96 | "source": [
97 | "### Import Packages"
98 | ]
99 | },
100 | {
101 | "cell_type": "code",
102 | "metadata": {
103 | "id": "BlcPho8lOOuF"
104 | },
105 | "source": [
106 | "# import the necessary packages\n",
107 | "import matplotlib.pyplot as plt\n",
108 | "import argparse\n",
109 | "import imutils\n",
110 | "import cv2"
111 | ],
112 | "execution_count": null,
113 | "outputs": []
114 | },
115 | {
116 | "cell_type": "markdown",
117 | "metadata": {
118 | "id": "uY1ceK63OuFY"
119 | },
120 | "source": [
121 | "### Function to display images in Jupyter Notebooks and Google Colab"
122 | ]
123 | },
124 | {
125 | "cell_type": "code",
126 | "metadata": {
127 | "id": "gkPDb7emOuwQ"
128 | },
129 | "source": [
130 | "def plt_imshow(title, image):\n",
131 | " # convert the image frame BGR to RGB color space and display it\n",
132 | "\timage = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n",
133 | "\tplt.imshow(image)\n",
134 | "\tplt.title(title)\n",
135 | "\tplt.grid(False)\n",
136 | "\tplt.show()"
137 | ],
138 | "execution_count": null,
139 | "outputs": []
140 | },
141 | {
142 | "cell_type": "markdown",
143 | "metadata": {
144 | "id": "DgaM1Gy4Styv"
145 | },
146 | "source": [
147 | "### Implementing basic image resizing with OpenCV"
148 | ]
149 | },
150 | {
151 | "cell_type": "code",
152 | "metadata": {
153 | "id": "diZ5qxvYSyUT"
154 | },
155 | "source": [
156 | "# # construct the argument parser and parse the arguments\n",
157 | "# ap = argparse.ArgumentParser()\n",
158 | "# ap.add_argument(\"-i\", \"--image\", type=str, default=\"adrian.png\",\n",
159 | "# \thelp=\"path to the input image\")\n",
160 | "# args = vars(ap.parse_args())\n",
161 | "\n",
162 | "# since we are using Jupyter Notebooks we can replace our argument\n",
163 | "# parsing code with *hard coded* arguments and values\n",
164 | "args = {\n",
165 | " \"image\": \"adrian.png\"\n",
166 | "}"
167 | ],
168 | "execution_count": null,
169 | "outputs": []
170 | },
171 | {
172 | "cell_type": "code",
173 | "metadata": {
174 | "id": "GkgiFwtoS6rk"
175 | },
176 | "source": [
177 | "# load the original input image and display it to our screen\n",
178 | "image = cv2.imread(args[\"image\"])\n",
179 | "plt_imshow(\"Original\", image)\n",
180 | "\n",
181 | "# let's resize our image to be 150 pixels wide, but in order to\n",
182 | "# prevent our resized image from being skewed/distorted, we must\n",
183 | "# first calculate the ratio of the *new* width to the *old* width\n",
184 | "r = 150.0 / image.shape[1]\n",
185 | "dim = (150, int(image.shape[0] * r))\n",
186 | "\n",
187 | "# perform the actual resizing of the image\n",
188 | "resized = cv2.resize(image, dim, interpolation=cv2.INTER_AREA)\n",
189 | "plt_imshow(\"Resized (Width)\", resized)"
190 | ],
191 | "execution_count": null,
192 | "outputs": []
193 | },
194 | {
195 | "cell_type": "code",
196 | "metadata": {
197 | "id": "ORkobHoUS-pc"
198 | },
199 | "source": [
200 | "# let's resize the image to have a width of 50 pixels, again keeping\n",
201 | "# in mind the aspect ratio\n",
202 | "r = 50.0 / image.shape[0]\n",
203 | "dim = (int(image.shape[1] * r), 50)\n",
204 | "\n",
205 | "# perform the resizing\n",
206 | "resized = cv2.resize(image, dim, interpolation=cv2.INTER_AREA)\n",
207 | "plt_imshow(\"Resized (Height)\", resized)"
208 | ],
209 | "execution_count": null,
210 | "outputs": []
211 | },
212 | {
213 | "cell_type": "code",
214 | "metadata": {
215 | "id": "5uwuHLG9TEjr"
216 | },
217 | "source": [
218 | "# calculating the ratio each and every time we want to resize an\n",
219 | "# image is a real pain, so let's use the imutils convenience\n",
220 | "# function which will *automatically* maintain our aspect ratio\n",
221 | "# for us\n",
222 | "resized = imutils.resize(image, width=100)\n",
223 | "plt_imshow(\"Resized via imutils\", resized)"
224 | ],
225 | "execution_count": null,
226 | "outputs": []
227 | },
228 | {
229 | "cell_type": "markdown",
230 | "metadata": {
231 | "id": "6pXy8QKSTRsm"
232 | },
233 | "source": [
234 | "### Comparing OpenCV interpolation methods\n"
235 | ]
236 | },
237 | {
238 | "cell_type": "code",
239 | "metadata": {
240 | "id": "EFo7fN-UTH1b"
241 | },
242 | "source": [
243 | "# construct the list of interpolation methods in OpenCV\n",
244 | "methods = [\n",
245 | "\t(\"cv2.INTER_NEAREST\", cv2.INTER_NEAREST),\n",
246 | "\t(\"cv2.INTER_LINEAR\", cv2.INTER_LINEAR),\n",
247 | "\t(\"cv2.INTER_AREA\", cv2.INTER_AREA),\n",
248 | "\t(\"cv2.INTER_CUBIC\", cv2.INTER_CUBIC),\n",
249 | "\t(\"cv2.INTER_LANCZOS4\", cv2.INTER_LANCZOS4)]\n",
250 | "\n",
251 | "# loop over the interpolation methods\n",
252 | "for (name, method) in methods:\n",
253 | "\t# increase the size of the image by 3x using the current\n",
254 | "\t# interpolation method\n",
255 | "\tprint(\"[INFO] {}\".format(name))\n",
256 | "\tresized = imutils.resize(image, width=image.shape[1] * 3,\n",
257 | "\t\tinter=method)\n",
258 | "\tplt_imshow(\"Method: {}\".format(name), resized)"
259 | ],
260 | "execution_count": null,
261 | "outputs": []
262 | },
263 | {
264 | "cell_type": "markdown",
265 | "metadata": {
266 | "id": "iIK0y_52aETm"
267 | },
268 | "source": [
269 | "For a detailed walkthrough of the concepts and code, be sure to refer to the full tutorial, [OpenCV Resize Image ( cv2.resize )](https://www.pyimagesearch.com/2021/01/20/opencv-resize-image-cv2-resize/) published on 01-20-2021."
270 | ]
271 | }
272 | ]
273 | }
--------------------------------------------------------------------------------
/205-opencv_thresholding.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "colab": {
6 | "name": "Copy of opencv_thresholding.ipynb",
7 | "provenance": [],
8 | "collapsed_sections": [],
9 | "toc_visible": true,
10 | "include_colab_link": true
11 | },
12 | "kernelspec": {
13 | "name": "python3",
14 | "display_name": "Python 3"
15 | },
16 | "language_info": {
17 | "name": "python"
18 | }
19 | },
20 | "cells": [
21 | {
22 | "cell_type": "markdown",
23 | "metadata": {
24 | "id": "view-in-github",
25 | "colab_type": "text"
26 | },
27 | "source": [
28 | "
"
29 | ]
30 | },
31 | {
32 | "cell_type": "markdown",
33 | "metadata": {
34 | "id": "c7uPgNc0NyO7"
35 | },
36 | "source": [
37 | "# OpenCV Thresholding ( cv2.threshold )\n",
38 | "\n"
39 | ]
40 | },
41 | {
42 | "cell_type": "markdown",
43 | "metadata": {
44 | "id": "Mpthbjs-N2qJ"
45 | },
46 | "source": [
47 | "\n",
48 | "This notebook is associated with the [OpenCV Thresholding ( cv2.threshold )](https://www.pyimagesearch.com/2021/04/28/opencv-thresholding-cv2-threshold/) blog post published on 04-28-21.\n",
49 | "\n",
50 | "Only the code for the blog post is here. Most codeblocks have a 1:1 relationship with what you find in the blog post with two exceptions: (1) Python classes are not separate files as they are typically organized with PyImageSearch projects, and (2) Command Line Argument parsing is replaced with an `args` dictionary that you can manipulate as needed.\n",
51 | "\n",
52 | "We recommend that you execute (press ▶️) the code block-by-block, as-is, before adjusting parameters and `args` inputs. Once you've verified that the code is working, you are welcome to hack with it and learn from manipulating inputs, settings, and parameters. For more information on using Jupyter and Colab, please refer to these resources:\n",
53 | "\n",
54 | "* [Jupyter Notebook User Interface](https://jupyter-notebook.readthedocs.io/en/stable/notebook.html#notebook-user-interface)\n",
55 | "* [Overview of Google Colaboratory Features](https://colab.research.google.com/notebooks/basic_features_overview.ipynb)\n",
56 | "\n",
57 | "\n",
58 | "Happy hacking!\n",
59 | "\n",
60 | "\n",
61 | "
\n"
62 | ]
63 | },
64 | {
65 | "cell_type": "markdown",
66 | "metadata": {
67 | "id": "0pL5rHGgOAMk"
68 | },
69 | "source": [
70 | "### Download the code zip file"
71 | ]
72 | },
73 | {
74 | "cell_type": "code",
75 | "metadata": {
76 | "id": "uEZbwcwepI9V"
77 | },
78 | "source": [
79 | "!wget https://pyimagesearch-code-downloads.s3-us-west-2.amazonaws.com/opencv-thresholding/opencv-thresholding.zip\n",
80 | "!unzip -qq opencv-thresholding.zip\n",
81 | "%cd opencv-thresholding"
82 | ],
83 | "execution_count": null,
84 | "outputs": []
85 | },
86 | {
87 | "cell_type": "markdown",
88 | "metadata": {
89 | "id": "8yYRCnThOQXl"
90 | },
91 | "source": [
92 | "## Blog Post Code"
93 | ]
94 | },
95 | {
96 | "cell_type": "markdown",
97 | "metadata": {
98 | "id": "BcmY4DDJOSIt"
99 | },
100 | "source": [
101 | "### Import Packages"
102 | ]
103 | },
104 | {
105 | "cell_type": "code",
106 | "metadata": {
107 | "id": "BlcPho8lOOuF"
108 | },
109 | "source": [
110 | "# import the necessary packages\n",
111 | "import matplotlib.pyplot as plt\n",
112 | "import cv2"
113 | ],
114 | "execution_count": null,
115 | "outputs": []
116 | },
117 | {
118 | "cell_type": "markdown",
119 | "metadata": {
120 | "id": "uY1ceK63OuFY"
121 | },
122 | "source": [
123 | "### Function to display images in Jupyter Notebooks and Google Colab"
124 | ]
125 | },
126 | {
127 | "cell_type": "code",
128 | "metadata": {
129 | "id": "gkPDb7emOuwQ"
130 | },
131 | "source": [
132 | "def plt_imshow(title, image):\n",
133 | " # convert the image frame BGR to RGB color space and display it\n",
134 | " if len(image.shape) == 3:\n",
135 | " image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n",
136 | " plt.imshow(image)\n",
137 | " plt.title(title)\n",
138 | " plt.grid(False)\n",
139 | " plt.show()"
140 | ],
141 | "execution_count": null,
142 | "outputs": []
143 | },
144 | {
145 | "cell_type": "markdown",
146 | "metadata": {
147 | "id": "iYgNuCJ1v3U8"
148 | },
149 | "source": [
150 | "### Implementing simple thresholding with OpenCV"
151 | ]
152 | },
153 | {
154 | "cell_type": "code",
155 | "metadata": {
156 | "id": "Cz3IK2-6v24m"
157 | },
158 | "source": [
159 | "# # construct the argument parser and parse the arguments\n",
160 | "# ap = argparse.ArgumentParser()\n",
161 | "# ap.add_argument(\"-i\", \"--image\", type=str, required=True,\n",
162 | "# \thelp=\"path to input image\")\n",
163 | "# args = vars(ap.parse_args())\n",
164 | "\n",
165 | "# since we are using Jupyter Notebooks we can replace our argument\n",
166 | "# parsing code with *hard coded* arguments and values\n",
167 | "args = {\n",
168 | " \"image\": \"images/opencv_logo.png\"\n",
169 | "}"
170 | ],
171 | "execution_count": null,
172 | "outputs": []
173 | },
174 | {
175 | "cell_type": "code",
176 | "metadata": {
177 | "id": "Ka2rnlNNwPIH"
178 | },
179 | "source": [
180 | "# load the image and display it\n",
181 | "image = cv2.imread(args[\"image\"])\n",
182 | "plt_imshow(\"Image\", image)"
183 | ],
184 | "execution_count": null,
185 | "outputs": []
186 | },
187 | {
188 | "cell_type": "code",
189 | "metadata": {
190 | "id": "YzGT2N8dwHDS"
191 | },
192 | "source": [
193 | "# convert the image to grayscale and blur it slightly\n",
194 | "gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)\n",
195 | "blurred = cv2.GaussianBlur(gray, (7, 7), 0)"
196 | ],
197 | "execution_count": null,
198 | "outputs": []
199 | },
200 | {
201 | "cell_type": "code",
202 | "metadata": {
203 | "id": "XkfOEfNKwLy2"
204 | },
205 | "source": [
206 | "# apply basic thresholding -- the first parameter is the image\n",
207 | "# we want to threshold, the second value is is our threshold\n",
208 | "# check; if a pixel value is greater than our threshold (in this\n",
209 | "# case, 200), we set it to be *black, otherwise it is *white*\n",
210 | "(T, threshInv) = cv2.threshold(blurred, 200, 255,\n",
211 | "\tcv2.THRESH_BINARY_INV)\n",
212 | "plt_imshow(\"Threshold Binary Inverse\", threshInv)"
213 | ],
214 | "execution_count": null,
215 | "outputs": []
216 | },
217 | {
218 | "cell_type": "code",
219 | "metadata": {
220 | "id": "BEvYEJBAwvHR"
221 | },
222 | "source": [
223 | "# using normal thresholding (rather than inverse thresholding)\n",
224 | "(T, thresh) = cv2.threshold(blurred, 200, 255, cv2.THRESH_BINARY)\n",
225 | "plt_imshow(\"Threshold Binary\", thresh)"
226 | ],
227 | "execution_count": null,
228 | "outputs": []
229 | },
230 | {
231 | "cell_type": "code",
232 | "metadata": {
233 | "id": "6egO32bowzm4"
234 | },
235 | "source": [
236 | "# visualize only the masked regions in the image\n",
237 | "masked = cv2.bitwise_and(image, image, mask=threshInv)\n",
238 | "plt_imshow(\"Output\", masked)"
239 | ],
240 | "execution_count": null,
241 | "outputs": []
242 | },
243 | {
244 | "cell_type": "markdown",
245 | "metadata": {
246 | "id": "EoVb48ZVw6za"
247 | },
248 | "source": [
249 | "### Implementing Otsu thresholding with OpenCV"
250 | ]
251 | },
252 | {
253 | "cell_type": "code",
254 | "metadata": {
255 | "id": "UvOGsunNxAF4"
256 | },
257 | "source": [
258 | "# apply Otsu's automatic thresholding which automatically determines\n",
259 | "# the best threshold value\n",
260 | "(T, threshInv) = cv2.threshold(blurred, 0, 255,\n",
261 | "\tcv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)\n",
262 | "plt_imshow(\"Threshold\", threshInv)\n",
263 | "print(\"[INFO] otsu's thresholding value: {}\".format(T))"
264 | ],
265 | "execution_count": null,
266 | "outputs": []
267 | },
268 | {
269 | "cell_type": "code",
270 | "metadata": {
271 | "id": "SO8gbZmQxGSL"
272 | },
273 | "source": [
274 | "# visualize only the masked regions in the image\n",
275 | "masked = cv2.bitwise_and(image, image, mask=threshInv)\n",
276 | "plt_imshow(\"Output\", masked)"
277 | ],
278 | "execution_count": null,
279 | "outputs": []
280 | },
281 | {
282 | "cell_type": "markdown",
283 | "metadata": {
284 | "id": "iIK0y_52aETm"
285 | },
286 | "source": [
287 | "For a detailed walkthrough of the concepts and code, be sure to refer to the full tutorial, [OpenCV Thresholding ( cv2.threshold )](https://www.pyimagesearch.com/2021/04/28/opencv-thresholding-cv2-threshold/) published on 04-28-21."
288 | ]
289 | }
290 | ]
291 | }
--------------------------------------------------------------------------------
/102-rotate_image.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "colab": {
6 | "name": "rotate-image.ipynb",
7 | "provenance": [],
8 | "collapsed_sections": [],
9 | "toc_visible": true,
10 | "include_colab_link": true
11 | },
12 | "kernelspec": {
13 | "name": "python3",
14 | "display_name": "Python 3"
15 | }
16 | },
17 | "cells": [
18 | {
19 | "cell_type": "markdown",
20 | "metadata": {
21 | "id": "view-in-github",
22 | "colab_type": "text"
23 | },
24 | "source": [
25 | "
"
26 | ]
27 | },
28 | {
29 | "cell_type": "markdown",
30 | "metadata": {
31 | "id": "c7uPgNc0NyO7"
32 | },
33 | "source": [
34 | "# OpenCV Rotate Image\n",
35 | "\n"
36 | ]
37 | },
38 | {
39 | "cell_type": "markdown",
40 | "metadata": {
41 | "id": "Mpthbjs-N2qJ"
42 | },
43 | "source": [
44 | "\n",
45 | "## This notebook is associated with the [OpenCV Rotate Image](https://www.pyimagesearch.com/2021/01/20/opencv-rotate-image/) blog post published on 01-20-2021.\n",
46 | "\n",
47 | "Only the code for the blog post is here. Most codeblocks have a 1:1 relationship with what you find in the blog post with two exceptions: (1) Python classes are not separate files as they are typically organized with PyImageSearch projects, and (2) Command Line Argument parsing is replaced with an `args` dictionary that you can manipulate as needed.\n",
48 | "\n",
49 | "We recommend that you execute (press ▶️) the code block-by-block, as-is, before adjusting parameters and `args` inputs. Once you've verified that the code is working, you are welcome to hack with it and learn from manipulating inputs, settings, and parameters. For more information on using Jupyter and Colab, please refer to these resources:\n",
50 | "\n",
51 | "* [Jupyter Notebook User Interface](https://jupyter-notebook.readthedocs.io/en/stable/notebook.html#notebook-user-interface)\n",
52 | "* [Overview of Google Colaboratory Features](https://colab.research.google.com/notebooks/basic_features_overview.ipynb)\n",
53 | "\n",
54 | "\n",
55 | "Happy hacking!\n",
56 | "\n",
57 | "*Akhil*\n",
58 | "\n"
59 | ]
60 | },
61 | {
62 | "cell_type": "markdown",
63 | "metadata": {
64 | "id": "0pL5rHGgOAMk"
65 | },
66 | "source": [
67 | "### Download the code zip file"
68 | ]
69 | },
70 | {
71 | "cell_type": "code",
72 | "metadata": {
73 | "id": "uEZbwcwepI9V",
74 | "colab": {
75 | "base_uri": "https://localhost:8080/"
76 | },
77 | "outputId": "286e36ff-4c5e-4490-9afd-4c78d556ff8d"
78 | },
79 | "source": [
80 | "!wget https://pyimagesearch-code-downloads.s3-us-west-2.amazonaws.com/opencv-rotate/opencv-rotate.zip\n",
81 | "!unzip -qq opencv-rotate.zip\n",
82 | "%cd opencv-rotate"
83 | ],
84 | "execution_count": 1,
85 | "outputs": [
86 | {
87 | "output_type": "stream",
88 | "text": [
89 | "--2021-05-14 06:58:51-- https://pyimagesearch-code-downloads.s3-us-west-2.amazonaws.com/opencv-rotate/opencv-rotate.zip\n",
90 | "Resolving pyimagesearch-code-downloads.s3-us-west-2.amazonaws.com (pyimagesearch-code-downloads.s3-us-west-2.amazonaws.com)... 52.218.228.233\n",
91 | "Connecting to pyimagesearch-code-downloads.s3-us-west-2.amazonaws.com (pyimagesearch-code-downloads.s3-us-west-2.amazonaws.com)|52.218.228.233|:443... connected.\n",
92 | "HTTP request sent, awaiting response... 200 OK\n",
93 | "Length: 37160 (36K) [application/zip]\n",
94 | "Saving to: ‘opencv-rotate.zip’\n",
95 | "\n",
96 | "opencv-rotate.zip 100%[===================>] 36.29K --.-KB/s in 0.04s \n",
97 | "\n",
98 | "2021-05-14 06:58:51 (985 KB/s) - ‘opencv-rotate.zip’ saved [37160/37160]\n",
99 | "\n",
100 | "/content/opencv-rotate\n"
101 | ],
102 | "name": "stdout"
103 | }
104 | ]
105 | },
106 | {
107 | "cell_type": "markdown",
108 | "metadata": {
109 | "id": "8yYRCnThOQXl"
110 | },
111 | "source": [
112 | "## Blog Post Code"
113 | ]
114 | },
115 | {
116 | "cell_type": "markdown",
117 | "metadata": {
118 | "id": "BcmY4DDJOSIt"
119 | },
120 | "source": [
121 | "### Import Packages"
122 | ]
123 | },
124 | {
125 | "cell_type": "code",
126 | "metadata": {
127 | "id": "BlcPho8lOOuF"
128 | },
129 | "source": [
130 | "# import the necessary packages\n",
131 | "import matplotlib.pyplot as plt\n",
132 | "import argparse\n",
133 | "import imutils\n",
134 | "import cv2"
135 | ],
136 | "execution_count": null,
137 | "outputs": []
138 | },
139 | {
140 | "cell_type": "markdown",
141 | "metadata": {
142 | "id": "uY1ceK63OuFY"
143 | },
144 | "source": [
145 | "### Function to display images in Jupyter Notebooks and Google Colab"
146 | ]
147 | },
148 | {
149 | "cell_type": "code",
150 | "metadata": {
151 | "id": "gkPDb7emOuwQ"
152 | },
153 | "source": [
154 | "def plt_imshow(title, image):\n",
155 | " # convert the image frame BGR to RGB color space and display it\n",
156 | "\timage = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n",
157 | "\tplt.imshow(image)\n",
158 | "\tplt.title(title)\n",
159 | "\tplt.grid(False)\n",
160 | "\tplt.show()"
161 | ],
162 | "execution_count": null,
163 | "outputs": []
164 | },
165 | {
166 | "cell_type": "markdown",
167 | "metadata": {
168 | "id": "X7_c5NjTOZEe"
169 | },
170 | "source": [
171 | "### Implementing image rotation with OpenCV"
172 | ]
173 | },
174 | {
175 | "cell_type": "code",
176 | "metadata": {
177 | "id": "Txalo2DGObge"
178 | },
179 | "source": [
180 | "# # construct the argument parser and parse the arguments\n",
181 | "# ap = argparse.ArgumentParser()\n",
182 | "# ap.add_argument(\"-i\", \"--image\", type=str, default=\"opencv_logo.png\",\n",
183 | "# \thelp=\"path to the input image\")\n",
184 | "# args = vars(ap.parse_args())\n",
185 | "\n",
186 | "# since we are using Jupyter Notebooks we can replace our argument\n",
187 | "# parsing code with *hard coded* arguments and values\n",
188 | "args = {\n",
189 | " \"image\": \"opencv_logo.png\"\n",
190 | "}"
191 | ],
192 | "execution_count": null,
193 | "outputs": []
194 | },
195 | {
196 | "cell_type": "code",
197 | "metadata": {
198 | "id": "8ZgqVr3VOqlU"
199 | },
200 | "source": [
201 | "# load the image and show it\n",
202 | "image = cv2.imread(args[\"image\"])\n",
203 | "plt_imshow(\"Original\", image)\n",
204 | "\n",
205 | "# grab the dimensions of the image and calculate the center of the\n",
206 | "# image\n",
207 | "(h, w) = image.shape[:2]\n",
208 | "(cX, cY) = (w // 2, h // 2)\n",
209 | "\n",
210 | "# rotate our image by 45 degrees around the center of the image\n",
211 | "M = cv2.getRotationMatrix2D((cX, cY), 45, 1.0)\n",
212 | "rotated = cv2.warpAffine(image, M, (w, h))\n",
213 | "plt_imshow(\"Rotated by 45 Degrees\", rotated)\n",
214 | "\n",
215 | "# rotate our image by -90 degrees around the image\n",
216 | "M = cv2.getRotationMatrix2D((cX, cY), -90, 1.0)\n",
217 | "rotated = cv2.warpAffine(image, M, (w, h))\n",
218 | "plt_imshow(\"Rotated by -90 Degrees\", rotated)"
219 | ],
220 | "execution_count": null,
221 | "outputs": []
222 | },
223 | {
224 | "cell_type": "code",
225 | "metadata": {
226 | "id": "mP7WQv9zOveK"
227 | },
228 | "source": [
229 | "# rotate our image around an arbitrary point rather than the center\n",
230 | "M = cv2.getRotationMatrix2D((10, 10), 45, 1.0)\n",
231 | "rotated = cv2.warpAffine(image, M, (w, h))\n",
232 | "plt_imshow(\"Rotated by Arbitrary Point\", rotated)"
233 | ],
234 | "execution_count": null,
235 | "outputs": []
236 | },
237 | {
238 | "cell_type": "code",
239 | "metadata": {
240 | "id": "e03VvyFhO0o5"
241 | },
242 | "source": [
243 | "# use our imutils function to rotate an image 180 degrees\n",
244 | "rotated = imutils.rotate(image, 180)\n",
245 | "plt_imshow(\"Rotated by 180 Degrees\", rotated)"
246 | ],
247 | "execution_count": null,
248 | "outputs": []
249 | },
250 | {
251 | "cell_type": "code",
252 | "metadata": {
253 | "id": "15kHAH0PO3wv"
254 | },
255 | "source": [
256 | "# rotate our image by 33 degrees counterclockwise, ensuring the\n",
257 | "# entire rotated image still views in the viewing area\n",
258 | "rotated = imutils.rotate_bound(image, -33)\n",
259 | "plt_imshow(\"Rotated Without Cropping\", rotated)"
260 | ],
261 | "execution_count": null,
262 | "outputs": []
263 | },
264 | {
265 | "cell_type": "markdown",
266 | "metadata": {
267 | "id": "iIK0y_52aETm"
268 | },
269 | "source": [
270 | "For a detailed walkthrough of the concepts and code, be sure to refer to the full tutorial, [OpenCV Rotate Image](https://www.pyimagesearch.com/2021/01/20/opencv-rotate-image/) published on 01-20-2021."
271 | ]
272 | }
273 | ]
274 | }
--------------------------------------------------------------------------------
/502-opencv_generate_aruco.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "colab": {
6 | "name": "Copy of opencv_generate_aruco.ipynb",
7 | "provenance": [],
8 | "collapsed_sections": [],
9 | "include_colab_link": true
10 | },
11 | "kernelspec": {
12 | "name": "python3",
13 | "display_name": "Python 3"
14 | }
15 | },
16 | "cells": [
17 | {
18 | "cell_type": "markdown",
19 | "metadata": {
20 | "id": "view-in-github",
21 | "colab_type": "text"
22 | },
23 | "source": [
24 | "
"
25 | ]
26 | },
27 | {
28 | "cell_type": "markdown",
29 | "metadata": {
30 | "id": "bSIAjNLqI5LI"
31 | },
32 | "source": [
33 | "# Generating ArUco markers with OpenCV and Python\n",
34 | "\n"
35 | ]
36 | },
37 | {
38 | "cell_type": "markdown",
39 | "metadata": {
40 | "id": "viKSbM-CJDkK"
41 | },
42 | "source": [
43 | "\n",
44 | "This notebook is associated with the [Generating ArUco markers with OpenCV and Python](https://www.pyimagesearch.com/2020/12/14/generating-aruco-markers-with-opencv-and-python/) blog post published on 12-14-20.\n",
45 | "\n",
46 | "Only the code for the blog post is here. Most codeblocks have a 1:1 relationship with what you find in the blog post with two exceptions: (1) Python classes are not separate files as they are typically organized with PyImageSearch projects, and (2) Command Line Argument parsing is replaced with an `args` dictionary that you can manipulate as needed.\n",
47 | "\n",
48 | "We recommend that you execute (press ▶️) the code block-by-block, as-is, before adjusting parameters and `args` inputs. Once you've verified that the code is working, you are welcome to hack with it and learn from manipulating inputs, settings, and parameters. For more information on using Jupyter and Colab, please refer to these resources:\n",
49 | "\n",
50 | "* [Jupyter Notebook User Interface](https://jupyter-notebook.readthedocs.io/en/stable/notebook.html#notebook-user-interface)\n",
51 | "* [Overview of Google Colaboratory Features](https://colab.research.google.com/notebooks/basic_features_overview.ipynb)\n",
52 | "\n",
53 | "\n",
54 | "\n",
55 | "Happy hacking!\n",
56 | "\n",
57 | "\n",
58 | "\n",
59 | "
\n"
60 | ]
61 | },
62 | {
63 | "cell_type": "markdown",
64 | "metadata": {
65 | "id": "uX9B9dPlJO9k"
66 | },
67 | "source": [
68 | "### Download the code zip file"
69 | ]
70 | },
71 | {
72 | "cell_type": "code",
73 | "metadata": {
74 | "id": "dwa3GuDLIZA3"
75 | },
76 | "source": [
77 | "!wget https://pyimagesearch-code-downloads.s3-us-west-2.amazonaws.com/opencv-generate-aruco/opencv-generate-aruco.zip\n",
78 | "!unzip -qq opencv-generate-aruco.zip\n",
79 | "%cd opencv-generate-aruco"
80 | ],
81 | "execution_count": null,
82 | "outputs": []
83 | },
84 | {
85 | "cell_type": "markdown",
86 | "metadata": {
87 | "id": "C5V8gTAZJhhn"
88 | },
89 | "source": [
90 | "## Blog Post Code"
91 | ]
92 | },
93 | {
94 | "cell_type": "markdown",
95 | "metadata": {
96 | "id": "PAxelcDxJjie"
97 | },
98 | "source": [
99 | "### Import Packages"
100 | ]
101 | },
102 | {
103 | "cell_type": "code",
104 | "metadata": {
105 | "id": "FkyV3l7NJbfE"
106 | },
107 | "source": [
108 | "# import the necessary packages\n",
109 | "import matplotlib.pyplot as plt\n",
110 | "import numpy as np\n",
111 | "import argparse\n",
112 | "import cv2\n",
113 | "import sys"
114 | ],
115 | "execution_count": null,
116 | "outputs": []
117 | },
118 | {
119 | "cell_type": "markdown",
120 | "metadata": {
121 | "id": "rUEQ4cboJrZh"
122 | },
123 | "source": [
124 | "### Function to display images in Jupyter Notebooks and Google Colab"
125 | ]
126 | },
127 | {
128 | "cell_type": "code",
129 | "metadata": {
130 | "id": "HRCKkoEdJoww"
131 | },
132 | "source": [
133 | "def plt_imshow(title, image):\n",
134 | " # convert the image frame BGR to RGB color space and display it\n",
135 | "\timage = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n",
136 | "\tplt.imshow(image)\n",
137 | "\tplt.title(title)\n",
138 | "\tplt.grid(False)\n",
139 | "\tplt.show()"
140 | ],
141 | "execution_count": null,
142 | "outputs": []
143 | },
144 | {
145 | "cell_type": "markdown",
146 | "metadata": {
147 | "id": "lzxxUUFNKNFv"
148 | },
149 | "source": [
150 | "### Implementing our ArUco marker generation script with OpenCV and Python"
151 | ]
152 | },
153 | {
154 | "cell_type": "code",
155 | "metadata": {
156 | "id": "i02kLEQ8JzGA"
157 | },
158 | "source": [
159 | "# # construct the argument parser and parse the arguments\n",
160 | "# ap = argparse.ArgumentParser()\n",
161 | "# ap.add_argument(\"-o\", \"--output\", required=True,\n",
162 | "# \thelp=\"path to output image containing ArUCo tag\")\n",
163 | "# ap.add_argument(\"-i\", \"--id\", type=int, required=True,\n",
164 | "# \thelp=\"ID of ArUCo tag to generate\")\n",
165 | "# ap.add_argument(\"-t\", \"--type\", type=str,\n",
166 | "# \tdefault=\"DICT_ARUCO_ORIGINAL\",\n",
167 | "# \thelp=\"type of ArUCo tag to generate\")\n",
168 | "# args = vars(ap.parse_args())\n",
169 | "\n",
170 | "# since we are using Jupyter Notebooks we can replace our argument\n",
171 | "# parsing code with *hard coded* arguments and values\n",
172 | "args = {\n",
173 | "\t\"output\": \"tags/DICT_5X5_100_id24.png\",\n",
174 | " \"id\": 24,\n",
175 | " \"type\": \"DICT_ARUCO_ORIGINAL\",\n",
176 | "}"
177 | ],
178 | "execution_count": null,
179 | "outputs": []
180 | },
181 | {
182 | "cell_type": "code",
183 | "metadata": {
184 | "id": "zotC5od9Kn3e"
185 | },
186 | "source": [
187 | "# define names of each possible ArUco tag OpenCV supports\n",
188 | "ARUCO_DICT = {\n",
189 | "\t\"DICT_4X4_50\": cv2.aruco.DICT_4X4_50,\n",
190 | "\t\"DICT_4X4_100\": cv2.aruco.DICT_4X4_100,\n",
191 | "\t\"DICT_4X4_250\": cv2.aruco.DICT_4X4_250,\n",
192 | "\t\"DICT_4X4_1000\": cv2.aruco.DICT_4X4_1000,\n",
193 | "\t\"DICT_5X5_50\": cv2.aruco.DICT_5X5_50,\n",
194 | "\t\"DICT_5X5_100\": cv2.aruco.DICT_5X5_100,\n",
195 | "\t\"DICT_5X5_250\": cv2.aruco.DICT_5X5_250,\n",
196 | "\t\"DICT_5X5_1000\": cv2.aruco.DICT_5X5_1000,\n",
197 | "\t\"DICT_6X6_50\": cv2.aruco.DICT_6X6_50,\n",
198 | "\t\"DICT_6X6_100\": cv2.aruco.DICT_6X6_100,\n",
199 | "\t\"DICT_6X6_250\": cv2.aruco.DICT_6X6_250,\n",
200 | "\t\"DICT_6X6_1000\": cv2.aruco.DICT_6X6_1000,\n",
201 | "\t\"DICT_7X7_50\": cv2.aruco.DICT_7X7_50,\n",
202 | "\t\"DICT_7X7_100\": cv2.aruco.DICT_7X7_100,\n",
203 | "\t\"DICT_7X7_250\": cv2.aruco.DICT_7X7_250,\n",
204 | "\t\"DICT_7X7_1000\": cv2.aruco.DICT_7X7_1000,\n",
205 | "\t\"DICT_ARUCO_ORIGINAL\": cv2.aruco.DICT_ARUCO_ORIGINAL,\n",
206 | "\t\"DICT_APRILTAG_16h5\": cv2.aruco.DICT_APRILTAG_16h5,\n",
207 | "\t\"DICT_APRILTAG_25h9\": cv2.aruco.DICT_APRILTAG_25h9,\n",
208 | "\t\"DICT_APRILTAG_36h10\": cv2.aruco.DICT_APRILTAG_36h10,\n",
209 | "\t\"DICT_APRILTAG_36h11\": cv2.aruco.DICT_APRILTAG_36h11\n",
210 | "}"
211 | ],
212 | "execution_count": null,
213 | "outputs": []
214 | },
215 | {
216 | "cell_type": "code",
217 | "metadata": {
218 | "id": "InU3PaYJKt2x"
219 | },
220 | "source": [
221 | "# verify that the supplied ArUCo tag exists and is supported by\n",
222 | "# OpenCV\n",
223 | "if ARUCO_DICT.get(args[\"type\"], None) is None:\n",
224 | "\tprint(\"[INFO] ArUCo tag of '{}' is not supported\".format(\n",
225 | "\t\targs[\"type\"]))\n",
226 | "\tsys.exit(0)\n",
227 | "\n",
228 | "# load the ArUCo dictionary\n",
229 | "arucoDict = cv2.aruco.Dictionary_get(ARUCO_DICT[args[\"type\"]])"
230 | ],
231 | "execution_count": null,
232 | "outputs": []
233 | },
234 | {
235 | "cell_type": "code",
236 | "metadata": {
237 | "id": "rgEZvrJSKxOx"
238 | },
239 | "source": [
240 | "# allocate memory for the output ArUCo tag and then draw the ArUCo\n",
241 | "# tag on the output image\n",
242 | "print(\"[INFO] generating ArUCo tag type '{}' with ID '{}'\".format(\n",
243 | "\targs[\"type\"], args[\"id\"]))\n",
244 | "tag = np.zeros((300, 300, 1), dtype=\"uint8\")\n",
245 | "cv2.aruco.drawMarker(arucoDict, args[\"id\"], 300, tag, 1)\n",
246 | "\n",
247 | "# write the generated ArUCo tag to disk and then display it to our\n",
248 | "# screen\n",
249 | "cv2.imwrite(args[\"output\"], tag)\n",
250 | "plt_imshow(\"ArUCo Tag\", tag)"
251 | ],
252 | "execution_count": null,
253 | "outputs": []
254 | },
255 | {
256 | "cell_type": "markdown",
257 | "metadata": {
258 | "id": "0q1x1gzOLEHB"
259 | },
260 | "source": [
261 | "For a detailed walkthrough of the concepts and code, be sure to refer to the full tutorial, [*Generating ArUco markers with OpenCV and Python*](https://www.pyimagesearch.com/2020/12/14/generating-aruco-markers-with-opencv-and-python/) blog post published on 12-14-20."
262 | ]
263 | }
264 | ]
265 | }
--------------------------------------------------------------------------------
/207_image_gradients.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "colab": {
6 | "name": "207-image_gradients.ipynb",
7 | "provenance": [],
8 | "collapsed_sections": [],
9 | "toc_visible": true,
10 | "include_colab_link": true
11 | },
12 | "kernelspec": {
13 | "name": "python3",
14 | "display_name": "Python 3"
15 | },
16 | "language_info": {
17 | "name": "python"
18 | }
19 | },
20 | "cells": [
21 | {
22 | "cell_type": "markdown",
23 | "metadata": {
24 | "id": "view-in-github",
25 | "colab_type": "text"
26 | },
27 | "source": [
28 | "
"
29 | ]
30 | },
31 | {
32 | "cell_type": "markdown",
33 | "metadata": {
34 | "id": "j4RpK9pawQzP"
35 | },
36 | "source": [
37 | "# Image Gradients with OpenCV (Sobel and Scharr)\n"
38 | ]
39 | },
40 | {
41 | "cell_type": "markdown",
42 | "metadata": {
43 | "id": "8ntZ1AkXZIxY"
44 | },
45 | "source": [
46 | "\n",
47 | "\n",
48 | "This notebook is associated with the [Image Gradients with OpenCV (Sobel and Scharr)](https://www.pyimagesearch.com/2021/05/12/image-gradients-with-opencv-sobel-and-scharr/) blog post published on 2021-05-12.\n",
49 | "\n",
50 | "Only the code for the blog post is here. Most codeblocks have a 1:1 relationship with what you find in the blog post with two exceptions: (1) Python classes are not separate files as they are typically organized with PyImageSearch projects, and (2) Command Line Argument parsing is replaced with an `args` dictionary that you can manipulate as needed.\n",
51 | "\n",
52 | "We recommend that you execute (press ▶️) the code block-by-block, as-is, before adjusting parameters and `args` inputs. Once you've verified that the code is working, you are welcome to hack with it and learn from manipulating inputs, settings, and parameters. For more information on using Jupyter and Colab, please refer to these resources:\n",
53 | "\n",
54 | "* [Jupyter Notebook User Interface](https://jupyter-notebook.readthedocs.io/en/stable/notebook.html#notebook-user-interface)\n",
55 | "* [Overview of Google Colaboratory Features](https://colab.research.google.com/notebooks/basic_features_overview.ipynb)\n",
56 | "\n",
57 | "\n",
58 | "Happy hacking!\n",
59 | "\n",
60 | "
\n",
61 | "\n"
62 | ]
63 | },
64 | {
65 | "cell_type": "markdown",
66 | "metadata": {
67 | "id": "NFhAzQB3aNMa"
68 | },
69 | "source": [
70 | "### Download the code zip file"
71 | ]
72 | },
73 | {
74 | "cell_type": "code",
75 | "metadata": {
76 | "id": "7y0LG1EuaRlB"
77 | },
78 | "source": [
79 | "!wget https://pyimagesearch-code-downloads.s3-us-west-2.amazonaws.com/image-gradients/image-gradients.zip\n",
80 | "!unzip -qq image-gradients.zip\n",
81 | "%cd image-gradients"
82 | ],
83 | "execution_count": null,
84 | "outputs": []
85 | },
86 | {
87 | "cell_type": "markdown",
88 | "metadata": {
89 | "id": "_SgTVT3HagGZ"
90 | },
91 | "source": [
92 | "## Blog Post Code"
93 | ]
94 | },
95 | {
96 | "cell_type": "markdown",
97 | "metadata": {
98 | "id": "wcrOk6pURp50"
99 | },
100 | "source": [
101 | "### Import Packages"
102 | ]
103 | },
104 | {
105 | "cell_type": "code",
106 | "metadata": {
107 | "id": "VJaCNlDDRz6d"
108 | },
109 | "source": [
110 | "# import the necessary packages\n",
111 | "import matplotlib.pyplot as plt\n",
112 | "import numpy as np\n",
113 | "import cv2"
114 | ],
115 | "execution_count": null,
116 | "outputs": []
117 | },
118 | {
119 | "cell_type": "markdown",
120 | "metadata": {
121 | "id": "lBrLwCtN5kqy"
122 | },
123 | "source": [
124 | "### Function to display images in Jupyter Notebooks and Google Colab"
125 | ]
126 | },
127 | {
128 | "cell_type": "code",
129 | "metadata": {
130 | "id": "sYaD_Es9-8y6"
131 | },
132 | "source": [
133 | "def plt_imshow(title, image):\n",
134 | "\t# convert the image frame BGR to RGB color space and display it\n",
135 | "\timage = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n",
136 | "\tplt.imshow(image)\n",
137 | "\tplt.title(title)\n",
138 | "\tplt.grid(False)\n",
139 | "\tplt.show()"
140 | ],
141 | "execution_count": null,
142 | "outputs": []
143 | },
144 | {
145 | "cell_type": "markdown",
146 | "metadata": {
147 | "id": "xst3eUidYbOM"
148 | },
149 | "source": [
150 | "### Implementing Sobel and Scharr kernels with OpenCV"
151 | ]
152 | },
153 | {
154 | "cell_type": "code",
155 | "metadata": {
156 | "id": "UAIp1ELqXa2d"
157 | },
158 | "source": [
159 | "# # construct the argument parser and parse the arguments\n",
160 | "# ap = argparse.ArgumentParser()\n",
161 | "# ap.add_argument(\"-i\", \"--image\", type=str, required=True,\n",
162 | "# \thelp=\"path to input image\")\n",
163 | "# ap.add_argument(\"-s\", \"--scharr\", type=int, default=0,\n",
164 | "# \thelp=\"path to input image\")\n",
165 | "\n",
166 | "# since we are using Jupyter Notebooks we can replace our argument\n",
167 | "# parsing code with *hard coded* arguments and values\n",
168 | "args = {\n",
169 | "\t\"image\": \"images/coins01.png\",\n",
170 | " \"scharr\": 0\n",
171 | "}"
172 | ],
173 | "execution_count": null,
174 | "outputs": []
175 | },
176 | {
177 | "cell_type": "code",
178 | "metadata": {
179 | "id": "fN2c5IhsYrgs"
180 | },
181 | "source": [
182 | "# load the image, convert it to grayscale, and display the original\n",
183 | "# grayscale image\n",
184 | "image = cv2.imread(args[\"image\"])\n",
185 | "gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)\n",
186 | "plt_imshow(\"Gray\", gray)"
187 | ],
188 | "execution_count": null,
189 | "outputs": []
190 | },
191 | {
192 | "cell_type": "code",
193 | "metadata": {
194 | "id": "DFJivN6yYwZB"
195 | },
196 | "source": [
197 | "# set the kernel size, depending on whether we are using the Sobel\n",
198 | "# operator of the Scharr operator, then compute the gradients along\n",
199 | "# the x and y axis, respectively\n",
200 | "ksize = -1 if args[\"scharr\"] > 0 else 3\n",
201 | "gX = cv2.Sobel(gray, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=ksize)\n",
202 | "gY = cv2.Sobel(gray, ddepth=cv2.CV_32F, dx=0, dy=1, ksize=ksize)\n",
203 | "\n",
204 | "# the gradient magnitude images are now of the floating point data\n",
205 | "# type, so we need to take care to convert them back a to unsigned\n",
206 | "# 8-bit integer representation so other OpenCV functions can operate\n",
207 | "# on them and visualize them\n",
208 | "gX = cv2.convertScaleAbs(gX)\n",
209 | "gY = cv2.convertScaleAbs(gY)\n",
210 | "\n",
211 | "# combine the gradient representations into a single image\n",
212 | "combined = cv2.addWeighted(gX, 0.5, gY, 0.5, 0)\n",
213 | "\n",
214 | "# show our output images\n",
215 | "plt_imshow(\"Sobel/Scharr X\", gX)\n",
216 | "plt_imshow(\"Sobel/Scharr Y\", gY)\n",
217 | "plt_imshow(\"Sobel/Scharr Combined\", combined)"
218 | ],
219 | "execution_count": null,
220 | "outputs": []
221 | },
222 | {
223 | "cell_type": "markdown",
224 | "metadata": {
225 | "id": "HSXSpgw5Y-zf"
226 | },
227 | "source": [
228 | "### Computing gradient magnitude and orientation with OpenCV"
229 | ]
230 | },
231 | {
232 | "cell_type": "code",
233 | "metadata": {
234 | "id": "soh5yreRY5kp"
235 | },
236 | "source": [
237 | "# load the input image and convert it to grayscale\n",
238 | "image = cv2.imread(args[\"image\"])\n",
239 | "gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)\n",
240 | "\n",
241 | "# compute gradients along the x and y axis, respectively\n",
242 | "gX = cv2.Sobel(gray, cv2.CV_64F, 1, 0)\n",
243 | "gY = cv2.Sobel(gray, cv2.CV_64F, 0, 1)\n",
244 | "\n",
245 | "# compute the gradient magnitude and orientation\n",
246 | "magnitude = np.sqrt((gX ** 2) + (gY ** 2))\n",
247 | "orientation = np.arctan2(gY, gX) * (180 / np.pi) % 180"
248 | ],
249 | "execution_count": null,
250 | "outputs": []
251 | },
252 | {
253 | "cell_type": "code",
254 | "metadata": {
255 | "id": "UrllQ3aHZHcZ"
256 | },
257 | "source": [
258 | "# initialize a figure to display the input grayscale image along with\n",
259 | "# the gradient magnitude and orientation representations, respectively\n",
260 | "(fig, axs) = plt.subplots(nrows=1, ncols=3, figsize=(8, 4))\n",
261 | "\n",
262 | "# plot each of the images\n",
263 | "axs[0].imshow(gray, cmap=\"gray\")\n",
264 | "axs[1].imshow(magnitude, cmap=\"jet\")\n",
265 | "axs[2].imshow(orientation, cmap=\"jet\")\n",
266 | "\n",
267 | "# set the titles of each axes\n",
268 | "axs[0].set_title(\"Grayscale\")\n",
269 | "axs[1].set_title(\"Gradient Magnitude\")\n",
270 | "axs[2].set_title(\"Gradient Orientation [0, 180]\")\n",
271 | "\n",
272 | "# loop over each of the axes and turn off the x and y ticks\n",
273 | "for i in range(0, 3):\n",
274 | "\taxs[i].get_xaxis().set_ticks([])\n",
275 | "\taxs[i].get_yaxis().set_ticks([])\n",
276 | "\n",
277 | "# show the plots\n",
278 | "plt.tight_layout()\n",
279 | "plt.show()"
280 | ],
281 | "execution_count": null,
282 | "outputs": []
283 | },
284 | {
285 | "cell_type": "markdown",
286 | "metadata": {
287 | "id": "4ogkNauArL6u"
288 | },
289 | "source": [
290 | "For a detailed walkthrough of the concepts and code, be sure to refer to the full tutorial, [Image Gradients with OpenCV (Sobel and Scharr)](https://www.pyimagesearch.com/2021/05/12/image-gradients-with-opencv-sobel-and-scharr/) published on 2021-05-12."
291 | ]
292 | }
293 | ]
294 | }
--------------------------------------------------------------------------------
/203_smoothing_and_blurring.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "colab": {
6 | "name": "203-smoothing_and_blurring.ipynb",
7 | "provenance": [],
8 | "collapsed_sections": [],
9 | "include_colab_link": true
10 | },
11 | "kernelspec": {
12 | "display_name": "Python 3",
13 | "language": "python",
14 | "name": "python3"
15 | },
16 | "language_info": {
17 | "codemirror_mode": {
18 | "name": "ipython",
19 | "version": 3
20 | },
21 | "file_extension": ".py",
22 | "mimetype": "text/x-python",
23 | "name": "python",
24 | "nbconvert_exporter": "python",
25 | "pygments_lexer": "ipython3",
26 | "version": "3.8.5"
27 | }
28 | },
29 | "cells": [
30 | {
31 | "cell_type": "markdown",
32 | "metadata": {
33 | "id": "view-in-github",
34 | "colab_type": "text"
35 | },
36 | "source": [
37 | "
"
38 | ]
39 | },
40 | {
41 | "cell_type": "markdown",
42 | "metadata": {
43 | "id": "j4RpK9pawQzP"
44 | },
45 | "source": [
46 | "# OpenCV Smoothing and Blurring\n"
47 | ]
48 | },
49 | {
50 | "cell_type": "markdown",
51 | "metadata": {
52 | "id": "8ntZ1AkXZIxY"
53 | },
54 | "source": [
55 | "\n",
56 | "\n",
57 | "This notebook is associated with the [OpenCV Smoothing and Blurring](https://www.pyimagesearch.com/2021/04/28/opencv-smoothing-and-blurring/) blog post published on 2021-04-28.\n",
58 | "\n",
59 | "Only the code for the blog post is here. Most codeblocks have a 1:1 relationship with what you find in the blog post with two exceptions: (1) Python classes are not separate files as they are typically organized with PyImageSearch projects, and (2) Command Line Argument parsing is replaced with an `args` dictionary that you can manipulate as needed.\n",
60 | "\n",
61 | "We recommend that you execute (press ▶️) the code block-by-block, as-is, before adjusting parameters and `args` inputs. Once you've verified that the code is working, you are welcome to hack with it and learn from manipulating inputs, settings, and parameters. For more information on using Jupyter and Colab, please refer to these resources:\n",
62 | "\n",
63 | "* [Jupyter Notebook User Interface](https://jupyter-notebook.readthedocs.io/en/stable/notebook.html#notebook-user-interface)\n",
64 | "* [Overview of Google Colaboratory Features](https://colab.research.google.com/notebooks/basic_features_overview.ipynb)\n",
65 | "\n",
66 | "Happy hacking!\n",
67 | "\n",
68 | "\n",
69 | "\n",
70 | "
\n"
71 | ]
72 | },
73 | {
74 | "cell_type": "markdown",
75 | "metadata": {
76 | "id": "NFhAzQB3aNMa"
77 | },
78 | "source": [
79 | "### Download the code zip file"
80 | ]
81 | },
82 | {
83 | "cell_type": "code",
84 | "metadata": {
85 | "id": "7y0LG1EuaRlB"
86 | },
87 | "source": [
88 | "!wget https://pyimagesearch-code-downloads.s3-us-west-2.amazonaws.com/smoothing-and-blurring/smoothing-and-blurring.zip\n",
89 | "!unzip -qq smoothing-and-blurring.zip\n",
90 | "%cd smoothing-and-blurring"
91 | ],
92 | "execution_count": null,
93 | "outputs": []
94 | },
95 | {
96 | "cell_type": "markdown",
97 | "metadata": {
98 | "id": "_SgTVT3HagGZ"
99 | },
100 | "source": [
101 | "## Blog Post Code"
102 | ]
103 | },
104 | {
105 | "cell_type": "markdown",
106 | "metadata": {
107 | "id": "wcrOk6pURp50"
108 | },
109 | "source": [
110 | "### Import Packages"
111 | ]
112 | },
113 | {
114 | "cell_type": "code",
115 | "metadata": {
116 | "id": "VJaCNlDDRz6d"
117 | },
118 | "source": [
119 | "# import the necessary packages\n",
120 | "from matplotlib import pyplot as plt\n",
121 | "import argparse\n",
122 | "import cv2"
123 | ],
124 | "execution_count": null,
125 | "outputs": []
126 | },
127 | {
128 | "cell_type": "markdown",
129 | "metadata": {
130 | "id": "lBrLwCtN5kqy"
131 | },
132 | "source": [
133 | "### Function to display images in Jupyter Notebooks and Google Colab"
134 | ]
135 | },
136 | {
137 | "cell_type": "code",
138 | "metadata": {
139 | "id": "fRw969Dp5Kdm"
140 | },
141 | "source": [
142 | "def plt_imshow(title, image):\n",
143 | "\t# convert the image frame BGR to RGB color space and display it\n",
144 | "\timage = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n",
145 | "\tplt.imshow(image)\n",
146 | "\tplt.title(title)\n",
147 | "\tplt.grid(False)\n",
148 | "\tplt.show()"
149 | ],
150 | "execution_count": null,
151 | "outputs": []
152 | },
153 | {
154 | "cell_type": "markdown",
155 | "metadata": {
156 | "id": "Jppw5-Bd56H-"
157 | },
158 | "source": [
159 | "### Average blurring (`cv2.blur`)"
160 | ]
161 | },
162 | {
163 | "cell_type": "code",
164 | "metadata": {
165 | "id": "okM7Bpyeq8Kc"
166 | },
167 | "source": [
168 | "# construct the argument parser and parse the arguments\n",
169 | "#ap = argparse.ArgumentParser()\n",
170 | "#ap.add_argument(\"-i\", \"--image\", type=str, default=\"adrian.png\",\n",
171 | "#\thelp=\"path to input image\")\n",
172 | "#args = vars(ap.parse_args())\n",
173 | "\n",
174 | "# since we are using Jupyter Notebooks we can replace our argument\n",
175 | "# parsing code with *hard coded* arguments and values\n",
176 | "args = {\n",
177 | "\t\"image\": \"adrian.png\"\n",
178 | "}"
179 | ],
180 | "execution_count": null,
181 | "outputs": []
182 | },
183 | {
184 | "cell_type": "code",
185 | "metadata": {
186 | "id": "1G2mbSTcRjdn"
187 | },
188 | "source": [
189 | "# load the image, display it to our screen, and initialize a list of\n",
190 | "# kernel sizes (so we can evaluate the relationship between kernel\n",
191 | "# size and amount of blurring)\n",
192 | "image = cv2.imread(args[\"image\"])\n",
193 | "plt_imshow(\"Original\", image)\n",
194 | "kernelSizes = [(3, 3), (9, 9), (15, 15)]\n",
195 | "\n",
196 | "# loop over the kernel sizes\n",
197 | "for (kX, kY) in kernelSizes:\n",
198 | "\t# apply an \"average\" blur to the image using the current kernel\n",
199 | "\t# size\n",
200 | "\tblurred = cv2.blur(image, (kX, kY))\n",
201 | "\tplt_imshow(\"Average ({}, {})\".format(kX, kY), blurred)"
202 | ],
203 | "execution_count": null,
204 | "outputs": []
205 | },
206 | {
207 | "cell_type": "code",
208 | "metadata": {
209 | "id": "bpckoy-ERmHJ"
210 | },
211 | "source": [
212 | "# display the original image\n",
213 | "plt_imshow(\"Original\", image)\n",
214 | "\n",
215 | "# loop over the kernel sizes again\n",
216 | "for (kX, kY) in kernelSizes:\n",
217 | "\t# apply a \"Gaussian\" blur to the image\n",
218 | "\tblurred = cv2.GaussianBlur(image, (kX, kY), 0)\n",
219 | "\tplt_imshow(\"Gaussian ({}, {})\".format(kX, kY), blurred)"
220 | ],
221 | "execution_count": null,
222 | "outputs": []
223 | },
224 | {
225 | "cell_type": "code",
226 | "metadata": {
227 | "id": "HOdmDAFpRqn5"
228 | },
229 | "source": [
230 | "# display the original image\n",
231 | "plt_imshow(\"Original\", image)\n",
232 | "\n",
233 | "# loop over the kernel sizes a final time\n",
234 | "for k in (3, 9, 15):\n",
235 | "\t# apply a \"median\" blur to the image\n",
236 | "\tblurred = cv2.medianBlur(image, k)\n",
237 | "\tplt_imshow(\"Median {}\".format(k), blurred)"
238 | ],
239 | "execution_count": null,
240 | "outputs": []
241 | },
242 | {
243 | "cell_type": "markdown",
244 | "metadata": {
245 | "id": "sL1qUq8WRuRE"
246 | },
247 | "source": [
248 | "### Bilateral blurring (`cv2.bilateralFilter`)"
249 | ]
250 | },
251 | {
252 | "cell_type": "code",
253 | "metadata": {
254 | "id": "ZUuqKfqRRrK5"
255 | },
256 | "source": [
257 | "# construct the argument parser and parse the arguments\n",
258 | "#ap = argparse.ArgumentParser()\n",
259 | "#ap.add_argument(\"-i\", \"--image\", type=str, default=\"adrian.png\",\n",
260 | "#\thelp=\"path to input image\")\n",
261 | "#args = vars(ap.parse_args())\n",
262 | "\n",
263 | "# since we are using Jupyter Notebooks we can replace our argument\n",
264 | "# parsing code with *hard coded* arguments and values\n",
265 | "args = {\n",
266 | "\t\"image\": \"adrian.png\"\n",
267 | "}"
268 | ],
269 | "execution_count": null,
270 | "outputs": []
271 | },
272 | {
273 | "cell_type": "code",
274 | "metadata": {
275 | "id": "psE4BNrlSD58"
276 | },
277 | "source": [
278 | "# load the image, display it to our screen, and construct a list of\n",
279 | "# bilateral filtering parameters that we are going to explore\n",
280 | "image = cv2.imread(args[\"image\"])\n",
281 | "plt_imshow(\"Original\", image)\n",
282 | "params = [(11, 21, 7), (11, 41, 21), (11, 61, 39)]\n",
283 | "\n",
284 | "# loop over the diameter, sigma color, and sigma space\n",
285 | "for (diameter, sigmaColor, sigmaSpace) in params:\n",
286 | "\t# apply bilateral filtering to the image using the current set of\n",
287 | "\t# parameters\n",
288 | "\tblurred = cv2.bilateralFilter(image, diameter, sigmaColor, sigmaSpace)\n",
289 | "\n",
290 | "\t# show the output image and associated parameters\n",
291 | "\ttitle = \"Blurred d={}, sc={}, ss={}\".format(\n",
292 | "\t\tdiameter, sigmaColor, sigmaSpace)\n",
293 | "\tplt_imshow(title, blurred)"
294 | ],
295 | "execution_count": null,
296 | "outputs": []
297 | },
298 | {
299 | "cell_type": "markdown",
300 | "metadata": {
301 | "id": "4ogkNauArL6u"
302 | },
303 | "source": [
304 | "For a detailed walkthrough of the concepts and code, be sure to refer to the full tutorial, [*OpenCV Smoothing and Blurring*](https://www.pyimagesearch.com/2021/04/28/opencv-smoothing-and-blurring/) published on 2021-04-28."
305 | ]
306 | }
307 | ]
308 | }
--------------------------------------------------------------------------------
/1102_siamese_image_pairs.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "colab": {
6 | "name": "1102-siamese_image_pairs.ipynb",
7 | "provenance": [],
8 | "collapsed_sections": [],
9 | "include_colab_link": true
10 | },
11 | "kernelspec": {
12 | "name": "python3",
13 | "display_name": "Python 3"
14 | }
15 | },
16 | "cells": [
17 | {
18 | "cell_type": "markdown",
19 | "metadata": {
20 | "id": "view-in-github",
21 | "colab_type": "text"
22 | },
23 | "source": [
24 | "
"
25 | ]
26 | },
27 | {
28 | "cell_type": "markdown",
29 | "metadata": {
30 | "id": "d3HxshYShGnN"
31 | },
32 | "source": [
33 | "# Building image pairs for siamese networks with Python\n",
34 | "\n"
35 | ]
36 | },
37 | {
38 | "cell_type": "markdown",
39 | "metadata": {
40 | "id": "VE4PGr_IhOXp"
41 | },
42 | "source": [
43 | "\n",
44 | "This notebook is associated with the [Building image pairs for siamese networks with Python](https://www.pyimagesearch.com/2020/11/23/building-image-pairs-for-siamese-networks-with-python/) blog post published on 11-23-20.\n",
45 | "\n",
46 | "Only the code for the blog post is here. Most codeblocks have a 1:1 relationship with what you find in the blog post with two exceptions: (1) Python classes are not separate files as they are typically organized with PyImageSearch projects, and (2) Command Line Argument parsing is replaced with an `args` dictionary that you can manipulate as needed.\n",
47 | "\n",
48 | "We recommend that you execute (press ▶️) the code block-by-block, as-is, before adjusting parameters and `args` inputs. Once you've verified that the code is working, you are welcome to hack with it and learn from manipulating inputs, settings, and parameters. For more information on using Jupyter and Colab, please refer to these resources:\n",
49 | "\n",
50 | "* [Jupyter Notebook User Interface](https://jupyter-notebook.readthedocs.io/en/stable/notebook.html#notebook-user-interface)\n",
51 | "* [Overview of Google Colaboratory Features](https://colab.research.google.com/notebooks/basic_features_overview.ipynb)\n",
52 | "\n",
53 | "\n",
54 | "Happy hacking!\n",
55 | "\n",
56 | "\n",
57 | "\n",
58 | "
\n"
59 | ]
60 | },
61 | {
62 | "cell_type": "markdown",
63 | "metadata": {
64 | "id": "Hx5R09V1hbQM"
65 | },
66 | "source": [
67 | "### Download the code zip file"
68 | ]
69 | },
70 | {
71 | "cell_type": "code",
72 | "metadata": {
73 | "id": "0rU24Rwag5sF"
74 | },
75 | "source": [
76 | "!wget https://pyimagesearch-code-downloads.s3-us-west-2.amazonaws.com/siamese-image-pairs/siamese-image-pairs.zip\n",
77 | "!unzip -qq siamese-image-pairs.zip\n",
78 | "%cd siamese-image-pairs"
79 | ],
80 | "execution_count": null,
81 | "outputs": []
82 | },
83 | {
84 | "cell_type": "markdown",
85 | "metadata": {
86 | "id": "DST7MDR0hnuw"
87 | },
88 | "source": [
89 | "## Blog Post Code"
90 | ]
91 | },
92 | {
93 | "cell_type": "markdown",
94 | "metadata": {
95 | "id": "-e1MhjRuhtUr"
96 | },
97 | "source": [
98 | "### Import Packages"
99 | ]
100 | },
101 | {
102 | "cell_type": "code",
103 | "metadata": {
104 | "id": "Y329lP2JhlYr"
105 | },
106 | "source": [
107 | "# import the necessary packages\n",
108 | "from tensorflow.keras.datasets import mnist\n",
109 | "from imutils import build_montages\n",
110 | "import matplotlib.pyplot as plt\n",
111 | "import numpy as np\n",
112 | "import cv2"
113 | ],
114 | "execution_count": null,
115 | "outputs": []
116 | },
117 | {
118 | "cell_type": "markdown",
119 | "metadata": {
120 | "id": "MmmM5W0_iJMR"
121 | },
122 | "source": [
123 | "### Function to display images in Jupyter Notebooks and Google Colab"
124 | ]
125 | },
126 | {
127 | "cell_type": "code",
128 | "metadata": {
129 | "id": "_hp4BbXriLDu"
130 | },
131 | "source": [
132 | "def plt_imshow(title, image):\n",
133 | "\t# convert the image frame BGR to RGB color space and display it\n",
134 | "\tplt.figure(figsize=(12, 12))\n",
135 | "\timage = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)\n",
136 | "\tplt.imshow(image)\n",
137 | "\tplt.title(title)\n",
138 | "\tplt.grid(False)\n",
139 | "\tplt.show()"
140 | ],
141 | "execution_count": null,
142 | "outputs": []
143 | },
144 | {
145 | "cell_type": "markdown",
146 | "metadata": {
147 | "id": "_fkE1a2OpaDH"
148 | },
149 | "source": [
150 | "### Implementing our image pair generator for siamese networks"
151 | ]
152 | },
153 | {
154 | "cell_type": "code",
155 | "metadata": {
156 | "id": "LEZlRWxzh5_R"
157 | },
158 | "source": [
159 | "def make_pairs(images, labels):\n",
160 | "\t# initialize two empty lists to hold the (image, image) pairs and\n",
161 | "\t# labels to indicate if a pair is positive or negative\n",
162 | "\tpairImages = []\n",
163 | "\tpairLabels = []\n",
164 | "\n",
165 | "\t# calculate the total number of classes present in the dataset\n",
166 | "\t# and then build a list of indexes for each class label that\n",
167 | "\t# provides the indexes for all examples with a given label\n",
168 | "\tnumClasses = len(np.unique(labels))\n",
169 | "\tidx = [np.where(labels == i)[0] for i in range(0, numClasses)]\n",
170 | "\n",
171 | "\t# loop over all images\n",
172 | "\tfor idxA in range(len(images)):\n",
173 | "\t\t# grab the current image and label belonging to the current\n",
174 | "\t\t# iteration\n",
175 | "\t\tcurrentImage = images[idxA]\n",
176 | "\t\tlabel = labels[idxA]\n",
177 | "\n",
178 | "\t\t# randomly pick an image that belongs to the *same* class\n",
179 | "\t\t# label\n",
180 | "\t\tidxB = np.random.choice(idx[label])\n",
181 | "\t\tposImage = images[idxB]\n",
182 | "\n",
183 | "\t\t# prepare a positive pair and update the images and labels\n",
184 | "\t\t# lists, respectively\n",
185 | "\t\tpairImages.append([currentImage, posImage])\n",
186 | "\t\tpairLabels.append([1])\n",
187 | "\n",
188 | "\t\t# grab the indices for each of the class labels *not* equal to\n",
189 | "\t\t# the current label and randomly pick an image corresponding\n",
190 | "\t\t# to a label *not* equal to the current label\n",
191 | "\t\tnegIdx = np.where(labels != label)[0]\n",
192 | "\t\tnegImage = images[np.random.choice(negIdx)]\n",
193 | "\n",
194 | "\t\t# prepare a negative pair of images and update our lists\n",
195 | "\t\tpairImages.append([currentImage, negImage])\n",
196 | "\t\tpairLabels.append([0])\n",
197 | "\n",
198 | "\t# return a 2-tuple of our image pairs and labels\n",
199 | "\treturn (np.array(pairImages), np.array(pairLabels))"
200 | ],
201 | "execution_count": null,
202 | "outputs": []
203 | },
204 | {
205 | "cell_type": "code",
206 | "metadata": {
207 | "id": "L2QjVomHiGdz"
208 | },
209 | "source": [
210 | "# load MNIST dataset and scale the pixel values to the range of [0, 1]\n",
211 | "print(\"[INFO] loading MNIST dataset...\")\n",
212 | "(trainX, trainY), (testX, testY) = mnist.load_data()\n",
213 | "\n",
214 | "# build the positive and negative image pairs\n",
215 | "print(\"[INFO] preparing positive and negative pairs...\")\n",
216 | "(pairTrain, labelTrain) = make_pairs(trainX, trainY)\n",
217 | "(pairTest, labelTest) = make_pairs(testX, testY)\n",
218 | "\n",
219 | "# initialize the list of images that will be used when building our\n",
220 | "# montage\n",
221 | "images = []"
222 | ],
223 | "execution_count": null,
224 | "outputs": []
225 | },
226 | {
227 | "cell_type": "code",
228 | "metadata": {
229 | "id": "b_gqOSZOiShE"
230 | },
231 | "source": [
232 | "# loop over a sample of our training pairs\n",
233 | "for i in np.random.choice(np.arange(0, len(pairTrain)), size=(49,)):\n",
234 | "\t# grab the current image pair and label\n",
235 | "\timageA = pairTrain[i][0]\n",
236 | "\timageB = pairTrain[i][1]\n",
237 | "\tlabel = labelTrain[i]\n",
238 | "\n",
239 | "\t# to make it easier to visualize the pairs and their positive or\n",
240 | "\t# negative annotations, we're going to \"pad\" the pair with four\n",
241 | "\t# pixels along the top, bottom, and right borders, respectively\n",
242 | "\toutput = np.zeros((36, 60), dtype=\"uint8\")\n",
243 | "\tpair = np.hstack([imageA, imageB])\n",
244 | "\toutput[4:32, 0:56] = pair\n",
245 | "\n",
246 | "\t# set the text label for the pair along with what color we are\n",
247 | "\t# going to draw the pair in (green for a \"positive\" pair and\n",
248 | "\t# red for a \"negative\" pair)\n",
249 | "\ttext = \"neg\" if label[0] == 0 else \"pos\"\n",
250 | "\tcolor = (0, 0, 255) if label[0] == 0 else (0, 255, 0)\n",
251 | "\n",
252 | "\t# create a 3-channel RGB image from the grayscale pair, resize\n",
253 | "\t# it from 28x28 to 96x51 (so we can better see it), and then\n",
254 | "\t# draw what type of pair it is on the image\n",
255 | "\tvis = cv2.merge([output] * 3)\n",
256 | "\tvis = cv2.resize(vis, (96, 51), interpolation=cv2.INTER_LINEAR)\n",
257 | "\tcv2.putText(vis, text, (2, 12), cv2.FONT_HERSHEY_SIMPLEX, 0.75,\n",
258 | "\t\tcolor, 2)\n",
259 | "\n",
260 | "\t# add the pair visualization to our list of output images\n",
261 | "\timages.append(vis)\n",
262 | "\n",
263 | "# construct the montage for the images\n",
264 | "montage = build_montages(images, (96, 51), (7, 7))[0]\n",
265 | "\n",
266 | "# show the output montage\n",
267 | "plt_imshow(\"Siamese Image Pairs\", montage)"
268 | ],
269 | "execution_count": null,
270 | "outputs": []
271 | },
272 | {
273 | "cell_type": "markdown",
274 | "metadata": {
275 | "id": "F-cKUZwKi28k"
276 | },
277 | "source": [
278 | "For a detailed walkthrough of the concepts and code, be sure to refer to the full tutorial, [*Building image pairs for siamese networks with Python*](https://www.pyimagesearch.com/2020/11/23/building-image-pairs-for-siamese-networks-with-python/) blog post published on 11-23-20."
279 | ]
280 | }
281 | ]
282 | }
--------------------------------------------------------------------------------
/801_perceptron_neural_network.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "colab": {
6 | "name": "801-perceptron_neural_network.ipynb",
7 | "provenance": [],
8 | "collapsed_sections": [],
9 | "include_colab_link": true
10 | },
11 | "kernelspec": {
12 | "name": "python3",
13 | "display_name": "Python 3"
14 | },
15 | "language_info": {
16 | "name": "python"
17 | }
18 | },
19 | "cells": [
20 | {
21 | "cell_type": "markdown",
22 | "metadata": {
23 | "id": "view-in-github",
24 | "colab_type": "text"
25 | },
26 | "source": [
27 | "
"
28 | ]
29 | },
30 | {
31 | "cell_type": "markdown",
32 | "metadata": {
33 | "id": "j4RpK9pawQzP"
34 | },
35 | "source": [
36 | "# Implementing the Perceptron Neural Network with Python\n"
37 | ]
38 | },
39 | {
40 | "cell_type": "markdown",
41 | "metadata": {
42 | "id": "8ntZ1AkXZIxY"
43 | },
44 | "source": [
45 | "\n",
46 | "\n",
47 | "This notebook is associated with the [Implementing the Perceptron Neural Network with Python](https://www.pyimagesearch.com/2021/05/06/implementing-the-perceptron-neural-network-with-python/) blog post published on 2021-05-06.\n",
48 | "\n",
49 | "Only the code for the blog post is here. Most codeblocks have a 1:1 relationship with what you find in the blog post with two exceptions: (1) Python classes are not separate files as they are typically organized with PyImageSearch projects, and (2) Command Line Argument parsing is replaced with an `args` dictionary that you can manipulate as needed.\n",
50 | "\n",
51 | "We recommend that you execute (press ▶️) the code block-by-block, as-is, before adjusting parameters and `args` inputs. Once you've verified that the code is working, you are welcome to hack with it and learn from manipulating inputs, settings, and parameters. For more information on using Jupyter and Colab, please refer to these resources:\n",
52 | "\n",
53 | "* [Jupyter Notebook User Interface](https://jupyter-notebook.readthedocs.io/en/stable/notebook.html#notebook-user-interface)\n",
54 | "* [Overview of Google Colaboratory Features](https://colab.research.google.com/notebooks/basic_features_overview.ipynb)\n",
55 | "\n",
56 | "\n",
57 | "Happy hacking!\n",
58 | "\n",
59 | "
\n"
60 | ]
61 | },
62 | {
63 | "cell_type": "markdown",
64 | "metadata": {
65 | "id": "NFhAzQB3aNMa"
66 | },
67 | "source": [
68 | "### Download the code zip file"
69 | ]
70 | },
71 | {
72 | "cell_type": "code",
73 | "metadata": {
74 | "id": "7y0LG1EuaRlB"
75 | },
76 | "source": [
77 | "!wget https://pyimagesearch-code-downloads.s3-us-west-2.amazonaws.com/perceptron-neural-network/perceptron-neural-network.zip\n",
78 | "!unzip -qq perceptron-neural-network.zip\n",
79 | "%cd perceptron-neural-network"
80 | ],
81 | "execution_count": null,
82 | "outputs": []
83 | },
84 | {
85 | "cell_type": "markdown",
86 | "metadata": {
87 | "id": "_SgTVT3HagGZ"
88 | },
89 | "source": [
90 | "## Blog Post Code"
91 | ]
92 | },
93 | {
94 | "cell_type": "markdown",
95 | "metadata": {
96 | "id": "wcrOk6pURp50"
97 | },
98 | "source": [
99 | "### Import Packages"
100 | ]
101 | },
102 | {
103 | "cell_type": "code",
104 | "metadata": {
105 | "id": "VJaCNlDDRz6d"
106 | },
107 | "source": [
108 | "# import the necessary packages\n",
109 | "import numpy as np"
110 | ],
111 | "execution_count": null,
112 | "outputs": []
113 | },
114 | {
115 | "cell_type": "markdown",
116 | "metadata": {
117 | "id": "OBXf2pjTPi7C"
118 | },
119 | "source": [
120 | "### Implementing the Perceptron in Python"
121 | ]
122 | },
123 | {
124 | "cell_type": "code",
125 | "metadata": {
126 | "id": "lHIVGWIwPieH"
127 | },
128 | "source": [
129 | "class Perceptron:\n",
130 | "\tdef __init__(self, N, alpha=0.1):\n",
131 | "\t\t# initialize the weight matrix and store the learning rate\n",
132 | "\t\tself.W = np.random.randn(N + 1) / np.sqrt(N)\n",
133 | "\t\tself.alpha = alpha\n",
134 | "\n",
135 | "\tdef step(self, x):\n",
136 | "\t\t# apply the step function\n",
137 | "\t\treturn 1 if x > 0 else 0\n",
138 | "\n",
139 | "\tdef fit(self, X, y, epochs=10):\n",
140 | "\t\t# insert a column of 1's as the last entry in the feature\n",
141 | "\t\t# matrix -- this little trick allows us to treat the bias\n",
142 | "\t\t# as a trainable parameter within the weight matrix\n",
143 | "\t\tX = np.c_[X, np.ones((X.shape[0]))]\n",
144 | "\n",
145 | "\t\t# loop over the desired number of epochs\n",
146 | "\t\tfor epoch in np.arange(0, epochs):\n",
147 | "\t\t\t# loop over each individual data point\n",
148 | "\t\t\tfor (x, target) in zip(X, y):\n",
149 | "\t\t\t\t# take the dot product between the input features\n",
150 | "\t\t\t\t# and the weight matrix, then pass this value\n",
151 | "\t\t\t\t# through the step function to obtain the prediction\n",
152 | "\t\t\t\tp = self.step(np.dot(x, self.W))\n",
153 | "\n",
154 | "\t\t\t\t# only perform a weight update if our prediction\n",
155 | "\t\t\t\t# does not match the target\n",
156 | "\t\t\t\tif p != target:\n",
157 | "\t\t\t\t\t# determine the error\n",
158 | "\t\t\t\t\terror = p - target\n",
159 | "\n",
160 | "\t\t\t\t\t# update the weight matrix\n",
161 | "\t\t\t\t\tself.W += -self.alpha * error * x\n",
162 | "\n",
163 | "\tdef predict(self, X, addBias=True):\n",
164 | "\t\t# ensure our input is a matrix\n",
165 | "\t\tX = np.atleast_2d(X)\n",
166 | "\n",
167 | "\t\t# check to see if the bias column should be added\n",
168 | "\t\tif addBias:\n",
169 | "\t\t\t# insert a column of 1's as the last entry in the feature\n",
170 | "\t\t\t# matrix (bias)\n",
171 | "\t\t\tX = np.c_[X, np.ones((X.shape[0]))]\n",
172 | "\n",
173 | "\t\t# take the dot product between the input features and the\n",
174 | "\t\t# weight matrix, then pass the value through the step\n",
175 | "\t\t# function\n",
176 | "\t\treturn self.step(np.dot(X, self.W))"
177 | ],
178 | "execution_count": null,
179 | "outputs": []
180 | },
181 | {
182 | "cell_type": "markdown",
183 | "metadata": {
184 | "id": "BiBcQuWWPrOM"
185 | },
186 | "source": [
187 | "### Evaluating the Perceptron on Bitwise Datasets"
188 | ]
189 | },
190 | {
191 | "cell_type": "code",
192 | "metadata": {
193 | "id": "CgpGL440PmNB"
194 | },
195 | "source": [
196 | "# construct the OR dataset\n",
197 | "X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])\n",
198 | "y = np.array([[0], [1], [1], [1]])\n",
199 | "\n",
200 | "# define our perceptron and train it\n",
201 | "print(\"[INFO] training perceptron...\")\n",
202 | "p = Perceptron(X.shape[1], alpha=0.1)\n",
203 | "p.fit(X, y, epochs=20)"
204 | ],
205 | "execution_count": null,
206 | "outputs": []
207 | },
208 | {
209 | "cell_type": "code",
210 | "metadata": {
211 | "id": "Bv0CVSwmPwep"
212 | },
213 | "source": [
214 | "# now that our perceptron is trained we can evaluate it\n",
215 | "print(\"[INFO] testing perceptron...\")\n",
216 | "\n",
217 | "# now that our network is trained, loop over the data points\n",
218 | "for (x, target) in zip(X, y):\n",
219 | "\t# make a prediction on the data point and display the result\n",
220 | "\t# to our console\n",
221 | "\tpred = p.predict(x)\n",
222 | "\tprint(\"[INFO] data={}, ground-truth={}, pred={}\".format(\n",
223 | "\t\tx, target[0], pred))"
224 | ],
225 | "execution_count": null,
226 | "outputs": []
227 | },
228 | {
229 | "cell_type": "code",
230 | "metadata": {
231 | "id": "XoiD0LGbP6j9"
232 | },
233 | "source": [
234 | "# construct the AND dataset\n",
235 | "X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])\n",
236 | "y = np.array([[0], [0], [0], [1]])\n",
237 | "\n",
238 | "# define our perceptron and train it\n",
239 | "print(\"[INFO] training perceptron...\")\n",
240 | "p = Perceptron(X.shape[1], alpha=0.1)\n",
241 | "p.fit(X, y, epochs=20)\n",
242 | "\n",
243 | "# now that our perceptron is trained we can evaluate it\n",
244 | "print(\"[INFO] testing perceptron...\")\n",
245 | "\n",
246 | "# now that our network is trained, loop over the data points\n",
247 | "for (x, target) in zip(X, y):\n",
248 | "\t# make a prediction on the data point and display the result\n",
249 | "\t# to our console\n",
250 | "\tpred = p.predict(x)\n",
251 | "\tprint(\"[INFO] data={}, ground-truth={}, pred={}\".format(\n",
252 | "\t\tx, target[0], pred))"
253 | ],
254 | "execution_count": null,
255 | "outputs": []
256 | },
257 | {
258 | "cell_type": "code",
259 | "metadata": {
260 | "id": "lCBfCEp5P9kt"
261 | },
262 | "source": [
263 | "# construct the XOR dataset\n",
264 | "X = np.array([[0, 0], [0, 1], [1, 0], [1, 1]])\n",
265 | "y = np.array([[0], [1], [1], [0]])\n",
266 | "\n",
267 | "# define our perceptron and train it\n",
268 | "print(\"[INFO] training perceptron...\")\n",
269 | "p = Perceptron(X.shape[1], alpha=0.1)\n",
270 | "p.fit(X, y, epochs=20)\n",
271 | "\n",
272 | "# now that our perceptron is trained we can evaluate it\n",
273 | "print(\"[INFO] testing perceptron...\")\n",
274 | "\n",
275 | "# now that our network is trained, loop over the data points\n",
276 | "for (x, target) in zip(X, y):\n",
277 | "\t# make a prediction on the data point and display the result\n",
278 | "\t# to our console\n",
279 | "\tpred = p.predict(x)\n",
280 | "\tprint(\"[INFO] data={}, ground-truth={}, pred={}\".format(\n",
281 | "\t\tx, target[0], pred))"
282 | ],
283 | "execution_count": null,
284 | "outputs": []
285 | },
286 | {
287 | "cell_type": "markdown",
288 | "metadata": {
289 | "id": "4ogkNauArL6u"
290 | },
291 | "source": [
292 | "For a detailed walkthrough of the concepts and code, be sure to refer to the full tutorial, [*Implementing the Perceptron Neural Network with Python*](https://www.pyimagesearch.com/2021/05/06/implementing-the-perceptron-neural-network-with-python/) published on 2021-05-06."
293 | ]
294 | }
295 | ]
296 | }
--------------------------------------------------------------------------------
/701_gradient_descent.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "colab": {
6 | "name": "601-gradient_descent.ipynb",
7 | "provenance": [],
8 | "collapsed_sections": [],
9 | "toc_visible": true,
10 | "include_colab_link": true
11 | },
12 | "kernelspec": {
13 | "name": "python3",
14 | "display_name": "Python 3"
15 | }
16 | },
17 | "cells": [
18 | {
19 | "cell_type": "markdown",
20 | "metadata": {
21 | "id": "view-in-github",
22 | "colab_type": "text"
23 | },
24 | "source": [
25 | "
"
26 | ]
27 | },
28 | {
29 | "cell_type": "markdown",
30 | "metadata": {
31 | "id": "j4RpK9pawQzP"
32 | },
33 | "source": [
34 | "# Gradient descent with Python\n"
35 | ]
36 | },
37 | {
38 | "cell_type": "markdown",
39 | "metadata": {
40 | "id": "8ntZ1AkXZIxY"
41 | },
42 | "source": [
43 | "\n",
44 | "This notebook is associated with the [Gradient descent with Python](https://www.pyimagesearch.com/2016/10/10/gradient-descent-with-python/) blog post published on 2016-10-10.\n",
45 | "\n",
46 | "Only the code for the blog post is here. Most codeblocks have a 1:1 relationship with what you find in the blog post with two exceptions: (1) Python classes are not separate files as they are typically organized with PyImageSearch projects, and (2) Command Line Argument parsing is replaced with an `args` dictionary that you can manipulate as needed.\n",
47 | "\n",
48 | "We recommend that you execute (press ▶️) the code block-by-block, as-is, before adjusting parameters and `args` inputs. Once you've verified that the code is working, you are welcome to hack with it and learn from manipulating inputs, settings, and parameters. For more information on using Jupyter and Colab, please refer to these resources:\n",
49 | "\n",
50 | "* [Jupyter Notebook User Interface](https://jupyter-notebook.readthedocs.io/en/stable/notebook.html#notebook-user-interface)\n",
51 | "* [Overview of Google Colaboratory Features](https://colab.research.google.com/notebooks/basic_features_overview.ipynb)\n",
52 | "\n",
53 | "\n",
54 | "Happy hacking!\n",
55 | "\n",
56 | "\n",
57 | "\n",
58 | "
\n"
59 | ]
60 | },
61 | {
62 | "cell_type": "markdown",
63 | "metadata": {
64 | "id": "NFhAzQB3aNMa"
65 | },
66 | "source": [
67 | "### Download the code zip file"
68 | ]
69 | },
70 | {
71 | "cell_type": "code",
72 | "metadata": {
73 | "id": "7y0LG1EuaRlB"
74 | },
75 | "source": [
76 | "!wget https://www.pyimagesearch.com/wp-content/uploads/2016/08/gradient-descent.zip\n",
77 | "!unzip -qq gradient-descent.zip\n",
78 | "%cd gradient-descent"
79 | ],
80 | "execution_count": null,
81 | "outputs": []
82 | },
83 | {
84 | "cell_type": "markdown",
85 | "metadata": {
86 | "id": "_SgTVT3HagGZ"
87 | },
88 | "source": [
89 | "## Blog Post Code"
90 | ]
91 | },
92 | {
93 | "cell_type": "markdown",
94 | "metadata": {
95 | "id": "wcrOk6pURp50"
96 | },
97 | "source": [
98 | "### Import Packages"
99 | ]
100 | },
101 | {
102 | "cell_type": "code",
103 | "metadata": {
104 | "id": "VJaCNlDDRz6d"
105 | },
106 | "source": [
107 | "# import the necessary packages\n",
108 | "from sklearn.datasets.samples_generator import make_blobs\n",
109 | "import matplotlib.pyplot as plt\n",
110 | "import numpy as np\n",
111 | "import argparse"
112 | ],
113 | "execution_count": null,
114 | "outputs": []
115 | },
116 | {
117 | "cell_type": "markdown",
118 | "metadata": {
119 | "id": "NBHxDn2YBCVp"
120 | },
121 | "source": [
122 | "### Implementing gradient descent with Python\n"
123 | ]
124 | },
125 | {
126 | "cell_type": "code",
127 | "metadata": {
128 | "id": "P6qnpHoCAgdn"
129 | },
130 | "source": [
131 | "def sigmoid_activation(x):\n",
132 | "\t# compute and return the sigmoid activation value for a\n",
133 | "\t# given input value\n",
134 | "\treturn 1.0 / (1 + np.exp(-x))"
135 | ],
136 | "execution_count": null,
137 | "outputs": []
138 | },
139 | {
140 | "cell_type": "code",
141 | "metadata": {
142 | "id": "KnurPvAVBJ4c"
143 | },
144 | "source": [
145 | "# construct the argument parse and parse the arguments\n",
146 | "# ap = argparse.ArgumentParser()\n",
147 | "# ap.add_argument(\"-e\", \"--epochs\", type=float, default=100,\n",
148 | "# \thelp=\"# of epochs\")\n",
149 | "# ap.add_argument(\"-a\", \"--alpha\", type=float, default=0.01,\n",
150 | "# \thelp=\"learning rate\")\n",
151 | "# args = vars(ap.parse_args())\n",
152 | "\n",
153 | "# since we are using Jupyter Notebooks we can replace our argument\n",
154 | "# parsing code with *hard coded* arguments and values\n",
155 | "args = {\n",
156 | "\t\"epochs\": 100,\n",
157 | "\t\"alpha\": 0.01\n",
158 | "}"
159 | ],
160 | "execution_count": null,
161 | "outputs": []
162 | },
163 | {
164 | "cell_type": "code",
165 | "metadata": {
166 | "id": "4AxfRQkEBRid"
167 | },
168 | "source": [
169 | "# generate a 2-class classification problem with 250 data points,\n",
170 | "# where each data point is a 2D feature vector\n",
171 | "(X, y) = make_blobs(n_samples=250, n_features=2, centers=2,\n",
172 | "\tcluster_std=1.05, random_state=20)\n",
173 | "\n",
174 | "# insert a column of 1's as the first entry in the feature\n",
175 | "# vector -- this is a little trick that allows us to treat\n",
176 | "# the bias as a trainable parameter *within* the weight matrix\n",
177 | "# rather than an entirely separate variable\n",
178 | "X = np.c_[np.ones((X.shape[0])), X]\n",
179 | "\n",
180 | "# initialize our weight matrix such it has the same number of\n",
181 | "# columns as our input features\n",
182 | "print(\"[INFO] starting training...\")\n",
183 | "W = np.random.uniform(size=(X.shape[1],))\n",
184 | "\n",
185 | "# initialize a list to store the loss value for each epoch\n",
186 | "lossHistory = []"
187 | ],
188 | "execution_count": null,
189 | "outputs": []
190 | },
191 | {
192 | "cell_type": "code",
193 | "metadata": {
194 | "id": "Xt_CiZrDBV7N"
195 | },
196 | "source": [
197 | "# loop over the desired number of epochs\n",
198 | "for epoch in np.arange(0, args[\"epochs\"]):\n",
199 | "\t# take the dot product between our features `X` and the\n",
200 | "\t# weight matrix `W`, then pass this value through the\n",
201 | "\t# sigmoid activation function, thereby giving us our\n",
202 | "\t# predictions on the dataset\n",
203 | "\tpreds = sigmoid_activation(X.dot(W))\n",
204 | "\n",
205 | "\t# now that we have our predictions, we need to determine\n",
206 | "\t# our `error`, which is the difference between our predictions\n",
207 | "\t# and the true values\n",
208 | "\terror = preds - y\n",
209 | "\n",
210 | "\t# given our `error`, we can compute the total loss value as\n",
211 | "\t# the sum of squared loss -- ideally, our loss should\n",
212 | "\t# decrease as we continue training\n",
213 | "\tloss = np.sum(error ** 2)\n",
214 | "\tlossHistory.append(loss)\n",
215 | "\tprint(\"[INFO] epoch #{}, loss={:.7f}\".format(epoch + 1, loss))\n",
216 | "\n",
217 | "\t# the gradient update is therefore the dot product between\n",
218 | "\t# the transpose of `X` and our error, scaled by the total\n",
219 | "\t# number of data points in `X`\n",
220 | "\tgradient = X.T.dot(error) / X.shape[0]\n",
221 | "\n",
222 | "\t# in the update stage, all we need to do is nudge our weight\n",
223 | "\t# matrix in the opposite direction of the gradient (hence the\n",
224 | "\t# term \"gradient descent\" by taking a small step towards a\n",
225 | "\t# set of \"more optimal\" parameters\n",
226 | "\tW += -args[\"alpha\"] * gradient"
227 | ],
228 | "execution_count": null,
229 | "outputs": []
230 | },
231 | {
232 | "cell_type": "code",
233 | "metadata": {
234 | "id": "t6qEezI6BdjW"
235 | },
236 | "source": [
237 | "# to demonstrate how to use our weight matrix as a classifier,\n",
238 | "# let's look over our a sample of training examples\n",
239 | "for i in np.random.choice(250, 10):\n",
240 | "\t# compute the prediction by taking the dot product of the\n",
241 | "\t# current feature vector with the weight matrix W, then\n",
242 | "\t# passing it through the sigmoid activation function\n",
243 | "\tactivation = sigmoid_activation(X[i].dot(W))\n",
244 | "\n",
245 | "\t# the sigmoid function is defined over the range y=[0, 1],\n",
246 | "\t# so we can use 0.5 as our threshold -- if `activation` is\n",
247 | "\t# below 0.5, it's class `0`; otherwise it's class `1`\n",
248 | "\tlabel = 0 if activation < 0.5 else 1\n",
249 | "\n",
250 | "\t# show our output classification\n",
251 | "\tprint(\"activation={:.4f}; predicted_label={}, true_label={}\".format(\n",
252 | "\t\tactivation, label, y[i]))"
253 | ],
254 | "execution_count": null,
255 | "outputs": []
256 | },
257 | {
258 | "cell_type": "code",
259 | "metadata": {
260 | "id": "d2swUTHgBgP3"
261 | },
262 | "source": [
263 | "# compute the line of best fit by setting the sigmoid function\n",
264 | "# to 0 and solving for X2 in terms of X1\n",
265 | "Y = (-W[0] - (W[1] * X)) / W[2]\n",
266 | "\n",
267 | "# plot the original data along with our line of best fit\n",
268 | "plt.figure()\n",
269 | "plt.scatter(X[:, 1], X[:, 2], marker=\"o\", c=y)\n",
270 | "plt.plot(X, Y, \"r-\")\n",
271 | "\n",
272 | "# construct a figure that plots the loss over time\n",
273 | "fig = plt.figure()\n",
274 | "plt.plot(np.arange(0, args[\"epochs\"]), lossHistory)\n",
275 | "fig.suptitle(\"Training Loss\")\n",
276 | "plt.xlabel(\"Epoch #\")\n",
277 | "plt.ylabel(\"Loss\")\n",
278 | "plt.show()"
279 | ],
280 | "execution_count": null,
281 | "outputs": []
282 | },
283 | {
284 | "cell_type": "markdown",
285 | "metadata": {
286 | "id": "4ogkNauArL6u"
287 | },
288 | "source": [
289 | "For a detailed walkthrough of the concepts and code, be sure to refer to the full tutorial, [*Gradient descent with Python*](https://www.pyimagesearch.com/2016/10/10/gradient-descent-with-python/) blog post published on 2016-10-10."
290 | ]
291 | }
292 | ]
293 | }
294 |
--------------------------------------------------------------------------------
/702_stochastic_gradient_descent.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "nbformat": 4,
3 | "nbformat_minor": 0,
4 | "metadata": {
5 | "colab": {
6 | "name": "602-stochastic_gradient_descent.ipynb",
7 | "provenance": [],
8 | "collapsed_sections": [],
9 | "toc_visible": true,
10 | "include_colab_link": true
11 | },
12 | "kernelspec": {
13 | "name": "python3",
14 | "display_name": "Python 3"
15 | }
16 | },
17 | "cells": [
18 | {
19 | "cell_type": "markdown",
20 | "metadata": {
21 | "id": "view-in-github",
22 | "colab_type": "text"
23 | },
24 | "source": [
25 | "
"
26 | ]
27 | },
28 | {
29 | "cell_type": "markdown",
30 | "metadata": {
31 | "id": "j4RpK9pawQzP"
32 | },
33 | "source": [
34 | "# Stochastic Gradient Descent (SGD) with Python\n"
35 | ]
36 | },
37 | {
38 | "cell_type": "markdown",
39 | "metadata": {
40 | "id": "8ntZ1AkXZIxY"
41 | },
42 | "source": [
43 | "\n",
44 | "This notebook is associated with the [Stochastic Gradient Descent (SGD) with Python](https://www.pyimagesearch.com/2016/10/17/stochastic-gradient-descent-sgd-with-python/) blog post published on 2016-10-17.\n",
45 | "\n",
46 | "Only the code for the blog post is here. Most codeblocks have a 1:1 relationship with what you find in the blog post with two exceptions: (1) Python classes are not separate files as they are typically organized with PyImageSearch projects, and (2) Command Line Argument parsing is replaced with an `args` dictionary that you can manipulate as needed.\n",
47 | "\n",
48 | "We recommend that you execute (press ▶️) the code block-by-block, as-is, before adjusting parameters and `args` inputs. Once you've verified that the code is working, you are welcome to hack with it and learn from manipulating inputs, settings, and parameters. For more information on using Jupyter and Colab, please refer to these resources:\n",
49 | "\n",
50 | "* [Jupyter Notebook User Interface](https://jupyter-notebook.readthedocs.io/en/stable/notebook.html#notebook-user-interface)\n",
51 | "* [Overview of Google Colaboratory Features](https://colab.research.google.com/notebooks/basic_features_overview.ipynb)\n",
52 | "\n",
53 | " \n",
54 | "\n",
55 | "Happy hacking!\n",
56 | "\n",
57 | "\n",
58 | "\n",
59 | "
\n",
60 | "\n"
61 | ]
62 | },
63 | {
64 | "cell_type": "markdown",
65 | "metadata": {
66 | "id": "NFhAzQB3aNMa"
67 | },
68 | "source": [
69 | "### Download the code zip file"
70 | ]
71 | },
72 | {
73 | "cell_type": "code",
74 | "metadata": {
75 | "id": "7y0LG1EuaRlB"
76 | },
77 | "source": [
78 | "!wget https://www.pyimagesearch.com/wp-content/uploads/2016/08/stochastic-gradient-descent.zip\n",
79 | "!unzip -qq stochastic-gradient-descent.zip\n",
80 | "%cd stochastic-gradient-descent"
81 | ],
82 | "execution_count": null,
83 | "outputs": []
84 | },
85 | {
86 | "cell_type": "markdown",
87 | "metadata": {
88 | "id": "_SgTVT3HagGZ"
89 | },
90 | "source": [
91 | "## Blog Post Code"
92 | ]
93 | },
94 | {
95 | "cell_type": "markdown",
96 | "metadata": {
97 | "id": "wcrOk6pURp50"
98 | },
99 | "source": [
100 | "### Import Packages"
101 | ]
102 | },
103 | {
104 | "cell_type": "code",
105 | "metadata": {
106 | "id": "VJaCNlDDRz6d"
107 | },
108 | "source": [
109 | "# import the necessary packages\n",
110 | "from sklearn.datasets.samples_generator import make_blobs\n",
111 | "import matplotlib.pyplot as plt\n",
112 | "import numpy as np\n",
113 | "import argparse"
114 | ],
115 | "execution_count": null,
116 | "outputs": []
117 | },
118 | {
119 | "cell_type": "markdown",
120 | "metadata": {
121 | "id": "OTk6EY43-5We"
122 | },
123 | "source": [
124 | "### Implementing Stochastic Gradient Descent (SGD) with Python"
125 | ]
126 | },
127 | {
128 | "cell_type": "code",
129 | "metadata": {
130 | "id": "gkybQERh-lLI"
131 | },
132 | "source": [
133 | "def sigmoid_activation(x):\n",
134 | "\t# compute and return the sigmoid activation value for a\n",
135 | "\t# given input value\n",
136 | "\treturn 1.0 / (1 + np.exp(-x))"
137 | ],
138 | "execution_count": null,
139 | "outputs": []
140 | },
141 | {
142 | "cell_type": "code",
143 | "metadata": {
144 | "id": "L3mcSCMv_Mlm"
145 | },
146 | "source": [
147 | "def next_batch(X, y, batchSize):\n",
148 | "\t# loop over our dataset `X` in mini-batches of size `batchSize`\n",
149 | "\tfor i in np.arange(0, X.shape[0], batchSize):\n",
150 | "\t\t# yield a tuple of the current batched data and labels\n",
151 | "\t\tyield (X[i:i + batchSize], y[i:i + batchSize])"
152 | ],
153 | "execution_count": null,
154 | "outputs": []
155 | },
156 | {
157 | "cell_type": "code",
158 | "metadata": {
159 | "id": "d61GTWbZ_M-_"
160 | },
161 | "source": [
162 | "# construct the argument parse and parse the arguments\n",
163 | "# ap = argparse.ArgumentParser()\n",
164 | "# ap.add_argument(\"-e\", \"--epochs\", type=float, default=100,\n",
165 | "# \thelp=\"# of epochs\")\n",
166 | "# ap.add_argument(\"-a\", \"--alpha\", type=float, default=0.01,\n",
167 | "# \thelp=\"learning rate\")\n",
168 | "# ap.add_argument(\"-b\", \"--batch-size\", type=int, default=32,\n",
169 | "# \thelp=\"size of SGD mini-batches\")\n",
170 | "# args = vars(ap.parse_args())\n",
171 | "\n",
172 | "# since we are using Jupyter Notebooks we can replace our argument\n",
173 | "# parsing code with *hard coded* arguments and values\n",
174 | "args = {\n",
175 | "\t\"epochs\": 100,\n",
176 | "\t\"alpha\": 0.01,\n",
177 | " \"batch_size\": 32\n",
178 | "}"
179 | ],
180 | "execution_count": null,
181 | "outputs": []
182 | },
183 | {
184 | "cell_type": "code",
185 | "metadata": {
186 | "id": "a2DSnY5O_ayf"
187 | },
188 | "source": [
189 | "# generate a 2-class classification problem with 400 data points,\n",
190 | "# where each data point is a 2D feature vector\n",
191 | "(X, y) = make_blobs(n_samples=400, n_features=2, centers=2,\n",
192 | "\tcluster_std=2.5, random_state=95)"
193 | ],
194 | "execution_count": null,
195 | "outputs": []
196 | },
197 | {
198 | "cell_type": "code",
199 | "metadata": {
200 | "id": "thuvQNW3_eo3"
201 | },
202 | "source": [
203 | "# insert a column of 1's as the first entry in the feature\n",
204 | "# vector -- this is a little trick that allows us to treat\n",
205 | "# the bias as a trainable parameter *within* the weight matrix\n",
206 | "# rather than an entirely separate variable\n",
207 | "X = np.c_[np.ones((X.shape[0])), X]\n",
208 | "\n",
209 | "# initialize our weight matrix such it has the same number of\n",
210 | "# columns as our input features\n",
211 | "print(\"[INFO] starting training...\")\n",
212 | "W = np.random.uniform(size=(X.shape[1],))\n",
213 | "\n",
214 | "# initialize a list to store the loss value for each epoch\n",
215 | "lossHistory = []"
216 | ],
217 | "execution_count": null,
218 | "outputs": []
219 | },
220 | {
221 | "cell_type": "code",
222 | "metadata": {
223 | "id": "_4FloDKY_jZY"
224 | },
225 | "source": [
226 | "# loop over the desired number of epochs\n",
227 | "for epoch in np.arange(0, args[\"epochs\"]):\n",
228 | "\t# initialize the total loss for the epoch\n",
229 | "\tepochLoss = []\n",
230 | "\n",
231 | "\t# loop over our data in batches\n",
232 | "\tfor (batchX, batchY) in next_batch(X, y, args[\"batch_size\"]):\n",
233 | "\t\t# take the dot product between our current batch of\n",
234 | "\t\t# features and weight matrix `W`, then pass this value\n",
235 | "\t\t# through the sigmoid activation function\n",
236 | "\t\tpreds = sigmoid_activation(batchX.dot(W))\n",
237 | "\n",
238 | "\t\t# now that we have our predictions, we need to determine\n",
239 | "\t\t# our `error`, which is the difference between our predictions\n",
240 | "\t\t# and the true values\n",
241 | "\t\terror = preds - batchY\n",
242 | "\n",
243 | "\t\t# given our `error`, we can compute the total loss value on\n",
244 | "\t\t# the batch as the sum of squared loss\n",
245 | "\t\tloss = np.sum(error ** 2)\n",
246 | "\t\tepochLoss.append(loss)\n",
247 | "\n",
248 | "\t\t# the gradient update is therefore the dot product between\n",
249 | "\t\t# the transpose of our current batch and the error on the\n",
250 | "\t\t# # batch\n",
251 | "\t\tgradient = batchX.T.dot(error) / batchX.shape[0]\n",
252 | "\n",
253 | "\t\t# use the gradient computed on the current batch to take\n",
254 | "\t\t# a \"step\" in the correct direction\n",
255 | "\t\tW += -args[\"alpha\"] * gradient\n",
256 | "\n",
257 | "\t# update our loss history list by taking the average loss\n",
258 | "\t# across all batches\n",
259 | "\tlossHistory.append(np.average(epochLoss))"
260 | ],
261 | "execution_count": null,
262 | "outputs": []
263 | },
264 | {
265 | "cell_type": "code",
266 | "metadata": {
267 | "id": "UBNb52ao_pSA"
268 | },
269 | "source": [
270 | "# compute the line of best fit by setting the sigmoid function\n",
271 | "# to 0 and solving for X2 in terms of X1\n",
272 | "Y = (-W[0] - (W[1] * X)) / W[2]\n",
273 | "\n",
274 | "# plot the original data along with our line of best fit\n",
275 | "plt.figure()\n",
276 | "plt.scatter(X[:, 1], X[:, 2], marker=\"o\", c=y)\n",
277 | "plt.plot(X, Y, \"r-\")\n",
278 | "\n",
279 | "# construct a figure that plots the loss over time\n",
280 | "fig = plt.figure()\n",
281 | "plt.plot(np.arange(0, args[\"epochs\"]), lossHistory)\n",
282 | "fig.suptitle(\"Training Loss\")\n",
283 | "plt.xlabel(\"Epoch #\")\n",
284 | "plt.ylabel(\"Loss\")\n",
285 | "plt.show()"
286 | ],
287 | "execution_count": null,
288 | "outputs": []
289 | },
290 | {
291 | "cell_type": "markdown",
292 | "metadata": {
293 | "id": "4ogkNauArL6u"
294 | },
295 | "source": [
296 | "For a detailed walkthrough of the concepts and code, be sure to refer to the full tutorial, [*Stochastic Gradient Descent (SGD) with Python*](https://www.pyimagesearch.com/2016/10/17/stochastic-gradient-descent-sgd-with-python/) blog post published on 2016-10-17."
297 | ]
298 | }
299 | ]
300 | }
301 |
--------------------------------------------------------------------------------