├── .github
└── workflows
│ └── pep8-check.yml
├── .gitignore
├── LICENSE
├── README.md
├── TESTING.md
├── abs_difference.py
├── bilateral_filter.py
├── butterworth_high_pass_filter.py
├── butterworth_low_pass_filter.py
├── camera_stream.py
├── capture_camera.py
├── capture_video.py
├── checkbuildinfo.py
├── clahe_equalization.py
├── colour_object_tracking.py
├── colour_query.py
├── contrast_stretching.py
├── correlation_template_matching.py
├── dct_low_pass_filter.py
├── exponential.py
├── fourier.py
├── gamma.py
├── high_pass_filter.py
├── histogram.py
├── histogram_equalize.py
├── hsv_viewer.py
├── jpeg_compression_noise.py
├── logarithmic.py
├── low_pass_filter.py
├── mean_filter.py
├── median_filter.py
├── nlm_filter.py
├── rgb_viewer.py
├── save_image.py
├── save_video.py
├── skeleton.py
├── smooth_image.py
├── test_all.sh
├── version.py
└── ycrcb_viewer.py
/.github/workflows/pep8-check.yml:
--------------------------------------------------------------------------------
1 | # This workflow will install Python dependencies, run tests and lint with a single version of Python
2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
3 |
4 | name: Python - PEP8
5 |
6 | on:
7 | push:
8 | branches: [ master ]
9 | pull_request:
10 | branches: [ master ]
11 |
12 | jobs:
13 | build:
14 |
15 | runs-on: ubuntu-latest
16 |
17 | steps:
18 | - uses: actions/checkout@v2
19 | - name: Set up Python 3.8
20 | uses: actions/setup-python@v2
21 | with:
22 | python-version: 3.8
23 | - name: Install dependencies
24 | run: |
25 | python -m pip install --upgrade pip
26 | pip install flake8 pytest
27 | if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
28 | - name: Lint with flake8
29 | run: |
30 | # check for all PEP8 compliance issues
31 | flake8 .
32 |
--------------------------------------------------------------------------------
/.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 | env/
12 | build/
13 | develop-eggs/
14 | dist/
15 | downloads/
16 | eggs/
17 | .eggs/
18 | lib/
19 | lib64/
20 | parts/
21 | sdist/
22 | var/
23 | *.egg-info/
24 | .installed.cfg
25 | *.egg
26 |
27 | # PyInstaller
28 | # Usually these files are written by a python script from a template
29 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
30 | *.manifest
31 | *.spec
32 |
33 | # Installer logs
34 | pip-log.txt
35 | pip-delete-this-directory.txt
36 |
37 | # Unit test / coverage reports
38 | htmlcov/
39 | .tox/
40 | .coverage
41 | .coverage.*
42 | .cache
43 | nosetests.xml
44 | coverage.xml
45 | *,cover
46 | .hypothesis/
47 |
48 | # Translations
49 | *.mo
50 | *.pot
51 |
52 | # Django stuff:
53 | *.log
54 | local_settings.py
55 |
56 | # Flask stuff:
57 | instance/
58 | .webassets-cache
59 |
60 | # Scrapy stuff:
61 | .scrapy
62 |
63 | # Sphinx documentation
64 | docs/_build/
65 |
66 | # PyBuilder
67 | target/
68 |
69 | # IPython Notebook
70 | .ipynb_checkpoints
71 |
72 | # pyenv
73 | .python-version
74 |
75 | # celery beat schedule file
76 | celerybeat-schedule
77 |
78 | # dotenv
79 | .env
80 |
81 | # virtualenv
82 | venv/
83 | ENV/
84 |
85 | # Spyder project settings
86 | .spyderproject
87 |
88 | # Rope project settings
89 | .ropeproject
90 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Python Image Processing OpenCV Teaching Examples
2 |
3 | OpenCV Python image processing examples used for teaching within the undergraduate Computer Science programme
4 | at [Durham University](http://www.durham.ac.uk) (UK) by [Prof. Toby Breckon](https://breckon.org/toby/).
5 |
6 | 
7 |
8 | All tested with [OpenCV](http://www.opencv.org) 3.x / 4.x and Python 3.x.
9 |
10 | ```
11 | # Example : <................................> processing from a video file
12 | # specified on the command line (e.g. python FILE.py video_file) or from an
13 | # attached web camera
14 | ```
15 |
16 | More generally most of the examples accessing camera or video can be used as follows:
17 |
18 | ```
19 | python3 ./skeleton.py -h
20 | usage: skeleton.py [-h] [-c CAMERA_TO_USE] [-r RESCALE] [video_file]
21 |
22 | Perform ./skeleton.py example operation on incoming camera/video image
23 |
24 | positional arguments:
25 | video_file specify optional video file
26 |
27 | optional arguments:
28 | -h, --help show this help message and exit
29 | -c CAMERA_TO_USE, --camera_to_use CAMERA_TO_USE
30 | specify camera to use
31 | -r RESCALE, --rescale RESCALE
32 | rescale image by this factor
33 | ```
34 |
35 | Most run with a webcam connected or from a command line supplied video file of a format OpenCV supports on your system (supplied as a command line argument as per above).
36 |
37 | Demo source code is provided _"as is"_ to aid learning and understanding of topics on the course and beyond.
38 |
39 | ---
40 |
41 | ### Background:
42 |
43 | Directly adapted from the [C++](https://github.com/tobybreckon/cpp-examples-ipcv.git) and earlier [C](https://github.com/tobybreckon/cpp-examples-ipcv.git) language teaching examples used to generate the video examples within the ebook version of:
44 |
45 | [Dictionary of Computer Vision and Image Processing](http://dx.doi.org/10.1002/9781119286462) (R.B. Fisher, T.P. Breckon, K. Dawson-Howe, A. Fitzgibbon, C. Robertson, E. Trucco, C.K.I. Williams), Wiley, 2014.
46 | [[Google Books](http://books.google.co.uk/books?id=TaEQAgAAQBAJ&lpg=PP1&dq=isbn%3A1118706811&pg=PP1v=onepage&q&f=false)] [[doi](http://dx.doi.org/10.1002/9781119286462)]
47 |
48 | Notably, the [C++](https://github.com/tobybreckon/cpp-examples-ipcv.git) examples may contain further speed optimizations.
49 |
50 | ---
51 | ### How to download and run:
52 |
53 | Download each file as needed or to download the entire repository and run each try:
54 |
55 | ```
56 | git clone https://github.com/tobybreckon/python-examples-ip.git
57 | cd python-examples-ip
58 | python3 ./.py [optional video file]
59 | ```
60 |
61 | An extremely simple example to check if OpenCV and the other python libraries commonly needed by these examples are present/working on your system and which version of them is in use, is the ``version.py`` example:
62 |
63 | ```
64 | python3 ./version.py
65 | ```
66 |
67 | which should then output something like this (but with the _"x"_ elements completed
68 | specific to your system install):
69 |
70 | ```
71 | We are using OpenCV: x.x.x
72 | .. do we have the Open CV Contrib Modules: xxxx
73 | We are using numpy: x.x.x
74 | We are using matplotlib: x.x.x
75 | .. and this is in Python: x.x.x (default, xxxxx) [xxx]
76 | ```
77 |
78 | More generally an extended set of [OpenCV functionality tests](TESTING.md) is available (used to check OpenCV itself is working) and also a simple bash shell script (``test_all.sh``) to run through all the examples for semi-automated testing.
79 |
80 | ---
81 |
82 | ### Re-usable Exemplar Components (Python Classes):
83 |
84 | This codebase contains the following re-usable exemplar elements:
85 |
86 | - ```camera_stream.py``` - a re-usable threaded camera class, that is call compatible with the existing OpenCV VideoCapture class, designed to always deliver the latest frame from a single camera without buffering delays (used by all examples if available).
87 |
88 | The master copy of the above is available from the the [OpenCV Python Computer Vision Examples used for Teaching](https://github.com/tobybreckon/python-examples-cv) repository.
89 |
90 | ---
91 |
92 | ### Reference:
93 |
94 | All techniques are fully explained in corresponding section of:
95 |
96 | _Fundamentals of Digital Image Processing: A Practical Approach with Examples in Matlab_,
97 | Chris J. Solomon and Toby P. Breckon, Wiley-Blackwell, 2010
98 | ISBN: 0470844736, DOI:10.1002/9780470689776, http://www.fundipbook.com
99 |
100 | (which also has Matlab code examples of many of the same techniques here - [https://github.com/tobybreckon/solomon-breckon-book.git]( https://github.com/tobybreckon/solomon-breckon-book.git))
101 |
102 | ```
103 | @Book{solomonbreckon10fundamentals,
104 | author = {Solomon, C.J. and Breckon, T.P.},
105 | title = {Fundamentals of Digital Image Processing: A Practical Approach with Examples in Matlab},
106 | publisher = {Wiley-Blackwell},
107 | year = {2010},
108 | isbn = {0470844736},
109 | doi = {10.1002/9780470689776},
110 | url = {http://www.fundipbook.com}
111 | }
112 | ```
113 |
114 | ---
115 |
116 | If you find any bugs raise an issue (or much better still submit a git pull request with a fix) - toby.breckon@durham.ac.uk
117 |
118 | _"may the source be with you"_ - anon.
119 |
--------------------------------------------------------------------------------
/TESTING.md:
--------------------------------------------------------------------------------
1 | # Verification Testing for OpenCV Installation
2 |
3 | As OpenCV is a complex beast, to ensure the full installation of OpenCV is working correctly we perform the following tests.
4 |
5 | All tested with [OpenCV](http://www.opencv.org) 3.x / 4.x and Python 3.x.
6 |
7 | _Assumes that git and wget tools are available on the command line or that similar tools are available to access git / download files._
8 |
9 | (_On-site at Durham University_: For testing on MS Windows, download and unzip example files from source URL as specified - [here](https://github.com/tobybreckon/python-examples-ip.git) - onto the user space J:/ drive. On Linux run the associated ``opencv ... .init`` shell script before testing.).
10 |
11 | ---
12 |
13 | ## Test #1 - check versions:
14 |
15 | (for testing on MS Windows at Durham (DUDE system), open all ```.py``` scripts from J:/ in IDLE and run module from there)
16 |
17 | ```
18 | git clone https://github.com/tobybreckon/python-examples-ip.git
19 | cd python-examples-ip
20 | python3 ./version.py
21 | ```
22 | ### Result #1:
23 |
24 | - Text output to console such that:
25 |
26 | ```
27 | We are using OpenCV: CCC
28 | .. do we have the OpenCV Contrib Modules: True
29 | .. do we have the OpenCV Non-free algorithms: True
30 | .. do we have the Intel Performance Primitives (IPP):
31 | .. version: ??> (in use: True)
32 | We are using numpy: ??>
33 | We are using matplotlib: ??>
34 | .. and this is in Python: PPP ??? (64 bit)
35 |
36 | Check Video I/O (OS identifier: MMM)
37 | ... available camera backends: LLL
38 | ... available stream backends: LLL
39 | ... available video writer backends: LLL
40 |
41 | Available Cuda Information:
42 | ... ['NVIDIA CUDA: YES (ver NNN, RRR)', 'NVIDIA GPU arch: ???', 'NVIDIA PTX archs: ZZZ']
43 |
44 | GGG
45 |
46 | DNN module CUDA backend/target availability :
47 | ... DNN_TARGET_CUDA: True
48 | ... DNN_TARGET_CUDA_FP16: True
49 | ... DNN_TARGET_CPU: True
50 | ... DNN_TARGET_OPENCL: True
51 | ... DNN_TARGET_OPENCL_FP16: True
52 |
53 | OpenCL available (within OpenCV) ? : True
54 |
55 | Available CPU Optimizations (*: build enabled; ?: not CPU supported):
56 | ... ???
57 |
58 | ```
59 | - such that CCC >= 4.3.x (or higher), PPP > 3.x, MMM is sensible for the OS in use, each of the LLL list are sensible (may not all be identical) and ideally include FFMPEG + GSTREAMER in addition to V4L/V4L (for MMM = linux*), QT (for MMM = darwin) or DSHOW / MSMF (for MMM = win*), NNN > 10.x, ZZZ includes ``cuDNN: Yes``, GGG is sensible if a CUDA compatible GPU is present + configured and ??? = (doesn't matter). In addition, for maximum performance RRR ideally includes ``CUFFT CUBLAS FAST_MATH``.
60 |
61 | [ N.B. to build with Non-free algorithms set OPENCV_ENABLE_NONFREE=TRUE in CMake ]
62 |
63 | ---
64 |
65 | ## Test #1a - check we have all the correct functionality:
66 |
67 | Only to be used if building OpenCV from source (any platform) or using a pre-built version from a 3rd party repository (on Linux / Mac OS).
68 |
69 | ```
70 | .. (as per test 1 for steps 1 + 2)
71 | python3 ./checkbuildinfo.py
72 | ```
73 | ### Results #1a
74 |
75 | - The resulting build element information should ideally contain the following as a subset of the configuration (where _present_ indicates a reference to a system file or a version number that tells us it is present on the system / in the build):
76 |
77 | | build element | Linux | MS Windows |
78 | |------------------------------------ | ----- | --------|
79 | | Platform: ... Configuration: |Release|Release|
80 | | Built as dynamic libs: | YES | YES |
81 | | OpenCV modules: | contains: core flann ... imgproc ... ml ... imgcodecs ... videoio .. xfeatures2d ... dnn ... dnn_objdetect ... ximgproc ... optflow ... stitching ... **cuda** | <-- same as Linux|
82 | | Non-free algorithms: | YES | YES |
83 | | QT: | NO | NO |
84 | | GTK+ 2.x: | YES | NO |
85 | | ZLib: | present | present |
86 | | JPEG: | present | present |
87 | | WEBP: | present | present |
88 | | PNG: | present | present |
89 | | JPEG 2000: | present | present |
90 | | OpenEXR: | present | present |
91 | | PNG: | present | present |
92 | | FFMPEG: | YES (all sub-elements)| NO |
93 | | GStreamer: | YES (all sub-elements)| NO |
94 | | V4L/V4L2: | present | NO |
95 | | XINE: | YES | NO |
96 | | gPhoto2: | YES | NO |
97 | | Parallel framework: | pthreads | ??? |
98 | | Use IPP: | present | NO |
99 | | **NVIDIA CUDA:** | YES ( >= 10.x) | NO |
100 | | **OpenCL:** | YES | YES |
101 |
102 | - elements **in bold** required for OpenCV 4.3.x and later on Linux (to enable GPU use for CNN/DNN inference via DNN module).
103 |
104 | ---
105 |
106 | ## Test #2 - check image read + window display functions:
107 |
108 | (for MS Windows download image from [here](https://upload.wikimedia.org/wikipedia/commons/b/b4/JPEG_example_JPG_RIP_100.jpg) and save as example.jpg in directory python-examples-ip-master)
109 |
110 | ```
111 | .. (as per test 1 for steps 1 + 2)
112 | wget https://upload.wikimedia.org/wikipedia/commons/b/b4/JPEG_example_JPG_RIP_100.jpg
113 | mv JPEG_example_JPG_RIP_100.jpg example.jpg
114 | python3 ./smooth_image.py
115 | ```
116 |
117 | ### Result #2:
118 | - image is displayed in window (a blurred version of example.jpg),
119 | pressing 'x' closes window.
120 |
121 | ---
122 |
123 | ## Test #3 - test camera access and video write function:
124 |
125 | ```
126 | .. (as per test 1 for steps 1 + 2)
127 | <<< connect a usb web-cam (any web-cam)
128 | python3 ./save_video.py -c 0
129 | ```
130 |
131 | ## Result #3:
132 | - possible error message such as "???... ???? Unable to open source 'input.avi'" - _ignore this_.
133 | - possible error message relating to inability to read from camera or video device (try with ``-c 1`` or greater to address different video devices)
134 | - a window appears with live video from camera, pressing 'x' closes window and ends program (saving a video file).
135 | - video file saved as _output.avi_ file can be played in [vlc](http://www.vlc.org) or similar.
136 | - Ignore _"cannot open video messages"_ from ffpmeg/xine or similar (this is it failing to open video file as alt. to camera, not write from camera).
137 |
138 | ---
139 |
140 | ## Test #4 - test video read function:
141 |
142 | (for MS Windows download video from [here](https://download.blender.org/peach/bigbuckbunny_movies/big_buck_bunny_720p_surround.avi) and save as video.avi in directory python-examples-ip-master)
143 |
144 | ```
145 | .. (as per test 1 for steps 1 + 2)
146 | wget https://download.blender.org/peach/bigbuckbunny_movies/big_buck_bunny_720p_surround.avi
147 | mv big_buck_bunny_720p_surround.avi video.avi
148 | python3 ./capture_video.py
149 | ```
150 |
151 | ### Result #4:
152 |
153 | - The video available at
154 | http://camendesign.co.uk/code/video_for_everybody/test.html is played
155 | back in a window, but with no audio.
156 |
157 | ---
158 |
--------------------------------------------------------------------------------
/abs_difference.py:
--------------------------------------------------------------------------------
1 | #####################################################################
2 |
3 | # Example : simple image differencing and contrast via multiplication
4 | # from a video file specified on the command line
5 | # (e.g. python FILE.py video_file) or from an attached web camera
6 |
7 | # Author : Toby Breckon, toby.breckon@durham.ac.uk
8 |
9 | # Copyright (c) 2015 School of Engineering & Computing Science,
10 | # Copyright (c) 2019 Dept Computer Science,
11 | # Durham University, UK
12 | # License : LGPL - http://www.gnu.org/licenses/lgpl.html
13 |
14 | #####################################################################
15 |
16 | import cv2
17 | import argparse
18 | import sys
19 |
20 | #####################################################################
21 |
22 | keep_processing = True
23 |
24 | # parse command line arguments for camera ID or video file
25 |
26 | parser = argparse.ArgumentParser(
27 | description='Perform ' +
28 | sys.argv[0] +
29 | ' example operation on incoming camera/video image')
30 | parser.add_argument(
31 | "-c",
32 | "--camera_to_use",
33 | type=int,
34 | help="specify camera to use",
35 | default=0)
36 | parser.add_argument(
37 | "-r",
38 | "--rescale",
39 | type=float,
40 | help="rescale image by this factor",
41 | default=1.0)
42 | parser.add_argument(
43 | 'video_file',
44 | metavar='video_file',
45 | type=str,
46 | nargs='?',
47 | help='specify optional video file')
48 | args = parser.parse_args()
49 | use_greyscale = False
50 |
51 |
52 | #####################################################################
53 |
54 | # this function is called as a call-back everytime the trackbar is moved
55 | # (here we just do nothing)
56 |
57 | def nothing(x):
58 | pass
59 |
60 |
61 | #####################################################################
62 |
63 | # define video capture object
64 |
65 | try:
66 | # to use a non-buffered camera stream (via a separate thread)
67 |
68 | if not (args.video_file):
69 | import camera_stream
70 | cap = camera_stream.CameraVideoStream(use_tapi=False)
71 | else:
72 | cap = cv2.VideoCapture() # not needed for video files
73 |
74 | except BaseException:
75 | # if not then just use OpenCV default
76 |
77 | print("INFO: camera_stream class not found - camera input may be buffered")
78 | cap = cv2.VideoCapture()
79 |
80 | # define display window name
81 |
82 | window_name = "Live Camera Input" # window name
83 | window_name2 = "Difference Image" # window name
84 |
85 | # if command line arguments are provided try to read video_file
86 | # otherwise default to capture from attached H/W camera
87 |
88 | if (((args.video_file) and (cap.open(str(args.video_file))))
89 | or (cap.open(args.camera_to_use))):
90 |
91 | # create windows by name (as resizable)
92 |
93 | cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
94 | cv2.namedWindow(window_name2, cv2.WINDOW_NORMAL)
95 |
96 | # add some track bar controllers for settings
97 |
98 | contrast = 1
99 | cv2.createTrackbar("contrast", window_name2, contrast, 30, nothing)
100 |
101 | fps = 25
102 | cv2.createTrackbar("fps", window_name2, fps, 25, nothing)
103 |
104 | threshold = 0
105 | cv2.createTrackbar("threshold", window_name2, threshold, 255, nothing)
106 |
107 | # if video file or camera successfully open then read frame from video
108 |
109 | if (cap.isOpened):
110 | ret, frame = cap.read()
111 |
112 | # rescale if specified
113 |
114 | if (args.rescale != 1.0):
115 | frame = cv2.resize(frame, (0, 0), fx=args.rescale, fy=args.rescale)
116 |
117 | # make a deep copy of this (as all camera frames otherwise reside
118 | # in the same portion of allocated memory)
119 |
120 | prev_frame = frame.copy()
121 |
122 | while (keep_processing):
123 |
124 | # if video file or camera successfully open then read frame from video
125 |
126 | if (cap.isOpened):
127 | ret, frame = cap.read()
128 |
129 | # when we reach the end of the video (file) exit cleanly
130 |
131 | if (ret == 0):
132 | keep_processing = False
133 | continue
134 |
135 | # rescale if specified
136 |
137 | if (args.rescale != 1.0):
138 | frame = cv2.resize(
139 | frame, (0, 0), fx=args.rescale, fy=args.rescale)
140 |
141 | if (use_greyscale):
142 | frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
143 | # if the previous frame we stored also has 3 channels (colour)
144 | if (len(prev_frame.shape) == 3):
145 | # convert it, otherwise absdiff() will break
146 | prev_frame = cv2.cvtColor(prev_frame, cv2.COLOR_BGR2GRAY)
147 |
148 | # performing absolute differencing between consecutive frames
149 |
150 | diff_img = cv2.absdiff(prev_frame, frame)
151 |
152 | # retrieve the contrast setting from the track bar
153 |
154 | contrast = cv2.getTrackbarPos("contrast", window_name2)
155 |
156 | # multiple the result to increase the contrast (so we can see small
157 | # pixel changes)
158 |
159 | brightened_img = diff_img * contrast
160 |
161 | # display images
162 |
163 | cv2.imshow(window_name, frame)
164 |
165 | # threshold the image if its in grayscale and we have a valid threshold
166 |
167 | threshold = cv2.getTrackbarPos("threshold", window_name2)
168 |
169 | if (use_greyscale and (threshold > 0)):
170 |
171 | # display thresholded image if threshold > 0
172 | # thresholding : if pixel > (threshold value) set to 255 (white),
173 | # otherwise set to 0 (black)
174 |
175 | ret, thresholded_img = cv2.threshold(
176 | brightened_img, 127, 255, cv2.THRESH_BINARY)
177 | cv2.imshow(window_name2, thresholded_img)
178 | else:
179 | # otherwise just display the non-thresholded one
180 |
181 | cv2.imshow(window_name2, brightened_img)
182 |
183 | # start the event loop - essential
184 |
185 | # cv2.waitKey() is a keyboard binding function (argument is the time in
186 | # ms). It waits for specified milliseconds for any keyboard event.
187 | # If you press any key in that time, the program continues.
188 | # If 0 is passed, it waits indefinitely for a key stroke.
189 | # (bitwise and with 0xFF to extract least significant byte of
190 | # multi-byte response)
191 |
192 | fps = cv2.getTrackbarPos("fps", window_name2)
193 | # wait T ms (i.e. 1000ms / 25 fps = 40 ms)
194 | key = cv2.waitKey(int(1000 / max(1, fps))) & 0xFF
195 |
196 | # It can also be set to detect specific key strokes by recording which
197 | # key is pressed
198 |
199 | # e.g. if user presses "x" then exit
200 |
201 | if (key == ord('x')):
202 | keep_processing = False
203 |
204 | elif (key == ord('g')):
205 |
206 | # toggle grayscale usage (when they press 'g')
207 |
208 | use_greyscale = not (use_greyscale)
209 |
210 | # if the previous frame we stored also has 3 channels (colour)
211 | if (len(prev_frame.shape) != 3):
212 | # convert it to just copying the gray information to all of the
213 | # three channels (this is a hack), otherwise absdiff() will
214 | # break
215 | prev_frame = cv2.cvtColor(prev_frame, cv2.COLOR_GRAY2BGR)
216 | else:
217 |
218 | # make a deep copy of the current frame (as all camera frames
219 | # otherwise reside in the same portion of allocated memory)
220 | prev_frame = frame.copy()
221 |
222 | # close all windows
223 |
224 | cv2.destroyAllWindows()
225 |
226 | else:
227 | print("No video file specified or camera connected.")
228 |
229 | #####################################################################
230 |
--------------------------------------------------------------------------------
/bilateral_filter.py:
--------------------------------------------------------------------------------
1 | #####################################################################
2 |
3 | # Example : gaussian and bi-lateral filtering on an image from an attached
4 | # web camera
5 |
6 | # Author : Toby Breckon, toby.breckon@durham.ac.uk
7 |
8 | # Copyright (c) 2015 School of Engineering & Computing Science,
9 | # Copyright (c) 2019 Dept Computer Science,
10 | # Durham University, UK
11 | # License : LGPL - http://www.gnu.org/licenses/lgpl.html
12 |
13 | #####################################################################
14 |
15 | import cv2
16 | import sys
17 | import argparse
18 |
19 | #####################################################################
20 |
21 | keep_processing = True
22 |
23 | # parse command line arguments for camera ID or video file
24 |
25 | parser = argparse.ArgumentParser(
26 | description='Perform ' +
27 | sys.argv[0] +
28 | ' example operation on incoming camera/video image')
29 | parser.add_argument(
30 | "-c",
31 | "--camera_to_use",
32 | type=int,
33 | help="specify camera to use",
34 | default=0)
35 | parser.add_argument(
36 | "-r",
37 | "--rescale",
38 | type=float,
39 | help="rescale image by this factor",
40 | default=1.0)
41 | parser.add_argument(
42 | 'video_file',
43 | metavar='video_file',
44 | type=str,
45 | nargs='?',
46 | help='specify optional video file')
47 | args = parser.parse_args()
48 |
49 |
50 | #####################################################################
51 |
52 | # this function is called as a call-back everytime the trackbar is moved
53 | # (here we just do nothing)
54 |
55 | def nothing(x):
56 | pass
57 |
58 |
59 | #####################################################################
60 |
61 | # define video capture object
62 |
63 | try:
64 | # to use a non-buffered camera stream (via a separate thread)
65 |
66 | if not (args.video_file):
67 | import camera_stream
68 | cap = camera_stream.CameraVideoStream(use_tapi=False)
69 | else:
70 | cap = cv2.VideoCapture() # not needed for video files
71 |
72 | except BaseException:
73 | # if not then just use OpenCV default
74 |
75 | print("INFO: camera_stream class not found - camera input may be buffered")
76 | cap = cv2.VideoCapture()
77 |
78 | # define display window name
79 |
80 | window_name = "Live Camera Input" # window name
81 | window_name2 = "Gaussian Smoothing" # window name
82 | window_name3 = "Bilaterial Filtering" # window name
83 |
84 | # if command line arguments are provided try to read video_file
85 | # otherwise default to capture from attached H/W camera
86 |
87 | if (((args.video_file) and (cap.open(str(args.video_file))))
88 | or (cap.open(args.camera_to_use))):
89 |
90 | # create window by name
91 |
92 | cv2.namedWindow(window_name, cv2.WINDOW_AUTOSIZE)
93 | cv2.namedWindow(window_name2, cv2.WINDOW_AUTOSIZE)
94 | cv2.namedWindow(window_name3, cv2.WINDOW_AUTOSIZE)
95 |
96 | # add some track bar controllers for settings Gaussian smoothing
97 |
98 | neighbourhood = 3
99 | cv2.createTrackbar(
100 | "neighbourhood, N",
101 | window_name2,
102 | neighbourhood,
103 | 40,
104 | nothing)
105 | sigma = 1
106 | cv2.createTrackbar("sigma", window_name2, sigma, 10, nothing)
107 |
108 | # add some track bar controllers for settings bilateral smoothing
109 |
110 | sigma_s = 10
111 | cv2.createTrackbar("sigma S", window_name3, sigma_s, 25, nothing)
112 | sigma_r = 10
113 | cv2.createTrackbar("sigma R", window_name3, sigma_r, 25, nothing)
114 |
115 | while (keep_processing):
116 |
117 | # if video file or camera successfully open then read frame from video
118 |
119 | if (cap.isOpened):
120 | ret, frame = cap.read()
121 |
122 | # when we reach the end of the video (file) exit cleanly
123 |
124 | if (ret == 0):
125 | keep_processing = False
126 | continue
127 |
128 | # rescale if specified
129 |
130 | if (args.rescale != 1.0):
131 | frame = cv2.resize(
132 | frame, (0, 0), fx=args.rescale, fy=args.rescale)
133 |
134 | # get parameter from track bars - Gaussian
135 |
136 | neighbourhood = cv2.getTrackbarPos("neighbourhood, N", window_name2)
137 | sigma = cv2.getTrackbarPos("sigma", window_name2)
138 |
139 | # get parameter from track bars - bilateral
140 |
141 | sigma_s = cv2.getTrackbarPos("sigma S", window_name3)
142 | sigma_r = cv2.getTrackbarPos("sigma R", window_name3)
143 |
144 | # check neighbourhood is greater than 3 and odd
145 |
146 | neighbourhood = max(3, neighbourhood)
147 | if not (neighbourhood % 2):
148 | neighbourhood = neighbourhood + 1
149 |
150 | # perform Gaussian smoothing using NxN neighbourhood
151 |
152 | smoothed_img = cv2.GaussianBlur(
153 | frame,
154 | (neighbourhood,
155 | neighbourhood),
156 | sigma,
157 | sigma,
158 | borderType=cv2.BORDER_REPLICATE)
159 |
160 | # perform bilateral filtering using a neighbourhood calculated
161 | # automatically from sigma_s
162 |
163 | filtered_img = cv2.bilateralFilter(
164 | frame, -1, sigma_r, sigma_s, borderType=cv2.BORDER_REPLICATE)
165 |
166 | # display image
167 |
168 | cv2.imshow(window_name, frame)
169 | cv2.imshow(window_name2, smoothed_img)
170 | cv2.imshow(window_name3, filtered_img)
171 |
172 | # start the event loop - essential
173 |
174 | # cv2.waitKey() is a keyboard binding function (argument is the time in
175 | # ms). It waits for specified milliseconds for any keyboard event.
176 | # If you press any key in that time, the program continues.
177 | # If 0 is passed, it waits indefinitely for a key stroke.
178 | # (bitwise and with 0xFF to extract least significant byte of
179 | # multi-byte response)
180 |
181 | # wait 40ms (i.e. 1000ms / 25 fps = 40 ms)
182 | key = cv2.waitKey(40) & 0xFF
183 |
184 | # It can also be set to detect specific key strokes by recording which
185 | # key is pressed
186 |
187 | # e.g. if user presses "x" then exit
188 |
189 | if (key == ord('x')):
190 | keep_processing = False
191 |
192 | # close all windows
193 |
194 | cv2.destroyAllWindows()
195 |
196 | else:
197 | print("No usable camera connected.")
198 |
199 |
200 | #####################################################################
201 |
--------------------------------------------------------------------------------
/butterworth_low_pass_filter.py:
--------------------------------------------------------------------------------
1 | #####################################################################
2 |
3 | # Example : perform butterworth low pass filtering in fourier space of
4 | # image frame from a video file specified on the command line
5 | # (e.g. python FILE.py video_file) or from an attached web camera
6 |
7 | # Author : Toby Breckon, toby.breckon@durham.ac.uk
8 |
9 | # Copyright (c) 2015 School of Engineering & Computing Science,
10 | # Copyright (c) 2019 Dept Computer Science,
11 | # Durham University, UK
12 | # License : LGPL - http://www.gnu.org/licenses/lgpl.html
13 |
14 | #####################################################################
15 |
16 | import cv2
17 | import argparse
18 | import sys
19 | import numpy as np
20 | import math
21 |
22 | #####################################################################
23 |
24 | # ignore divide by zero errors in np.log() operations
25 |
26 | np.seterr(divide='ignore')
27 |
28 | #####################################################################
29 |
30 | keep_processing = True
31 |
32 | # parse command line arguments for camera ID or video file
33 |
34 | parser = argparse.ArgumentParser(
35 | description='Perform ' +
36 | sys.argv[0] +
37 | ' example operation on incoming camera/video image')
38 | parser.add_argument(
39 | "-c",
40 | "--camera_to_use",
41 | type=int,
42 | help="specify camera to use",
43 | default=0)
44 | parser.add_argument(
45 | "-r",
46 | "--rescale",
47 | type=float,
48 | help="rescale image by this factor",
49 | default=1.0)
50 | parser.add_argument(
51 | 'video_file',
52 | metavar='video_file',
53 | type=str,
54 | nargs='?',
55 | help='specify optional video file')
56 | args = parser.parse_args()
57 |
58 |
59 | recompute_filter = True
60 |
61 | #####################################################################
62 |
63 | # create a butterworth low pass filter
64 |
65 |
66 | def create_butterworth_low_pass_filter(width, height, d, n):
67 | lp_filter = np.zeros((height, width, 2), np.float32)
68 | centre = (width / 2, height / 2)
69 |
70 | # based on the forumla in lecture 8 (2015 version)
71 | # see also HIPR2 on-line
72 |
73 | for i in range(0, lp_filter.shape[1]): # image width
74 | for j in range(0, lp_filter.shape[0]): # image height
75 | radius = max(
76 | 1,
77 | math.sqrt(
78 | math.pow(
79 | (i -
80 | centre[0]),
81 | 2.0) +
82 | math.pow(
83 | (j -
84 | centre[1]),
85 | 2.0)))
86 | lp_filter[j, i] = 1 / (1 + math.pow((radius / d), (2 * n)))
87 |
88 | return lp_filter
89 |
90 |
91 | #####################################################################
92 |
93 | # this function is called as a call-back everytime the trackbar is moved
94 | # to signal we need to reconstruct the filter
95 |
96 | def reset_butterworth_filter(_):
97 | global recompute_filter
98 | recompute_filter = True
99 | return
100 |
101 |
102 | #####################################################################
103 |
104 | # define video capture object
105 |
106 | try:
107 | # to use a non-buffered camera stream (via a separate thread)
108 |
109 | if not (args.video_file):
110 | import camera_stream
111 | cap = camera_stream.CameraVideoStream(use_tapi=False)
112 | else:
113 | cap = cv2.VideoCapture() # not needed for video files
114 |
115 | except BaseException:
116 | # if not then just use OpenCV default
117 |
118 | print("INFO: camera_stream class not found - camera input may be buffered")
119 | cap = cv2.VideoCapture()
120 |
121 | # define display window name
122 |
123 | window_name = "Live Camera Input" # window name
124 | window_name2 = "Fourier Magnitude Spectrum" # window name
125 | window_name3 = "Filtered Image" # window name
126 | window_name4 = "Butterworth Filter" # window name
127 |
128 | # if command line arguments are provided try to read video_file
129 | # otherwise default to capture from attached H/W camera
130 |
131 | if (((args.video_file) and (cap.open(str(args.video_file))))
132 | or (cap.open(args.camera_to_use))):
133 |
134 | # create windows by name (as resizable)
135 |
136 | cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
137 | cv2.namedWindow(window_name2, cv2.WINDOW_NORMAL)
138 | cv2.namedWindow(window_name3, cv2.WINDOW_NORMAL)
139 | cv2.namedWindow(window_name4, cv2.WINDOW_NORMAL)
140 |
141 | # add some track bar controllers for settings
142 |
143 | radius = 5
144 | cv2.createTrackbar(
145 | "radius",
146 | window_name4,
147 | radius,
148 | 100,
149 | reset_butterworth_filter)
150 | order = 1
151 | cv2.createTrackbar(
152 | "order",
153 | window_name4,
154 | order,
155 | 10,
156 | reset_butterworth_filter)
157 |
158 | # if video file or camera successfully open then read frame from video
159 |
160 | if (cap.isOpened):
161 | ret, frame = cap.read()
162 |
163 | # rescale if specified
164 |
165 | if (args.rescale != 1.0):
166 | frame = cv2.resize(frame, (0, 0), fx=args.rescale, fy=args.rescale)
167 |
168 | # convert to grayscale
169 |
170 | gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
171 |
172 | # use this single frame to set up optimized DFT settings
173 |
174 | hieght, width = gray_frame.shape
175 | nheight = cv2.getOptimalDFTSize(hieght)
176 | nwidth = cv2.getOptimalDFTSize(width)
177 |
178 | while (keep_processing):
179 |
180 | # if video file or camera successfully open then read frame from video
181 |
182 | if (cap.isOpened):
183 | ret, frame = cap.read()
184 |
185 | # when we reach the end of the video (file) exit cleanly
186 |
187 | if (ret == 0):
188 | keep_processing = False
189 | continue
190 |
191 | # rescale if specified
192 |
193 | if (args.rescale != 1.0):
194 | frame = cv2.resize(
195 | frame, (0, 0), fx=args.rescale, fy=args.rescale)
196 |
197 | # start a timer (to see how long processing and display takes)
198 |
199 | start_t = cv2.getTickCount()
200 |
201 | # convert to grayscale
202 |
203 | gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
204 |
205 | # Performance of DFT calculation, via the FFT, is better for array
206 | # sizes of power of two. Arrays whose size is a product of
207 | # 2's, 3's, and 5's are also processed quite efficiently.
208 | # Hence we modify the size of the array to the optimal size (by padding
209 | # zeros) before finding DFT.
210 |
211 | pad_right = nwidth - width
212 | pad_bottom = nheight - hieght
213 | nframe = cv2.copyMakeBorder(
214 | gray_frame,
215 | 0,
216 | pad_bottom,
217 | 0,
218 | pad_right,
219 | cv2.BORDER_CONSTANT,
220 | value=0)
221 |
222 | # perform the DFT and get complex output
223 |
224 | dft = cv2.dft(np.float32(nframe), flags=cv2.DFT_COMPLEX_OUTPUT)
225 |
226 | # shift it so that we the zero-frequency, F(0,0), DC component to the
227 | # center of the spectrum.
228 |
229 | dft_shifted = np.fft.fftshift(dft)
230 |
231 | # perform low pass filtering
232 |
233 | radius = cv2.getTrackbarPos("radius", window_name4)
234 | order = cv2.getTrackbarPos("order", window_name4)
235 |
236 | # butterworth is slow to construct so only do it when needed (i.e.
237 | # trackbar changes)
238 |
239 | if (recompute_filter):
240 | lp_filter = create_butterworth_low_pass_filter(
241 | nwidth, nheight, radius, order)
242 | recompute_filter = False
243 |
244 | dft_filtered = cv2.mulSpectrums(dft_shifted, lp_filter, flags=0)
245 |
246 | # shift it back to original quaderant ordering
247 |
248 | dft = np.fft.fftshift(dft_filtered)
249 |
250 | # recover the original image via the inverse DFT
251 |
252 | filtered_img = cv2.dft(dft, flags=cv2.DFT_INVERSE)
253 |
254 | # normalized the filtered image into 0 -> 255 (8-bit grayscale) so we
255 | # can see the output
256 |
257 | min_val, max_val, min_loc, max_loc = \
258 | cv2.minMaxLoc(filtered_img[:, :, 0])
259 | filtered_img_normalized = filtered_img[:, :, 0] * (
260 | 1.0 / (max_val - min_val)) + ((-min_val) / (max_val - min_val))
261 | filtered_img_normalized = np.uint8(filtered_img_normalized * 255)
262 |
263 | # calculate the magnitude spectrum and log transform + scale it for
264 | # visualization
265 |
266 | magnitude_spectrum = np.log(cv2.magnitude(
267 | dft_filtered[:, :, 0], dft_filtered[:, :, 1]))
268 |
269 | # create a 8-bit image to put the magnitude spectrum into
270 |
271 | magnitude_spectrum_normalized = np.zeros(
272 | (nheight, nwidth, 1), np.uint8)
273 |
274 | # normalized the magnitude spectrum into 0 -> 255 (8-bit grayscale) so
275 | # we can see the output
276 |
277 | cv2.normalize(
278 | np.uint8(magnitude_spectrum),
279 | magnitude_spectrum_normalized,
280 | alpha=0,
281 | beta=255,
282 | norm_type=cv2.NORM_MINMAX)
283 |
284 | # display images
285 |
286 | cv2.imshow(window_name, gray_frame)
287 | cv2.imshow(window_name2, magnitude_spectrum_normalized)
288 | cv2.imshow(window_name3, filtered_img_normalized)
289 | cv2.imshow(window_name4, lp_filter[:, :, 0] * 255)
290 |
291 | # stop timer and convert to ms. (to see how long processing and display
292 | # takes)
293 |
294 | stop_t = ((cv2.getTickCount() - start_t) /
295 | cv2.getTickFrequency()) * 1000
296 |
297 | # start the event loop - essential
298 |
299 | # cv2.waitKey() is a keyboard binding function (argument is the time in
300 | # ms). It waits for specified milliseconds for any keyboard event.
301 | # If you press any key in that time, the program continues.
302 | # If 0 is passed, it waits indefinitely for a key stroke.
303 | # (bitwise and with 0xFF to extract least significant byte of
304 | # multi-byte response)
305 |
306 | # here we use a wait time in ms. that takes account of processing time
307 | # already used in the loop
308 |
309 | # wait 40ms (i.e. 1000ms / 25 fps = 40 ms)
310 | key = cv2.waitKey(max(2, 40 - int(math.ceil(stop_t)))) & 0xFF
311 |
312 | # It can also be set to detect specific key strokes by recording which
313 | # key is pressed
314 |
315 | # e.g. if user presses "x" then exit
316 |
317 | if (key == ord('x')):
318 | keep_processing = False
319 |
320 | # close all windows
321 |
322 | cv2.destroyAllWindows()
323 |
324 | else:
325 | print("No video file specified or camera connected.")
326 |
327 | #####################################################################
328 |
--------------------------------------------------------------------------------
/capture_camera.py:
--------------------------------------------------------------------------------
1 | #####################################################################
2 |
3 | # Example : capture an image from an attached camera
4 |
5 | # Author : Toby Breckon, toby.breckon@durham.ac.uk
6 |
7 | # Copyright (c) 2015 School of Engineering & Computing Science,
8 | # Copyright (c) 2019 Dept Computer Science,
9 | # Durham University, UK
10 | # License : LGPL - http://www.gnu.org/licenses/lgpl.html
11 |
12 | #####################################################################
13 |
14 | import cv2
15 | import argparse
16 | import sys
17 |
18 | #####################################################################
19 |
20 | # parse command line arguments for camera ID or video file
21 |
22 | parser = argparse.ArgumentParser(
23 | description='Perform ' +
24 | sys.argv[0] +
25 | ' example operation on incoming camera/video image')
26 | parser.add_argument(
27 | "-c",
28 | "--camera_to_use",
29 | type=int,
30 | help="specify camera to use",
31 | default=0)
32 | parser.add_argument(
33 | "-r",
34 | "--rescale",
35 | type=float,
36 | help="rescale image by this factor",
37 | default=1.0)
38 | args = parser.parse_args()
39 |
40 | #####################################################################
41 |
42 | # define video capture object
43 |
44 | try:
45 | # to use a non-buffered camera stream (via a separate thread)
46 |
47 | import camera_stream
48 | cap = camera_stream.CameraVideoStream(use_tapi=False)
49 |
50 | except BaseException:
51 | # if not then just use OpenCV default
52 |
53 | print("INFO: camera_stream class not found - camera input may be buffered")
54 | cap = cv2.VideoCapture()
55 |
56 | # define display window name
57 |
58 | window_name = "Live Camera Input" # window name
59 |
60 | # open camera device (and check it worked)
61 |
62 | if not (cap.open(args.camera_to_use)):
63 | print("Cannot open camera - check connection and operation as suggested.")
64 | sys.exit
65 |
66 | # read an image from the camera
67 |
68 | ret, frame = cap.read()
69 |
70 | # to avoid the black/blank first frame from many cameras
71 | # with some (not all) cameras you need to read the first frame twice
72 | # (first frame only)
73 |
74 | ret, frame = cap.read()
75 |
76 | # check it has loaded
77 |
78 | if frame is not None:
79 |
80 | # create window by name (as resizable)
81 |
82 | cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
83 |
84 | # display image
85 |
86 | cv2.imshow(window_name, frame)
87 |
88 | # start the event loop - essential
89 | # wait indefinitely for any key press
90 |
91 | cv2.waitKey(0)
92 |
93 | else:
94 | print("No image successfully loaded from camera.")
95 |
96 | # close all windows
97 |
98 | cv2.destroyAllWindows()
99 |
100 | #####################################################################
101 |
--------------------------------------------------------------------------------
/capture_video.py:
--------------------------------------------------------------------------------
1 | #####################################################################
2 |
3 | # Example : generic interface example for video processing from a video file
4 | # specified by filename or from an attached web camera
5 |
6 | # example test videos avilable from:
7 | # http://camendesign.co.uk/code/video_for_everybody/test.html
8 |
9 | # Author : Toby Breckon, toby.breckon@durham.ac.uk
10 |
11 | # Copyright (c) 2015 School of Engineering & Computing Science,
12 | # Copyright (c) 2019 Dept Computer Science,
13 | # Durham University, UK
14 | # License : LGPL - http://www.gnu.org/licenses/lgpl.html
15 |
16 | #####################################################################
17 |
18 | import cv2
19 | import argparse
20 | import sys
21 |
22 | #####################################################################
23 |
24 | keep_processing = True
25 |
26 | # parse command line arguments for camera ID or video file
27 |
28 | parser = argparse.ArgumentParser(
29 | description='Perform ' +
30 | sys.argv[0] +
31 | ' example operation on incoming camera/video image')
32 | parser.add_argument(
33 | "-c",
34 | "--camera_to_use",
35 | type=int,
36 | help="specify camera to use",
37 | default=0)
38 | parser.add_argument(
39 | "-r",
40 | "--rescale",
41 | type=float,
42 | help="rescale image by this factor",
43 | default=1.0)
44 | args = parser.parse_args()
45 |
46 | #####################################################################
47 |
48 | # define video capture object
49 |
50 | cap = cv2.VideoCapture()
51 |
52 | # define display window name
53 |
54 | window_name = "Live Camera Input" # window name
55 |
56 | # if file is present try to read video_file
57 | # otherwise default to capture from attached H/W camera
58 |
59 | if ((cap.open("video.avi")) or (cap.open(args.camera_to_use))):
60 |
61 | # create window by name (as resizable)
62 |
63 | cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
64 |
65 | while (keep_processing):
66 |
67 | # if video file or camera successfully open then read frame from video
68 |
69 | if (cap.isOpened):
70 | ret, frame = cap.read()
71 |
72 | # when we reach the end of the video (file) exit cleanly
73 |
74 | if (ret == 0):
75 | keep_processing = False
76 | continue
77 |
78 | # rescale if specified
79 |
80 | if (args.rescale != 1.0):
81 | frame = cv2.resize(
82 | frame, (0, 0), fx=args.rescale, fy=args.rescale)
83 |
84 | # *** do any processing here ****
85 |
86 | # display image
87 |
88 | cv2.imshow(window_name, frame)
89 |
90 | # start the event loop - essential
91 |
92 | # cv2.waitKey() is a keyboard binding function (argument is the time in
93 | # ms). It waits for specified milliseconds for any keyboard event.
94 | # If you press any key in that time, the program continues.
95 | # If 0 is passed, it waits indefinitely for a key stroke.
96 | # (bitwise and with 0xFF to extract least significant byte of
97 | # multi-byte response)
98 |
99 | # wait 40ms (i.e. 1000ms / 25 fps = 40 ms)
100 | key = cv2.waitKey(40) & 0xFF
101 |
102 | # It can also be set to detect specific key strokes by recording which
103 | # key is pressed
104 |
105 | # e.g. if user presses "x" then exit
106 |
107 | if (key == ord('x')):
108 | keep_processing = False
109 |
110 | # close all windows
111 |
112 | cv2.destroyAllWindows()
113 |
114 | else:
115 | print("No video file specified or camera connected.")
116 |
117 |
118 | #####################################################################
119 |
--------------------------------------------------------------------------------
/checkbuildinfo.py:
--------------------------------------------------------------------------------
1 | #####################################################################
2 |
3 | # Example : display the build options for OpenCV
4 |
5 | # Author : Toby Breckon, toby.breckon@durham.ac.uk
6 |
7 | # Copyright (c) 2017 Toby Breckon
8 | # Durham University, UK
9 | # License : LGPL - http://www.gnu.org/licenses/lgpl.html
10 |
11 | #####################################################################
12 |
13 | import cv2
14 |
15 | print("You are using OpenCV: " + cv2.__version__)
16 | print()
17 | print("OpenCV is built using the following options:")
18 | print(cv2.getBuildInformation())
19 |
20 | #####################################################################
21 |
--------------------------------------------------------------------------------
/clahe_equalization.py:
--------------------------------------------------------------------------------
1 | #####################################################################
2 |
3 | # Example : perform contrast limited histogram equalization (CLAHE)
4 | # from a video filespecified on the command line (e.g. python FILE.py
5 | # video_file) or from an attached web camera
6 |
7 | # Author : Toby Breckon, toby.breckon@durham.ac.uk
8 |
9 | # Copyright (c) 2015 School of Engineering & Computing Science,
10 | # Copyright (c) 2019 Dept Computer Science,
11 | # Durham University, UK
12 | # License : LGPL - http://www.gnu.org/licenses/lgpl.html
13 |
14 | #####################################################################
15 |
16 | import cv2
17 | import argparse
18 | import numpy as np
19 | import sys
20 |
21 | #####################################################################
22 |
23 | keep_processing = True
24 |
25 | # parse command line arguments for camera ID or video file
26 |
27 | parser = argparse.ArgumentParser(
28 | description='Perform ' +
29 | sys.argv[0] +
30 | ' example operation on incoming camera/video image')
31 | parser.add_argument(
32 | "-c",
33 | "--camera_to_use",
34 | type=int,
35 | help="specify camera to use",
36 | default=0)
37 | parser.add_argument(
38 | "-r",
39 | "--rescale",
40 | type=float,
41 | help="rescale image by this factor",
42 | default=1.0)
43 | parser.add_argument(
44 | 'video_file',
45 | metavar='video_file',
46 | type=str,
47 | nargs='?',
48 | help='specify optional video file')
49 | args = parser.parse_args()
50 |
51 | #####################################################################
52 |
53 | # basic grayscale histogram drawing in raw OpenCV using lines
54 |
55 | # adapted from:
56 | # https://raw.githubusercontent.com/Itseez/opencv/master/samples/python2/hist.py
57 |
58 |
59 | def hist_lines(hist):
60 | h = np.ones((300, 256, 3)) * 255 # white background
61 | cv2.normalize(hist, hist, 0, 255, cv2.NORM_MINMAX)
62 | hist = np.int32(np.around(hist))
63 | for x, y in enumerate(hist):
64 | y = y[0]
65 | cv2.line(h, (x, 0), (x, y), (0, 0, 0)) # black bars
66 | y = np.flipud(h)
67 | return y
68 |
69 |
70 | #####################################################################
71 |
72 | # this function is called as a call-back everytime the trackbar is moved
73 | # (here we just do nothing)
74 |
75 |
76 | def nothing(x):
77 | pass
78 |
79 |
80 | #####################################################################
81 |
82 | # define video capture object
83 |
84 | try:
85 | # to use a non-buffered camera stream (via a separate thread)
86 |
87 | if not (args.video_file):
88 | import camera_stream
89 | cap = camera_stream.CameraVideoStream(use_tapi=False)
90 | else:
91 | cap = cv2.VideoCapture() # not needed for video files
92 |
93 | except BaseException:
94 | # if not then just use OpenCV default
95 |
96 | print("INFO: camera_stream class not found - camera input may be buffered")
97 | cap = cv2.VideoCapture()
98 |
99 | # define display window name
100 |
101 | window_name1 = "Live Camera Input" # window name
102 | window_name2 = "Input Histogram" # window name
103 | window_name3 = "Processed Output" # window name
104 | window_name4 = "Output Histogram" # window name
105 |
106 | # if command line arguments are provided try to read video_file
107 | # otherwise default to capture from attached H/W camera
108 |
109 | if (((args.video_file) and (cap.open(str(args.video_file))))
110 | or (cap.open(args.camera_to_use))):
111 |
112 | # create window by name (as resizable)
113 |
114 | cv2.namedWindow(window_name1, cv2.WINDOW_NORMAL)
115 | cv2.namedWindow(window_name2, cv2.WINDOW_NORMAL)
116 | cv2.namedWindow(window_name3, cv2.WINDOW_NORMAL)
117 | cv2.namedWindow(window_name4, cv2.WINDOW_NORMAL)
118 |
119 | # add some track bar controllers for settings
120 |
121 | clip_limit = 2
122 | cv2.createTrackbar("clip limit", window_name4, clip_limit, 25, nothing)
123 | tile_size = 8
124 | cv2.createTrackbar("tile size", window_name4, tile_size, 64, nothing)
125 |
126 | while (keep_processing):
127 |
128 | # if video file or camera successfully open then read frame from video
129 |
130 | if (cap.isOpened):
131 | ret, frame = cap.read()
132 |
133 | # when we reach the end of the video (file) exit cleanly
134 |
135 | if (ret == 0):
136 | keep_processing = False
137 | continue
138 |
139 | # rescale if specified
140 |
141 | if (args.rescale != 1.0):
142 | frame = cv2.resize(
143 | frame, (0, 0), fx=args.rescale, fy=args.rescale)
144 |
145 | # convert to grayscale
146 |
147 | gray_img = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
148 |
149 | # perform contrast limited adaptive equalization
150 | # based on example at:
151 | # http://docs.opencv.org/3.0-beta/doc/py_tutorials/py_imgproc/py_histograms/py_histogram_equalization/py_histogram_equalization.html
152 |
153 | # get parameters from track bars
154 |
155 | clip_limit = cv2.getTrackbarPos("clip limit", window_name4)
156 | tile_size = cv2.getTrackbarPos("tile size", window_name4)
157 |
158 | # perform filtering
159 |
160 | clahe = cv2.createCLAHE(
161 | clipLimit=clip_limit, tileGridSize=(
162 | tile_size, tile_size)) # create filter
163 | output = clahe.apply(gray_img) # apply filter
164 |
165 | # display image
166 |
167 | cv2.imshow(window_name1, gray_img)
168 | cv2.imshow(
169 | window_name2, hist_lines(
170 | cv2.calcHist(
171 | [gray_img], [0], None, [256], [
172 | 0, 256])))
173 | cv2.imshow(window_name3, output)
174 | cv2.imshow(
175 | window_name4, hist_lines(
176 | cv2.calcHist(
177 | [output], [0], None, [256], [
178 | 0, 256])))
179 |
180 | # start the event loop - essential
181 |
182 | # cv2.waitKey() is a keyboard binding function (argument is the time in
183 | # ms). It waits for specified milliseconds for any keyboard event.
184 | # If you press any key in that time, the program continues.
185 | # If 0 is passed, it waits indefinitely for a key stroke.
186 | # (bitwise and with 0xFF to extract least significant byte of
187 | # multi-byte response)
188 |
189 | # wait 40ms (i.e. 1000ms / 25 fps = 40 ms)
190 | key = cv2.waitKey(40) & 0xFF
191 |
192 | # It can also be set to detect specific key strokes by recording which
193 | # key is pressed
194 |
195 | # e.g. if user presses "x" then exit
196 |
197 | if (key == ord('x')):
198 | keep_processing = False
199 |
200 | # close all windows
201 |
202 | cv2.destroyAllWindows()
203 |
204 | else:
205 | print("No video file specified or camera connected.")
206 |
207 | #####################################################################
208 |
--------------------------------------------------------------------------------
/colour_object_tracking.py:
--------------------------------------------------------------------------------
1 | #####################################################################
2 |
3 | # Example : mean shift object tracking processing from a video file
4 | # specified on the command line (e.g. python FILE.py video_file) or from an
5 | # attached web camera
6 |
7 | # N.B. use mouse to select region
8 |
9 | # Author : Toby Breckon, toby.breckon@durham.ac.uk
10 |
11 | # Copyright (c) 2015 School of Engineering & Computing Science,
12 | # Copyright (c) 2019 Dept Computer Science,
13 | # Durham University, UK
14 | # License : LGPL - http://www.gnu.org/licenses/lgpl.html
15 |
16 | # based in part on tutorial at:
17 | # http://docs.opencv.org/master/db/df8/tutorial_py_meanshift.html#gsc.tab=0
18 |
19 | #####################################################################
20 |
21 | import cv2
22 | import argparse
23 | import sys
24 | import math
25 | import numpy as np
26 |
27 | #####################################################################
28 |
29 | keep_processing = True
30 |
31 | # parse command line arguments for camera ID or video file
32 |
33 | parser = argparse.ArgumentParser(
34 | description='Perform ' +
35 | sys.argv[0] +
36 | ' example operation on incoming camera/video image')
37 | parser.add_argument(
38 | "-c",
39 | "--camera_to_use",
40 | type=int,
41 | help="specify camera to use",
42 | default=0)
43 | parser.add_argument(
44 | "-r",
45 | "--rescale",
46 | type=float,
47 | help="rescale image by this factor",
48 | default=1.0)
49 | parser.add_argument(
50 | 'video_file',
51 | metavar='video_file',
52 | type=str,
53 | nargs='?',
54 | help='specify optional video file')
55 | args = parser.parse_args()
56 |
57 |
58 | selection_in_progress = False # support interactive region selection
59 |
60 | #####################################################################
61 |
62 | # select a region using the mouse
63 |
64 | boxes = []
65 | current_mouse_position = np.ones(2, dtype=np.int32)
66 |
67 |
68 | def on_mouse(event, x, y, flags, params):
69 |
70 | global boxes
71 | global selection_in_progress
72 |
73 | current_mouse_position[0] = x
74 | current_mouse_position[1] = y
75 |
76 | if event == cv2.EVENT_LBUTTONDOWN:
77 | boxes = []
78 | # print 'Start Mouse Position: '+str(x)+', '+str(y)
79 | sbox = [x, y]
80 | selection_in_progress = True
81 | boxes.append(sbox)
82 |
83 | elif event == cv2.EVENT_LBUTTONUP:
84 | # print 'End Mouse Position: '+str(x)+', '+str(y)
85 | ebox = [x, y]
86 | selection_in_progress = False
87 | boxes.append(ebox)
88 |
89 |
90 | #####################################################################
91 |
92 | # this function is called as a call-back everytime the trackbar is moved
93 | # (here we just do nothing)
94 |
95 | def nothing(x):
96 | pass
97 |
98 |
99 | #####################################################################
100 |
101 | # define video capture object
102 |
103 | try:
104 | # to use a non-buffered camera stream (via a separate thread)
105 |
106 | if not (args.video_file):
107 | import camera_stream
108 | cap = camera_stream.CameraVideoStream(use_tapi=False)
109 | else:
110 | cap = cv2.VideoCapture() # not needed for video files
111 |
112 | except BaseException:
113 | # if not then just use OpenCV default
114 |
115 | print("INFO: camera_stream class not found - camera input may be buffered")
116 | cap = cv2.VideoCapture()
117 |
118 | # define display window name
119 |
120 | window_name = "Live Camera Input" # window name
121 | window_name2 = "Hue histogram back projection" # window name
122 | window_name_selection = "selected"
123 |
124 | # if command line arguments are provided try to read video_file
125 | # otherwise default to capture from attached H/W camera
126 |
127 | if (((args.video_file) and (cap.open(str(args.video_file))))
128 | or (cap.open(args.camera_to_use))):
129 |
130 | # create window by name (note flags for resizable or not)
131 |
132 | cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
133 | cv2.namedWindow(window_name2, cv2.WINDOW_NORMAL)
134 | cv2.namedWindow(window_name_selection, cv2.WINDOW_NORMAL)
135 |
136 | # set sliders for HSV selection thresholds
137 |
138 | s_lower = 60
139 | cv2.createTrackbar("s lower", window_name2, s_lower, 255, nothing)
140 | s_upper = 255
141 | cv2.createTrackbar("s upper", window_name2, s_upper, 255, nothing)
142 | v_lower = 32
143 | cv2.createTrackbar("v lower", window_name2, v_lower, 255, nothing)
144 | v_upper = 255
145 | cv2.createTrackbar("v upper", window_name2, v_upper, 255, nothing)
146 |
147 | # set a mouse callback
148 |
149 | cv2.setMouseCallback(window_name, on_mouse, 0)
150 | cropped = False
151 |
152 | # Setup the termination criteria for search, either 10 iteration or
153 | # move by at least 1 pixel pos. difference
154 | term_crit = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1)
155 |
156 | while (keep_processing):
157 |
158 | # if video file or camera successfully open then read frame from video
159 |
160 | if (cap.isOpened):
161 | ret, frame = cap.read()
162 |
163 | # when we reach the end of the video (file) exit cleanly
164 |
165 | if (ret == 0):
166 | keep_processing = False
167 | continue
168 |
169 | # rescale if specified
170 |
171 | if (args.rescale != 1.0):
172 | frame = cv2.resize(
173 | frame, (0, 0), fx=args.rescale, fy=args.rescale)
174 |
175 | # start a timer (to see how long processing and display takes)
176 |
177 | start_t = cv2.getTickCount()
178 |
179 | # get parameters from track bars
180 |
181 | s_lower = cv2.getTrackbarPos("s lower", window_name2)
182 | s_upper = cv2.getTrackbarPos("s upper", window_name2)
183 | v_lower = cv2.getTrackbarPos("v lower", window_name2)
184 | v_upper = cv2.getTrackbarPos("v upper", window_name2)
185 |
186 | # select region using the mouse and display it
187 |
188 | if (len(boxes) > 1) and (boxes[0][1] < boxes[1][1]) and (
189 | boxes[0][0] < boxes[1][0]):
190 | crop = frame[boxes[0][1]:boxes[1][1],
191 | boxes[0][0]:boxes[1][0]].copy()
192 |
193 | h, w, c = crop.shape # size of template
194 | if (h > 0) and (w > 0):
195 | cropped = True
196 |
197 | # convert region to HSV
198 |
199 | hsv_crop = cv2.cvtColor(crop, cv2.COLOR_BGR2HSV)
200 |
201 | # select all Hue (0-> 180) and Sat. values but eliminate values
202 | # with very low saturation or value (due to lack of useful
203 | # colour information)
204 |
205 | mask = cv2.inRange(
206 | hsv_crop, np.array(
207 | (0., float(s_lower), float(v_lower))), np.array(
208 | (180., float(s_upper), float(v_upper))))
209 |
210 | # construct a histogram of hue and saturation values and
211 | # normalize it
212 |
213 | crop_hist = cv2.calcHist(
214 | [hsv_crop], [
215 | 0, 1], mask, [
216 | 180, 255], [
217 | 0, 180, 0, 255])
218 | cv2.normalize(crop_hist, crop_hist, 0, 255, cv2.NORM_MINMAX)
219 |
220 | # set intial position of object
221 |
222 | track_window = (
223 | boxes[0][0],
224 | boxes[0][1],
225 | boxes[1][0] -
226 | boxes[0][0],
227 | boxes[1][1] -
228 | boxes[0][1])
229 |
230 | cv2.imshow(window_name_selection, crop)
231 |
232 | # reset list of boxes
233 |
234 | boxes = []
235 |
236 | # interactive display of selection box
237 |
238 | if (selection_in_progress):
239 | top_left = (boxes[0][0], boxes[0][1])
240 | bottom_right = (
241 | current_mouse_position[0],
242 | current_mouse_position[1])
243 | cv2.rectangle(frame, top_left, bottom_right, (0, 255, 0), 2)
244 |
245 | # if we have a selected region
246 |
247 | if (cropped):
248 |
249 | # convert incoming image to HSV
250 |
251 | img_hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
252 |
253 | img_bproject = cv2.calcBackProject(
254 | [img_hsv], [
255 | 0, 1], crop_hist, [
256 | 0, 180, 0, 255], 1)
257 | cv2.imshow(window_name2, img_bproject)
258 |
259 | # apply meanshift to get the new location
260 | ret, track_window = cv2.meanShift(
261 | img_bproject, track_window, term_crit)
262 |
263 | # Draw it on image
264 | x, y, w, h = track_window
265 | frame = cv2.rectangle(
266 | frame, (x, y), (x + w, y + h), (255, 0, 0), 2)
267 |
268 | else:
269 |
270 | # before we have cropped anything show the mask we are using
271 | # for the S and V components of the HSV image
272 |
273 | img_hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
274 |
275 | # select all Hue values (0-> 180) but eliminate values with very
276 | # low saturation or value (due to lack of useful colour info.)
277 |
278 | mask = cv2.inRange(
279 | img_hsv, np.array(
280 | (0., float(s_lower), float(v_lower))), np.array(
281 | (180., float(s_upper), float(v_upper))))
282 |
283 | cv2.imshow(window_name2, mask)
284 |
285 | # display image
286 |
287 | cv2.imshow(window_name, frame)
288 |
289 | # stop the timer and convert to ms. (to see how long processing and
290 | # display takes)
291 |
292 | stop_t = ((cv2.getTickCount() - start_t) /
293 | cv2.getTickFrequency()) * 1000
294 |
295 | # start the event loop - essential
296 |
297 | # cv2.waitKey() is a keyboard binding function (argument is the time in
298 | # ms). It waits for specified milliseconds for any keyboard event.
299 | # If you press any key in that time, the program continues.
300 | # If 0 is passed, it waits indefinitely for a key stroke.
301 | # (bitwise and with 0xFF to extract least significant byte of
302 | # multi-byte response)
303 |
304 | # wait 40ms or less depending on processing time taken (i.e. 1000ms /
305 | # 25 fps = 40 ms)
306 |
307 | key = cv2.waitKey(max(2, 40 - int(math.ceil(stop_t)))) & 0xFF
308 |
309 | # It can also be set to detect specific key strokes by recording which
310 | # key is pressed
311 |
312 | # e.g. if user presses "x" then exit
313 |
314 | if (key == ord('x')):
315 | keep_processing = False
316 |
317 | # close all windows
318 |
319 | cv2.destroyAllWindows()
320 |
321 | else:
322 | print("No video file specified or camera connected.")
323 |
324 | #####################################################################
325 |
--------------------------------------------------------------------------------
/colour_query.py:
--------------------------------------------------------------------------------
1 | #####################################################################
2 |
3 | # Example : displaying and interact with image from file
4 |
5 | # Author : Toby Breckon, toby.breckon@durham.ac.uk
6 |
7 | # Copyright (c) 2015 School of Engineering & Computing Science,
8 | # Durham University, UK
9 | # License : LGPL - http://www.gnu.org/licenses/lgpl.html
10 |
11 | #####################################################################
12 |
13 | import cv2
14 |
15 | #####################################################################
16 |
17 | # mouse callback function - displays or sets image colour at the click
18 | # location of the mouse
19 |
20 |
21 | def colour_query_mouse_callback(event, x, y, flags, param):
22 |
23 | # records mouse events at postion (x,y) in the image window
24 |
25 | # left button click prints colour information at click location to stdout
26 |
27 | if event == cv2.EVENT_LBUTTONDOWN:
28 | print("BGR colour @ position (%d,%d) = %s" %
29 | (x, y, ', '.join(str(i) for i in img[y, x])))
30 |
31 | # right button sets colour information at click location to white
32 |
33 | elif event == cv2.EVENT_RBUTTONDOWN:
34 | img[y, x] = [255, 255, 255]
35 |
36 |
37 | #####################################################################
38 |
39 | # define display window name
40 |
41 | window_name = "Displayed Image" # window name
42 |
43 | # read an image from the specified file (in colour)
44 |
45 | img = cv2.imread('example.jpg', cv2.IMREAD_COLOR)
46 |
47 | # check it has loaded
48 |
49 | if img is not None:
50 |
51 | # create a named window object
52 |
53 | cv2.namedWindow(window_name)
54 |
55 | # set the mouse call back function that will be called every time
56 | # the mouse is clicked inside the associated window
57 |
58 | cv2.setMouseCallback(window_name, colour_query_mouse_callback)
59 |
60 | # set a loop control flag
61 |
62 | keep_processing = True
63 |
64 | while (keep_processing):
65 |
66 | # display this blurred image in a named window
67 |
68 | cv2.imshow(window_name, img)
69 |
70 | # start the event loop - essential
71 |
72 | # cv2.waitKey() is a keyboard binding function (argument is the time in
73 | # ms). It waits for specified milliseconds for any keyboard event.
74 | # If you press any key in that time, the program continues.
75 | # If 0 is passed, it waits indefinitely for a key stroke.
76 | # (bitwise and with 0xFF to extract least significant byte of
77 | # multi-byte response)
78 |
79 | # wait 40ms (i.e. 1000ms / 25 fps = 40 ms)
80 | key = cv2.waitKey(40) & 0xFF
81 |
82 | # It can also be set to detect specific key strokes by recording which
83 | # key is pressed
84 |
85 | # e.g. if user presses "x" then exit
86 |
87 | if (key == ord('x')):
88 | keep_processing = False
89 |
90 | else:
91 | print("No image file successfully loaded.")
92 |
93 | # ... and finally close all windows
94 |
95 | cv2.destroyAllWindows()
96 |
97 | #####################################################################
98 |
--------------------------------------------------------------------------------
/contrast_stretching.py:
--------------------------------------------------------------------------------
1 | #####################################################################
2 |
3 | # Example : contrast stretching from a video file
4 | # specified on the command line (e.g. python FILE.py video_file) or from an
5 | # attached web camera
6 |
7 | # Author : Toby Breckon, toby.breckon@durham.ac.uk
8 |
9 | # Copyright (c) 2015 School of Engineering & Computing Science,
10 | # Copyright (c) 2019 Dept Computer Science,
11 | # Durham University, UK
12 | # License : LGPL - http://www.gnu.org/licenses/lgpl.html
13 |
14 | #####################################################################
15 |
16 | import cv2
17 | import argparse
18 | import numpy as np
19 | import sys
20 |
21 | #####################################################################
22 |
23 | keep_processing = True
24 |
25 | # parse command line arguments for camera ID or video file
26 |
27 | parser = argparse.ArgumentParser(
28 | description='Perform ' +
29 | sys.argv[0] +
30 | ' example operation on incoming camera/video image')
31 | parser.add_argument(
32 | "-c",
33 | "--camera_to_use",
34 | type=int,
35 | help="specify camera to use",
36 | default=0)
37 | parser.add_argument(
38 | "-r",
39 | "--rescale",
40 | type=float,
41 | help="rescale image by this factor",
42 | default=1.0)
43 | parser.add_argument(
44 | 'video_file',
45 | metavar='video_file',
46 | type=str,
47 | nargs='?',
48 | help='specify optional video file')
49 | args = parser.parse_args()
50 |
51 |
52 | #####################################################################
53 |
54 | # basic grayscale histogram drawing in raw OpenCV using lines
55 |
56 | # adapted from:
57 | # https://raw.githubusercontent.com/Itseez/opencv/master/samples/python2/hist.py
58 |
59 | def hist_lines(hist):
60 | h = np.ones((300, 256, 3)) * 255 # white background
61 | cv2.normalize(hist, hist, 0, 255, cv2.NORM_MINMAX)
62 | hist = np.int32(np.around(hist))
63 | for x, y in enumerate(hist):
64 | y = y[0]
65 | cv2.line(h, (x, 0), (x, y), (0, 0, 0)) # black bars
66 | y = np.flipud(h)
67 | return y
68 |
69 |
70 | #####################################################################
71 |
72 | # define video capture object
73 |
74 | try:
75 | # to use a non-buffered camera stream (via a separate thread)
76 |
77 | if not (args.video_file):
78 | import camera_stream
79 | cap = camera_stream.CameraVideoStream(use_tapi=False)
80 | else:
81 | cap = cv2.VideoCapture() # not needed for video files
82 |
83 | except BaseException:
84 | # if not then just use OpenCV default
85 |
86 | print("INFO: camera_stream class not found - camera input may be buffered")
87 | cap = cv2.VideoCapture()
88 |
89 | # define display window name
90 |
91 | window_name1 = "Live Camera Input" # window name
92 | window_name2 = "Input Histogram" # window name
93 | window_name3 = "Processed Output" # window name
94 | window_name4 = "Output Histogram" # window name
95 |
96 | # if command line arguments are provided try to read video_file
97 | # otherwise default to capture from attached H/W camera
98 |
99 | if (((args.video_file) and (cap.open(str(args.video_file))))
100 | or (cap.open(args.camera_to_use))):
101 |
102 | # create window by name (as resizable)
103 |
104 | cv2.namedWindow(window_name1, cv2.WINDOW_NORMAL)
105 | cv2.namedWindow(window_name2, cv2.WINDOW_NORMAL)
106 | cv2.namedWindow(window_name3, cv2.WINDOW_NORMAL)
107 | cv2.namedWindow(window_name4, cv2.WINDOW_NORMAL)
108 |
109 | while (keep_processing):
110 |
111 | # if video file or camera successfully open then read frame from video
112 |
113 | if (cap.isOpened):
114 | ret, frame = cap.read()
115 |
116 | # when we reach the end of the video (file) exit cleanly
117 |
118 | if (ret == 0):
119 | keep_processing = False
120 | continue
121 |
122 | # rescale if specified
123 |
124 | if (args.rescale != 1.0):
125 | frame = cv2.resize(
126 | frame, (0, 0), fx=args.rescale, fy=args.rescale)
127 |
128 | # convert to grayscale
129 |
130 | gray_img = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
131 |
132 | # create an empty image of the same size for the output
133 |
134 | output = np.empty(gray_img.shape, dtype=np.uint8)
135 |
136 | # perform basic contrast stretching
137 |
138 | # cv2.normalize() with these parameters does
139 | # basic constrast stretching
140 |
141 | cv2.normalize(
142 | gray_img,
143 | output,
144 | alpha=0,
145 | beta=255,
146 | norm_type=cv2.NORM_MINMAX)
147 |
148 | # display image
149 |
150 | cv2.imshow(window_name1, gray_img)
151 | cv2.imshow(
152 | window_name2, hist_lines(
153 | cv2.calcHist(
154 | [gray_img], [0], None, [256], [
155 | 0, 256])))
156 | cv2.imshow(window_name3, output)
157 | cv2.imshow(
158 | window_name4, hist_lines(
159 | cv2.calcHist(
160 | [output], [0], None, [256], [
161 | 0, 256])))
162 |
163 | # start the event loop - essential
164 |
165 | # cv2.waitKey() is a keyboard binding function (argument is the time in
166 | # ms). It waits for specified milliseconds for any keyboard event.
167 | # If you press any key in that time, the program continues.
168 | # If 0 is passed, it waits indefinitely for a key stroke.
169 | # (bitwise and with 0xFF to extract least significant byte of
170 | # multi-byte response)
171 |
172 | # wait 40ms (i.e. 1000ms / 25 fps = 40 ms)
173 | key = cv2.waitKey(40) & 0xFF
174 |
175 | # It can also be set to detect specific key strokes by recording which
176 | # key is pressed
177 |
178 | # e.g. if user presses "x" then exit
179 |
180 | if (key == ord('x')):
181 | keep_processing = False
182 |
183 | # close all windows
184 |
185 | cv2.destroyAllWindows()
186 |
187 | else:
188 | print("No video file specified or camera connected.")
189 |
190 | #####################################################################
191 |
--------------------------------------------------------------------------------
/correlation_template_matching.py:
--------------------------------------------------------------------------------
1 | #####################################################################
2 |
3 | # Example : live template matching via processing from a video file
4 | # specified on the command line (e.g. python FILE.py video_file) or from an
5 | # attached web camera
6 |
7 | # N.B. use mouse to select region
8 |
9 | # Author : Toby Breckon, toby.breckon@durham.ac.uk
10 |
11 | # Copyright (c) 2015 School of Engineering & Computing Science,
12 | # Copyright (c) 2019 Dept Computer Science,
13 | # Durham University, UK
14 | # License : LGPL - http://www.gnu.org/licenses/lgpl.html
15 |
16 | # version 0.2
17 |
18 | #####################################################################
19 |
20 | import cv2
21 | import argparse
22 | import sys
23 | import math
24 | import numpy as np
25 |
26 | #####################################################################
27 |
28 | keep_processing = True
29 |
30 | # parse command line arguments for camera ID or video file
31 |
32 | parser = argparse.ArgumentParser(
33 | description='Perform ' +
34 | sys.argv[0] +
35 | ' example operation on incoming camera/video image')
36 | parser.add_argument(
37 | "-c",
38 | "--camera_to_use",
39 | type=int,
40 | help="specify camera to use",
41 | default=0)
42 | parser.add_argument(
43 | "-r",
44 | "--rescale",
45 | type=float,
46 | help="rescale image by this factor",
47 | default=1.0)
48 | parser.add_argument(
49 | 'video_file',
50 | metavar='video_file',
51 | type=str,
52 | nargs='?',
53 | help='specify optional video file')
54 | args = parser.parse_args()
55 |
56 |
57 | selection_in_progress = False # support interactive region selection
58 |
59 | #####################################################################
60 |
61 | # select a region using the mouse
62 |
63 | boxes = []
64 | current_mouse_position = np.ones(2, dtype=np.int32)
65 |
66 |
67 | def on_mouse(event, x, y, flags, params):
68 |
69 | global boxes
70 | global selection_in_progress
71 |
72 | current_mouse_position[0] = x
73 | current_mouse_position[1] = y
74 |
75 | if event == cv2.EVENT_LBUTTONDOWN:
76 | boxes = []
77 | # print 'Start Mouse Position: '+str(x)+', '+str(y)
78 | sbox = [x, y]
79 | selection_in_progress = True
80 | boxes.append(sbox)
81 |
82 | elif event == cv2.EVENT_LBUTTONUP:
83 | # print 'End Mouse Position: '+str(x)+', '+str(y)
84 | ebox = [x, y]
85 | selection_in_progress = False
86 | boxes.append(ebox)
87 |
88 |
89 | #####################################################################
90 |
91 | # define video capture object
92 |
93 | try:
94 | # to use a non-buffered camera stream (via a separate thread)
95 |
96 | if not (args.video_file):
97 | import camera_stream
98 | cap = camera_stream.CameraVideoStream(use_tapi=False)
99 | else:
100 | cap = cv2.VideoCapture() # not needed for video files
101 |
102 | except BaseException:
103 | # if not then just use OpenCV default
104 |
105 | print("INFO: camera_stream class not found - camera input may be buffered")
106 | cap = cv2.VideoCapture()
107 |
108 | # define display window name
109 |
110 | window_name = "Live Camera Input" # window name
111 | window_name2 = "Correlation Output" # window name
112 | window_name_selection = "selected"
113 |
114 | # if command line arguments are provided try to read video_file
115 | # otherwise default to capture from attached H/W camera
116 |
117 | if (((args.video_file) and (cap.open(str(args.video_file))))
118 | or (cap.open(args.camera_to_use))):
119 |
120 | # create window by name (note flags for resizable or not)
121 |
122 | cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
123 | cv2.namedWindow(window_name2, cv2.WINDOW_NORMAL)
124 | cv2.namedWindow(window_name_selection, cv2.WINDOW_NORMAL)
125 |
126 | # set a mouse callback
127 |
128 | cv2.setMouseCallback(window_name, on_mouse, 0)
129 | cropped = False
130 |
131 | # usage
132 |
133 | print("USAGE: click and drag left to right to select an image region")
134 |
135 | while (keep_processing):
136 |
137 | # if video file or camera successfully open then read frame from video
138 |
139 | if (cap.isOpened):
140 | ret, frame = cap.read()
141 |
142 | # when we reach the end of the video (file) exit cleanly
143 |
144 | if (ret == 0):
145 | keep_processing = False
146 | continue
147 |
148 | # rescale if specified
149 |
150 | if (args.rescale != 1.0):
151 | frame = cv2.resize(
152 | frame, (0, 0), fx=args.rescale, fy=args.rescale)
153 |
154 | # start a timer (to see how long processing and display takes)
155 |
156 | start_t = cv2.getTickCount()
157 |
158 | # select region using the mouse and display it
159 |
160 | if (len(boxes) > 1) and (boxes[0][1] < boxes[1][1]) and (
161 | boxes[0][0] < boxes[1][0]):
162 | crop = frame[boxes[0][1]:boxes[1][1],
163 | boxes[0][0]:boxes[1][0]].copy()
164 | boxes = []
165 | h, w, c = crop.shape # size of template
166 | if (h > 0) and (w > 0):
167 | cropped = True
168 | cv2.imshow(window_name_selection, crop)
169 |
170 | # interactive display of selection box
171 |
172 | if (selection_in_progress):
173 | top_left = (boxes[0][0], boxes[0][1])
174 | bottom_right = (
175 | current_mouse_position[0],
176 | current_mouse_position[1])
177 | cv2.rectangle(frame, top_left, bottom_right, (0, 255, 0), 2)
178 |
179 | # if we have cropped a region perform template matching using
180 | # (normalized) cross correlation and draw rectangle around best match
181 |
182 | if cropped:
183 | correlation = cv2.matchTemplate(frame, crop, cv2.TM_CCOEFF_NORMED)
184 | min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(correlation)
185 | h, w, c = crop.shape # size of template
186 | top_left = max_loc # top left of template matching image frame
187 | bottom_right = (top_left[0] + w, top_left[1] + h)
188 | cv2.rectangle(frame, top_left, bottom_right, (0, 0, 255), 2)
189 |
190 | cv2.imshow(window_name2, correlation)
191 |
192 | # display image
193 |
194 | cv2.imshow(window_name, frame)
195 |
196 | # stop the timer and convert to ms. (to see how long processing and
197 | # display takes)
198 |
199 | stop_t = ((cv2.getTickCount() - start_t) /
200 | cv2.getTickFrequency()) * 1000
201 |
202 | # start the event loop - essential
203 |
204 | # cv2.waitKey() is a keyboard binding function (argument is the time in
205 | # ms). It waits for specified milliseconds for any keyboard event.
206 | # If you press any key in that time, the program continues.
207 | # If 0 is passed, it waits indefinitely for a key stroke.
208 | # (bitwise and with 0xFF to extract least significant byte of
209 | # multi-byte response)
210 |
211 | # wait 40ms or less depending on processing time taken (i.e. 1000ms /
212 | # 25 fps = 40 ms)
213 |
214 | key = cv2.waitKey(max(2, 40 - int(math.ceil(stop_t)))) & 0xFF
215 |
216 | # It can also be set to detect specific key strokes by recording which
217 | # key is pressed
218 |
219 | # e.g. if user presses "x" then exit
220 |
221 | if (key == ord('x')):
222 | keep_processing = False
223 |
224 | # close all windows
225 |
226 | cv2.destroyAllWindows()
227 |
228 | else:
229 | print("No video file specified or camera connected.")
230 |
231 | #####################################################################
232 |
--------------------------------------------------------------------------------
/dct_low_pass_filter.py:
--------------------------------------------------------------------------------
1 | #####################################################################
2 |
3 | # Example : perform low pass filterings in DCT space of image frame
4 | # from a video file specified on the command line (e.g. python FILE.py
5 | # video_file) or from an attached web camera
6 |
7 | # Author : Toby Breckon, toby.breckon@durham.ac.uk
8 |
9 | # Copyright (c) 2015 School of Engineering & Computing Science,
10 | # Copyright (c) 2019 Dept Computer Science,
11 | # Durham University, UK
12 | # License : LGPL - http://www.gnu.org/licenses/lgpl.html
13 |
14 | #####################################################################
15 |
16 | import cv2
17 | import argparse
18 | import sys
19 | import numpy as np
20 | import math
21 |
22 | #####################################################################
23 |
24 | keep_processing = True
25 |
26 | # parse command line arguments for camera ID or video file
27 |
28 | parser = argparse.ArgumentParser(
29 | description='Perform ' +
30 | sys.argv[0] +
31 | ' example operation on incoming camera/video image')
32 | parser.add_argument(
33 | "-c",
34 | "--camera_to_use",
35 | type=int,
36 | help="specify camera to use",
37 | default=0)
38 | parser.add_argument(
39 | "-r",
40 | "--rescale",
41 | type=float,
42 | help="rescale image by this factor",
43 | default=1.0)
44 | parser.add_argument(
45 | 'video_file',
46 | metavar='video_file',
47 | type=str,
48 | nargs='?',
49 | help='specify optional video file')
50 | args = parser.parse_args()
51 |
52 |
53 | #####################################################################
54 |
55 | # create a simple low pass filter - DCT version (top left corner)
56 |
57 | def create_low_pass_filter(width, height, radius):
58 | lp_filter = np.zeros((height, width), np.float32)
59 | cv2.circle(lp_filter, (0, 0), radius, (1, 1, 1), thickness=-1)
60 | return lp_filter
61 |
62 | #####################################################################
63 |
64 | # "Currently dct supports even-size arrays (2, 4, 6 ...). For data
65 | # analysis and approximation, you can pad the array when necessary.
66 | # Also, the function performance depends very much, and not
67 | # monotonically, on the array size (see getOptimalDFTSize() ). In the
68 | # current implementation DCT of a vector of size N is calculated
69 | # via DFT of a vector of size N/2 . Thus, the optimal DCT
70 | # size N1 >= N can be calculated as:" - OpenCV manual 3.0
71 |
72 |
73 | def get_optimal_dct_size(n):
74 | return (2 * cv2.getOptimalDFTSize(math.floor((n + 1) / 2)))
75 |
76 |
77 | #####################################################################
78 |
79 | # this function is called as a call-back everytime the trackbar is moved
80 | # (here we just do nothing)
81 |
82 | def nothing(x):
83 | pass
84 |
85 |
86 | #####################################################################
87 |
88 | # define video capture object
89 |
90 | try:
91 | # to use a non-buffered camera stream (via a separate thread)
92 |
93 | if not (args.video_file):
94 | import camera_stream
95 | cap = camera_stream.CameraVideoStream(use_tapi=False)
96 | else:
97 | cap = cv2.VideoCapture() # not needed for video files
98 |
99 | except BaseException:
100 | # if not then just use OpenCV default
101 |
102 | print("INFO: camera_stream class not found - camera input may be buffered")
103 | cap = cv2.VideoCapture()
104 |
105 | # define display window name
106 |
107 | window_name = "Live Camera Input" # window name
108 | window_name2 = "DCT Co-efficients Spectrum" # window name
109 | window_name3 = "Filtered Image" # window name
110 |
111 | # if command line arguments are provided try to read video_file
112 | # otherwise default to capture from attached H/W camera
113 |
114 | if (((args.video_file) and (cap.open(str(args.video_file))))
115 | or (cap.open(args.camera_to_use))):
116 |
117 | # create windows by name (as resizable)
118 |
119 | cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
120 | cv2.namedWindow(window_name2, cv2.WINDOW_NORMAL)
121 | cv2.namedWindow(window_name3, cv2.WINDOW_NORMAL)
122 |
123 | # if video file or camera successfully open then read frame from video
124 |
125 | if (cap.isOpened):
126 | ret, frame = cap.read()
127 |
128 | # rescale if specified
129 |
130 | if (args.rescale != 1.0):
131 | frame = cv2.resize(frame, (0, 0), fx=args.rescale, fy=args.rescale)
132 |
133 | # convert to grayscale
134 |
135 | gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
136 |
137 | # use this single frame to set up optimized DFT settings
138 |
139 | height, width = gray_frame.shape
140 | nheight = get_optimal_dct_size(height)
141 | nwidth = get_optimal_dct_size(width)
142 |
143 | # add some track bar controllers for settings
144 |
145 | radius = 25
146 | cv2.createTrackbar(
147 | "radius", window_name2, radius, max(
148 | nheight, nwidth) * 2, nothing)
149 |
150 | while (keep_processing):
151 |
152 | # if video file or camera successfully open then read frame from video
153 |
154 | if (cap.isOpened):
155 | ret, frame = cap.read()
156 |
157 | # when we reach the end of the video (file) exit cleanly
158 |
159 | if (ret == 0):
160 | keep_processing = False
161 | continue
162 |
163 | # rescale if specified
164 |
165 | if (args.rescale != 1.0):
166 | frame = cv2.resize(
167 | frame, (0, 0), fx=args.rescale, fy=args.rescale)
168 |
169 | # start a timer (to see how long processing and display takes)
170 |
171 | start_t = cv2.getTickCount()
172 |
173 | # convert to grayscale
174 |
175 | gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
176 |
177 | # Performance of DCT calculation, via the DFT/FFT, is better for array
178 | # sizes of power of two. Arrays whose size is a product of 2's, 3's,
179 | # and 5's are also processed quite efficiently.
180 | # Hence we modify the size of the array tothe optimal size (by padding
181 | # zeros) before finding DCT.
182 |
183 | pad_right = nwidth - width
184 | pad_bottom = nheight - height
185 | nframe = cv2.copyMakeBorder(
186 | gray_frame,
187 | 0,
188 | pad_bottom,
189 | 0,
190 | pad_right,
191 | cv2.BORDER_CONSTANT,
192 | value=0)
193 |
194 | # perform the DCT
195 |
196 | dct = cv2.dct(np.float32(nframe))
197 |
198 | # perform low pass filtering
199 |
200 | radius = cv2.getTrackbarPos("radius", window_name2)
201 | lp_filter = create_low_pass_filter(nwidth, nheight, radius)
202 |
203 | dct_filtered = cv2.multiply(dct, lp_filter)
204 |
205 | # recover the original image via the inverse DCT
206 |
207 | filtered_img = cv2.dct(dct_filtered, flags=cv2.DCT_INVERSE)
208 |
209 | # normalized the filtered image into 0 -> 255 (8-bit grayscale) so we
210 | # can see the output
211 |
212 | min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(filtered_img)
213 | filtered_img_normalized = filtered_img * \
214 | (1.0 / (max_val - min_val)) + ((-min_val) / (max_val - min_val))
215 | filtered_img_normalized = np.uint8(filtered_img_normalized * 255)
216 |
217 | # calculate the DCT spectrum for visualization
218 |
219 | # create a 8-bit image to put the magnitude spectrum into
220 |
221 | dct_spectrum_normalized = np.zeros((nheight, nwidth, 1), np.uint8)
222 |
223 | # normalized the magnitude spectrum into 0 -> 255 (8-bit grayscale) so
224 | # we can see the output
225 |
226 | cv2.normalize(
227 | np.uint8(dct_filtered),
228 | dct_spectrum_normalized,
229 | alpha=0,
230 | beta=255,
231 | norm_type=cv2.NORM_MINMAX)
232 |
233 | # display images
234 |
235 | cv2.imshow(window_name, gray_frame)
236 | cv2.imshow(window_name2, dct_spectrum_normalized)
237 | cv2.imshow(window_name3, filtered_img_normalized)
238 |
239 | # stop timer and convert to ms. (to see how long processing and display
240 | # takes)
241 |
242 | stop_t = ((cv2.getTickCount() - start_t) /
243 | cv2.getTickFrequency()) * 1000
244 |
245 | # start the event loop - essential
246 |
247 | # cv2.waitKey() is a keyboard binding function (argument is the time in
248 | # ms). It waits for specified milliseconds for any keyboard event.
249 | # If you press any key in that time, the program continues.
250 | # If 0 is passed, it waits indefinitely for a key stroke.
251 | # (bitwise and with 0xFF to extract least significant byte of
252 | # multi-byte response)
253 |
254 | # here we use a wait time in ms. that takes account of processing time
255 | # already used in the loop
256 |
257 | # wait 40ms (i.e. 1000ms / 25 fps = 40 ms)
258 | key = cv2.waitKey(max(2, 40 - int(math.ceil(stop_t)))) & 0xFF
259 |
260 | # It can also be set to detect specific key strokes by recording which
261 | # key is pressed
262 |
263 | # e.g. if user presses "x" then exit
264 |
265 | if (key == ord('x')):
266 | keep_processing = False
267 |
268 | # close all windows
269 |
270 | cv2.destroyAllWindows()
271 |
272 | else:
273 | print("No video file specified or camera connected.")
274 |
275 | #####################################################################
276 |
--------------------------------------------------------------------------------
/exponential.py:
--------------------------------------------------------------------------------
1 | #####################################################################
2 |
3 | # Example : exponential transform on an image from an attached web camera
4 |
5 | # Author : Toby Breckon, toby.breckon@durham.ac.uk
6 |
7 | # Copyright (c) 2015 School of Engineering & Computing Science,
8 | # Copyright (c) 2019 Dept Computer Science,
9 | # Durham University, UK
10 | # License : LGPL - http://www.gnu.org/licenses/lgpl.html
11 |
12 | #####################################################################
13 |
14 | import cv2
15 | import sys
16 | import argparse
17 | import math
18 |
19 | #####################################################################
20 |
21 | keep_processing = True
22 |
23 | # parse command line arguments for camera ID or video file
24 |
25 | parser = argparse.ArgumentParser(
26 | description='Perform ' +
27 | sys.argv[0] +
28 | ' example operation on incoming camera/video image')
29 | parser.add_argument(
30 | "-c",
31 | "--camera_to_use",
32 | type=int,
33 | help="specify camera to use",
34 | default=0)
35 | parser.add_argument(
36 | "-r",
37 | "--rescale",
38 | type=float,
39 | help="rescale image by this factor",
40 | default=1.0)
41 | parser.add_argument(
42 | 'video_file',
43 | metavar='video_file',
44 | type=str,
45 | nargs='?',
46 | help='specify optional video file')
47 | args = parser.parse_args()
48 |
49 |
50 | #####################################################################
51 |
52 | # this function is called as a call-back everytime the trackbar is moved
53 | # (here we just do nothing)
54 |
55 | def nothing(x):
56 | pass
57 |
58 |
59 | #####################################################################
60 |
61 | # exponential transform
62 | # image - greyscale image
63 | # c - scaling constant
64 | # alpha - "gradient" co-efficient of exponential function
65 |
66 | def exponential_transform(image, c, alpha):
67 | for i in range(0, image.shape[1]): # image width
68 | for j in range(0, image.shape[0]): # image height
69 |
70 | # compute exponential transform
71 |
72 | image[j, i] = int(c * (math.pow(1 + alpha, image[j, i]) - 1))
73 | return image
74 |
75 |
76 | #####################################################################
77 |
78 | # define video capture object
79 |
80 | try:
81 | # to use a non-buffered camera stream (via a separate thread)
82 |
83 | if not (args.video_file):
84 | import camera_stream
85 | cap = camera_stream.CameraVideoStream(use_tapi=False)
86 | else:
87 | cap = cv2.VideoCapture() # not needed for video files
88 |
89 | except BaseException:
90 | # if not then just use OpenCV default
91 |
92 | print("INFO: camera_stream class not found - camera input may be buffered")
93 | cap = cv2.VideoCapture()
94 |
95 | # define display window name
96 |
97 | window_name = "Live Camera Input" # window name
98 | window_name2 = "Exponential Transform" # window name
99 |
100 | # if command line arguments are provided try to read video_file
101 | # otherwise default to capture from attached H/W camera
102 |
103 | if (((args.video_file) and (cap.open(str(args.video_file))))
104 | or (cap.open(args.camera_to_use))):
105 |
106 | # create window by name (as resizable)
107 |
108 | cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
109 | cv2.namedWindow(window_name2, cv2.WINDOW_NORMAL)
110 |
111 | # add some track bar controllers for settings
112 |
113 | constant = 10
114 | cv2.createTrackbar("constant, C", window_name2, constant, 100, nothing)
115 |
116 | alpha = 10
117 | cv2.createTrackbar("alpha (*0.001)", window_name2, alpha, 50, nothing)
118 |
119 | while (keep_processing):
120 |
121 | # if video file or camera successfully open then read frame from video
122 |
123 | if (cap.isOpened):
124 | ret, frame = cap.read()
125 |
126 | # when we reach the end of the video (file) exit cleanly
127 |
128 | if (ret == 0):
129 | keep_processing = False
130 | continue
131 |
132 | # rescale if specified
133 |
134 | if (args.rescale != 1.0):
135 | frame = cv2.resize(
136 | frame, (0, 0), fx=args.rescale, fy=args.rescale)
137 |
138 | # convert to grayscale
139 |
140 | gray_img = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
141 |
142 | # get parameters from track bars
143 |
144 | constant = cv2.getTrackbarPos("constant, C", window_name2)
145 | alpha = cv2.getTrackbarPos("alpha (*0.001)", window_name2) * 0.001
146 |
147 | # make a copy and exp tranform it
148 |
149 | exp_img = gray_img.copy()
150 | exp_img = exponential_transform(exp_img, constant, alpha)
151 |
152 | # display image
153 |
154 | cv2.imshow(window_name, gray_img)
155 | cv2.imshow(window_name2, exp_img)
156 |
157 | # start the event loop - essential
158 |
159 | # cv2.waitKey() is a keyboard binding function (argument is the time in
160 | # ms). It waits for specified milliseconds for any keyboard event.
161 | # If you press any key in that time, the program continues.
162 | # If 0 is passed, it waits indefinitely for a key stroke.
163 | # (bitwise and with 0xFF to extract least significant byte of
164 | # multi-byte response)
165 |
166 | # wait 40ms (i.e. 1000ms / 25 fps = 40 ms)
167 | key = cv2.waitKey(40) & 0xFF
168 |
169 | # It can also be set to detect specific key strokes by recording which
170 | # key is pressed
171 |
172 | # e.g. if user presses "x" then exit
173 |
174 | if (key == ord('x')):
175 | keep_processing = False
176 |
177 | # close all windows
178 |
179 | cv2.destroyAllWindows()
180 |
181 | else:
182 | print("No usable camera connected.")
183 |
184 |
185 | #####################################################################
186 |
--------------------------------------------------------------------------------
/fourier.py:
--------------------------------------------------------------------------------
1 | #####################################################################
2 |
3 | # Example : display fourier magnitude spectrum of image frame from a
4 | # video file specified on the command line (e.g. python FILE.py
5 | # video_file) or from an attached web camera
6 |
7 | # Author : Toby Breckon, toby.breckon@durham.ac.uk
8 | # Copyright (c) 2015 School of Engineering & Computing Science,
9 | # Copyright (c) 2019 Dept Computer Science,
10 | # Durham University, UK
11 | # License : LGPL - http://www.gnu.org/licenses/lgpl.html
12 |
13 | #####################################################################
14 |
15 | import cv2
16 | import argparse
17 | import sys
18 | import numpy as np
19 | import math
20 |
21 | #####################################################################
22 |
23 | # ignore divide by zero errors in np.log() operations
24 |
25 | np.seterr(divide='ignore')
26 |
27 | #####################################################################
28 |
29 | keep_processing = True
30 |
31 | # parse command line arguments for camera ID or video file
32 |
33 | parser = argparse.ArgumentParser(
34 | description='Perform ' +
35 | sys.argv[0] +
36 | ' example operation on incoming camera/video image')
37 | parser.add_argument(
38 | "-c",
39 | "--camera_to_use",
40 | type=int,
41 | help="specify camera to use",
42 | default=0)
43 | parser.add_argument(
44 | "-r",
45 | "--rescale",
46 | type=float,
47 | help="rescale image by this factor",
48 | default=1.0)
49 | parser.add_argument(
50 | 'video_file',
51 | metavar='video_file',
52 | type=str,
53 | nargs='?',
54 | help='specify optional video file')
55 | args = parser.parse_args()
56 |
57 |
58 | #####################################################################
59 |
60 | # define video capture object
61 |
62 | try:
63 | # to use a non-buffered camera stream (via a separate thread)
64 |
65 | if not (args.video_file):
66 | import camera_stream
67 | cap = camera_stream.CameraVideoStream(use_tapi=False)
68 | else:
69 | cap = cv2.VideoCapture() # not needed for video files
70 |
71 | except BaseException:
72 | # if not then just use OpenCV default
73 |
74 | print("INFO: camera_stream class not found - camera input may be buffered")
75 | cap = cv2.VideoCapture()
76 |
77 | # define display window name
78 |
79 | window_name = "Live Camera Input" # window name
80 | window_name2 = "Fourier Magnitude Spectrum" # window name
81 |
82 |
83 | # if command line arguments are provided try to read video_file
84 | # otherwise default to capture from attached H/W camera
85 |
86 | if (((args.video_file) and (cap.open(str(args.video_file))))
87 | or (cap.open(args.camera_to_use))):
88 |
89 | # create windows by name (as resizable)
90 |
91 | cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
92 | cv2.namedWindow(window_name2, cv2.WINDOW_NORMAL)
93 |
94 | # if video file or camera successfully open then read frame from video
95 |
96 | if (cap.isOpened):
97 | ret, frame = cap.read()
98 |
99 | # rescale if specified
100 |
101 | if (args.rescale != 1.0):
102 | frame = cv2.resize(frame, (0, 0), fx=args.rescale, fy=args.rescale)
103 |
104 | # convert to grayscale
105 |
106 | gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
107 |
108 | # use this single frame to set up optimized DFT settings
109 |
110 | hieght, width = gray_frame.shape
111 | nhieght = cv2.getOptimalDFTSize(hieght)
112 | nwidth = cv2.getOptimalDFTSize(width)
113 |
114 | while (keep_processing):
115 |
116 | # if video file or camera successfully open then read frame from video
117 |
118 | if (cap.isOpened):
119 | ret, frame = cap.read()
120 |
121 | # when we reach the end of the video (file) exit cleanly
122 |
123 | if (ret == 0):
124 | keep_processing = False
125 | continue
126 |
127 | # rescale if specified
128 |
129 | if (args.rescale != 1.0):
130 | frame = cv2.resize(
131 | frame, (0, 0), fx=args.rescale, fy=args.rescale)
132 |
133 | # start a timer (to see how long processing and display takes)
134 |
135 | start_t = cv2.getTickCount()
136 |
137 | # convert to grayscale
138 |
139 | gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
140 |
141 | # Performance of DFT calculation, via the FFT, is better for array
142 | # sizes of power of two. Arrays whose size is a product of
143 | # 2's, 3's, and 5's are also processed quite efficiently.
144 | # Hence we modify the size of the array to the optimal size (by padding
145 | # zeros) before finding DFT.
146 |
147 | pad_right = nwidth - width
148 | pad_bottom = nhieght - hieght
149 | nframe = cv2.copyMakeBorder(
150 | gray_frame,
151 | 0,
152 | pad_bottom,
153 | 0,
154 | pad_right,
155 | cv2.BORDER_CONSTANT,
156 | value=0)
157 |
158 | # perform the DFT and get complex output
159 |
160 | dft = cv2.dft(np.float32(nframe), flags=cv2.DFT_COMPLEX_OUTPUT)
161 |
162 | # shift it so that we the zero-frequency, F(0,0), DC component to the
163 | # center of the spectrum.
164 |
165 | dft_shifted = np.fft.fftshift(dft)
166 |
167 | # calculate the magnitude spectrum and log transform + scale it for
168 | # visualization
169 |
170 | magnitude_spectrum = np.log(cv2.magnitude(
171 | dft_shifted[:, :, 0], dft_shifted[:, :, 1]))
172 |
173 | # create a 8-bit image to put the magnitude spectrum into
174 |
175 | magnitude_spectrum_normalized = np.zeros(
176 | (nhieght, nwidth, 1), np.uint8)
177 |
178 | # normalized the magnitude spectrum into 0 -> 255 (8-bit grayscale) so
179 | # we can see the output
180 |
181 | cv2.normalize(
182 | np.uint8(magnitude_spectrum),
183 | magnitude_spectrum_normalized,
184 | alpha=0,
185 | beta=255,
186 | norm_type=cv2.NORM_MINMAX)
187 |
188 | # display images
189 |
190 | cv2.imshow(window_name, gray_frame)
191 | cv2.imshow(window_name2, magnitude_spectrum_normalized)
192 |
193 | # stop timer and convert to ms. (to see how long processing and display
194 | # takes)
195 |
196 | stop_t = ((cv2.getTickCount() - start_t) /
197 | cv2.getTickFrequency()) * 1000
198 |
199 | # start the event loop - essential
200 |
201 | # cv2.waitKey() is a keyboard binding function (argument is the time in
202 | # ms). It waits for specified milliseconds for any keyboard event.
203 | # If you press any key in that time, the program continues.
204 | # If 0 is passed, it waits indefinitely for a key stroke.
205 | # (bitwise and with 0xFF to extract least significant byte of
206 | # multi-byte response)
207 |
208 | # here we use a wait time in ms. that takes account of processing time
209 | # already used in the loop
210 |
211 | # wait 40ms (i.e. 1000ms / 25 fps = 40 ms)
212 | key = cv2.waitKey(max(2, 40 - int(math.ceil(stop_t)))) & 0xFF
213 |
214 | # It can also be set to detect specific key strokes by recording which
215 | # key is pressed
216 |
217 | # e.g. if user presses "x" then exit
218 |
219 | if (key == ord('x')):
220 | keep_processing = False
221 |
222 | # close all windows
223 |
224 | cv2.destroyAllWindows()
225 |
226 | else:
227 | print("No video file specified or camera connected.")
228 |
229 | #####################################################################
230 |
--------------------------------------------------------------------------------
/gamma.py:
--------------------------------------------------------------------------------
1 | #####################################################################
2 |
3 | # Example : gamma correction /power-law transform on an image
4 | # from an attached web camera (or video file specified on command line)
5 |
6 | # Author : Toby Breckon, toby.breckon@durham.ac.uk
7 |
8 | # Copyright (c) 2015 School of Engineering & Computing Science,
9 | # Copyright (c) 2019 Dept Computer Science,
10 | # Durham University, UK
11 | # License : LGPL - http://www.gnu.org/licenses/lgpl.html
12 |
13 | #####################################################################
14 |
15 | import cv2
16 | import argparse
17 | import sys
18 | import numpy as np
19 |
20 | #####################################################################
21 |
22 | keep_processing = True
23 |
24 | # parse command line arguments for camera ID or video file
25 |
26 | parser = argparse.ArgumentParser(
27 | description='Perform ' +
28 | sys.argv[0] +
29 | ' example operation on incoming camera/video image')
30 | parser.add_argument(
31 | "-c",
32 | "--camera_to_use",
33 | type=int,
34 | help="specify camera to use",
35 | default=0)
36 | parser.add_argument(
37 | "-r",
38 | "--rescale",
39 | type=float,
40 | help="rescale image by this factor",
41 | default=1.0)
42 | parser.add_argument(
43 | 'video_file',
44 | metavar='video_file',
45 | type=str,
46 | nargs='?',
47 | help='specify optional video file')
48 | args = parser.parse_args()
49 |
50 |
51 | #####################################################################
52 |
53 | # this function is called as a call-back everytime the trackbar is moved
54 | # (here we just do nothing)
55 |
56 | def nothing(x):
57 | pass
58 |
59 |
60 | #####################################################################
61 |
62 | # power law transform
63 | # image - colour image
64 | # gamma - "gradient" co-efficient of gamma function
65 |
66 |
67 | def powerlaw_transform(image, gamma):
68 |
69 | # compute power-law transform
70 | # remembering not defined for pixel = 0 (!)
71 |
72 | # handle any overflow in a quick and dirty way using 0-255 clipping
73 |
74 | image = np.clip(np.power(image, gamma), 0, 255).astype('uint8')
75 |
76 | return image
77 |
78 |
79 | #####################################################################
80 |
81 | # define video capture object
82 |
83 | try:
84 | # to use a non-buffered camera stream (via a separate thread)
85 |
86 | if not (args.video_file):
87 | import camera_stream
88 | cap = camera_stream.CameraVideoStream(use_tapi=False)
89 | else:
90 | cap = cv2.VideoCapture() # not needed for video files
91 |
92 | except BaseException:
93 | # if not then just use OpenCV default
94 |
95 | print("INFO: camera_stream class not found - camera input may be buffered")
96 | cap = cv2.VideoCapture()
97 |
98 | # define display window name
99 |
100 | window_name = "Live Camera Input" # window name
101 | window_name2 = "Gamma Corrected (Power-Law Transform)" # window name
102 |
103 | # if command line arguments are provided try to read video_file
104 | # otherwise default to capture from attached H/W camera
105 |
106 | if (((args.video_file) and (cap.open(str(args.video_file))))
107 | or (cap.open(args.camera_to_use))):
108 |
109 | # create window by name (as resizable)
110 |
111 | cv2.namedWindow(window_name, cv2.WINDOW_AUTOSIZE)
112 | cv2.namedWindow(window_name2, cv2.WINDOW_AUTOSIZE)
113 |
114 | # add some track bar controllers for settings
115 |
116 | gamma = 100 # default gamma - no change
117 |
118 | cv2.createTrackbar("gamma, (* 0.01)", window_name2, gamma, 500, nothing)
119 |
120 | while (keep_processing):
121 |
122 | # if video file or camera successfully open then read frame from video
123 |
124 | if (cap.isOpened):
125 | ret, frame = cap.read()
126 |
127 | # when we reach the end of the video (file) exit cleanly
128 |
129 | if (ret == 0):
130 | keep_processing = False
131 | continue
132 |
133 | # rescale if specified
134 |
135 | if (args.rescale != 1.0):
136 | frame = cv2.resize(
137 | frame, (0, 0), fx=args.rescale, fy=args.rescale)
138 |
139 | # get parameters from track bars
140 |
141 | gamma = cv2.getTrackbarPos("gamma, (* 0.01)", window_name2) * 0.01
142 |
143 | # make a copy
144 |
145 | gamma_img = frame.copy()
146 |
147 | # use power-law function to perform gamma correction
148 |
149 | gamma_img = powerlaw_transform(gamma_img, gamma)
150 |
151 | # display image
152 |
153 | cv2.imshow(window_name, frame)
154 | cv2.imshow(window_name2, gamma_img)
155 |
156 | # start the event loop - essential
157 |
158 | # cv2.waitKey() is a keyboard binding function (argument is the time in
159 | # ms). It waits for specified milliseconds for any keyboard event.
160 | # If you press any key in that time, the program continues.
161 | # If 0 is passed, it waits indefinitely for a key stroke.
162 | # (bitwise and with 0xFF to extract least significant byte of
163 | # multi-byte response)
164 |
165 | # wait 40ms (i.e. 1000ms / 25 fps = 40 ms)
166 | key = cv2.waitKey(40) & 0xFF
167 |
168 | # It can also be set to detect specific key strokes by recording which
169 | # key is pressed
170 |
171 | # e.g. if user presses "x" then exit
172 |
173 | if (key == ord('x')):
174 | keep_processing = False
175 |
176 | # close all windows
177 |
178 | cv2.destroyAllWindows()
179 |
180 | else:
181 | print("No usable camera connected.")
182 |
183 |
184 | #####################################################################
185 |
--------------------------------------------------------------------------------
/high_pass_filter.py:
--------------------------------------------------------------------------------
1 | #####################################################################
2 |
3 | # Example : perform high pass filterings in fourier space of image frame
4 | # from a video file specified on the command line (e.g. python FILE.py
5 | # video_file) or from an attached web camera
6 |
7 | # Author : Toby Breckon, toby.breckon@durham.ac.uk
8 |
9 | # Copyright (c) 2015 School of Engineering & Computing Science,
10 | # Copyright (c) 2019 Dept Computer Science,
11 | # Durham University, UK
12 | # License : LGPL - http://www.gnu.org/licenses/lgpl.html
13 |
14 | #####################################################################
15 |
16 | import cv2
17 | import argparse
18 | import sys
19 | import numpy as np
20 | import math
21 | #####################################################################
22 |
23 | # ignore divide by zero errors in np.log() operations
24 |
25 | np.seterr(divide='ignore')
26 |
27 | #####################################################################
28 |
29 | keep_processing = True
30 |
31 | # parse command line arguments for camera ID or video file
32 |
33 | parser = argparse.ArgumentParser(
34 | description='Perform ' +
35 | sys.argv[0] +
36 | ' example operation on incoming camera/video image')
37 | parser.add_argument(
38 | "-c",
39 | "--camera_to_use",
40 | type=int,
41 | help="specify camera to use",
42 | default=0)
43 | parser.add_argument(
44 | "-r",
45 | "--rescale",
46 | type=float,
47 | help="rescale image by this factor",
48 | default=1.0)
49 | parser.add_argument(
50 | 'video_file',
51 | metavar='video_file',
52 | type=str,
53 | nargs='?',
54 | help='specify optional video file')
55 | args = parser.parse_args()
56 |
57 |
58 | #####################################################################
59 |
60 | # create a simple high pass filter
61 |
62 | def create_high_pass_filter(width, height, radius):
63 | hp_filter = np.ones((height, width, 2), np.float32)
64 | cv2.circle(hp_filter, (int(width / 2), int(height / 2)),
65 | radius, (0, 0, 0), thickness=-1)
66 | return hp_filter
67 |
68 |
69 | #####################################################################
70 |
71 | # this function is called as a call-back everytime the trackbar is moved
72 | # (here we just do nothing)
73 |
74 |
75 | def nothing(x):
76 | pass
77 |
78 |
79 | #####################################################################
80 |
81 | # define video capture object
82 |
83 | try:
84 | # to use a non-buffered camera stream (via a separate thread)
85 |
86 | if not (args.video_file):
87 | import camera_stream
88 | cap = camera_stream.CameraVideoStream(use_tapi=False)
89 | else:
90 | cap = cv2.VideoCapture() # not needed for video files
91 |
92 | except BaseException:
93 | # if not then just use OpenCV default
94 |
95 | print("INFO: camera_stream class not found - camera input may be buffered")
96 | cap = cv2.VideoCapture()
97 |
98 | # define display window name
99 |
100 | window_name = "Live Camera Input" # window name
101 | window_name2 = "Fourier Magnitude Spectrum" # window name
102 | window_name3 = "Filtered Image" # window name
103 |
104 | # if command line arguments are provided try to read video_file
105 | # otherwise default to capture from attached H/W camera
106 |
107 | if (((args.video_file) and (cap.open(str(args.video_file))))
108 | or (cap.open(args.camera_to_use))):
109 |
110 | # create windows by name (as resizable)
111 |
112 | cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
113 | cv2.namedWindow(window_name2, cv2.WINDOW_NORMAL)
114 | cv2.namedWindow(window_name3, cv2.WINDOW_NORMAL)
115 |
116 | # add some track bar controllers for settings
117 |
118 | radius = 25
119 | cv2.createTrackbar("radius", window_name2, radius, 200, nothing)
120 |
121 | # if video file or camera successfully open then read frame from video
122 |
123 | if (cap.isOpened):
124 | ret, frame = cap.read()
125 |
126 | # rescale if specified
127 |
128 | if (args.rescale != 1.0):
129 | frame = cv2.resize(frame, (0, 0), fx=args.rescale, fy=args.rescale)
130 |
131 | # convert to grayscale
132 |
133 | gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
134 |
135 | # use this single frame to set up optimized DFT settings
136 |
137 | hieght, width = gray_frame.shape
138 | nheight = cv2.getOptimalDFTSize(hieght)
139 | nwidth = cv2.getOptimalDFTSize(width)
140 |
141 | while (keep_processing):
142 |
143 | # if video file or camera successfully open then read frame from video
144 |
145 | if (cap.isOpened):
146 | ret, frame = cap.read()
147 |
148 | # when we reach the end of the video (file) exit cleanly
149 |
150 | if (ret == 0):
151 | keep_processing = False
152 | continue
153 |
154 | # rescale if specified
155 |
156 | if (args.rescale != 1.0):
157 | frame = cv2.resize(
158 | frame, (0, 0), fx=args.rescale, fy=args.rescale)
159 |
160 | # start a timer (to see how long processing and display takes)
161 |
162 | start_t = cv2.getTickCount()
163 |
164 | # convert to grayscale
165 |
166 | gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
167 |
168 | # Performance of DFT calculation, via the FFT, is better for array
169 | # sizes of power of two. Arrays whose size is a product of
170 | # 2's, 3's, and 5's are also processed quite efficiently.
171 | # Hence we modify the size of the array to the optimal size (by padding
172 | # zeros) before finding DFT.
173 |
174 | pad_right = nwidth - width
175 | pad_bottom = nheight - hieght
176 | nframe = cv2.copyMakeBorder(
177 | gray_frame,
178 | 0,
179 | pad_bottom,
180 | 0,
181 | pad_right,
182 | cv2.BORDER_CONSTANT,
183 | value=0)
184 |
185 | # perform the DFT and get complex output
186 |
187 | dft = cv2.dft(np.float32(nframe), flags=cv2.DFT_COMPLEX_OUTPUT)
188 |
189 | # shift it so that we the zero-frequency, F(0,0), DC component to the
190 | # center of the spectrum.
191 |
192 | dft_shifted = np.fft.fftshift(dft)
193 |
194 | # perform high pass filtering
195 |
196 | radius = cv2.getTrackbarPos("radius", window_name2)
197 | hp_filter = create_high_pass_filter(nwidth, nheight, radius)
198 |
199 | dft_filtered = cv2.mulSpectrums(dft_shifted, hp_filter, flags=0)
200 |
201 | # shift it back to original quaderant ordering
202 |
203 | dft = np.fft.fftshift(dft_filtered)
204 |
205 | # recover the original image via the inverse DFT
206 |
207 | filtered_img = cv2.dft(dft, flags=cv2.DFT_INVERSE)
208 |
209 | # normalized the filtered image into 0 -> 255 (8-bit grayscale) so we
210 | # can see the output
211 |
212 | min_val, max_val, min_loc, max_loc = \
213 | cv2.minMaxLoc(filtered_img[:, :, 0])
214 | filtered_img_normalized = filtered_img[:, :, 0] * (
215 | 1.0 / (max_val - min_val)) + ((-min_val) / (max_val - min_val))
216 | filtered_img_normalized = np.uint8(filtered_img_normalized * 255)
217 |
218 | # calculate the magnitude spectrum and log transform + scale it for
219 | # visualization
220 |
221 | magnitude_spectrum = np.log(cv2.magnitude(
222 | dft_filtered[:, :, 0], dft_filtered[:, :, 1]))
223 |
224 | # create a 8-bit image to put the magnitude spectrum into
225 |
226 | magnitude_spectrum_normalized = np.zeros(
227 | (nheight, nwidth, 1), np.uint8)
228 |
229 | # normalized the magnitude spectrum into 0 -> 255 (8-bit grayscale) so
230 | # we can see the output
231 |
232 | cv2.normalize(
233 | np.uint8(magnitude_spectrum),
234 | magnitude_spectrum_normalized,
235 | alpha=0,
236 | beta=255,
237 | norm_type=cv2.NORM_MINMAX)
238 |
239 | # display images
240 |
241 | cv2.imshow(window_name, gray_frame)
242 | cv2.imshow(window_name2, magnitude_spectrum_normalized)
243 | cv2.imshow(window_name3, filtered_img_normalized)
244 |
245 | # stop timer and convert to ms. (to see how long processing and display
246 | # takes)
247 |
248 | stop_t = ((cv2.getTickCount() - start_t) /
249 | cv2.getTickFrequency()) * 1000
250 |
251 | # start the event loop - essential
252 |
253 | # cv2.waitKey() is a keyboard binding function (argument is the time in
254 | # ms). It waits for specified milliseconds for any keyboard event.
255 | # If you press any key in that time, the program continues.
256 | # If 0 is passed, it waits indefinitely for a key stroke.
257 | # (bitwise and with 0xFF to extract least significant byte of
258 | # multi-byte response)
259 |
260 | # here we use a wait time in ms. that takes account of processing time
261 | # already used in the loop
262 |
263 | # wait 40ms (i.e. 1000ms / 25 fps = 40 ms)
264 | key = cv2.waitKey(max(2, 40 - int(math.ceil(stop_t)))) & 0xFF
265 |
266 | # It can also be set to detect specific key strokes by recording which
267 | # key is pressed
268 |
269 | # e.g. if user presses "x" then exit
270 |
271 | if (key == ord('x')):
272 | keep_processing = False
273 |
274 | # close all windows
275 |
276 | cv2.destroyAllWindows()
277 |
278 | else:
279 | print("No video file specified or camera connected.")
280 |
281 | #####################################################################
282 |
--------------------------------------------------------------------------------
/histogram.py:
--------------------------------------------------------------------------------
1 | #####################################################################
2 |
3 | # Example : calculate and display the grayscale histogram from a video file
4 | # specified on the command line (e.g. python FILE.py video_file) or from an
5 | # attached web camera
6 |
7 | # Author : Toby Breckon, toby.breckon@durham.ac.uk
8 |
9 | # Copyright (c) 2015 School of Engineering & Computing Science,
10 | # Copyright (c) 2019 Dept Computer Science,
11 | # Durham University, UK
12 | # License : LGPL - http://www.gnu.org/licenses/lgpl.html
13 |
14 | #####################################################################
15 |
16 | import cv2
17 | import argparse
18 | import numpy as np
19 | import sys
20 |
21 | #####################################################################
22 |
23 | keep_processing = True
24 |
25 | # parse command line arguments for camera ID or video file
26 |
27 | parser = argparse.ArgumentParser(
28 | description='Perform ' +
29 | sys.argv[0] +
30 | ' example operation on incoming camera/video image')
31 | parser.add_argument(
32 | "-c",
33 | "--camera_to_use",
34 | type=int,
35 | help="specify camera to use",
36 | default=0)
37 | parser.add_argument(
38 | "-r",
39 | "--rescale",
40 | type=float,
41 | help="rescale image by this factor",
42 | default=1.0)
43 | parser.add_argument(
44 | 'video_file',
45 | metavar='video_file',
46 | type=str,
47 | nargs='?',
48 | help='specify optional video file')
49 | args = parser.parse_args()
50 |
51 |
52 | #####################################################################
53 |
54 | # basic grayscale histogram drawing in raw OpenCV using either a curve or lines
55 |
56 | # adapted from:
57 | # https://raw.githubusercontent.com/Itseez/opencv/master/samples/python2/hist.py
58 |
59 | def hist_curve(hist):
60 | h = np.ones((300, 256, 3)) * 255 # white background
61 | bins = np.arange(256).reshape(256, 1)
62 | cv2.normalize(hist, hist, 0, 255, cv2.NORM_MINMAX)
63 | hist = np.int32(np.around(hist))
64 | pts = np.int32(np.column_stack((bins, hist)))
65 | cv2.polylines(h, [pts], False, (0, 0, 0)) # black line
66 | y = np.flipud(h)
67 | return y
68 |
69 |
70 | def hist_lines(hist):
71 | h = np.ones((300, 256, 3)) * 255 # white background
72 | cv2.normalize(hist, hist, 0, 255, cv2.NORM_MINMAX)
73 | hist = np.int32(np.around(hist))
74 | for x, y in enumerate(hist):
75 | y = y[0]
76 | cv2.line(h, (x, 0), (x, y), (0, 0, 0)) # black bars
77 | y = np.flipud(h)
78 | return y
79 |
80 |
81 | #####################################################################
82 |
83 | # define video capture object
84 |
85 | try:
86 | # to use a non-buffered camera stream (via a separate thread)
87 |
88 | if not (args.video_file):
89 | import camera_stream
90 | cap = camera_stream.CameraVideoStream(use_tapi=False)
91 | else:
92 | cap = cv2.VideoCapture() # not needed for video files
93 |
94 | except BaseException:
95 | # if not then just use OpenCV default
96 |
97 | print("INFO: camera_stream class not found - camera input may be buffered")
98 | cap = cv2.VideoCapture()
99 |
100 | # define display window name
101 |
102 | window_name = "Live Camera Input (as Greyscale)" # window name
103 | window_name2 = "Histogram (bar graph)" # window name
104 | window_name3 = "Histogram (line graph)" # window name
105 |
106 |
107 | # if command line arguments are provided try to read video_file
108 | # otherwise default to capture from attached H/W camera
109 |
110 | if (((args.video_file) and (cap.open(str(args.video_file))))
111 | or (cap.open(args.camera_to_use))):
112 |
113 | # create window by name (as resizable)
114 |
115 | cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
116 | cv2.namedWindow(window_name2, cv2.WINDOW_NORMAL)
117 | cv2.namedWindow(window_name3, cv2.WINDOW_NORMAL)
118 |
119 | while (keep_processing):
120 |
121 | # if video file or camera successfully open then read frame from video
122 |
123 | if (cap.isOpened):
124 | ret, frame = cap.read()
125 |
126 | # when we reach the end of the video (file) exit cleanly
127 |
128 | if (ret == 0):
129 | keep_processing = False
130 | continue
131 |
132 | # rescale if specified
133 |
134 | if (args.rescale != 1.0):
135 | frame = cv2.resize(
136 | frame, (0, 0), fx=args.rescale, fy=args.rescale)
137 |
138 | # convert to grayscale
139 |
140 | gray_img = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
141 |
142 | # calculate the histogram over the whole image, for 1 channel
143 | # with one bin (histogram entry) for each value in the range 0 -> 255
144 |
145 | hist = cv2.calcHist([gray_img], [0], None, [256], [0, 256])
146 |
147 | # draw the histogram distribution as an image
148 | # in two different visual forms (same info.)
149 |
150 | hist_img = hist_lines(hist)
151 | hist_img2 = hist_curve(hist)
152 |
153 | # display images
154 |
155 | cv2.imshow(window_name, gray_img)
156 | cv2.imshow(window_name2, hist_img)
157 | cv2.imshow(window_name3, hist_img2)
158 |
159 | # start the event loop - essential
160 |
161 | # cv2.waitKey() is a keyboard binding function (argument is the time in
162 | # ms). It waits for specified milliseconds for any keyboard event.
163 | # If you press any key in that time, the program continues.
164 | # If 0 is passed, it waits indefinitely for a key stroke.
165 | # (bitwise and with 0xFF to extract least significant byte of
166 | # multi-byte response)
167 |
168 | # wait 40ms (i.e. 1000ms / 25 fps = 40 ms)
169 | key = cv2.waitKey(40) & 0xFF
170 |
171 | # It can also be set to detect specific key strokes by recording which
172 | # key is pressed
173 |
174 | # e.g. if user presses "x" then exit
175 |
176 | if (key == ord('x')):
177 | keep_processing = False
178 |
179 | # close all windows
180 |
181 | cv2.destroyAllWindows()
182 |
183 | else:
184 | print("No video file specified or camera connected.")
185 |
186 | #####################################################################
187 |
--------------------------------------------------------------------------------
/histogram_equalize.py:
--------------------------------------------------------------------------------
1 | #####################################################################
2 |
3 | # Example : histogram equalization from a video file
4 | # specified on the command line (e.g. python FILE.py video_file) or from an
5 | # attached web camera
6 |
7 | # Author : Toby Breckon, toby.breckon@durham.ac.uk
8 |
9 | # Copyright (c) 2015 School of Engineering & Computing Science,
10 | # Copyright (c) 2019 Dept Computer Science,
11 | # Durham University, UK
12 | # License : LGPL - http://www.gnu.org/licenses/lgpl.html
13 |
14 | #####################################################################
15 |
16 | import cv2
17 | import argparse
18 | import numpy as np
19 | import sys
20 |
21 | #####################################################################
22 |
23 | keep_processing = True
24 |
25 | # parse command line arguments for camera ID or video file
26 |
27 | parser = argparse.ArgumentParser(
28 | description='Perform ' +
29 | sys.argv[0] +
30 | ' example operation on incoming camera/video image')
31 | parser.add_argument(
32 | "-c",
33 | "--camera_to_use",
34 | type=int,
35 | help="specify camera to use",
36 | default=0)
37 | parser.add_argument(
38 | "-r",
39 | "--rescale",
40 | type=float,
41 | help="rescale image by this factor",
42 | default=1.0)
43 | parser.add_argument(
44 | 'video_file',
45 | metavar='video_file',
46 | type=str,
47 | nargs='?',
48 | help='specify optional video file')
49 | args = parser.parse_args()
50 |
51 |
52 | #####################################################################
53 |
54 | # basic grayscale histogram drawing in raw OpenCV using lines
55 |
56 | # adapted from:
57 | # https://raw.githubusercontent.com/Itseez/opencv/master/samples/python2/hist.py
58 |
59 | def hist_lines(hist):
60 | h = np.ones((300, 256, 3)) * 255 # white background
61 | cv2.normalize(hist, hist, 0, 255, cv2.NORM_MINMAX)
62 | hist = np.int32(np.around(hist))
63 | for x, y in enumerate(hist):
64 | y = y[0]
65 | cv2.line(h, (x, 0), (x, y), (0, 0, 0)) # black bars
66 | y = np.flipud(h)
67 | return y
68 |
69 |
70 | #####################################################################
71 |
72 | # define video capture object
73 |
74 | try:
75 | # to use a non-buffered camera stream (via a separate thread)
76 |
77 | if not (args.video_file):
78 | import camera_stream
79 | cap = camera_stream.CameraVideoStream(use_tapi=False)
80 | else:
81 | cap = cv2.VideoCapture() # not needed for video files
82 |
83 | except BaseException:
84 | # if not then just use OpenCV default
85 |
86 | print("INFO: camera_stream class not found - camera input may be buffered")
87 | cap = cv2.VideoCapture()
88 |
89 | # define display window name
90 |
91 | window_name1 = "Live Camera Input" # window name
92 | window_name2 = "Input Histogram" # window name
93 | window_name3 = "Processed Output" # window name
94 | window_name4 = "Output Histogram" # window name
95 |
96 | # if command line arguments are provided try to read video_file
97 | # otherwise default to capture from attached H/W camera
98 |
99 | if (((args.video_file) and (cap.open(str(args.video_file))))
100 | or (cap.open(args.camera_to_use))):
101 |
102 | # create window by name (as resizable)
103 |
104 | cv2.namedWindow(window_name1, cv2.WINDOW_NORMAL)
105 | cv2.namedWindow(window_name2, cv2.WINDOW_NORMAL)
106 | cv2.namedWindow(window_name3, cv2.WINDOW_NORMAL)
107 | cv2.namedWindow(window_name4, cv2.WINDOW_NORMAL)
108 |
109 | while (keep_processing):
110 |
111 | # if video file or camera successfully open then read frame from video
112 |
113 | if (cap.isOpened):
114 | ret, frame = cap.read()
115 |
116 | # when we reach the end of the video (file) exit cleanly
117 |
118 | if (ret == 0):
119 | keep_processing = False
120 | continue
121 |
122 | # rescale if specified
123 |
124 | if (args.rescale != 1.0):
125 | frame = cv2.resize(
126 | frame, (0, 0), fx=args.rescale, fy=args.rescale)
127 |
128 | # convert to grayscale
129 |
130 | gray_img = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
131 |
132 | # perform histogram equalization
133 |
134 | output = cv2.equalizeHist(gray_img)
135 |
136 | # display image
137 |
138 | cv2.imshow(window_name1, gray_img)
139 | cv2.imshow(
140 | window_name2, hist_lines(
141 | cv2.calcHist(
142 | [gray_img], [0], None, [256], [
143 | 0, 256])))
144 | cv2.imshow(window_name3, output)
145 | cv2.imshow(
146 | window_name4, hist_lines(
147 | cv2.calcHist(
148 | [output], [0], None, [256], [
149 | 0, 256])))
150 |
151 | # start the event loop - essential
152 |
153 | # cv2.waitKey() is a keyboard binding function (argument is the time in
154 | # ms). It waits for specified milliseconds for any keyboard event.
155 | # If you press any key in that time, the program continues.
156 | # If 0 is passed, it waits indefinitely for a key stroke.
157 | # (bitwise and with 0xFF to extract least significant byte of
158 | # multi-byte response)
159 |
160 | # wait 40ms (i.e. 1000ms / 25 fps = 40 ms)
161 | key = cv2.waitKey(40) & 0xFF
162 |
163 | # It can also be set to detect specific key strokes by recording which
164 | # key is pressed
165 |
166 | # e.g. if user presses "x" then exit
167 |
168 | if (key == ord('x')):
169 | keep_processing = False
170 |
171 | # close all windows
172 |
173 | cv2.destroyAllWindows()
174 |
175 | else:
176 | print("No video file specified or camera connected.")
177 |
178 | #####################################################################
179 |
--------------------------------------------------------------------------------
/hsv_viewer.py:
--------------------------------------------------------------------------------
1 | #####################################################################
2 |
3 | # Example : display individual HSV channels from an video file
4 | # specified on the command line (e.g. python FILE.py video_file) or from an
5 | # attached web camera
6 |
7 | # Author : Toby Breckon, toby.breckon@durham.ac.uk
8 |
9 | # Copyright (c) 2015 School of Engineering & Computing Science,
10 | # Copyright (c) 2019 Dept Computer Science,
11 | # Durham University, UK
12 | # License : LGPL - http://www.gnu.org/licenses/lgpl.html
13 |
14 | #####################################################################
15 |
16 | import cv2
17 | import argparse
18 | import sys
19 | import numpy as np
20 | import math
21 |
22 | #####################################################################
23 |
24 | keep_processing = True
25 |
26 | # parse command line arguments for camera ID or video file
27 |
28 | parser = argparse.ArgumentParser(
29 | description='Perform ' +
30 | sys.argv[0] +
31 | ' example operation on incoming camera/video image')
32 | parser.add_argument(
33 | "-c",
34 | "--camera_to_use",
35 | type=int,
36 | help="specify camera to use",
37 | default=0)
38 | parser.add_argument(
39 | "-r",
40 | "--rescale",
41 | type=float,
42 | help="rescale image by this factor",
43 | default=1.0)
44 | parser.add_argument(
45 | 'video_file',
46 | metavar='video_file',
47 | type=str,
48 | nargs='?',
49 | help='specify optional video file')
50 | args = parser.parse_args()
51 |
52 |
53 | colour_map_hue = False # use colour mapping to display Hue
54 |
55 | #####################################################################
56 |
57 | # define video capture object
58 |
59 | try:
60 | # to use a non-buffered camera stream (via a separate thread)
61 |
62 | if not (args.video_file):
63 | import camera_stream
64 | cap = camera_stream.CameraVideoStream(use_tapi=False)
65 | else:
66 | cap = cv2.VideoCapture() # not needed for video files
67 |
68 | except BaseException:
69 | # if not then just use OpenCV default
70 |
71 | print("INFO: camera_stream class not found - camera input may be buffered")
72 | cap = cv2.VideoCapture()
73 |
74 | # define display window name
75 |
76 | window_name = "Live Camera Input" # window name
77 | window_name_hue = "Hue Channel" # window name
78 | window_name_sat = "Saturation Channel" # window name
79 | window_name_val = "Value Channel" # window name
80 |
81 | # if command line arguments are provided try to read video_file
82 | # otherwise default to capture from attached H/W camera
83 |
84 | if (((args.video_file) and (cap.open(str(args.video_file))))
85 | or (cap.open(args.camera_to_use))):
86 |
87 | # create window by name (note flags for resizable or not)
88 |
89 | cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
90 |
91 | # usage
92 |
93 | print("USAGE: press 'c' to toggle Hue channel colour mapping")
94 |
95 | while (keep_processing):
96 |
97 | # if video file or camera successfully open then read frame from video
98 |
99 | if (cap.isOpened):
100 | ret, frame = cap.read()
101 |
102 | # when we reach the end of the video (file) exit cleanly
103 |
104 | if (ret == 0):
105 | keep_processing = False
106 | continue
107 |
108 | # rescale if specified
109 |
110 | if (args.rescale != 1.0):
111 | frame = cv2.resize(
112 | frame, (0, 0), fx=args.rescale, fy=args.rescale)
113 |
114 | # start a timer (to see how long processing and display takes)
115 |
116 | start_t = cv2.getTickCount()
117 |
118 | img_hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
119 |
120 | # display images
121 |
122 | cv2.imshow(window_name, frame)
123 |
124 | # colour channels are HSV ordering in OpenCV
125 |
126 | cv2.imshow(window_name_sat, img_hsv[:, :, 1]) # saturation
127 | cv2.imshow(window_name_val, img_hsv[:, :, 2]) # value
128 |
129 | if (colour_map_hue):
130 | # re map S and V to top outer rim of HSV colour space
131 |
132 | img_hsv[:, :, 1] = np.ones(img_hsv[:, :, 1].shape) * 255
133 | img_hsv[:, :, 2] = np.ones(img_hsv[:, :, 1].shape) * 255
134 |
135 | # convert the result back to BGR to produce a false colour
136 | # version of hue for display
137 |
138 | colour_mapped_hue = cv2.cvtColor(img_hsv, cv2.COLOR_HSV2BGR)
139 | cv2.imshow(window_name_hue, colour_mapped_hue) # colour mapped hue
140 | else:
141 | cv2.imshow(window_name_hue, img_hsv[:, :, 0]) # hue
142 |
143 | # stop the timer and convert to ms. (to see how long processing and
144 | # display takes)
145 |
146 | stop_t = ((cv2.getTickCount() - start_t) /
147 | cv2.getTickFrequency()) * 1000
148 |
149 | # start the event loop - essential
150 |
151 | # cv2.waitKey() is a keyboard binding function (argument is the time in
152 | # ms). It waits for specified milliseconds for any keyboard event.
153 | # If you press any key in that time, the program continues.
154 | # If 0 is passed, it waits indefinitely for a key stroke.
155 | # (bitwise and with 0xFF to extract least significant byte of
156 | # multi-byte response)
157 |
158 | # wait 40ms or less depending on processing time taken (i.e. 1000ms /
159 | # 25 fps = 40 ms)
160 |
161 | key = cv2.waitKey(max(2, 40 - int(math.ceil(stop_t)))) & 0xFF
162 |
163 | # It can also be set to detect specific key strokes by recording which
164 | # key is pressed
165 |
166 | # e.g. if user presses "x" then exit
167 |
168 | if (key == ord('x')):
169 | keep_processing = False
170 | elif (key == ord('c')):
171 | colour_map_hue = not (colour_map_hue)
172 |
173 | # close all windows
174 |
175 | cv2.destroyAllWindows()
176 |
177 | else:
178 | print("No video file specified or camera connected.")
179 |
180 | #####################################################################
181 |
--------------------------------------------------------------------------------
/jpeg_compression_noise.py:
--------------------------------------------------------------------------------
1 | #####################################################################
2 |
3 | # Example : JPEG compression as processing on frames from a video file
4 | # specified on the command line (e.g. python FILE.py video_file) or from an
5 | # attached web camera
6 |
7 | # Author : Toby Breckon, toby.breckon@durham.ac.uk
8 |
9 | # Copyright (c) 2015 School of Engineering & Computing Science,
10 | # Copyright (c) 2019 Dept Computer Science,
11 | # Durham University, UK
12 | # License : LGPL - http://www.gnu.org/licenses/lgpl.html
13 |
14 | #####################################################################
15 |
16 | import cv2
17 | import argparse
18 | import sys
19 | import math
20 |
21 | #####################################################################
22 |
23 | keep_processing = True
24 |
25 | # parse command line arguments for camera ID or video file
26 |
27 | parser = argparse.ArgumentParser(
28 | description='Perform ' +
29 | sys.argv[0] +
30 | ' example operation on incoming camera/video image')
31 | parser.add_argument(
32 | "-c",
33 | "--camera_to_use",
34 | type=int,
35 | help="specify camera to use",
36 | default=0)
37 | parser.add_argument(
38 | "-r",
39 | "--rescale",
40 | type=float,
41 | help="rescale image by this factor",
42 | default=1.0)
43 | parser.add_argument(
44 | 'video_file',
45 | metavar='video_file',
46 | type=str,
47 | nargs='?',
48 | help='specify optional video file')
49 | args = parser.parse_args()
50 |
51 |
52 | #####################################################################
53 |
54 | # this function is called as a call-back everytime the trackbar is moved
55 | # (here we just do nothing)
56 |
57 |
58 | def nothing(x):
59 | pass
60 |
61 |
62 | #####################################################################
63 |
64 | # define video capture object
65 |
66 | try:
67 | # to use a non-buffered camera stream (via a separate thread)
68 |
69 | if not (args.video_file):
70 | import camera_stream
71 | cap = camera_stream.CameraVideoStream(use_tapi=False)
72 | else:
73 | cap = cv2.VideoCapture() # not needed for video files
74 |
75 | except BaseException:
76 | # if not then just use OpenCV default
77 |
78 | print("INFO: camera_stream class not found - camera input may be buffered")
79 | cap = cv2.VideoCapture()
80 |
81 | # define display window name
82 |
83 | window_name = "Live Camera Input" # window name
84 | window_name2 = "JPEG compression noise" # window name
85 | window_name_jpeg = "JPEG compressed version" # window name
86 |
87 | # if command line arguments are provided try to read video_file
88 | # otherwise default to capture from attached H/W camera
89 |
90 | if (((args.video_file) and (cap.open(str(args.video_file))))
91 | or (cap.open(args.camera_to_use))):
92 |
93 | # create window by name (note flags for resizable or not)
94 |
95 | cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
96 | cv2.namedWindow(window_name2, cv2.WINDOW_NORMAL)
97 | cv2.namedWindow(window_name_jpeg, cv2.WINDOW_NORMAL)
98 |
99 | jpeg_quality = 90
100 | cv2.createTrackbar("JPEG quality",
101 | window_name2, jpeg_quality, 100, nothing)
102 |
103 | amplification = 0
104 | cv2.createTrackbar(
105 | "amplification",
106 | window_name2,
107 | amplification,
108 | 255,
109 | nothing)
110 |
111 | while (keep_processing):
112 |
113 | # if video file or camera successfully open then read frame from video
114 |
115 | if (cap.isOpened):
116 | ret, frame = cap.read()
117 |
118 | # when we reach the end of the video (file) exit cleanly
119 |
120 | if (ret == 0):
121 | keep_processing = False
122 | continue
123 |
124 | # rescale if specified
125 |
126 | if (args.rescale != 1.0):
127 | frame = cv2.resize(
128 | frame, (0, 0), fx=args.rescale, fy=args.rescale)
129 |
130 | # start a timer (to see how long processing and display takes)
131 |
132 | start_t = cv2.getTickCount()
133 |
134 | # write/compress and then read back from as JPEG
135 |
136 | jpeg_quality = cv2.getTrackbarPos("JPEG quality", window_name2)
137 | encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), jpeg_quality]
138 |
139 | # either via file output / input
140 |
141 | # cv2.imwrite("camera.jpg", frame, encode_param)
142 | # jpeg_img = cv2.imread("camera.jpg")
143 |
144 | # or via encoding / decoding in a memory buffer
145 |
146 | retval, buffer = cv2.imencode(".JPG", frame, encode_param)
147 | jpeg_img = cv2.imdecode(buffer, flags=cv2.IMREAD_COLOR)
148 |
149 | # compute absolute difference between original and compressed version
150 |
151 | diff_img = cv2.absdiff(jpeg_img, frame)
152 |
153 | # retrieve the amplification setting from the track bar
154 |
155 | amplification = cv2.getTrackbarPos("amplification", window_name2)
156 |
157 | # multiple the result to increase the amplification (so we can see
158 | # small pixel changes)
159 |
160 | amplified_diff_img = diff_img * amplification
161 |
162 | # display images
163 |
164 | cv2.imshow(window_name, frame)
165 | cv2.imshow(window_name2, amplified_diff_img)
166 | cv2.imshow(window_name_jpeg, jpeg_img)
167 |
168 | # stop the timer and convert to ms. (to see how long processing and
169 | # display takes)
170 |
171 | stop_t = ((cv2.getTickCount() - start_t) /
172 | cv2.getTickFrequency()) * 1000
173 |
174 | # start the event loop - essential
175 |
176 | # cv2.waitKey() is a keyboard binding function (argument is the time in
177 | # ms). It waits for specified milliseconds for any keyboard event.
178 | # If you press any key in that time, the program continues.
179 | # If 0 is passed, it waits indefinitely for a key stroke.
180 | # (bitwise and with 0xFF to extract least significant byte of
181 | # multi-byte response)
182 |
183 | # wait 40ms or less depending on processing time taken (i.e. 1000ms /
184 | # 25 fps = 40 ms)
185 |
186 | key = cv2.waitKey(max(2, 40 - int(math.ceil(stop_t)))) & 0xFF
187 |
188 | # It can also be set to detect specific key strokes by recording which
189 | # key is pressed
190 |
191 | # e.g. if user presses "x" then exit
192 |
193 | if (key == ord('x')):
194 | keep_processing = False
195 |
196 | # close all windows
197 |
198 | cv2.destroyAllWindows()
199 |
200 | else:
201 | print("No video file specified or camera connected.")
202 |
203 | #####################################################################
204 |
--------------------------------------------------------------------------------
/logarithmic.py:
--------------------------------------------------------------------------------
1 | #####################################################################
2 |
3 | # Example : logarithmic transform on an image from an attached web camera
4 |
5 | # Author : Toby Breckon, toby.breckon@durham.ac.uk
6 |
7 | # Copyright (c) 2015 School of Engineering & Computing Science,
8 | # Copyright (c) 2019 Dept Computer Science,
9 | # Durham University, UK
10 | # License : LGPL - http://www.gnu.org/licenses/lgpl.html
11 |
12 | #####################################################################
13 |
14 | import cv2
15 | import sys
16 | import argparse
17 | import math
18 |
19 | #####################################################################
20 |
21 | keep_processing = True
22 |
23 | # parse command line arguments for camera ID or video file
24 |
25 | parser = argparse.ArgumentParser(
26 | description='Perform ' +
27 | sys.argv[0] +
28 | ' example operation on incoming camera/video image')
29 | parser.add_argument(
30 | "-c",
31 | "--camera_to_use",
32 | type=int,
33 | help="specify camera to use",
34 | default=0)
35 | parser.add_argument(
36 | "-r",
37 | "--rescale",
38 | type=float,
39 | help="rescale image by this factor",
40 | default=1.0)
41 | parser.add_argument(
42 | 'video_file',
43 | metavar='video_file',
44 | type=str,
45 | nargs='?',
46 | help='specify optional video file')
47 | args = parser.parse_args()
48 |
49 |
50 | #####################################################################
51 |
52 | # this function is called as a call-back everytime the trackbar is moved
53 | # (here we just do nothing)
54 |
55 | def nothing(x):
56 | pass
57 |
58 |
59 | #####################################################################
60 |
61 | # logarithmic transform
62 | # image - greyscale image
63 | # c - scaling constant
64 | # sigma - "gradient" co-efficient of logarithmic function
65 |
66 |
67 | def logarithmic_transform(image, c, sigma):
68 | for i in range(0, image.shape[1]): # image width
69 | for j in range(0, image.shape[0]): # image height
70 |
71 | # compute logarithmic transform
72 |
73 | image[j, i] = int(c * math.log(1 +
74 | ((math.exp(sigma) - 1) * image[j, i])))
75 |
76 | return image
77 |
78 |
79 | #####################################################################
80 |
81 | # define video capture object
82 |
83 | try:
84 | # to use a non-buffered camera stream (via a separate thread)
85 |
86 | if not (args.video_file):
87 | import camera_stream
88 | cap = camera_stream.CameraVideoStream(use_tapi=False)
89 | else:
90 | cap = cv2.VideoCapture() # not needed for video files
91 |
92 | except BaseException:
93 | # if not then just use OpenCV default
94 |
95 | print("INFO: camera_stream class not found - camera input may be buffered")
96 | cap = cv2.VideoCapture()
97 |
98 | # define display window name
99 |
100 | window_name = "Live Camera Input" # window name
101 | window_name2 = "Logarithmic Transform" # window name
102 |
103 | # if command line arguments are provided try to read video_file
104 | # otherwise default to capture from attached H/W camera
105 |
106 | if (((args.video_file) and (cap.open(str(args.video_file))))
107 | or (cap.open(args.camera_to_use))):
108 |
109 | # create window by name (as resizable)
110 |
111 | cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
112 | cv2.namedWindow(window_name2, cv2.WINDOW_NORMAL)
113 |
114 | # add some track bar controllers for settings
115 |
116 | constant = 10
117 | cv2.createTrackbar("constant, C", window_name2, constant, 100, nothing)
118 |
119 | sigma = 1
120 | cv2.createTrackbar("sigma (*0.01)", window_name2, sigma, 10, nothing)
121 |
122 | while (keep_processing):
123 |
124 | # if video file or camera successfully open then read frame from video
125 |
126 | if (cap.isOpened):
127 | ret, frame = cap.read()
128 |
129 | # when we reach the end of the video (file) exit cleanly
130 |
131 | if (ret == 0):
132 | keep_processing = False
133 | continue
134 |
135 | # rescale if specified
136 |
137 | if (args.rescale != 1.0):
138 | frame = cv2.resize(
139 | frame, (0, 0), fx=args.rescale, fy=args.rescale)
140 |
141 | # convert to grayscale
142 |
143 | gray_img = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
144 |
145 | # get parameters from track bars
146 |
147 | constant = cv2.getTrackbarPos("constant, C", window_name2)
148 | sigma = cv2.getTrackbarPos("sigma (*0.01)", window_name2) * 0.01
149 |
150 | # make a copy and log tranform it
151 |
152 | log_img = gray_img.copy()
153 | log_img = logarithmic_transform(log_img, constant, sigma)
154 |
155 | # display image
156 |
157 | cv2.imshow(window_name, gray_img)
158 | cv2.imshow(window_name2, log_img)
159 |
160 | # start the event loop - essential
161 |
162 | # cv2.waitKey() is a keyboard binding function (argument is the time in
163 | # ms). It waits for specified milliseconds for any keyboard event.
164 | # If you press any key in that time, the program continues.
165 | # If 0 is passed, it waits indefinitely for a key stroke.
166 | # (bitwise and with 0xFF to extract least significant byte of
167 | # multi-byte response)
168 |
169 | # wait 40ms (i.e. 1000ms / 25 fps = 40 ms)
170 | key = cv2.waitKey(40) & 0xFF
171 |
172 | # It can also be set to detect specific key strokes by recording which
173 | # key is pressed
174 |
175 | # e.g. if user presses "x" then exit
176 |
177 | if (key == ord('x')):
178 | keep_processing = False
179 |
180 | # close all windows
181 |
182 | cv2.destroyAllWindows()
183 |
184 | else:
185 | print("No usable camera connected.")
186 |
187 |
188 | #####################################################################
189 |
--------------------------------------------------------------------------------
/low_pass_filter.py:
--------------------------------------------------------------------------------
1 | #####################################################################
2 |
3 | # Example : perform low pass filterings in fourier space of image frame
4 | # from a video file specified on the command line (e.g. python FILE.py
5 | # video_file) or from an attached web camera
6 |
7 | # Author : Toby Breckon, toby.breckon@durham.ac.uk
8 |
9 | # Copyright (c) 2015 School of Engineering & Computing Science,
10 | # Copyright (c) 2019 Dept Computer Science,
11 | # Durham University, UK
12 | # License : LGPL - http://www.gnu.org/licenses/lgpl.html
13 |
14 | #####################################################################
15 |
16 | import cv2
17 | import argparse
18 | import sys
19 | import numpy as np
20 | import math
21 |
22 | #####################################################################
23 |
24 | # ignore divide by zero errors in np.log() operations
25 |
26 | np.seterr(divide='ignore')
27 |
28 | #####################################################################
29 |
30 | keep_processing = True
31 |
32 | # parse command line arguments for camera ID or video file
33 |
34 | parser = argparse.ArgumentParser(
35 | description='Perform ' +
36 | sys.argv[0] +
37 | ' example operation on incoming camera/video image')
38 | parser.add_argument(
39 | "-c",
40 | "--camera_to_use",
41 | type=int,
42 | help="specify camera to use",
43 | default=0)
44 | parser.add_argument(
45 | "-r",
46 | "--rescale",
47 | type=float,
48 | help="rescale image by this factor",
49 | default=1.0)
50 | parser.add_argument(
51 | 'video_file',
52 | metavar='video_file',
53 | type=str,
54 | nargs='?',
55 | help='specify optional video file')
56 | args = parser.parse_args()
57 |
58 | #####################################################################
59 |
60 | # create a simple low pass filter
61 |
62 |
63 | def create_low_pass_filter(width, height, radius):
64 | lp_filter = np.zeros((height, width, 2), np.float32)
65 | cv2.circle(lp_filter, (int(width / 2), int(height / 2)),
66 | radius, (1, 1, 1), thickness=-1)
67 | return lp_filter
68 |
69 |
70 | #####################################################################
71 |
72 | # this function is called as a call-back everytime the trackbar is moved
73 | # (here we just do nothing)
74 |
75 |
76 | def nothing(x):
77 | pass
78 |
79 |
80 | #####################################################################
81 |
82 | # define video capture object
83 |
84 | try:
85 | # to use a non-buffered camera stream (via a separate thread)
86 |
87 | if not (args.video_file):
88 | import camera_stream
89 | cap = camera_stream.CameraVideoStream(use_tapi=False)
90 | else:
91 | cap = cv2.VideoCapture() # not needed for video files
92 |
93 | except BaseException:
94 | # if not then just use OpenCV default
95 |
96 | print("INFO: camera_stream class not found - camera input may be buffered")
97 | cap = cv2.VideoCapture()
98 |
99 | # define display window name
100 |
101 | window_name = "Live Camera Input" # window name
102 | window_name2 = "Fourier Magnitude Spectrum" # window name
103 | window_name3 = "Filtered Image" # window name
104 |
105 | # if command line arguments are provided try to read video_file
106 | # otherwise default to capture from attached H/W camera
107 |
108 | if (((args.video_file) and (cap.open(str(args.video_file))))
109 | or (cap.open(args.camera_to_use))):
110 |
111 | # create windows by name (as resizable)
112 |
113 | cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
114 | cv2.namedWindow(window_name2, cv2.WINDOW_NORMAL)
115 | cv2.namedWindow(window_name3, cv2.WINDOW_NORMAL)
116 |
117 | # add some track bar controllers for settings
118 |
119 | radius = 25
120 | cv2.createTrackbar("radius", window_name2, radius, 400, nothing)
121 |
122 | # if video file or camera successfully open then read frame from video
123 |
124 | if (cap.isOpened):
125 | ret, frame = cap.read()
126 |
127 | # rescale if specified
128 |
129 | if (args.rescale != 1.0):
130 | frame = cv2.resize(frame, (0, 0), fx=args.rescale, fy=args.rescale)
131 |
132 | # convert to grayscale
133 |
134 | gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
135 |
136 | # use this single frame to set up optimized DFT settings
137 |
138 | height, width = gray_frame.shape
139 | nheight = cv2.getOptimalDFTSize(height)
140 | nwidth = cv2.getOptimalDFTSize(width)
141 |
142 | while (keep_processing):
143 |
144 | # if video file or camera successfully open then read frame from video
145 |
146 | if (cap.isOpened):
147 | ret, frame = cap.read()
148 |
149 | # when we reach the end of the video (file) exit cleanly
150 |
151 | if (ret == 0):
152 | keep_processing = False
153 | continue
154 |
155 | # rescale if specified
156 |
157 | if (args.rescale != 1.0):
158 | frame = cv2.resize(
159 | frame, (0, 0), fx=args.rescale, fy=args.rescale)
160 |
161 | # start a timer (to see how long processing and display takes)
162 |
163 | start_t = cv2.getTickCount()
164 |
165 | # convert to grayscale
166 |
167 | gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
168 |
169 | # Performance of DFT calculation, via the FFT, is better for array
170 | # sizes of power of two. Arrays whose size is a product of
171 | # 2's, 3's, and 5's are also processed quite efficiently.
172 | # Hence we modify the size of the array to the optimal size (by padding
173 | # zeros) before finding DFT.
174 |
175 | pad_right = nwidth - width
176 | pad_bottom = nheight - height
177 | nframe = cv2.copyMakeBorder(
178 | gray_frame,
179 | 0,
180 | pad_bottom,
181 | 0,
182 | pad_right,
183 | cv2.BORDER_CONSTANT,
184 | value=0)
185 |
186 | # perform the DFT and get complex output
187 |
188 | dft = cv2.dft(np.float32(nframe), flags=cv2.DFT_COMPLEX_OUTPUT)
189 |
190 | # shift it so that we the zero-frequency, F(0,0), DC component to the
191 | # center of the spectrum.
192 |
193 | dft_shifted = np.fft.fftshift(dft)
194 |
195 | # perform low pass filtering
196 |
197 | radius = cv2.getTrackbarPos("radius", window_name2)
198 | hp_filter = create_low_pass_filter(nwidth, nheight, radius)
199 |
200 | dft_filtered = cv2.mulSpectrums(dft_shifted, hp_filter, flags=0)
201 |
202 | # shift it back to original quaderant ordering
203 |
204 | dft = np.fft.fftshift(dft_filtered)
205 |
206 | # recover the original image via the inverse DFT
207 |
208 | filtered_img = cv2.dft(dft, flags=cv2.DFT_INVERSE)
209 |
210 | # normalized the filtered image into 0 -> 255 (8-bit grayscale) so we
211 | # can see the output
212 |
213 | min_val, max_val, min_loc, max_loc = \
214 | cv2.minMaxLoc(filtered_img[:, :, 0])
215 | filtered_img_normalized = filtered_img[:, :, 0] * (
216 | 1.0 / (max_val - min_val)) + ((-min_val) / (max_val - min_val))
217 | filtered_img_normalized = np.uint8(filtered_img_normalized * 255)
218 |
219 | # calculate the magnitude spectrum and log transform + scale it for
220 | # visualization
221 |
222 | magnitude_spectrum = np.log(cv2.magnitude(
223 | dft_filtered[:, :, 0], dft_filtered[:, :, 1]))
224 |
225 | # create a 8-bit image to put the magnitude spectrum into
226 |
227 | magnitude_spectrum_normalized = np.zeros(
228 | (nheight, nwidth, 1), np.uint8)
229 |
230 | # normalized the magnitude spectrum into 0 -> 255 (8-bit grayscale) so
231 | # we can see the output
232 |
233 | cv2.normalize(
234 | np.uint8(magnitude_spectrum),
235 | magnitude_spectrum_normalized,
236 | alpha=0,
237 | beta=255,
238 | norm_type=cv2.NORM_MINMAX)
239 |
240 | # display images
241 |
242 | cv2.imshow(window_name, gray_frame)
243 | cv2.imshow(window_name2, magnitude_spectrum_normalized)
244 | cv2.imshow(window_name3, filtered_img_normalized)
245 |
246 | # stop timer and convert to ms. (to see how long processing and display
247 | # takes)
248 |
249 | stop_t = ((cv2.getTickCount() - start_t) /
250 | cv2.getTickFrequency()) * 1000
251 |
252 | # start the event loop - essential
253 |
254 | # cv2.waitKey() is a keyboard binding function (argument is the time in
255 | # ms). It waits for specified milliseconds for any keyboard event.
256 | # If you press any key in that time, the program continues.
257 | # If 0 is passed, it waits indefinitely for a key stroke.
258 | # (bitwise and with 0xFF to extract least significant byte of
259 | # multi-byte response)
260 |
261 | # here we use a wait time in ms. that takes account of processing time
262 | # already used in the loop
263 |
264 | # wait 40ms (i.e. 1000ms / 25 fps = 40 ms)
265 | key = cv2.waitKey(max(2, 40 - int(math.ceil(stop_t)))) & 0xFF
266 |
267 | # It can also be set to detect specific key strokes by recording which
268 | # key is pressed
269 |
270 | # e.g. if user presses "x" then exit
271 |
272 | if (key == ord('x')):
273 | keep_processing = False
274 |
275 | # close all windows
276 |
277 | cv2.destroyAllWindows()
278 |
279 | else:
280 | print("No video file specified or camera connected.")
281 |
282 | #####################################################################
283 |
--------------------------------------------------------------------------------
/mean_filter.py:
--------------------------------------------------------------------------------
1 | #####################################################################
2 |
3 | # Example : mean filter on an image from an attached web camera
4 |
5 | # Author : Toby Breckon, toby.breckon@durham.ac.uk
6 |
7 | # Copyright (c) 2015 School of Engineering & Computing Science,
8 | # Copyright (c) 2019 Dept Computer Science,
9 | # Durham University, UK
10 | # License : LGPL - http://www.gnu.org/licenses/lgpl.html
11 |
12 | #####################################################################
13 |
14 | import cv2
15 | import sys
16 | import argparse
17 |
18 | #####################################################################
19 |
20 | keep_processing = True
21 |
22 | # parse command line arguments for camera ID or video file
23 |
24 | parser = argparse.ArgumentParser(
25 | description='Perform ' +
26 | sys.argv[0] +
27 | ' example operation on incoming camera/video image')
28 | parser.add_argument(
29 | "-c",
30 | "--camera_to_use",
31 | type=int,
32 | help="specify camera to use",
33 | default=0)
34 | parser.add_argument(
35 | "-r",
36 | "--rescale",
37 | type=float,
38 | help="rescale image by this factor",
39 | default=1.0)
40 | parser.add_argument(
41 | 'video_file',
42 | metavar='video_file',
43 | type=str,
44 | nargs='?',
45 | help='specify optional video file')
46 | args = parser.parse_args()
47 |
48 |
49 | #####################################################################
50 |
51 | # this function is called as a call-back everytime the trackbar is moved
52 | # (here we just do nothing)
53 |
54 | def nothing(x):
55 | pass
56 |
57 |
58 | #####################################################################
59 |
60 | # define video capture object
61 |
62 | try:
63 | # to use a non-buffered camera stream (via a separate thread)
64 |
65 | if not (args.video_file):
66 | import camera_stream
67 | cap = camera_stream.CameraVideoStream(use_tapi=False)
68 | else:
69 | cap = cv2.VideoCapture() # not needed for video files
70 |
71 | except BaseException:
72 | # if not then just use OpenCV default
73 |
74 | print("INFO: camera_stream class not found - camera input may be buffered")
75 | cap = cv2.VideoCapture()
76 |
77 | # define display window name
78 |
79 | window_name = "Live Camera Input" # window name
80 | window_name2 = "Mean Filtering" # window name
81 |
82 | # if command line arguments are provided try to read video_file
83 | # otherwise default to capture from attached H/W camera
84 |
85 | if (((args.video_file) and (cap.open(str(args.video_file))))
86 | or (cap.open(args.camera_to_use))):
87 |
88 | # create window by name
89 |
90 | cv2.namedWindow(window_name, cv2.WINDOW_AUTOSIZE)
91 | cv2.namedWindow(window_name2, cv2.WINDOW_AUTOSIZE)
92 |
93 | # add some track bar controllers for settings
94 |
95 | neighbourhood = 3
96 | cv2.createTrackbar(
97 | "neighbourhood, N",
98 | window_name2,
99 | neighbourhood,
100 | 25,
101 | nothing)
102 |
103 | while (keep_processing):
104 |
105 | # if video file or camera successfully open then read frame from video
106 |
107 | if (cap.isOpened):
108 | ret, frame = cap.read()
109 |
110 | # when we reach the end of the video (file) exit cleanly
111 |
112 | if (ret == 0):
113 | keep_processing = False
114 | continue
115 |
116 | # rescale if specified
117 |
118 | if (args.rescale != 1.0):
119 | frame = cv2.resize(
120 | frame, (0, 0), fx=args.rescale, fy=args.rescale)
121 |
122 | # get parameters from track bars
123 |
124 | neighbourhood = cv2.getTrackbarPos("neighbourhood, N", window_name2)
125 |
126 | neighbourhood = max(3, neighbourhood)
127 |
128 | # in opencv blur() performs filtering with a NxN kernel where each
129 | # element has a weight of 1 / (N^2) - this is mean filtering
130 |
131 | mean_img = cv2.blur(
132 | frame,
133 | (neighbourhood,
134 | neighbourhood),
135 | borderType=cv2.BORDER_DEFAULT)
136 |
137 | # display image
138 |
139 | cv2.imshow(window_name, frame)
140 | cv2.imshow(window_name2, mean_img)
141 |
142 | # start the event loop - essential
143 |
144 | # cv2.waitKey() is a keyboard binding function (argument is the time in
145 | # ms). It waits for specified milliseconds for any keyboard event.
146 | # If you press any key in that time, the program continues.
147 | # If 0 is passed, it waits indefinitely for a key stroke.
148 | # (bitwise and with 0xFF to extract least significant byte of
149 | # multi-byte response)
150 |
151 | # wait 40ms (i.e. 1000ms / 25 fps = 40 ms)
152 | key = cv2.waitKey(40) & 0xFF
153 |
154 | # It can also be set to detect specific key strokes by recording which
155 | # key is pressed
156 |
157 | # e.g. if user presses "x" then exit
158 |
159 | if (key == ord('x')):
160 | keep_processing = False
161 |
162 | # close all windows
163 |
164 | cv2.destroyAllWindows()
165 |
166 | else:
167 | print("No usable camera connected.")
168 |
169 |
170 | #####################################################################
171 |
--------------------------------------------------------------------------------
/median_filter.py:
--------------------------------------------------------------------------------
1 | #####################################################################
2 |
3 | # Example : median filter on an image from an attached web camera
4 |
5 | # Author : Toby Breckon, toby.breckon@durham.ac.uk
6 |
7 | # Copyright (c) 2015 School of Engineering & Computing Science,
8 | # Copyright (c) 2019 Dept Computer Science,
9 | # Durham University, UK
10 | # License : LGPL - http://www.gnu.org/licenses/lgpl.html
11 |
12 | #####################################################################
13 |
14 | import cv2
15 | import sys
16 | import argparse
17 |
18 | #####################################################################
19 |
20 | keep_processing = True
21 |
22 | # parse command line arguments for camera ID or video file
23 |
24 | parser = argparse.ArgumentParser(
25 | description='Perform ' +
26 | sys.argv[0] +
27 | ' example operation on incoming camera/video image')
28 | parser.add_argument(
29 | "-c",
30 | "--camera_to_use",
31 | type=int,
32 | help="specify camera to use",
33 | default=0)
34 | parser.add_argument(
35 | "-r",
36 | "--rescale",
37 | type=float,
38 | help="rescale image by this factor",
39 | default=1.0)
40 | parser.add_argument(
41 | 'video_file',
42 | metavar='video_file',
43 | type=str,
44 | nargs='?',
45 | help='specify optional video file')
46 | args = parser.parse_args()
47 |
48 |
49 | #####################################################################
50 |
51 | # this function is called as a call-back everytime the trackbar is moved
52 | # (here we just do nothing)
53 |
54 | def nothing(x):
55 | pass
56 |
57 |
58 | #####################################################################
59 |
60 | # define video capture object
61 |
62 | try:
63 | # to use a non-buffered camera stream (via a separate thread)
64 |
65 | if not (args.video_file):
66 | import camera_stream
67 | cap = camera_stream.CameraVideoStream(use_tapi=False)
68 | else:
69 | cap = cv2.VideoCapture() # not needed for video files
70 |
71 | except BaseException:
72 | # if not then just use OpenCV default
73 |
74 | print("INFO: camera_stream class not found - camera input may be buffered")
75 | cap = cv2.VideoCapture()
76 |
77 | # define display window name
78 |
79 | window_name = "Live Camera Input" # window name
80 | window_name2 = "Median Filtering" # window name
81 |
82 | # if command line arguments are provided try to read video_file
83 | # otherwise default to capture from attached H/W camera
84 |
85 | if (((args.video_file) and (cap.open(str(args.video_file))))
86 | or (cap.open(args.camera_to_use))):
87 |
88 | # create window by name
89 |
90 | cv2.namedWindow(window_name, cv2.WINDOW_AUTOSIZE)
91 | cv2.namedWindow(window_name2, cv2.WINDOW_AUTOSIZE)
92 |
93 | # add some track bar controllers for settings
94 |
95 | neighbourhood = 3
96 | cv2.createTrackbar(
97 | "neighbourhood, N",
98 | window_name2,
99 | neighbourhood,
100 | 40,
101 | nothing)
102 |
103 | while (keep_processing):
104 |
105 | # if video file or camera successfully open then read frame from video
106 |
107 | if (cap.isOpened):
108 | ret, frame = cap.read()
109 |
110 | # when we reach the end of the video (file) exit cleanly
111 |
112 | if (ret == 0):
113 | keep_processing = False
114 | continue
115 |
116 | # rescale if specified
117 |
118 | if (args.rescale != 1.0):
119 | frame = cv2.resize(
120 | frame, (0, 0), fx=args.rescale, fy=args.rescale)
121 |
122 | # get parameter from track bars
123 |
124 | neighbourhood = cv2.getTrackbarPos("neighbourhood, N", window_name2)
125 |
126 | # check it is greater than 3 and odd
127 |
128 | neighbourhood = max(3, neighbourhood)
129 | if not (neighbourhood % 2):
130 | neighbourhood = neighbourhood + 1
131 |
132 | # perform median filtering using NxN neighbourhood
133 |
134 | median_img = cv2.medianBlur(frame, neighbourhood)
135 |
136 | # display image
137 |
138 | cv2.imshow(window_name, frame)
139 | cv2.imshow(window_name2, median_img)
140 |
141 | # start the event loop - essential
142 |
143 | # cv2.waitKey() is a keyboard binding function (argument is the time in
144 | # ms). It waits for specified milliseconds for any keyboard event.
145 | # If you press any key in that time, the program continues.
146 | # If 0 is passed, it waits indefinitely for a key stroke.
147 | # (bitwise and with 0xFF to extract least significant byte of
148 | # multi-byte response)
149 |
150 | # wait 40ms (i.e. 1000ms / 25 fps = 40 ms)
151 | key = cv2.waitKey(40) & 0xFF
152 |
153 | # It can also be set to detect specific key strokes by recording which
154 | # key is pressed
155 |
156 | # e.g. if user presses "x" then exit
157 |
158 | if (key == ord('x')):
159 | keep_processing = False
160 |
161 | # close all windows
162 |
163 | cv2.destroyAllWindows()
164 |
165 | else:
166 | print("No usable camera connected.")
167 |
168 |
169 | #####################################################################
170 |
--------------------------------------------------------------------------------
/nlm_filter.py:
--------------------------------------------------------------------------------
1 | #####################################################################
2 |
3 | # Example : mean and non-local means filter on an image from an attached
4 | # web camera
5 |
6 | # Author : Toby Breckon, toby.breckon@durham.ac.uk
7 |
8 | # Copyright (c) 2015 School of Engineering & Computing Science,
9 | # Copyright (c) 2019 Dept Computer Science,
10 | # Durham University, UK
11 | # License : LGPL - http://www.gnu.org/licenses/lgpl.html
12 |
13 | #####################################################################
14 |
15 | import cv2
16 | import sys
17 | import argparse
18 |
19 | #####################################################################
20 |
21 | keep_processing = True
22 |
23 | # parse command line arguments for camera ID or video file
24 |
25 | parser = argparse.ArgumentParser(
26 | description='Perform ' +
27 | sys.argv[0] +
28 | ' example operation on incoming camera/video image')
29 | parser.add_argument(
30 | "-c",
31 | "--camera_to_use",
32 | type=int,
33 | help="specify camera to use",
34 | default=0)
35 | parser.add_argument(
36 | "-r",
37 | "--rescale",
38 | type=float,
39 | help="rescale image by this factor",
40 | default=1.0)
41 | parser.add_argument(
42 | 'video_file',
43 | metavar='video_file',
44 | type=str,
45 | nargs='?',
46 | help='specify optional video file')
47 | args = parser.parse_args()
48 |
49 |
50 | #####################################################################
51 |
52 | # this function is called as a call-back everytime the trackbar is moved
53 | # (here we just do nothing)
54 |
55 | def nothing(x):
56 | pass
57 |
58 |
59 | #####################################################################
60 |
61 | # define video capture object
62 |
63 | try:
64 | # to use a non-buffered camera stream (via a separate thread)
65 |
66 | if not (args.video_file):
67 | import camera_stream
68 | cap = camera_stream.CameraVideoStream(use_tapi=False)
69 | else:
70 | cap = cv2.VideoCapture() # not needed for video files
71 |
72 | except BaseException:
73 | # if not then just use OpenCV default
74 |
75 | print("INFO: camera_stream class not found - camera input may be buffered")
76 | cap = cv2.VideoCapture()
77 |
78 | # define display window name
79 |
80 | window_name = "Live Camera Input" # window name
81 | window_name2 = "Mean Filtering" # window name
82 | window_name3 = "Non-Local Means Filtering" # window name
83 |
84 | # if command line arguments are provided try to read video_file
85 | # otherwise default to capture from attached H/W camera
86 |
87 | if (((args.video_file) and (cap.open(str(args.video_file))))
88 | or (cap.open(args.camera_to_use))):
89 |
90 | # create window by name
91 |
92 | cv2.namedWindow(window_name, cv2.WINDOW_AUTOSIZE)
93 | cv2.namedWindow(window_name2, cv2.WINDOW_AUTOSIZE)
94 | cv2.namedWindow(window_name3, cv2.WINDOW_AUTOSIZE)
95 |
96 | # add some track bar controllers for settings
97 |
98 | neighbourhood = 7
99 | cv2.createTrackbar(
100 | "neighbourhood, N",
101 | window_name2,
102 | neighbourhood,
103 | 25,
104 | nothing)
105 | search_window = 21
106 | cv2.createTrackbar("search area, W", window_name3,
107 | search_window, 50, nothing)
108 | filter_strength = 10
109 | cv2.createTrackbar(
110 | "strength, h",
111 | window_name3,
112 | filter_strength,
113 | 25,
114 | nothing)
115 |
116 | while (keep_processing):
117 |
118 | # if video file or camera successfully open then read frame from video
119 |
120 | if (cap.isOpened):
121 | ret, frame = cap.read()
122 |
123 | # when we reach the end of the video (file) exit cleanly
124 |
125 | if (ret == 0):
126 | keep_processing = False
127 | continue
128 |
129 | # rescale if specified
130 |
131 | if (args.rescale != 1.0):
132 | frame = cv2.resize(
133 | frame, (0, 0), fx=args.rescale, fy=args.rescale)
134 |
135 | # get parameters from track bars
136 |
137 | neighbourhood = cv2.getTrackbarPos("neighbourhood, N", window_name2)
138 | search_window = cv2.getTrackbarPos("search area, W", window_name3)
139 | filter_strength = cv2.getTrackbarPos("strength, h", window_name3)
140 |
141 | # check neighbourhood is greater than 3 and odd
142 |
143 | neighbourhood = max(3, neighbourhood)
144 | if not (neighbourhood % 2):
145 | neighbourhood = neighbourhood + 1
146 |
147 | # in opencv blur() performs filtering with a NxN kernel where each
148 | # element has a weight of 1 / (N^2) - this is mean filtering
149 |
150 | mean_img = cv2.blur(
151 | frame,
152 | (neighbourhood,
153 | neighbourhood),
154 | borderType=cv2.BORDER_DEFAULT)
155 |
156 | # perform NLM filtering on the same image
157 |
158 | nlm_img = cv2.fastNlMeansDenoisingColored(
159 | frame,
160 | h=filter_strength,
161 | hColor=10,
162 | templateWindowSize=neighbourhood,
163 | searchWindowSize=search_window)
164 |
165 | # display image
166 |
167 | cv2.imshow(window_name, frame)
168 | cv2.imshow(window_name2, mean_img)
169 | cv2.imshow(window_name3, nlm_img)
170 |
171 | # start the event loop - essential
172 |
173 | # cv2.waitKey() is a keyboard binding function (argument is the time in
174 | # ms). It waits for specified milliseconds for any keyboard event.
175 | # If you press any key in that time, the program continues.
176 | # If 0 is passed, it waits indefinitely for a key stroke.
177 | # (bitwise and with 0xFF to extract least significant byte of
178 | # multi-byte response)
179 |
180 | # wait 40ms (i.e. 1000ms / 25 fps = 40 ms)
181 | key = cv2.waitKey(40) & 0xFF
182 |
183 | # It can also be set to detect specific key strokes by recording which
184 | # key is pressed
185 |
186 | # e.g. if user presses "x" then exit
187 |
188 | if (key == ord('x')):
189 | keep_processing = False
190 |
191 | # close all windows
192 |
193 | cv2.destroyAllWindows()
194 |
195 | else:
196 | print("No usable camera connected.")
197 |
198 |
199 | #####################################################################
200 |
--------------------------------------------------------------------------------
/rgb_viewer.py:
--------------------------------------------------------------------------------
1 | #####################################################################
2 |
3 | # Example : display individual RGB channels from an video file
4 | # specified on the command line (e.g. python FILE.py video_file) or from an
5 | # attached web camera
6 |
7 | # Author : Toby Breckon, toby.breckon@durham.ac.uk
8 |
9 | # Copyright (c) 2015 School of Engineering & Computing Science,
10 | # Copyright (c) 2019 Dept Computer Science,
11 | # Durham University, UK
12 | # License : LGPL - http://www.gnu.org/licenses/lgpl.html
13 |
14 | #####################################################################
15 |
16 | import cv2
17 | import argparse
18 | import sys
19 | import math
20 |
21 | #####################################################################
22 |
23 | keep_processing = True
24 |
25 | # parse command line arguments for camera ID or video file
26 |
27 | parser = argparse.ArgumentParser(
28 | description='Perform ' +
29 | sys.argv[0] +
30 | ' example operation on incoming camera/video image')
31 | parser.add_argument(
32 | "-c",
33 | "--camera_to_use",
34 | type=int,
35 | help="specify camera to use",
36 | default=0)
37 | parser.add_argument(
38 | "-r",
39 | "--rescale",
40 | type=float,
41 | help="rescale image by this factor",
42 | default=1.0)
43 | parser.add_argument(
44 | 'video_file',
45 | metavar='video_file',
46 | type=str,
47 | nargs='?',
48 | help='specify optional video file')
49 | args = parser.parse_args()
50 |
51 | #####################################################################
52 |
53 | # define video capture object
54 |
55 | try:
56 | # to use a non-buffered camera stream (via a separate thread)
57 |
58 | if not (args.video_file):
59 | import camera_stream
60 | cap = camera_stream.CameraVideoStream(use_tapi=False)
61 | else:
62 | cap = cv2.VideoCapture() # not needed for video files
63 |
64 | except BaseException:
65 | # if not then just use OpenCV default
66 |
67 | print("INFO: camera_stream class not found - camera input may be buffered")
68 | cap = cv2.VideoCapture()
69 |
70 | # define display window name
71 |
72 | window_name = "Live Camera Input" # window name
73 | window_name_red = "Red Colour Channel" # window name
74 | window_name_green = "Green Colour Channel" # window name
75 | window_name_blue = "Blue Colour Channel" # window name
76 |
77 | # if command line arguments are provided try to read video_file
78 | # otherwise default to capture from attached H/W camera
79 |
80 | if (((args.video_file) and (cap.open(str(args.video_file))))
81 | or (cap.open(args.camera_to_use))):
82 |
83 | # create window by name (note flags for resizable or not)
84 |
85 | cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
86 |
87 | while (keep_processing):
88 |
89 | # if video file or camera successfully open then read frame from video
90 |
91 | if (cap.isOpened):
92 | ret, frame = cap.read()
93 |
94 | # when we reach the end of the video (file) exit cleanly
95 |
96 | if (ret == 0):
97 | keep_processing = False
98 | continue
99 |
100 | # rescale if specified
101 |
102 | if (args.rescale != 1.0):
103 | frame = cv2.resize(
104 | frame, (0, 0), fx=args.rescale, fy=args.rescale)
105 |
106 | # start a timer (to see how long processing and display takes)
107 |
108 | start_t = cv2.getTickCount()
109 |
110 | # display images
111 |
112 | cv2.imshow(window_name, frame)
113 |
114 | # remember colour channels are BGR ordering in OpenCV
115 |
116 | cv2.imshow(window_name_red, frame[:, :, 2]) # red
117 | cv2.imshow(window_name_green, frame[:, :, 1]) # green
118 | cv2.imshow(window_name_blue, frame[:, :, 0]) # green
119 |
120 | # stop the timer and convert to ms. (to see how long processing and
121 | # display takes)
122 |
123 | stop_t = ((cv2.getTickCount() - start_t) /
124 | cv2.getTickFrequency()) * 1000
125 |
126 | # start the event loop - essential
127 |
128 | # cv2.waitKey() is a keyboard binding function (argument is the time in
129 | # ms). It waits for specified milliseconds for any keyboard event.
130 | # If you press any key in that time, the program continues.
131 | # If 0 is passed, it waits indefinitely for a key stroke.
132 | # (bitwise and with 0xFF to extract least significant byte of
133 | # multi-byte response)
134 |
135 | # wait 40ms or less depending on processing time taken (i.e. 1000ms /
136 | # 25 fps = 40 ms)
137 |
138 | key = cv2.waitKey(max(2, 40 - int(math.ceil(stop_t)))) & 0xFF
139 |
140 | # It can also be set to detect specific key strokes by recording which
141 | # key is pressed
142 |
143 | # e.g. if user presses "x" then exit
144 |
145 | if (key == ord('x')):
146 | keep_processing = False
147 |
148 | # close all windows
149 |
150 | cv2.destroyAllWindows()
151 |
152 | else:
153 | print("No video file specified or camera connected.")
154 |
155 | #####################################################################
156 |
--------------------------------------------------------------------------------
/save_image.py:
--------------------------------------------------------------------------------
1 | #####################################################################
2 |
3 | # Example : save an image from file (and invert it)
4 |
5 | # Author : Toby Breckon, toby.breckon@durham.ac.uk
6 |
7 | # Copyright (c) 2015 School of Engineering & Computing Science,
8 | # Durham University, UK
9 | # License : LGPL - http://www.gnu.org/licenses/lgpl.html
10 |
11 | #####################################################################
12 |
13 | import cv2
14 |
15 | #####################################################################
16 |
17 | # read an image from the specified file (in colour)
18 |
19 | img = cv2.imread('example.jpg', cv2.IMREAD_COLOR)
20 |
21 | # check it has loaded
22 |
23 | if img is not None:
24 |
25 | # performing logical inversion (see manual entry for bitwise_not ()
26 |
27 | inverted = cv2.bitwise_not(img)
28 |
29 | # write inverted image to file
30 |
31 | cv2.imwrite("inverted.jpg", inverted)
32 |
33 | else:
34 | print("No image file successfully loaded.")
35 |
36 | #####################################################################
37 |
--------------------------------------------------------------------------------
/save_video.py:
--------------------------------------------------------------------------------
1 | #####################################################################
2 |
3 | # Example : generic example for video processing from a video file
4 | # specified as video.avi or from an
5 | # attached web camera and saving to a video file
6 |
7 | # Author : Toby Breckon, toby.breckon@durham.ac.uk
8 |
9 | # Copyright (c) 2015 School of Engineering & Computing Science,
10 | # Copyright (c) 2019 Dept Computer Science,
11 | # Durham University, UK
12 | # License : LGPL - http://www.gnu.org/licenses/lgpl.html
13 |
14 | #####################################################################
15 |
16 | import cv2
17 | import argparse
18 | import sys
19 |
20 | #####################################################################
21 |
22 | keep_processing = True
23 |
24 | # parse command line arguments for camera ID or video file
25 |
26 | parser = argparse.ArgumentParser(
27 | description='Perform ' +
28 | sys.argv[0] +
29 | ' example operation on incoming camera/video image')
30 | parser.add_argument(
31 | "-c",
32 | "--camera_to_use",
33 | type=int,
34 | help="specify camera to use",
35 | default=0)
36 | parser.add_argument(
37 | "-r",
38 | "--rescale",
39 | type=float,
40 | help="rescale image by this factor",
41 | default=1.0)
42 | args = parser.parse_args()
43 |
44 | video_width = 640
45 | video_height = 480
46 |
47 | #####################################################################
48 |
49 | # define video capture object
50 |
51 | try:
52 | # to use a non-buffered camera stream (via a separate thread)
53 |
54 | import camera_stream
55 | cap = camera_stream.CameraVideoStream(use_tapi=False)
56 |
57 | except BaseException:
58 | # if not then just use OpenCV default
59 |
60 | print("INFO: camera_stream class not found - camera input may be buffered")
61 | cap = cv2.VideoCapture()
62 |
63 | # define display window name
64 |
65 | window_name = "Live Camera Input -> Video File" # window name
66 |
67 | # define video writer (video: 640 x 480 @ 25 fps)
68 |
69 | fourcc = cv2.VideoWriter_fourcc('M', 'J', 'P', 'G')
70 | output = cv2.VideoWriter('output.avi', fourcc, 25.0,
71 | (video_width, video_height))
72 |
73 | # if command line arguments are provided try to read video_file
74 | # otherwise default to capture from attached H/W camera
75 |
76 | if ((cap.open("input.avi")) or (cap.open(args.camera_to_use))):
77 |
78 | # create window by name (as resizable)
79 |
80 | cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
81 |
82 | while (keep_processing):
83 |
84 | # if video file or camera successfully open then read frame from video
85 |
86 | if (cap.isOpened):
87 | ret, frame = cap.read()
88 |
89 | # when we reach the end of the video (file) exit cleanly
90 |
91 | if (ret == 0):
92 | keep_processing = False
93 | continue
94 |
95 | # rescale if specified
96 |
97 | if (args.rescale != 1.0):
98 | frame = cv2.resize(
99 | frame, (0, 0), fx=args.rescale, fy=args.rescale)
100 |
101 | # *** do any processing here ****
102 |
103 | # write the frame to file (first resizing)
104 |
105 | frame2 = cv2.resize(
106 | frame,
107 | (video_width,
108 | video_height),
109 | interpolation=cv2.INTER_CUBIC)
110 | output.write(frame2)
111 |
112 | # display image
113 |
114 | cv2.imshow(window_name, frame)
115 |
116 | # start the event loop - essential
117 |
118 | # cv2.waitKey() is a keyboard binding function (argument is the time in
119 | # ms). It waits for specified milliseconds for any keyboard event.
120 | # If you press any key in that time, the program continues.
121 | # If 0 is passed, it waits indefinitely for a key stroke.
122 | # (bitwise and with 0xFF to extract least significant byte of
123 | # multi-byte response)
124 |
125 | key = cv2.waitKey(1) & 0xFF # wait 1ms only
126 |
127 | # e.g. if user presses "x" then exit
128 |
129 | if (key == ord('x')):
130 | keep_processing = False
131 |
132 | # close all windows
133 |
134 | cv2.destroyAllWindows()
135 |
136 | # Release everything if job is finished
137 | cap.release()
138 | output.release()
139 |
140 | else:
141 | print("No video file specified or camera connected.")
142 |
143 | #####################################################################
144 |
--------------------------------------------------------------------------------
/skeleton.py:
--------------------------------------------------------------------------------
1 | #####################################################################
2 |
3 | # Example : <................................> processing from a video file
4 | # specified on the command line (e.g. python FILE.py video_file) or from an
5 | # attached web camera
6 |
7 | # Author : , @durham.ac.uk
8 |
9 | # Copyright (c) 20xx
10 | # Durham University, UK
11 | # License : LGPL - http://www.gnu.org/licenses/lgpl.html
12 |
13 | #####################################################################
14 |
15 | import cv2
16 | import argparse
17 | import sys
18 | import math
19 |
20 | #####################################################################
21 |
22 | keep_processing = True
23 |
24 | # parse command line arguments for camera ID or video file
25 |
26 | parser = argparse.ArgumentParser(
27 | description='Perform ' +
28 | sys.argv[0] +
29 | ' example operation on incoming camera/video image')
30 | parser.add_argument(
31 | "-c",
32 | "--camera_to_use",
33 | type=int,
34 | help="specify camera to use",
35 | default=0)
36 | parser.add_argument(
37 | "-r",
38 | "--rescale",
39 | type=float,
40 | help="rescale image by this factor",
41 | default=1.0)
42 | parser.add_argument(
43 | 'video_file',
44 | metavar='video_file',
45 | type=str,
46 | nargs='?',
47 | help='specify optional video file')
48 | args = parser.parse_args()
49 |
50 | #####################################################################
51 |
52 | # define video capture object
53 |
54 | try:
55 | # to use a non-buffered camera stream (via a separate thread)
56 |
57 | if not (args.video_file):
58 | import camera_stream
59 | cap = camera_stream.CameraVideoStream(use_tapi=False)
60 | else:
61 | cap = cv2.VideoCapture() # not needed for video files
62 |
63 | except BaseException:
64 | # if not then just use OpenCV default
65 |
66 | print("INFO: camera_stream class not found - camera input may be buffered")
67 | cap = cv2.VideoCapture()
68 |
69 | # define display window name
70 |
71 | window_name = "Live Camera Input" # window name
72 |
73 | # if command line arguments are provided try to read video_file
74 | # otherwise default to capture from attached H/W camera
75 |
76 | if (((args.video_file) and (cap.open(str(args.video_file))))
77 | or (cap.open(args.camera_to_use))):
78 |
79 | # create window by name (note flags for resizable or not)
80 |
81 | cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
82 |
83 | while (keep_processing):
84 |
85 | # if video file or camera successfully open then read frame from video
86 |
87 | if (cap.isOpened):
88 | ret, frame = cap.read()
89 |
90 | # when we reach the end of the video (file) exit cleanly
91 |
92 | if (ret == 0):
93 | keep_processing = False
94 | continue
95 |
96 | # rescale if specified
97 |
98 | if (args.rescale != 1.0):
99 | frame = cv2.resize(
100 | frame, (0, 0), fx=args.rescale, fy=args.rescale)
101 |
102 | # start a timer (to see how long processing and display takes)
103 |
104 | start_t = cv2.getTickCount()
105 |
106 | # *******************************
107 |
108 | # *** do any processing here ****
109 |
110 | # *******************************
111 |
112 | # display image
113 |
114 | cv2.imshow(window_name, frame)
115 |
116 | # stop the timer and convert to ms. (to see how long processing and
117 | # display takes)
118 |
119 | stop_t = ((cv2.getTickCount() - start_t) /
120 | cv2.getTickFrequency()) * 1000
121 |
122 | # start the event loop - essential
123 |
124 | # cv2.waitKey() is a keyboard binding function (argument is the time in
125 | # ms). It waits for specified milliseconds for any keyboard event.
126 | # If you press any key in that time, the program continues.
127 | # If 0 is passed, it waits indefinitely for a key stroke.
128 | # (bitwise and with 0xFF to extract least significant byte of
129 | # multi-byte response)
130 |
131 | # wait 40ms or less depending on processing time taken (i.e. 1000ms /
132 | # 25 fps = 40 ms)
133 |
134 | key = cv2.waitKey(max(2, 40 - int(math.ceil(stop_t)))) & 0xFF
135 |
136 | # It can also be set to detect specific key strokes by recording which
137 | # key is pressed
138 |
139 | # e.g. if user presses "x" then exit
140 |
141 | if (key == ord('x')):
142 | keep_processing = False
143 |
144 | # close all windows
145 |
146 | cv2.destroyAllWindows()
147 |
148 | else:
149 | print("No video file specified or camera connected.")
150 |
151 | #####################################################################
152 |
--------------------------------------------------------------------------------
/smooth_image.py:
--------------------------------------------------------------------------------
1 | #####################################################################
2 |
3 | # Example : displaying an image from file (and smoothing it)
4 |
5 | # Author : Toby Breckon, toby.breckon@durham.ac.uk
6 |
7 | # Copyright (c) 2015 School of Engineering & Computing Science,
8 | # Durham University, UK
9 | # License : LGPL - http://www.gnu.org/licenses/lgpl.html
10 |
11 | #####################################################################
12 |
13 | import cv2
14 |
15 | #####################################################################
16 |
17 | # define display window name
18 |
19 | window_name = "Smoothed Image" # window name
20 |
21 | # read an image from the specified file (in colour)
22 |
23 | img = cv2.imread('example.jpg', cv2.IMREAD_COLOR)
24 |
25 | # check it has loaded
26 |
27 | if img is not None:
28 |
29 | # performing smoothing on the image using a 5x5 smoothing mark (see manual
30 | # entry for GaussianBlur())
31 |
32 | blur = cv2.GaussianBlur(img, (5, 5), 0)
33 |
34 | # display this blurred image in a named window
35 |
36 | cv2.imshow(window_name, blur)
37 |
38 | # start the event loop - essential
39 |
40 | # cv2.waitKey() is a keyboard binding function (argument is the time in
41 | # ms). It waits for specified milliseconds for any keyboard event.
42 | # If you press any key in that time, the program continues.
43 | # If 0 is passed, it waits indefinitely for a key stroke.
44 | # (bitwise and with 0xFF to extract least significant byte of
45 | # multi-byte response)
46 |
47 | key = cv2.waitKey(0) & 0xFF # wait
48 |
49 | # It can also be set to detect specific key strokes by recording which key
50 | # is pressed
51 |
52 | # e.g. if user presses "x" then exit and close all windows
53 |
54 | if (key == ord('x')):
55 | cv2.destroyAllWindows()
56 | else:
57 | print("No image file successfully loaded.")
58 |
59 | #####################################################################
60 |
--------------------------------------------------------------------------------
/test_all.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | ################################################################################
4 |
5 | # run a batch test over all the examples from the bash shell (linux)
6 |
7 | # Copyright (c) 2019 Dept Computer Science,
8 | # Durham University, UK
9 | # License : LGPL - http://www.gnu.org/licenses/lgpl.html
10 |
11 | ################################################################################
12 |
13 | PYTHON_INTERPRETATOR=python3
14 | CAM_TO_TEST=0
15 | VIDEO_TO_TEST=video.avi
16 |
17 | echo
18 | echo Using $PYTHON_INTERPRETATOR with camera $CAM_TO_TEST and video $VIDEO_TO_TEST
19 | echo "Running test suite - press 'x' in OpenCV window to exit each example."
20 | echo
21 |
22 | # get testing resouces if they do not exist
23 |
24 | [ -f example.jpg ] || { wget https://upload.wikimedia.org/wikipedia/commons/b/b4/JPEG_example_JPG_RIP_100.jpg; mv JPEG_example_JPG_RIP_100.jpg example.jpg; }
25 | [ -f video.avi ] || { wget http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4; mv big_buck_bunny.mp4 video.avi; }
26 |
27 | ################################################################################
28 |
29 | # run defaults
30 |
31 | echo "Running default tests ..."
32 | echo
33 |
34 | for example in *.py
35 | do
36 | echo "Testing example: " $example
37 | $PYTHON_INTERPRETATOR $example
38 | echo
39 | done
40 |
41 | ################################################################################
42 |
43 | # run cam test
44 |
45 | echo "Running camera based tests ..."
46 | echo
47 |
48 | for example in *.py
49 | do
50 | echo "Testing example: " $example -c $CAM_TO_TEST
51 | $PYTHON_INTERPRETATOR $example -c $CAM_TO_TEST
52 | echo
53 | done
54 |
55 | ################################################################################
56 |
57 | # run cam test and resize
58 |
59 | echo "Running camera based tests with resizing ..."
60 | echo
61 |
62 | for example in *.py
63 | do
64 | echo "Testing example: " $example -c $CAM_TO_TEST -r 0.25
65 | $PYTHON_INTERPRETATOR $example -c $CAM_TO_TEST -r 0.25
66 | echo
67 | done
68 |
69 |
70 | ################################################################################
71 |
72 | # run video file test
73 |
74 | echo "Running video file based tests ..."
75 | echo
76 |
77 | for example in *.py
78 | do
79 | echo "Testing example: " $example $VIDEO_TO_TEST
80 | $PYTHON_INTERPRETATOR $example $VIDEO_TO_TEST
81 | echo
82 | done
83 |
84 | ################################################################################
85 |
--------------------------------------------------------------------------------
/version.py:
--------------------------------------------------------------------------------
1 | #####################################################################
2 |
3 | # Example : test if opencv environment is working
4 |
5 | # Author : Toby Breckon, toby.breckon@durham.ac.uk
6 |
7 | # Copyright (c) 2017-2022 Toby Breckon, Durham University, UK
8 | # License : LGPL - http://www.gnu.org/licenses/lgpl.html
9 |
10 | #####################################################################
11 |
12 | import cv2
13 | import numpy as np
14 | import sys
15 | import re
16 | import struct
17 | import matplotlib
18 |
19 | #####################################################################
20 |
21 | # check if the OpenCV we are using has the extra modules available
22 |
23 |
24 | def extra_opencv_modules_present():
25 | (is_built, not_built) = cv2.getBuildInformation().split("Disabled:")
26 | return ('xfeatures2d' in is_built)
27 |
28 |
29 | def non_free_opencv_algorithms_present():
30 | (before, after) = cv2.getBuildInformation().split("Non-free algorithms:")
31 | output_list = after.split("\n")
32 | return ('YES' in output_list[0])
33 |
34 |
35 | #####################################################################
36 |
37 | print()
38 | print("We are using OpenCV: " + cv2.__version__)
39 | print(".. do we have the OpenCV Contrib Modules: " +
40 | str(extra_opencv_modules_present()))
41 | try:
42 | print(".. do we have the OpenCV Non-free algorithms: " +
43 | str(non_free_opencv_algorithms_present()))
44 | except BaseException:
45 | print(".. OpenCV version pre-dates (or does not have) " +
46 | "non-free algorithms module")
47 | try:
48 | print(".. do we have the Intel Performance Primitives (IPP): \n" +
49 | ".. version: " + str(cv2.ipp.getIppVersion()) + " (in use: "
50 | + str(cv2.ipp.useIPP()) + " )")
51 | except BaseException:
52 | print(".. OpenCV version does not have " +
53 | "Intel Performance Primitives (IPP)")
54 | print("We are using numpy: " + np.__version__)
55 | print("We are using matplotlib: " + matplotlib.__version__)
56 | print(".. and this is in Python: " + sys.version +
57 | " (" + str(struct.calcsize("P") * 8) + " bit)")
58 |
59 | #####################################################################
60 |
61 | print()
62 | print("Check Video I/O (OS identifier: " + sys.platform + ")")
63 | print("... available camera backends: ", end='')
64 | for backend in cv2.videoio_registry.getCameraBackends():
65 | print(" " + cv2.videoio_registry.getBackendName(backend), end='')
66 | print()
67 | print("... available stream backends: ", end='')
68 | for backend in cv2.videoio_registry.getStreamBackends():
69 | print(" " + cv2.videoio_registry.getBackendName(backend), end='')
70 | print()
71 | print("... available video writer backends: ", end='')
72 | for backend in cv2.videoio_registry.getWriterBackends():
73 | print(" " + cv2.videoio_registry.getBackendName(backend), end='')
74 | print()
75 | print()
76 |
77 | #####################################################################
78 |
79 | # credit to: https://tinyurl.com/y529vzc3
80 |
81 | print("Available Cuda Information: ")
82 | cuda_info = [re.sub('\\s+', ' ', ci.strip()) for ci in
83 | cv2.getBuildInformation().strip().split('\n')
84 | if len(ci) > 0 and re.search(r'(nvidia*:?)|(cuda*:)|(cudnn*:)',
85 | ci.lower()) is not None]
86 | print("... " + str(cuda_info))
87 | print()
88 |
89 | #####################################################################
90 |
91 | try:
92 | for gpu in range(cv2.cuda.getCudaEnabledDeviceCount()):
93 | print("CUDA enabled GPU device index: " + str(gpu) + " ")
94 | cv2.cuda.printShortCudaDeviceInfo(gpu)
95 | print()
96 | except BaseException:
97 | print("No CUDA enabled devices found : " +
98 | "[none present or in powered down state]")
99 |
100 | #####################################################################
101 |
102 | print("DNN module CUDA backend/target availability : ", end='')
103 | try:
104 | targets = cv2.dnn.getAvailableTargets(cv2.dnn.DNN_BACKEND_CUDA)
105 | print()
106 | print("... DNN_TARGET_CUDA: \t\t", end='')
107 | print(cv2.dnn.DNN_TARGET_CUDA in targets)
108 | print("... DNN_TARGET_CUDA_FP16: \t", end='')
109 | print(cv2.dnn.DNN_TARGET_CUDA_FP16 in targets)
110 | targets = cv2.dnn.getAvailableTargets(cv2.dnn.DNN_BACKEND_DEFAULT)
111 | print("... DNN_TARGET_CPU: \t\t", end='')
112 | print(cv2.dnn.DNN_TARGET_CPU in targets)
113 | print("... DNN_TARGET_OPENCL: \t\t", end='')
114 | print(cv2.dnn.DNN_TARGET_OPENCL in targets)
115 | print("... DNN_TARGET_OPENCL_FP16: \t", end='')
116 | print(cv2.dnn.DNN_TARGET_OPENCL_FP16 in targets)
117 | except BaseException:
118 | print("False")
119 |
120 | #####################################################################
121 |
122 | print()
123 | print("OpenCL available (within OpenCV) ? : " + str(cv2.ocl.haveOpenCL()))
124 | print()
125 |
126 | #####################################################################
127 |
128 | print("Available CPU Optimizations (*: build enabled; ?: not CPU supported):")
129 | try:
130 | print("... " + cv2.getCPUFeaturesLine())
131 | print()
132 | except BaseException:
133 | print("... [ CPU feature check not available in this version ]")
134 | print()
135 |
136 | #####################################################################
137 |
--------------------------------------------------------------------------------
/ycrcb_viewer.py:
--------------------------------------------------------------------------------
1 | #####################################################################
2 |
3 | # Example : display individual YCrCb channels from an video file
4 | # specified on the command line (e.g. python FILE.py video_file) or from an
5 | # attached web camera (with optional chroma subsampling as used in JPEG
6 | # image compression)
7 |
8 | # Author : Toby Breckon, toby.breckon@durham.ac.uk
9 |
10 | # Copyright (c) 2020 Dept Computer Science, Durham University, UK
11 | # License : LGPL - http://www.gnu.org/licenses/lgpl.html
12 |
13 | #####################################################################
14 |
15 | import cv2
16 | import argparse
17 | import sys
18 | import math
19 |
20 | #####################################################################
21 |
22 | keep_processing = True
23 |
24 | # parse command line arguments for camera ID or video file
25 |
26 | parser = argparse.ArgumentParser(
27 | description='Perform ' +
28 | sys.argv[0] +
29 | ' example operation on incoming camera/video image')
30 | parser.add_argument(
31 | "-c",
32 | "--camera_to_use",
33 | type=int,
34 | help="specify camera to use",
35 | default=0)
36 | parser.add_argument(
37 | "-r",
38 | "--rescale",
39 | type=float,
40 | help="rescale image by this factor",
41 | default=1.0)
42 | parser.add_argument(
43 | 'video_file',
44 | metavar='video_file',
45 | type=str,
46 | nargs='?',
47 | help='specify optional video file')
48 | args = parser.parse_args()
49 |
50 |
51 | perform_chroma_subsampling = False
52 |
53 | #####################################################################
54 |
55 | # define video capture object
56 |
57 | try:
58 | # to use a non-buffered camera stream (via a separate thread)
59 |
60 | if not (args.video_file):
61 | import camera_stream
62 | cap = camera_stream.CameraVideoStream(use_tapi=False)
63 | else:
64 | cap = cv2.VideoCapture() # not needed for video files
65 |
66 | except BaseException:
67 | # if not then just use OpenCV default
68 |
69 | print("INFO: camera_stream class not found - camera input may be buffered")
70 | cap = cv2.VideoCapture()
71 |
72 | # define display window name
73 |
74 | window_name = "Live Camera Input" # window name
75 | window_name_y = "Y Channel" # window name
76 | window_name_cr = "Cr Channel" # window name
77 | window_name_cb = "Cb Channel" # window name
78 |
79 | # if command line arguments are provided try to read video_file
80 | # otherwise default to capture from attached H/W camera
81 |
82 | if (((args.video_file) and (cap.open(str(args.video_file))))
83 | or (cap.open(args.camera_to_use))):
84 |
85 | # create window by name (note flags for resizable or not)
86 |
87 | cv2.namedWindow(window_name, cv2.WINDOW_NORMAL)
88 |
89 | # usage
90 |
91 | print("USAGE: press 's' to subsample the chroma")
92 |
93 | while (keep_processing):
94 |
95 | # if video file or camera successfully open then read frame from video
96 |
97 | if (cap.isOpened):
98 | ret, frame = cap.read()
99 |
100 | # when we reach the end of the video (file) exit cleanly
101 |
102 | if (ret == 0):
103 | keep_processing = False
104 | continue
105 |
106 | # rescale if specified
107 |
108 | if (args.rescale != 1.0):
109 | frame = cv2.resize(
110 | frame, (0, 0), fx=args.rescale, fy=args.rescale)
111 |
112 | # start a timer (to see how long processing and display takes)
113 |
114 | start_t = cv2.getTickCount()
115 |
116 | img_ycrcb = cv2.cvtColor(frame, cv2.COLOR_BGR2YCrCb)
117 |
118 | # subsample the chroma information in the same way as it is done in
119 | # JPEG
120 |
121 | if (perform_chroma_subsampling):
122 |
123 | # "Next, the chrominance channels Cr and Cb are subsampled.
124 | # The constant SSH defines the subsampling factor in horicontal
125 | # direction, SSV defines the vertical subsampling factor. Before
126 | # subsampling the chrominance channels are filtered using a (2x2)
127 | # box filter (=average filter). ..." Code from:
128 | # https://www.hdm-stuttgart.de/~maucher/Python/MMCodecs/html/jpegUpToQuant.html
129 |
130 | SSV = 2
131 | SSH = 2
132 | crf = cv2.boxFilter(img_ycrcb[:, :, 1], ddepth=-1, ksize=(2, 2))
133 | cbf = cv2.boxFilter(img_ycrcb[:, :, 2], ddepth=-1, ksize=(2, 2))
134 | crsub = crf[::SSV, ::SSH]
135 | cbsub = cbf[::SSV, ::SSH]
136 |
137 | # display images
138 |
139 | cv2.imshow(window_name, frame)
140 |
141 | # colour channels are YCrCb ordering in OpenCV
142 |
143 | cv2.imshow(window_name_y, img_ycrcb[:, :, 0]) # Y
144 | if (perform_chroma_subsampling):
145 | cv2.imshow(window_name_cr, crsub) # Cr
146 | cv2.imshow(window_name_cb, cbsub) # Cb
147 | else:
148 | cv2.imshow(window_name_cr, img_ycrcb[:, :, 1]) # Cr
149 | cv2.imshow(window_name_cb, img_ycrcb[:, :, 2]) # Cb
150 |
151 | # stop the timer and convert to ms. (to see how long processing and
152 | # display takes)
153 |
154 | stop_t = ((cv2.getTickCount() - start_t) /
155 | cv2.getTickFrequency()) * 1000
156 |
157 | # start the event loop - essential
158 |
159 | # cv2.waitKey() is a keyboard binding function (argument is the time in
160 | # ms). It waits for specified milliseconds for any keyboard event.
161 | # If you press any key in that time, the program continues.
162 | # If 0 is passed, it waits indefinitely for a key stroke.
163 | # (bitwise and with 0xFF to extract least significant byte of
164 | # multi-byte response)
165 |
166 | # wait 40ms or less depending on processing time taken (i.e. 1000ms /
167 | # 25 fps = 40 ms)
168 |
169 | key = cv2.waitKey(max(2, 40 - int(math.ceil(stop_t)))) & 0xFF
170 |
171 | # It can also be set to detect specific key strokes by recording which
172 | # key is pressed
173 |
174 | # e.g. if user presses "x" then exit
175 |
176 | if (key == ord('x')):
177 | keep_processing = False
178 | elif (key == ord('s')):
179 | perform_chroma_subsampling = not (perform_chroma_subsampling)
180 |
181 | # close all windows
182 |
183 | cv2.destroyAllWindows()
184 |
185 | else:
186 | print("No video file specified or camera connected.")
187 |
188 | #####################################################################
189 |
--------------------------------------------------------------------------------