Merge branch 'master' into pthreads_integration

This commit is contained in:
Joachim
2020-04-02 10:52:20 +02:00
166 changed files with 1207 additions and 486 deletions

168
README.md.bak Normal file
View File

@ -0,0 +1,168 @@
# OpenCV for Esp32
This is a clone of OpenCV (from commit 8808aaccffaec43d5d276af493ff408d81d4593c), modified to be cross-compiled on the ESP32. This Readme explains how to cross-compile on the ESP32 and also some details on the steps done.
## Hardware
The tests were done on the ESP32D0WDQ6 (revision 1):
* Xtensa dual core 32-bit LX6 uP, up to 600 MIPS
* 448 KB of ROM for booting and core functions
* 520 KB of SRAM for data and instructions cache
* 16 KB SRAM in RTC
* 8 MB of external SPI RAM
* 16 MB of external SPI Flash
## Benchmark
Below is a summary of the OpenCV features tested on the ESP32 and the time they took (adding the heap/stack used could also be useful).
## Installing esp-idf toolchain
First thing to do is to install the toolchain for the esp32 (see https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html)
```bash
### install some dependencies ###
sudo apt-get install -y git wget libncurses-dev flex bison gperf python python-pip python-setuptools python-serial python-click python-cryptography python-future python-pyparsing python-pyelftools ninja-build ccache libffi-dev libssl-dev
sudo apt-get install -y gawk gperf grep gettext python python-dev automake bison flex texinfo help2man libtool libtool-bin make git
mkdir -p $INSTALLDIR && cd $INSTALLDIR
git clone --recursive https://github.com/espressif/esp-idf.git
cd esp-idf/
export IDF_TOOLS_PATH=$INSTALLDIR
./install.sh
export IDF_PATH=$INSTALLDIR/esp-idf
. $INSTALLDIR/esp-idf/export.sh
```
This script can be found in [esp32/scripts/install_esp32_toolchain.sh](esp32/scripts/install_esp32_toolchain.sh).
## OpenCV cross-compilation:
This is the interesting part. OpenCV is statically cross-compiled. There are 3 ways to get it.
### Faster way:
The first way is to simply get the pre-built OpenCV library in [esp32/lib](esp32/lib), and copy it into your project (see [this section](#Compiling-esp-idf-project-using-opencv))
### Fast way:
The second way is by using the script in [esp32/scripts/build_opencv_for_esp32.sh](esp32/scripts/build_opencv_for_esp32.sh). This script automatically compiles OpenCV from this repository sources, and install the needed files into the desired project. It can tweaked as needed to add and remove some parts.
The script has 2 arguments. The first is the path to the `toolchain-esp32.cmake` (default is `$HOME/esp/esp-idf/tools/cmake/toolchain-esp32.cmake`), and the second is the path where the OpenCV library is installed (default is in [esp32/lib](esp32/lib)).
### Detailed way:
The last way explains all the commands and modifications done to be able to compile and run OpenCV on the ESP32. The detailed procedure is in [esp32/doc/detailed_build_procedure.md](esp32/doc/detailed_build_procedure.md).
## Get project RAM and Flash usages
### At compilation time:
* The command below can be used to see the different segments sizes of the application :
```bash
$ xtensa-esp32-elf-size -d -A build/<project-name>.elf
```
* The file `build/<project-name>.map` is also very useful. It indicates the memory mapping of the variables and can be used to find big variables in the application.
### At run time:
```c++
// Get the amount of stack (in Bytes) that remained unused when the task stack was at its greatest value
ESP_LOGI(TAG, "task stack watermark: %d Bytes", uxTaskGetStackHighWaterMark(NULL));
// Get the free heap in Bytes (may not be contiguous)
ESP_LOGI(TAG, "heap left: %d Bytes", esp_get_free_heap_size());
```
## Adding images codecs support
Things done to read/writes images in JPEG, PNG, etc..
#### PNG
* Remove `-DWITH_PNG=OFF` and add `-DBUILD_PNG=ON` and `-DBUILD_ZLIB=ON` of the cmake command
* => The lib `opencv_imgcodecs.a` build pass
The library is compiled in the `3rdparty/` folder. Copy this folder into the esp32 example project folder.
#### JPEG
* Remove `-DWITH_JPEG=OFF` and add `-DBUILD_JPEG=ON` of the cmake command
* => Problem at compilation time. TODO
## Adding parallel support
TODO
## Removing OpenCV unnecessary parts
Opencv is quite big, even when compiling only the core, imgproc and imgcodec modules. Because the ESP32 has limited resources, it is a good idea to remove some parts of opencv that are in most cases not used.
### Core module:
TODO
### Imgproc module:
#### Colorspaces
Opencv supports multiple colorspaces (RGB, BGR, RGB565, RGBA, CIELAB, CIEXYZ, Luv, YUV, HSV, HLS, YCrCb, Bayer, Gray). All these colorspaces are not mandatory for an embedded system, so some are removed.
* `color_lab.cpp`: This file contains conversion for CIELAB and CIEXYZ (https://en.wikipedia.org/wiki/CIELAB_color_space). The conversion tables takes a lot of space in the .bss segment (~88kB) , which is already overflowing. Here are the steps done to disable this code:
* Move `color_lab.cpp` to `color_lab.cpp.bak`
* In `color.hpp` disable :
```c++
```
* In `color.cpp` disable:
```c++
```
* todo
### Imgcodecs module:
TODO

254
README.rst Normal file
View File

@ -0,0 +1,254 @@
================
OpenCV for Esp32
================
This is a clone of OpenCV (from commit 8808aaccffaec43d5d276af493ff408d81d4593c), modified to be cross-compiled on the ESP32. This Readme explains how to cross-compile on the ESP32 and also some details on the steps done.
Hardware
========
The tests were done on the ESP32D0WDQ6 (revision 1):
- Xtensa dual core 32-bit LX6 uP, up to 600 MIPS
- 448 KB of ROM for booting and core functions
- 520 KB of SRAM for data and instructions cache
- 16 KB SRAM in RTC
- 8 MB of external SPI RAM
- 16 MB of external SPI Flash
Benchmark
=========
Below is a summary of the OpenCV features tested on the ESP32 and the time they took (adding the heap/stack used could also be useful).
All measures are in milliseconds.
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| Function name and arguments | BUILD_TYPE=Debug | BUILD_TYPE=Release |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| | 160x120 | 320x240 | 640x480 | 1024x768 | 160x120 | 320x240 | 640x480 | 1024x768 |
+================================================+=============+=============+=============+=============+=============+=============+=============+=============+
| | |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| **Threshold** | |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| binaryThreshold | 4.5 | 18 | 69 | 175 | 2.6 | 11 | 42 | 107 |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| triangleThreshold | 8.1 | 32 | 124 | 315 | 3.9 | 17 | 66 | 168 |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| OTSUThreshold | 11 | 35 | 127 | 318 | 6.5 | 20 | 69 | 171 |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| toZeroThreshold | 4.5 | 18 | 69 | 175 | 2.6 | 11 | 42 | 107 |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| | |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| **Blurring** | |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| GaussianBlur 9x9 kernel | 223 | 875 | 3473 | 9042 | 34 | 128 | 504 | 1458 |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| medianBlur 9x9 kernel | 141 | 608 | 2754 | 7505 | 56 | 273 | 1425 | 4091 |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| bilateralFilter diameter=9 | 413 | 1628 | 6487 | 16386 | 138 | 535 | 2119 | 5293 |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| | |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| **Morphological tranforms** | |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| erode 5x5 kernel | 41 | 151 | 587 | 1493 | 6.2 | 22 | 84 | 214 |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| dilate 5x5 kernel | 41 | 151 | 587 | 1494 | 6.2 | 22 | 84 | 214 |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| open 5x5 kernel | 81 | 299 | 1163 | 2959 | 11 | 41 | 158 | 400 |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| | |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| **Resize image** | |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| resize linear interpolation | 10 | 39 | 150 | 378 | 3.8 | 16 | 59 | 147 |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| resize cubic interpolation | 21 | 75 | 291 | 733 | 6.5 | 27 | 108 | 277 |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| | |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| **Edge detection** | |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| Sobel | 34 | 116 | 438 | 1129 | 14 | 50 | 187 | 497 |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| Canny | 81 | 260 | 894 | ERR | 32 | 108 | 375 | ERR |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| | |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| **Hough tranformations** | |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| HoughLines | 392 | 897 | ERR | ERR | 313 | 681 | 2121 | ERR |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| HoughLines probabilistic | 699 | 1652 | ERR | ERR | 608 | 1358 | 3766 | ERR |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
The ``ERR`` fields means that the test hasn't pass (most of time due to OutOfMemory error.
The benchmark code can be found in `esp32/examples/esp_opencv_tests/`_.
.. _`esp32/examples/esp_opencv_tests/`: esp32/examples/esp_opencv_tests/
Installing esp-idf toolchain
============================
First thing to do is to install the toolchain for the esp32 (see https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html)
.. code:: shell
### install some dependencies ###
sudo apt-get install -y git wget libncurses-dev flex bison gperf python python-pip python-setuptools python-serial python-click python-cryptography python-future python-pyparsing python-pyelftools ninja-build ccache libffi-dev libssl-dev
sudo apt-get install -y gawk gperf grep gettext python python-dev automake bison flex texinfo help2man libtool libtool-bin make git
mkdir -p $INSTALLDIR && cd $INSTALLDIR
git clone --recursive https://github.com/espressif/esp-idf.git
cd esp-idf/
export IDF_TOOLS_PATH=$INSTALLDIR
./install.sh
export IDF_PATH=$INSTALLDIR/esp-idf
. $INSTALLDIR/esp-idf/export.sh
This script can be found in `esp32/scripts/install_esp_toolchain.sh`_.
.. _`esp32/scripts/install_esp_toolchain.sh`: esp32/scripts/install_esp32_toolchain.sh
OpenCV cross-compilation:
=========================
This is the interesting part. OpenCV is statically cross-compiled. There are 3 ways to get it.
Faster way:
-----------
The first way is to simply get the pre-built OpenCV library in `esp32/lib/`_ folder, and copy it into your project (see Compiling-esp-idf-project-using-opencv)
.. _`esp32/lib/`: esp32/lib/
Fast way:
---------
The second way is by using the script in build_opencv_for_esp32.sh_. This script automatically compiles OpenCV from this repository sources, and install the needed files into the desired project. It can tweaked as needed to add and remove some parts.
The script has 2 arguments. The first is the path to the ``toolchain-esp32.cmake`` (default is ``$HOME/esp/esp-idf/tools/cmake/toolchain-esp32.cmake``), and the second is the path where the OpenCV library is installed (default is in esp32/lib).
.. _build_opencv_for_esp32.sh: esp32/scripts/build_opencv_for_esp32.sh
Detailed way:
-------------
The last way explains all the commands and modifications done to be able to compile and run OpenCV on the ESP32. The detailed procedure is in detailed_build_procedure.md_.
.. _detailed_build_procedure.md: esp32/doc/detailed_build_procedure.md
Get project RAM and Flash usages
===================================
At compilation time:
--------------------
- The command below can be used to see the different segments sizes of the application :
.. code shell
$ xtensa-esp32-elf-size -d -A build/<project-name>.elf
- The file ``build/<project-name>.map`` is also very useful. It indicates the memory mapping of the variables and can be used to find big variables in the application.
At run time:
------------
.. code:: c++
// Get the amount of stack (in Bytes) that remained unused when the task stack was at its greatest value
ESP_LOGI(TAG, "task stack watermark: %d Bytes", uxTaskGetStackHighWaterMark(NULL));
// Get the free heap in Bytes (may not be contiguous)
ESP_LOGI(TAG, "heap left: %d Bytes", esp_get_free_heap_size());
Adding images codecs support
============================
Things done to read/writes images in JPEG, PNG, etc..
PNG
---
- Remove ``-DWITH_PNG=OFF`` and add ``-DBUILD_PNG=ON`` and ``-DBUILD_ZLIB=ON`` of the cmake command
- The lib ``opencv_imgcodecs.a`` build pass
The library is compiled in the ``3rdparty/`` folder. Copy this folder into the esp32 example project folder.
JPEG
----
- Remove ``-DWITH_JPEG=OFF`` and add ``-DBUILD_JPEG=ON`` of the cmake command
- Problem at compilation time. TODO
Adding parallel support
=======================
TODO
Removing OpenCV unnecessary parts
=================================
Opencv is quite big, even when compiling only the core, imgproc and imgcodec modules. Because the ESP32 has limited resources, it is a good idea to remove some parts of opencv that are in most cases not used.
TODO: List the modules functionalities and what is kept or not
Core module:
------------
Imgproc module:
---------------
Colorspaces
^^^^^^^^^^^
Opencv supports multiple colorspaces (RGB, BGR, RGB565, RGBA, CIELAB, CIEXYZ, Luv, YUV, HSV, HLS, YCrCb, Bayer, Gray). All these colorspaces are not mandatory for an embedded system, so some are removed.
- ``color_lab.cpp``: This file contains conversion for CIELAB and CIEXYZ (https://en.wikipedia.org/wiki/CIELAB_color_space). The conversion tables takes a lot of space in the .bss segment (~88kB) , which is already overflowing. Here are the steps done to disable this code:
- Move ``color_lab.cpp`` to ``color_lab.cpp.bak``
- In ``color.hpp`` disable :
.. code:: c++
// todo
- In ``color.cpp`` disable:
.. code:: c++
// todo
- todo

View File

@ -1,77 +1,10 @@
# OpenCV for Esp32 # Detailed build procedure
This is a clone of OpenCV (from commit 8808aaccffaec43d5d276af493ff408d81d4593c), modified to be cross-compiled on the ESP32. This Readme explains how to cross-compile on the ESP32 and also some details on the steps done.
## Hardware
The tests were done on the ESP32D0WDQ6 (revision 1):
* Xtensa dual core 32-bit LX6 uP, up to 600 MIPS
* 448 KB of ROM for booting and core functions
* 520 KB of SRAM for data and instructions cache
* 16 KB SRAM in RTC
* 8 MB of external SPI RAM
* 16 MB of external SPI Flash
## What works
TODO: Resume what works
## Installing esp-idf toolchain
First thing to do is to install the toolchain for the esp32 (see https://docs.espressif.com/projects/esp-idf/en/latest/get-started/index.html)
```bash
### install some dependencies ###
sudo apt-get install -y git wget libncurses-dev flex bison gperf python python-pip python-setuptools python-serial python-click python-cryptography python-future python-pyparsing python-pyelftools ninja-build ccache libffi-dev libssl-dev
sudo apt-get install -y gawk gperf grep gettext python python-dev automake bison flex texinfo help2man libtool libtool-bin make git
mkdir -p $INSTALLDIR && cd $INSTALLDIR
git clone --recursive https://github.com/espressif/esp-idf.git
cd esp-idf/
export IDF_TOOLS_PATH=$INSTALLDIR
./install.sh
export IDF_PATH=$INSTALLDIR/esp-idf
. $INSTALLDIR/esp-idf/export.sh
```
This script can be found in [esp32/scripts/install_esp32_toolchain.sh](esp32/scripts/install_esp32_toolchain.sh).
## OpenCV cross-compilation:
This is the interesting part. OpenCV is statically cross-compiled. There are 3 ways to get it.
### Faster way:
The first way is to simply get the already compiled library in [esp32/lib](esp32/lib), and copy it into your project (see [this section](#Compiling-esp-idf-project-using-opencv))
### Fast way:
The second way is by using the script in [esp32/scripts/build_opencv_for_esp32.sh](esp32/scripts/build_opencv_for_esp32.sh). This script automatically compiles OpenCV from this repository sources, and install the needed files into the desired project. It can tweaked as needed to add and remove some parts.
The script has 2 arguments. The first is the path to the `toolchain-esp32.cmake` (default is `$HOME/esp/esp-idf/tools/cmake/toolchain-esp32.cmake`), and the second is the path where the OpenCV library is installed (default is in [esp32/lib](esp32/lib)).
### Detailed way:
The last way explains all the commands and modifications done to be able to compile and run OpenCV on the ESP32. The last way explains all the commands and modifications done to be able to compile and run OpenCV on the ESP32.
#### CMake command: ## CMake command:
The following cmake command is launched in the `build/` directory. The following cmake command is launched in the `build/` directory.
@ -128,23 +61,27 @@ cmake \
.. ..
``` ```
* `-DCMAKE_BUILD_TYPE` can be set to `Debug` to simplify debugging, but uses more RAM
* `-DBUILD_ZLIB` and `-DBUILD_PNG` are enabled to statically compile the libs instead of using dynamic libs of the system.
The toolchain file `toolchain-esp32.cmake` is taken from esp-idf github: * `-DOPENCV_ENABLE_MEMALIGN` is disabled because the ESP32 doesn't support memory alignment for now (https://github.com/espressif/esp-idf/issues/4218)
```cmake * The toolchain file `toolchain-esp32.cmake` is taken from esp-idf github:
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_C_COMPILER xtensa-esp32-elf-gcc) ```cmake
set(CMAKE_CXX_COMPILER xtensa-esp32-elf-g++) set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_ASM_COMPILER xtensa-esp32-elf-gcc)
set(CMAKE_C_COMPILER xtensa-esp32-elf-gcc)
set(CMAKE_C_FLAGS "-mlongcalls -Wno-frame-address" CACHE STRING "C Compiler Base Flags") set(CMAKE_CXX_COMPILER xtensa-esp32-elf-g++)
set(CMAKE_CXX_FLAGS "-mlongcalls -Wno-frame-address" CACHE STRING "C++ Compiler Base Flags") set(CMAKE_ASM_COMPILER xtensa-esp32-elf-gcc)
# Can be removed after gcc 5.2.0 support is removed (ref GCC_NOT_5_2_0) set(CMAKE_C_FLAGS "-mlongcalls -Wno-frame-address" CACHE STRING "C Compiler Base Flags")
set(CMAKE_EXE_LINKER_FLAGS "-nostdlib" CACHE STRING "Linker Base Flags") set(CMAKE_CXX_FLAGS "-mlongcalls -Wno-frame-address" CACHE STRING "C++ Compiler Base Flags")
```
# Can be removed after gcc 5.2.0 support is removed (ref GCC_NOT_5_2_0)
set(CMAKE_EXE_LINKER_FLAGS "-nostdlib" CACHE STRING "Linker Base Flags")
```
@ -227,7 +164,7 @@ When the `cmake` command works, the following summary is given:
#### Make command: ## Make command:
When the cmake is done, the compilation is started with: When the cmake is done, the compilation is started with:
@ -239,50 +176,62 @@ When the compilation has ended, the libs are in the `build/lib` folder.
#### Compiling esp-idf project using OpenCV: ## Compiling esp-idf project using OpenCV:
When the OpenCV library is cross-compiled, we have in result `*.a` files located in `build/lib` folder. We now want to try to compile an example project using OpenCV on the esp32. A basic example of esp-idf project can be found in [esp32/examples/esp_opencv_basic](esp32/examples/esp_opencv_basic). This project simply creates an OpenCV matrix, fill it with values and prints it on the console. When the OpenCV library is cross-compiled, we have in result `*.a` files located in `build/lib` folder. We now want to try to compile an example project using OpenCV on the esp32. A basic example of esp-idf project can be found in [esp32/examples/esp_opencv_basic](esp32/examples/esp_opencv_basic). This project simply creates an OpenCV matrix, fill it with values and prints it on the console.
Esp-idf environment uses cmake and is separated in components. Because OpenCV lib were compiled outside this example project, we use the pre-built library functionality of esp-idf (https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html#using-prebuilt-libraries-with-components). Esp-idf environment uses cmake and is separated in components. Because OpenCV libs were compiled outside this example project, we use the pre-built library functionality of esp-idf (https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html#using-prebuilt-libraries-with-components).
Here are the things done to add the OpenCV library to the project: Here are the things done to add the OpenCV library to the project:
* Create a folder named `opencv/` into the `main/` component's folder * Create a folder named `opencv/` into the `main/` component's folder
* Copy the generated libraries (`libade.a`, `libopencv_core.a`, `libopencv_imgproc.a` and `libopencv_imgcodecs.a`) into this directory * Copy the generated libraries (`libade.a`, `libopencv_core.a`, `libopencv_imgproc.a` and `libopencv_imgcodecs.a`) into this directory
* Create the folder `opencv2/` into this directory, and copy into it the needed headers : * Create the folder `opencv2/` into this directory, and copy into it the needed headers files :
* `cvconfig.h` * `cvconfig.h`
* `opencv_modules.hpp`
* `opencv.hpp`
* `core.hpp` * `core.hpp`
* `imgproc.hpp` * `imgproc.hpp`
* `opencv.hpp` * `imgcodecs.hpp`
* `opencv_modules.hpp`
* `core/` folder * `core/` folder
* `imgproc/` folder * `imgproc/` folder
* `imgcodecs/` folder
* Link the libraries to the project by modifying the `CMakeList.txt` of the `main` project's component is as below :
```cmake
idf_component_register(
SRC main.cpp
INCLUDE_DIRS ./opencv
)
# Be aware that the order of the librairies is important
add_prebuilt_library(opencv_imgcodecs "opencv/libopencv_imgcodecs.a")
add_prebuilt_library(libpng "opencv/3rdparty/liblibpng.a")
add_prebuilt_library(libzlib "opencv/3rdparty/libzlib.a")
add_prebuilt_library(opencv_imgproc "opencv/libopencv_imgproc.a")
add_prebuilt_library(opencv_core "opencv/libopencv_core.a")
add_prebuilt_library(ade "opencv/libade.a")
target_link_libraries(${COMPONENT_LIB} PRIVATE opencv_imgcodecs)
target_link_libraries(${COMPONENT_LIB} PRIVATE libpng)
target_link_libraries(${COMPONENT_LIB} PRIVATE libzlib)
target_link_libraries(${COMPONENT_LIB} PRIVATE opencv_imgproc)
target_link_libraries(${COMPONENT_LIB} PRIVATE opencv_core)
target_link_libraries(${COMPONENT_LIB} PRIVATE ade)
```
* Finally, include the OpenCV headers needed into your source files:
```c++
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/imgcodecs.hpp"
```
So the `CMakeList.txt` of the `main` project's component is as below : ## Modified files for OpenCV to compile and run:
```cmake
set(COMPONENT_SRCS "hello_opencv.cpp")
set(COMPONENT_ADD_INCLUDEDIRS "." "./opencv/")
set(COMPONENT_NAME "main")
register_component()
# Be aware that the order of the librairies is important
add_prebuilt_library(opencv_imgcodecs "opencv/libopencv_imgcodecs.a")
add_prebuilt_library(opencv_imgproc "opencv/libopencv_imgproc.a")
add_prebuilt_library(opencv_core "opencv/libopencv_core.a")
add_prebuilt_library(ade "opencv/libade.a")
target_link_libraries(${COMPONENT_LIB} PRIVATE opencv_imgcodecs)
target_link_libraries(${COMPONENT_LIB} PRIVATE opencv_imgproc)
target_link_libraries(${COMPONENT_LIB} PRIVATE opencv_core)
target_link_libraries(${COMPONENT_LIB} PRIVATE ade)
```
#### Modified files for OpenCV to compile and run:
To get the cmake configuration and make compilation to work, some modifications on OpenCV files had to be done. They are listed below. To get the cmake configuration and make compilation to work, some modifications on OpenCV files had to be done. They are listed below.
@ -315,13 +264,15 @@ if(UNIX OF ESP32)
The `cmake` command is run, leading to the following errors: The `cmake` command is run, leading to the following errors:
* Having error `C++11 compiler must support std::atomic`. The esp32 only has hardware support for 32-bit atomic operations but not wider (https://github.com/espressif/esp-idf/issues/3163) * *Having error `C++11 compiler must support std::atomic`*
The esp32 only has hardware support for 32-bit atomic operations but not wider (https://github.com/espressif/esp-idf/issues/3163)
**FIX:** **FIX:**
* Changed the file `cmake/checks/atomic_check.cpp` in OpenCV repo. The `std::atomic<long long>` was changed in `std::atomic<long>`, and also in file `modules/core/include/opencv2/core/utils/allocator_stats.impl.hpp` line 24. * Changed the file `cmake/checks/atomic_check.cpp` in OpenCV repo. The `std::atomic<long long>` was changed in `std::atomic<long>`, and also in file `modules/core/include/opencv2/core/utils/allocator_stats.impl.hpp` line 24.
* CMake Error at `/usr/share/cmake-3.16/Modules/TestBigEndian.cmake:50`. The ESP32 is in little endian. * *CMake Error at `/usr/share/cmake-3.16/Modules/TestBigEndian.cmake:50`. The ESP32 is in little endian.*
**FIX:** **FIX:**
@ -336,13 +287,15 @@ The `cmake` command is run, leading to the following errors:
After these fixes, the command `make` is run, with some new errors: After these fixes, the command `make` is run, with some new errors:
* alloc.cpp:31:16: error: 'posix_memalign' was not declared in this scope * *alloc.cpp:31:16: error: 'posix_memalign' was not declared in this scope*
**FIX:** Modify `alloc.cpp` **FIX:** Modify `alloc.cpp`
* When there is an `#if defined(ANDROID)`, add ` || defined(ESP32)` after, so that `malloc.h` is included and `memalign` is used * When there is an `#if defined(ANDROID)`, add ` || defined(ESP32)` after, so that `malloc.h` is included and `memalign` is used
* #error "<dirent.h> not supported". The ESP32 doesn't support directories (which are emulated with the filenames, like `mydir/mysubdir/myfile.c`). * *#error "<dirent.h> not supported"*
The ESP32 doesn't support directories (which are emulated with the filenames, like `mydir/mysubdir/myfile.c`).
**FIX:** Modify `modules/core/src/glob.cpp` **FIX:** Modify `modules/core/src/glob.cpp`
@ -389,16 +342,16 @@ After these fixes, the command `make` is run, with some new errors:
} }
} }
``` ```
The function are not implemented yet. Must be implemented if files reading/writing in SPIFFS needed. The function are not implemented yet. Must be implemented if files reading/writing in SPIFFS needed.
* system.cpp:1002:20: error: 'mkstemp' was not declared in this scope * *system.cpp:1002:20: error: 'mkstemp' was not declared in this scope*
**FIX:** **FIX:**
* Tried to include `<stdlib.h>` where `mkstemp` is, but didn't worked, so just commented lines 1003 to 1007 for now * Tried to include `<stdlib.h>` where `mkstemp` is, but didn't worked, so just commented lines 1003 to 1007 for now
* color.simd_helpers.hpp:148:5: error: insn does not satisfy its constraints * *color.simd_helpers.hpp:148:5: error: insn does not satisfy its constraints*
**FIX:** **FIX:**
@ -416,7 +369,7 @@ After these fixes, the command `make` is run, with some new errors:
* histogram.cpp:1813:1: error: insn does not satisfy its constraints * *histogram.cpp:1813:1: error: insn does not satisfy its constraints*
**FIX:** **FIX:**
@ -438,7 +391,7 @@ After these fixes, the command `make` is run, with some new errors:
When the `make` command compiles successfully, the library was tested with an example. This led to some new errors: When the `make` command compiles successfully, the library was tested with an example. This led to some new errors:
* parallel.cpp:949:58: undefined reference to sysconf * *parallel.cpp:949:58: undefined reference to sysconf*
This error appeared while trying to use the `canny()` method of the imgproc module This error appeared while trying to use the `canny()` method of the imgproc module
@ -452,18 +405,15 @@ When the `make` command compiles successfully, the library was tested with an ex
Which will bypass the unsupported call to `sysconf` that get the number of cpu Which will bypass the unsupported call to `sysconf` that get the number of cpu
* .dram0.bss will not fit in region dram0_0_seg ; region `dram0_0_seg' overflowed by 13496 bytes * *.dram0.bss will not fit in region dram0_0_seg ; region `dram0_0_seg' overflowed by 13496 bytes*
This error appeared while trying to add `cvtColor()` function This error appeared while trying to add `cvtColor()` function
**Fix:** **Fix:**
* The error says that BSS section (uninitialized variables) is too big. * The error says that `dram_0_0_seg` region (containing memory allocated statically at compile time) is overflowed.
* There are Linker Script that can be used to define the placements of the code into the memory but couldn't find how to increase dram_0_0_seg size. Some say that it's not possible for now because section after dram0_0_seg is static. If not, will need to find too big variables and put them on the heap..
See `esp-idf/components/esp32/ld/esp32.ld` file
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< HEAD:README.md
* Disabling the bluetooth in the `menuconfig` saves 56'156 Bytes, but doesn't work though * Disabling the bluetooth in the `menuconfig` saves 56'156 Bytes, but doesn't work though
* Searching in `build/<project-name>.map` for the `.dram0.bss` section, and looking at the opencv bss variables that are big * Searching in `build/<project-name>.map` for the `.dram0.bss` section, and looking at the opencv bss variables that are big
@ -569,6 +519,16 @@ Opencv supports multiple colorspaces (RGB, BGR, RGB565, RGBA, CIELAB, CIEXYZ, Lu
``` ```
* todo * todo
========================================================================================================================================================================================================
The Linker Script `esp-idf/components/esp32/ld/esp32.ld` defines the memory layout. It tells the linker where to put the compiler outputs.
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> master:esp32/doc/detailed_build_procedure.md
* The region `dram_0_0_seg` has a size of `0x2c200` which corresponds to `~180kB`
* It is said in this file that this dram segment *should* be `0x50000` (`~330kB`) and that extra DRAM is available in heap at runtime, but that due to static ROM memory usage at 176kB mark, the additional static memory cannot be used. (see also https://esp32.com/viewtopic.php?t=6699).
* Also enabling `Bluetooth` and `Trace Memory` features in menuconfig will decrease the amount of RAM available
* Because we can't have more static memory, some features had to be disabled:
* Disabling the Bluetooth (~56kB) and Trace Memory in the menuconfig
* Disabling some OpenCV features not mandatory and taking lot of memory. To find variables taking too much space, the `build/<project-name>.map` file is useful (looking for big variables under the `.dram0.bss` section).
* `imgproc/color_lab.cpp` has variables (trilinearLUTE, InvGammaTab and LabCbrtTab) taking ~88 kB. They are used for colorspace conversions in and from CIE LAB and XYZ images. These functions were removed.

View File

@ -2,15 +2,15 @@
This example uses OpenCV library on the Esp32. Only the modules `core`, `imgproc` and `imgcodecs` are compiled. This example uses OpenCV library on the Esp32. Only the modules `core`, `imgproc` and `imgcodecs` are compiled.
The goal of this example is to check which OpenCV features are working and to benchmark their computation time on the target.
The code reads PNG image of different size from the SPIFFS filesystem of the Esp32 (for now, only PNG files are supported). It then performs operations on each image and report the results in an array into the console.
The goal of this example is to check which OpenCV features are working and to benchmark their computation time on the target.
The example tests : The results obtained with can be seen in [benchmark/bm_concat.rst](benchmark/bm_concat.rst). It was tested on the following hardware:
* ESP32D0WDQ6 (revision 1)
* 8 MB of external SPI RAM
* 16 MB of external SPI Flash
* some matrices initialization, then basic image processing functions on these matrices.
* Reading a 470x400 pixels PNG image from the SPIFFS filesystem of the Esp32. For now, only PNG files are supported.
* Perform grayscale conversion and then binary threshold on the image, then write it on the spi flash
* Perform a canny edges detection on the image and the write it on the spi flash

View File

@ -0,0 +1,63 @@
+------------------------------------------------+-------------+-------------+-------------+-------------+
| Function name and arguments | BUILD_TYPE=Debug |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| | 160x120 | 320x240 | 640x480 | 1024x768 |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| All measures are in [ms] |
+================================================+=============+=============+=============+=============+
| |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| **Threshold** |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| binaryThreshold | 4.5 | 18 | 69 | 175 |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| triangleThreshold | 8.1 | 32 | 124 | 315 |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| OTSUThreshold | 11 | 35 | 127 | 318 |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| toZeroThreshold | 4.5 | 18 | 69 | 175 |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| **Blurring** |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| GaussianBlur 9x9 kernel | 223 | 875 | 3473 | 9042 |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| medianBlur 9x9 kernel | 141 | 608 | 2754 | 7505 |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| bilateralFilter diameter=9 | 413 | 1628 | 6487 | 16386 |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| **Morphological tranforms** |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| erode 5x5 kernel | 41 | 151 | 587 | 1493 |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| dilate 5x5 kernel | 41 | 151 | 587 | 1494 |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| open 5x5 kernel | 81 | 299 | 1163 | 2959 |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| **Resize image** |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| resize linear interpolation | 10 | 39 | 150 | 378 |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| resize cubic interpolation | 21 | 75 | 291 | 733 |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| **Edge detection** |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| Sobel | 34 | 116 | 438 | 1129 |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| Canny | 81 | 260 | 894 | - |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| **Hough tranformations** |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| HoughLines | 392 | 897 | - | - |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| HoughLines probabilistic | 699 | 1652 | - | - |
+------------------------------------------------+-------------+-------------+-------------+-------------+

View File

@ -0,0 +1,63 @@
+------------------------------------------------+-------------+-------------+-------------+-------------+
| Function name and arguments | BUILD_TYPE=Release |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| | 160x120 | 320x240 | 640x480 | 1024x768 |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| All measures are in [ms] |
+================================================+=============+=============+=============+=============+
| |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| **Threshold** |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| binaryThreshold | 2.6 | 11 | 42 | 107 |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| triangleThreshold | 3.9 | 17 | 66 | 168 |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| OTSUThreshold | 6.5 | 20 | 69 | 171 |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| toZeroThreshold | 2.6 | 11 | 42 | 107 |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| **Blurring** |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| GaussianBlur 9x9 kernel | 34 | 128 | 504 | 1458 |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| medianBlur 9x9 kernel | 56 | 273 | 1425 | 4091 |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| bilateralFilter diameter=9 | 138 | 535 | 2119 | 5293 |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| **Morphological tranforms** |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| erode 5x5 kernel | 6.2 | 22 | 84 | 214 |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| dilate 5x5 kernel | 6.2 | 22 | 84 | 214 |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| open 5x5 kernel | 11 | 41 | 158 | 400 |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| **Resize image** |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| resize linear interpolation | 3.8 | 16 | 59 | 147 |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| resize cubic interpolation | 6.5 | 27 | 108 | 277 |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| **Edge detection** |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| Sobel | 14 | 50 | 187 | 497 |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| Canny | 32 | 108 | 375 | - |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| **Hough tranformations** |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| HoughLines | 313 | 681 | 2121 | - |
+------------------------------------------------+-------------+-------------+-------------+-------------+
| HoughLines probabilistic | 608 | 1358 | 3766 | - |
+------------------------------------------------+-------------+-------------+-------------+-------------+

View File

@ -0,0 +1,63 @@
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| Function name and arguments | BUILD_TYPE=Debug | BUILD_TYPE=Release |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| | 160x120 | 320x240 | 640x480 | 1024x768 | 160x120 | 320x240 | 640x480 | 1024x768 |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| All measures are in [ms] | |
+================================================+=============+=============+=============+=============+=============+=============+=============+=============+
| | |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| **Threshold** | |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| binaryThreshold | 4.5 | 18 | 69 | 175 | 2.6 | 11 | 42 | 107 |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| triangleThreshold | 8.1 | 32 | 124 | 315 | 3.9 | 17 | 66 | 168 |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| OTSUThreshold | 11 | 35 | 127 | 318 | 6.5 | 20 | 69 | 171 |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| toZeroThreshold | 4.5 | 18 | 69 | 175 | 2.6 | 11 | 42 | 107 |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| | |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| **Blurring** | |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| GaussianBlur 9x9 kernel | 223 | 875 | 3473 | 9042 | 34 | 128 | 504 | 1458 |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| medianBlur 9x9 kernel | 141 | 608 | 2754 | 7505 | 56 | 273 | 1425 | 4091 |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| bilateralFilter diameter=9 | 413 | 1628 | 6487 | 16386 | 138 | 535 | 2119 | 5293 |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| | |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| **Morphological tranforms** | |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| erode 5x5 kernel | 41 | 151 | 587 | 1493 | 6.2 | 22 | 84 | 214 |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| dilate 5x5 kernel | 41 | 151 | 587 | 1494 | 6.2 | 22 | 84 | 214 |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| open 5x5 kernel | 81 | 299 | 1163 | 2959 | 11 | 41 | 158 | 400 |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| | |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| **Resize image** | |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| resize linear interpolation | 10 | 39 | 150 | 378 | 3.8 | 16 | 59 | 147 |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| resize cubic interpolation | 21 | 75 | 291 | 733 | 6.5 | 27 | 108 | 277 |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| | |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| **Edge detection** | |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| Sobel | 34 | 116 | 438 | 1129 | 14 | 50 | 187 | 497 |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| Canny | 81 | 260 | 894 | - | 32 | 108 | 375 | - |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| | |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| **Hough tranformations** | |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| HoughLines | 392 | 897 | - | - | 313 | 681 | 2121 | - |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+
| HoughLines probabilistic | 699 | 1652 | - | - | 608 | 1358 | 3766 | - |
+------------------------------------------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+-------------+

View File

@ -1,129 +0,0 @@
============================== Thresholding tests ==============================
Image 160x120 -------------------------
Binary threshold 2 [ms]
Triangle threshold 3 [ms]
OTSU threshold 6 [ms]
To zero threshold 2 [ms]
Image 320x240 -------------------------
Binary threshold 10 [ms]
Triangle threshold 17 [ms]
OTSU threshold 19 [ms]
To zero threshold 10 [ms]
Image 640x480 -------------------------
Binary threshold 42 [ms]
Triangle threshold 66 [ms]
OTSU threshold 68 [ms]
To zero threshold 42 [ms]
================================ Blurring tests ================================
Image 160x120 -------------------------
GaussianBlur9x9 33 [ms]
medianBlur9x9 53 [ms]
bilateralFilter 137 [ms]
Image 320x240 -------------------------
GaussianBlur9x9 128 [ms]
medianBlur9x9 272 [ms]
bilateralFilter 534 [ms]
Image 640x480 -------------------------
GaussianBlur9x9 503 [ms]
medianBlur9x9 1424 [ms]
bilateralFilter 2118 [ms]
======================= Morphology transformations tests =======================
Image 160x120 -------------------------
erode 8 [ms]
dilate 8 [ms]
open 14 [ms]
Image 320x240 -------------------------
erode 30 [ms]
dilate 30 [ms]
open 57 [ms]
Image 640x480 -------------------------
erode 117 [ms]
dilate 117 [ms]
open 224 [ms]
================================ Resizing tests ================================
Image 160x120 -------------------------
linear resize 3 [ms]
cubic resize 6 [ms]
pyrUp 11 [ms]
Image 320x240 -------------------------
linear resize 16 [ms]
cubic resize 26 [ms]
pyrUp 49 [ms]
Image 640x480 -------------------------
linear resize 59 [ms]
cubic resize 107 [ms]
pyrUp 195 [ms]
============================= Edge detection tests =============================
Image 160x120 -------------------------
Sobel 14 [ms]
Canny: 35 [ms]
Image 320x240 -------------------------
Sobel 49 [ms]
Canny: 123 [ms]
Image 640x480 -------------------------
Sobel 186 [ms]
Canny: 462 [ms]
============================= Hough transform tests ============================
Image 160x120 -------------------------
HoughLines 847 [ms]
HoughLineP 1580 [ms]
Image 320x240 -------------------------
HoughLines 3121 [ms]
HoughLineP 6209 [ms]
Image 640x480 -------------------------
HoughLines 9954 [ms]
HoughLineP 17904 [ms]
OpenCV compiled with:
cmake \
-DCMAKE_BUILD_TYPE=Release \
-DESP32=ON \
-DBUILD_SHARED_LIBS=OFF \
-DCV_DISABLE_OPTIMIZATION=OFF \
-DWITH_IPP=OFF \
-DWITH_TBB=OFF \
-DWITH_OPENMP=OFF \
-DWITH_PTHREADS_PF=OFF \
-DWITH_QUIRC=OFF \
-DWITH_1394=OFF \
-DWITH_CUDA=OFF \
-DWITH_OPENCL=OFF \
-DWITH_OPENCLAMDFFT=OFF \
-DWITH_OPENCLAMDBLAS=OFF \
-DWITH_VA_INTEL=OFF \
-DWITH_EIGEN=OFF \
\
-DWITH_GSTREAMER=OFF \
-DWITH_GTK=OFF \
-DWITH_JASPER=OFF \
-DWITH_JPEG=OFF \
-DWITH_WEBP=OFF \
-DBUILD_ZLIB=ON \
-DBUILD_PNG=ON \
-DWITH_TIFF=OFF \
-DWITH_V4L=OFF \
-DWITH_LAPACK=OFF \
-DWITH_ITT=OFF \
-DWITH_PROTOBUF=OFF \
-DWITH_IMGCODEC_HDR=OFF \
-DWITH_IMGCODEC_SUNRASTER=OFF \
-DWITH_IMGCODEC_PXM=OFF \
-DWITH_IMGCODEC_PFM=OFF \
\
-DBUILD_LIST=core,imgproc,imgcodecs \
-DBUILD_JAVA=OFF \
-DBUILD_opencv_python=OFF \
-DBUILD_opencv_java=OFF \
\
-DBUILD_opencv_apps=OFF \
-DBUILD_PACKAGE=OFF \
-DBUILD_PERF_TESTS=OFF \
-DBUILD_TESTS=OFF \
-DCV_ENABLE_INTRINSICS=OFF \
-DCV_TRACE=OFF \
-DOPENCV_ENABLE_MEMALIGN=OFF \
\
-DCMAKE_TOOLCHAIN_FILE=~/esp/esp-idf/tools/cmake/toolchain-esp32.cmake \
..

View File

@ -2,6 +2,7 @@ idf_component_register(
SRCS SRCS
main.cpp main.cpp
system.cpp system.cpp
report.cpp
INCLUDE_DIRS INCLUDE_DIRS
. .
./opencv ./opencv

View File

@ -11,21 +11,18 @@
#include <chrono> #include <chrono>
#include <iostream> #include <iostream>
#include <sys/unistd.h> #include <sys/unistd.h>
#include <pthread.h>
#include <thread>
#include <tuple>
#include "system.hpp" #include "system.hpp"
#include "measure.hpp" #include "report.hpp"
using namespace cv; using namespace cv;
using namespace std; using namespace std;
const char* TAG="opencv_tests"; const char* TAG="opencv_tests";
const int REPEAT = 3; // number of times to repeat the function call for the average
const int NB_IMAGES = 3; // number of images with different resolutions for the tests
const String images_res[] = {"160x120", "320x240", "640x480"};
extern "C" { extern "C" {
void app_main(void); void app_main(void);
@ -44,83 +41,104 @@ Mat read_image_specific_res(const String &fileName)
return img; return img;
} }
void test_thresholds(const Mat &src)
{
Mat dst;
// apply thresholds int64_t BM_binThresh(const Mat& src) {
BENCHMARK_MS("Binary threshold", REPEAT, threshold, src, dst, 128, 255, THRESH_BINARY); Mat dst;
BENCHMARK_MS("Triangle threshold", REPEAT, threshold, src, dst, 0, 255, THRESH_BINARY | THRESH_TRIANGLE); return BENCHMARK(threshold, src, dst, 128, 255, THRESH_BINARY);
BENCHMARK_MS("OTSU threshold", REPEAT, threshold, src, dst, 0, 255, THRESH_BINARY | THRESH_OTSU);
BENCHMARK_MS("To zero threshold", REPEAT, threshold, src, dst, 128, 255, THRESH_TOZERO);
} }
void test_blurring(const Mat &src) int64_t BM_triangleThresh(const Mat& src) {
{
Mat dst; Mat dst;
return BENCHMARK(threshold, src, dst, 0, 255, THRESH_BINARY | THRESH_TRIANGLE);
// apply blurs
BENCHMARK_MS("GaussianBlur9x9", REPEAT, GaussianBlur, src, dst, Size(9, 9), 0, 0, BORDER_DEFAULT);
BENCHMARK_MS("medianBlur9x9", REPEAT, medianBlur, src, dst, 9);
BENCHMARK_MS("bilateralFilter", REPEAT, bilateralFilter, src, dst, 9, 18, 5, BORDER_DEFAULT);
} }
void test_morphology_transform(const Mat &src) int64_t BM_OTSUThresh(const Mat& src) {
{
Mat dst; Mat dst;
return BENCHMARK(threshold, src, dst, 0, 255, THRESH_OTSU | THRESH_BINARY);
// create a kernel for the transformation
Mat element = getStructuringElement(MORPH_RECT, Size(9, 9), Point(4, 4));
// apply transformations
BENCHMARK_MS("erode", REPEAT, erode, src, dst, element, Point(-1,-1), 1, BORDER_CONSTANT, morphologyDefaultBorderValue());
BENCHMARK_MS("dilate", REPEAT, dilate, src, dst, element, Point(-1,-1), 1, BORDER_CONSTANT, morphologyDefaultBorderValue());
BENCHMARK_MS("open", REPEAT, morphologyEx, src, dst, MORPH_OPEN, element, Point(-1,-1), 1, BORDER_CONSTANT, morphologyDefaultBorderValue());
} }
void test_resize(const Mat &src) int64_t BM_toZeroThresh(const Mat& src) {
{
Mat dst; Mat dst;
return BENCHMARK(threshold, src, dst, 128, 255, THRESH_TOZERO);
BENCHMARK_MS("linear resize", REPEAT, resize, src, dst, Size(), 0.75, 0.75, INTER_LINEAR);
BENCHMARK_MS("cubic resize", REPEAT, resize, src, dst, Size(), 0.75, 0.75, INTER_CUBIC);
BENCHMARK_MS("pyrUp", REPEAT, pyrUp, src, dst, Size(), BORDER_DEFAULT);
// FIXME: pyrDown uses a lot of stack and then causes the next function to crash with a LoadProhibited
//BENCHMARK_MS("pyrDown", REPEAT, pyrDown, src, dst, Size(), BORDER_DEFAULT);
} }
void test_edge_detect(const Mat &src) int64_t BM_GaussianBlur9x9(const Mat& src) {
{
Mat dst; Mat dst;
return BENCHMARK(GaussianBlur, src, dst, Size(9, 9), 0, 0, BORDER_DEFAULT);
}
BENCHMARK_MS("Sobel", REPEAT, Sobel, src, dst, 2, 2, 1, 3, 1, 0, BORDER_DEFAULT); int64_t BM_medianBlur9x9(const Mat& src) {
//BENCHMARK_MS("Canny", REPEAT, Canny, src, dst, 8, 24, 3, false); // FIXME: can't deduce template parameter 'F' Mat dst;
Canny(src, dst, 8, 24, 3, false); // cache warm up return BENCHMARK(medianBlur, src, dst, 9);
}
int64_t BM_bilateralFilter(const Mat& src) {
Mat dst;
return BENCHMARK(bilateralFilter, src, dst, 9, 18, 5, BORDER_DEFAULT);
}
int64_t BM_erode(const Mat& src) {
Mat dst;
Mat element = getStructuringElement(MORPH_RECT, Size(5, 5), Point(4, 4));
return BENCHMARK(erode, src, dst, element, Point(-1,-1), 1, BORDER_CONSTANT, morphologyDefaultBorderValue());
}
int64_t BM_dilate(const Mat& src) {
Mat dst;
Mat element = getStructuringElement(MORPH_RECT, Size(5, 5), Point(4, 4));
return BENCHMARK(dilate, src, dst, element, Point(-1,-1), 1, BORDER_CONSTANT, morphologyDefaultBorderValue());
}
int64_t BM_open(const Mat& src) {
Mat dst;
Mat element = getStructuringElement(MORPH_RECT, Size(5, 5), Point(4, 4));
return BENCHMARK(morphologyEx, src, dst, MORPH_OPEN, element, Point(-1,-1), 1, BORDER_CONSTANT, morphologyDefaultBorderValue());
}
int64_t BM_resizeLinear(const Mat& src) {
Mat dst;
return BENCHMARK(resize, src, dst, Size(), 0.75, 0.75, INTER_LINEAR);
}
int64_t BM_resizeCubic(const Mat& src) {
Mat dst;
return BENCHMARK(resize, src, dst, Size(), 0.75, 0.75, INTER_CUBIC);
}
int64_t BM_Sobel(const Mat& src) {
Mat dst;
return BENCHMARK(Sobel, src, dst, 2, 2, 1, 3, 1, 0, BORDER_DEFAULT);
}
int64_t BM_Canny(const Mat& src) {
Mat dst;
Canny(src, dst, 50, 200, 3, false); // cache warm up
auto start = chrono::system_clock::now(); auto start = chrono::system_clock::now();
Canny(src, dst, 8, 24, 3, false); Canny(src, dst, 50, 200, 3, false);
auto duration = chrono::duration_cast<chrono::milliseconds >(chrono::system_clock::now() - start); auto duration = chrono::duration_cast<chrono::microseconds >(chrono::system_clock::now() - start);
std::cout << "Canny" << ": " << duration.count() << " [" << "ms" << "]" << std::endl; return duration.count();
} }
int64_t BM_HoughLines(const Mat& src) {
void test_hough(const Mat &src)
{
Mat dst, blurred, edge; Mat dst, blurred, edge;
blur(src, blurred, Size(3,3)); blur(src, blurred, Size(3,3));
Canny(blurred, edge, 10, 30, 3, false); Canny(blurred, edge, 50, 200, 3, false);
// hough
vector<Vec2f> lines; vector<Vec2f> lines;
BENCHMARK_MS("HoughLines", REPEAT, HoughLines, edge, lines, 1, CV_PI/180, 100, 0, 0, 0, CV_PI); return BENCHMARK(HoughLines, edge, lines, 1, CV_PI/180, 100, 0, 0, 0, CV_PI);
// probabilistic hough
vector<Vec4i> linesP;
BENCHMARK_MS("HoughLineP", REPEAT, HoughLinesP, edge, linesP, 1, CV_PI/180, 100, 80, 0);
} }
int64_t BM_HoughLinesP(const Mat& src) {
Mat dst, blurred, edge;
blur(src, blurred, Size(3,3));
Canny(blurred, edge, 50, 200, 3, false);
vector<Vec4i> linesP;
return BENCHMARK(HoughLinesP, edge, linesP, 1, CV_PI/180, 100, 80, 0);
}
void app_main(void) void app_main(void)
{ {
pthread_cond_t cond_test = PTHREAD_COND_INITIALIZER;
pthread_cond_init(&cond_test, nullptr);
unsigned ncpus = std::thread::hardware_concurrency();
ESP_LOGI(TAG, "Number of CPU with std::thread::hardware_concurrency() = %d", ncpus);
ESP_LOGI(TAG, "Starting main"); ESP_LOGI(TAG, "Starting main");
disp_mem_infos(); disp_mem_infos();
@ -128,58 +146,46 @@ void app_main(void)
init_spiffs(); init_spiffs();
/* Read the images for the tests */ /* Read the images for the tests */
Mat src = read_image_specific_res("/spiffs/"+images_res[0]+".png"); const vector<string> images_res = {"160x120", "320x240", "640x480", "1024x768"};
Mat src2 = read_image_specific_res("/spiffs/"+images_res[1]+".png"); imagesList testImages;
Mat src3 = read_image_specific_res("/spiffs/"+images_res[2]+".png"); for(const String &res : images_res) {
vector<Mat> matrices; testImages.push_back(tuple<string, const Mat&>(res, read_image_specific_res("/spiffs/"+res+".png")));
matrices.push_back(src);
matrices.push_back(src2);
matrices.push_back(src3);
// TODO: rename measure.hpp in benchmark.hpp and add printHeader method
// TODO: make an array of function and call them from a single loop
/* Conversions and thresholds tests */
printf("============================== Thresholding tests ==============================\n");
for(int i = 0; i < NB_IMAGES; i++) {
printf("Image %s -------------------------\n", images_res[i].c_str());
test_thresholds(matrices[i]);
} }
/* Blurring tests */ Report report("BUILD_TYPE=Release", testImages);
printf("================================ Blurring tests ================================\n");
for(int i = 0; i < NB_IMAGES; i++) {
printf("Image %s -------------------------\n", images_res[i].c_str());
test_blurring(matrices[i]);
}
/* Morphology transformations */ TestGroup &thresholds = report.addGroup("Threshold");
printf("======================= Morphology transformations tests =======================\n"); thresholds.addTestCase(TestCase("binaryThreshold", BM_binThresh));
for(int i = 0; i < NB_IMAGES; i++) { thresholds.addTestCase(TestCase("triangleThreshold", BM_triangleThresh));
printf("Image %s -------------------------\n", images_res[i].c_str()); thresholds.addTestCase(TestCase("OTSUThreshold", BM_OTSUThresh));
test_morphology_transform(matrices[i]); thresholds.addTestCase(TestCase("toZeroThreshold", BM_toZeroThresh));
}
/* Edge detection */ TestGroup &blurrings = report.addGroup("Blurring");
printf("================================ Resizing tests ================================\n"); blurrings.addTestCase(TestCase("GaussianBlur 9x9 kernel", BM_GaussianBlur9x9));
for(int i = 0; i < NB_IMAGES; i++) { blurrings.addTestCase(TestCase("medianBlur 9x9 kernel", BM_medianBlur9x9));
printf("Image %s -------------------------\n", images_res[i].c_str()); blurrings.addTestCase(TestCase("bilateralFilter diameter=9", BM_bilateralFilter));
test_resize(matrices[i]);
}
/* Image resizing */ TestGroup &morph = report.addGroup("Morphological tranforms");
printf("============================= Edge detection tests =============================\n"); morph.addTestCase(TestCase("erode 5x5 kernel", BM_erode));
for(int i = 0; i < NB_IMAGES; i++) { morph.addTestCase(TestCase("dilate 5x5 kernel", BM_dilate));
printf("Image %s -------------------------\n", images_res[i].c_str()); morph.addTestCase(TestCase("open 5x5 kernel", BM_open));
test_edge_detect(matrices[i]);
}
/* Hough transform */ TestGroup &resize = report.addGroup("Resize image");
printf("============================= Hough transform tests ============================\n"); resize.addTestCase(TestCase("resize linear interpolation", BM_resizeLinear));
for(int i = 0; i < NB_IMAGES; i++) { resize.addTestCase(TestCase("resize cubic interpolation", BM_resizeCubic));
printf("Image %s -------------------------\n", images_res[i].c_str());
test_hough(matrices[i]); TestGroup &edgeDetect = report.addGroup("Edge detection");
} edgeDetect.addTestCase(TestCase("Sobel", BM_Sobel));
edgeDetect.addTestCase(TestCase("Canny", BM_Canny));
TestGroup &houghTransform = report.addGroup("Hough tranformations");
houghTransform.addTestCase(TestCase("HoughLines", BM_HoughLines));
houghTransform.addTestCase(TestCase("HoughLines probabilistic", BM_HoughLinesP));
report.startBenchmark();
string summary = report.getSummary();
cout << summary << endl;
ESP_LOGI(TAG, "End of main"); ESP_LOGI(TAG, "End of main");
} }

View File

@ -1,103 +0,0 @@
//
// Helper to measure time taken by functions
//
// Code taken from https://github.com/picanumber/bureaucrat/blob/master/time_lapse.h
//
#ifndef MEASURE_HPP
#define MEASURE_HPP
#include <chrono>
#include <iostream>
#include <string>
/*
* @brief Macro to simplify the benchmark() function usage.
* - more concise
* - already fill the unit type
*
* @param name (String) representing the name of the function (for the log)
* @param repeat (Int) number of times to call the function for the time average
* @param fct (F type) function to call
* @param ... (Args type) arguments of the function to call
*
* Usage examples:
* - without macro:
* measure<std::chrono::milliseconds>::benchmark("ms", "medianBlur", repeat, medianBlur, src, dst, 9);
* - with macro:
* BENCHMARK_MS("medianBlur", repeat, medianBlur, src, dst, 9);
*/
#define BENCHMARK_NS(name, repeat, fct, ...) measure<std::chrono::nanoseconds>::benchmark("ns", name, repeat, fct, __VA_ARGS__)
#define BENCHMARK_US(name, repeat, fct, ...) measure<std::chrono::microseconds>::benchmark("us", name, repeat, fct, __VA_ARGS__)
#define BENCHMARK_MS(name, repeat, fct, ...) measure<std::chrono::milliseconds>::benchmark("ms", name, repeat, fct, __VA_ARGS__)
#define BENCHMARK_S(name, repeat, fct, ...) measure<std::chrono::seconds>::benchmark("s", name, repeat, fct, __VA_ARGS__)
#define fw(what) std::forward<decltype(what)>(what)
/**
* @ class measure
* @ brief Class to measure the execution time of a callable
*/
template <
typename TimeT = std::chrono::milliseconds, class ClockT = std::chrono::system_clock
>
struct measure
{
/**
* @ fn execution
* @ brief Returns the quantity (count) of the elapsed time as TimeT units
*/
template<typename F, typename ...Args>
static typename TimeT::rep execution(F&& func, Args&&... args)
{
auto start = ClockT::now();
fw(func)(std::forward<Args>(args)...);
auto duration = std::chrono::duration_cast<TimeT>(ClockT::now() - start);
return duration.count();
}
/**
* Function that executes the function 'repeat' times, measure the average time taken and logs on the console
* the time.
* @tparam F
* @tparam Args
* @param unit String representing the time unit (for the log). Can be either 's', 'ms', 'us' or 'ns'
* @param repeat Number of times to do the measure
* @param func Function to benchmark
* @param args Arguments of the function 'func'
*/
template<typename F, typename... Args>
static void benchmark(const std::string &unit, const std::string &name, int repeat, F&& func, Args&&... args)
{
auto avg = duration(func, (args)...);
for(int i = 0; i < repeat-1; i++) {
avg += duration(func, (args)...);
}
std::cout << name << "\t " << (avg / repeat).count() << " [" << unit << "]" << std::endl;
}
/**
* @ fn duration
* @ brief Returns the duration (in chrono's type system) of the elapsed time
*/
template<typename F, typename... Args>
static TimeT duration(F&& func, Args&&... args)
{
auto start = ClockT::now();
fw(func)(std::forward<Args>(args)...);
return std::chrono::duration_cast<TimeT>(ClockT::now() - start);
}
};
#undef fw
#endif // MEASURE_HPP

View File

@ -0,0 +1,208 @@
//
// Created by joachim on 01.04.20.
//
#include "report.hpp"
#include <utility>
#include <iomanip>
using namespace std;
// TestCase class
TestCase::TestCase(string _name, int _iterations, function<int(const cv::Mat &)> _func) :
name(move(_name)), iterations(_iterations), func(move(_func)) {}
TestCase::TestCase(string _name, function<int(const cv::Mat &)> _func) :
TestCase(move(_name), DEFAULT_ITERATIONS, move(_func)) {}
void TestCase::executeOn(const imagesList &testImages) {
for(auto img : testImages) {
float timeTaken;
try {
timeTaken = (float) func(get<1>(img)) / 1000.0f;
} catch(cv::Exception& e) {
cout << "Exception while trying to execute function " << name << " on image " << get<0>(img) << " :\n" << e.msg;
timeTaken = -1;
}
resultTime.push_back(timeTaken);
cout << "Testing " << name << " on " << get<0>(img) << " took "
<< resultTime.back() << " [ms] (in " << iterations << " iterations)" << endl;
}
}
// TestGroup class
TestGroup::TestGroup(string _name) : name(move(_name)) {}
void TestGroup::addTestCase(const TestCase &test) {
tests.push_back(test);
}
// Report class
Report::Report(string _name, const imagesList& _images) : name(move(_name)), images(_images), summary(_images) {}
TestGroup &Report::addGroup(const string &_name) {
groups.push_back(TestGroup(_name));
return groups.back();
}
TestGroup &Report::getGroup(const string &_name) {
auto it = find_if(groups.begin(), groups.end(), [&_name] (const TestGroup& g) {return (g.name == _name);});
if(it == groups.end()) {
cout << "group not found!" << endl;
return *it; // todo: exception?
}
else {
return *it;
}
}
void Report::startBenchmark() {
cout << "starting benchmark with " << images.size() << " images, " << groups.size() << " groups" << endl;
for(auto& group : groups) {
cout << "Group contains " << group.tests.size() << " testcases" << endl;
for(auto& test : group.tests) {
test.executeOn(images);
}
}
}
string Report::getSummary() {
string sum;
sum += summary.summaryHeader(name);
for(const auto& group : groups) {
sum += summary.summarySection(group);
for(const auto& test : group.tests) {
sum += summary.summaryTest(test);
}
}
return sum;
}
// Summary class
Summary::Summary(imagesList _images) : images(move(_images)) {
// Fill the columns width vector
columnsWidth.push_back(COL1_WIDTH);
for(int i = 0; i < images.size(); i++) {
columnsWidth.push_back(COL_VALUES_WIDTH);
}
// Get the total width FIXME: columns width and alignment is a bit messy
totalWidth = 0;
for (auto& w : columnsWidth)
totalWidth += (w-1);
totalWidth += 1;
}
string Summary::lineSeparator(const char sep) {
string line;
for(int size : columnsWidth) {
line += "+";
line += string(size-2, sep);
}
line += "+\n";
return line;
}
string Summary::alignTextLeft(const string &text, int colWidth) {
string s;
s += " " + text;
s += string(colWidth - text.size() - 3, ' ');
return s;
}
string Summary::alignTextRight(const string &text, int colWidth) {
string s;
s += string(colWidth - text.size() - 3, ' ');
s += text + " ";
return s;
}
string Summary::alignTextCenter(const string &text, int colWidth) {
string s;
int spaces = colWidth - text.size() - 2;
s += string(spaces/2, ' ') + text + string(spaces/2, ' ');
s += (spaces % 2 != 0) ? " " : "";
return s;
}
string Summary::lineText(const vector<string> &colTexts) {
string line;
int numOfTextCol = colTexts.size();
int remainingWidth = totalWidth;
for(int c = 0; c < numOfTextCol; c++) {
// if last text but not last column, fit it in the rest of the row
line += "|";
if((c == numOfTextCol-1) && (c < columnsWidth.size()-1)) {
line += alignTextLeft(colTexts[c], remainingWidth);
}
else {
// align text left on first col, right on the rest
line += (c==0 ? alignTextLeft(colTexts[c], columnsWidth.at(c)) : alignTextRight(colTexts[c], columnsWidth.at(c)));
remainingWidth -= (columnsWidth.at(c)-1);
}
}
line += "|\n";
return line;
}
string Summary::summaryHeader(const string &reportName) {
string summaryHeaderLines;
// extract images names
vector<string> imagesNames;
for(auto img : images) {
imagesNames.push_back(get<0>(img));
}
imagesNames.insert(imagesNames.begin(), "");
summaryHeaderLines += lineSeparator('-');
summaryHeaderLines += lineText({"Function name and arguments", reportName});
summaryHeaderLines += lineSeparator('-');
summaryHeaderLines += lineText(imagesNames);
summaryHeaderLines += lineSeparator('-');
summaryHeaderLines += lineText({"Measures are in [ms]"});
summaryHeaderLines += lineSeparator('=');
return summaryHeaderLines;
}
string Summary::summarySection(const TestGroup &group) {
string summarySectionLines;
summarySectionLines += lineText({""});
summarySectionLines += lineSeparator('-');
summarySectionLines += lineText({"**" + group.name + "**"});
summarySectionLines += lineSeparator('-');
return summarySectionLines;
}
string Summary::summaryTest(const TestCase &test) {
string summaryTestLines;
vector<string> text;
// fill text vector with name and values
text.push_back(test.name);
for(auto res : test.resultTime) {
string value;
if(res == -1) {
value = " - ";
}
else {
stringstream ss;
ss << fixed << setprecision(((res < 10) ? 1 : 0)) << res;
value = ss.str();
}
text.push_back(value);
}
summaryTestLines += lineText(text);
summaryTestLines += lineSeparator('-');
return summaryTestLines;
}

View File

@ -0,0 +1,167 @@
//
// Helper to benchmark time taken by functions
//
// Code taken from https://github.com/picanumber/bureaucrat/blob/master/time_lapse.h
// and https://github.com/espressif/esp-dsp/blob/master/test/report.inc
//
#ifndef REPORT_HPP
#define REPORT_HPP
#include <opencv2/core.hpp>
#include <chrono>
#include <iostream>
#include <string>
#include <tuple>
#include <vector>
#include <string>
#include <algorithm>
#define BENCHMARK(fct, ...) Report::benchmark(fct, __VA_ARGS__)
using functionSignature = std::function<int (const cv::Mat&)>;
using imagesList = std::vector<std::tuple<std::string, cv::Mat> >;
#define fw(what) std::forward<decltype(what)>(what)
// ==============
// class TestCase
// ==============
class TestCase
{
public:
static constexpr int DEFAULT_ITERATIONS = 3;
std::string name;
std::vector<float> resultTime;
int iterations;
functionSignature func;
TestCase(std::string _name, int _iterations, functionSignature _func);
TestCase(std::string _name, functionSignature _func);
void executeOn(const imagesList &testImages);
};
// ===============
// class TestGroup
// ===============
class TestGroup
{
public:
std::string name;
std::vector<TestCase> tests;
explicit TestGroup(std::string _name);
void addTestCase(const TestCase& test);
};
// =============
// class Summary
// =============
class Summary
{
private:
const int COL1_WIDTH = 50;
const int COL_VALUES_WIDTH = 15;
imagesList images;
std::vector<int> columnsWidth;
int totalWidth;
std::string lineSeparator(const char sep);
std::string alignTextLeft(const std::string &text, int colWidth);
std::string alignTextRight(const std::string &text, int colWidth);
std::string alignTextCenter(const std::string &text, int colWidth);
std::string lineText(const std::vector<std::string>& colTexts);
public:
Summary(imagesList _images);
std::string summaryHeader(const std::string &reportName);
std::string summarySection(const TestGroup& group);
std::string summaryTest(const TestCase& test);
};
// ============
// class Report
// ============
class Report
/**
* @ class report
* @ brief Class to report a benchmark of image processing functions
*/
{
private:
std::string name;
std::vector<TestGroup> groups;
imagesList images;
Summary summary;
public:
explicit Report(std::string _name, const imagesList& _images);
TestGroup& addGroup(const std::string &_name);
TestGroup& getGroup(const std::string &_name);
void startBenchmark();
std::string getSummary();
/**
* Function that executes the function 'repeat' times, benchmark the average time taken and logs on the console
* the time.
* @tparam F
* @tparam Args
* @param unit String representing the time unit (for the log). Can be either 's', 'ms', 'us' or 'ns'
* @param repeat Number of times to do the benchmark
* @param func Function to benchmark
* @param args Arguments of the function 'func'
*/
template<typename F, typename... Args>
static int64_t benchmark(int repeat, F&& func, Args&&... args)
{
auto avg = duration(func, (args)...);
for(int i = 0; i < repeat-1; i++) {
avg += duration(func, (args)...);
}
return (avg/repeat).count();
}
template<typename F, typename... Args>
static int64_t benchmark(F&& func, Args&&... args)
{
const int defaultIterations = 3;
return benchmark(defaultIterations, func, (args)...);
}
using TimeT = std::chrono::microseconds ;
using ClockT = std::chrono::system_clock ;
/**
* @ fn duration
* @ brief Returns the duration (in chrono's type system microseconds) of the elapsed time
*/
template<typename F, typename... Args>
static TimeT duration(F&& func, Args&&... args)
{
auto start = ClockT::now();
fw(func)(std::forward<Args>(args)...);
return std::chrono::duration_cast<TimeT>(ClockT::now() - start);
}
};
#undef fw
#endif // REPORT_HPP

View File

@ -2,5 +2,5 @@
# Name, Type, SubType, Offset, Size, Flags # Name, Type, SubType, Offset, Size, Flags
nvs, data, nvs, 0x9000, 0x6000, nvs, data, nvs, 0x9000, 0x6000,
phy_init, data, phy, 0xf000, 0x1000, phy_init, data, phy, 0xf000, 0x1000,
factory, app, factory, 0x10000, 2M, factory, app, factory, 0x10000, 3M,
storage, data, spiffs, , 1M, storage, data, spiffs, , 1500k,

1 # Espressif ESP32 Partition Table
2 # Name, Type, SubType, Offset, Size, Flags
3 nvs, data, nvs, 0x9000, 0x6000,
4 phy_init, data, phy, 0xf000, 0x1000,
5 factory, app, factory, 0x10000, 2M, factory, app, factory, 0x10000, 3M,
6 storage, data, spiffs, , 1M, storage, data, spiffs, , 1500k,

View File

@ -83,10 +83,10 @@ CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
CONFIG_ESPTOOLPY_FLASHFREQ="80m" CONFIG_ESPTOOLPY_FLASHFREQ="80m"
# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set # CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set
# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set # CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y # CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set
# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set # CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set
# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
CONFIG_ESPTOOLPY_FLASHSIZE="4MB" CONFIG_ESPTOOLPY_FLASHSIZE="16MB"
CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y
CONFIG_ESPTOOLPY_BEFORE_RESET=y CONFIG_ESPTOOLPY_BEFORE_RESET=y
# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set # CONFIG_ESPTOOLPY_BEFORE_NORESET is not set
@ -355,7 +355,7 @@ CONFIG_ADC_CAL_LUT_ENABLE=y
CONFIG_ESP_ERR_TO_NAME_LOOKUP=y CONFIG_ESP_ERR_TO_NAME_LOOKUP=y
CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32 CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2304 CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2304
CONFIG_ESP_MAIN_TASK_STACK_SIZE=16384 CONFIG_ESP_MAIN_TASK_STACK_SIZE=20480
CONFIG_ESP_IPC_TASK_STACK_SIZE=1024 CONFIG_ESP_IPC_TASK_STACK_SIZE=1024
CONFIG_ESP_IPC_USES_CALLERS_PRIORITY=y CONFIG_ESP_IPC_USES_CALLERS_PRIORITY=y
CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048 CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048
@ -884,7 +884,7 @@ CONFIG_OPENSSL_ASSERT_DO_NOTHING=y
# PThreads # PThreads
# #
CONFIG_PTHREAD_TASK_PRIO_DEFAULT=5 CONFIG_PTHREAD_TASK_PRIO_DEFAULT=5
CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=8192
CONFIG_PTHREAD_STACK_MIN=768 CONFIG_PTHREAD_STACK_MIN=768
CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY=y CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY=y
# CONFIG_PTHREAD_DEFAULT_CORE_0 is not set # CONFIG_PTHREAD_DEFAULT_CORE_0 is not set
@ -1088,7 +1088,7 @@ CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC=y
# CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS is not set # CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS is not set
CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32
CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304 CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2304
CONFIG_MAIN_TASK_STACK_SIZE=16384 CONFIG_MAIN_TASK_STACK_SIZE=20480
CONFIG_IPC_TASK_STACK_SIZE=1024 CONFIG_IPC_TASK_STACK_SIZE=1024
CONFIG_CONSOLE_UART_DEFAULT=y CONFIG_CONSOLE_UART_DEFAULT=y
# CONFIG_CONSOLE_UART_CUSTOM is not set # CONFIG_CONSOLE_UART_CUSTOM is not set
@ -1149,7 +1149,7 @@ CONFIG_TCPIP_TASK_AFFINITY_NO_AFFINITY=y
CONFIG_TCPIP_TASK_AFFINITY=0x7FFFFFFF CONFIG_TCPIP_TASK_AFFINITY=0x7FFFFFFF
# CONFIG_PPP_SUPPORT is not set # CONFIG_PPP_SUPPORT is not set
CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5 CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5
CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=8192
CONFIG_ESP32_PTHREAD_STACK_MIN=768 CONFIG_ESP32_PTHREAD_STACK_MIN=768
CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY=y CONFIG_ESP32_DEFAULT_PTHREAD_CORE_NO_AFFINITY=y
# CONFIG_ESP32_DEFAULT_PTHREAD_CORE_0 is not set # CONFIG_ESP32_DEFAULT_PTHREAD_CORE_0 is not set

View File

@ -83,10 +83,10 @@ CONFIG_ESPTOOLPY_FLASHFREQ_80M=y
CONFIG_ESPTOOLPY_FLASHFREQ="80m" CONFIG_ESPTOOLPY_FLASHFREQ="80m"
# CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set # CONFIG_ESPTOOLPY_FLASHSIZE_1MB is not set
# CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set # CONFIG_ESPTOOLPY_FLASHSIZE_2MB is not set
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y # CONFIG_ESPTOOLPY_FLASHSIZE_4MB is not set
# CONFIG_ESPTOOLPY_FLASHSIZE_8MB is not set CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y
# CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set # CONFIG_ESPTOOLPY_FLASHSIZE_16MB is not set
CONFIG_ESPTOOLPY_FLASHSIZE="4MB" CONFIG_ESPTOOLPY_FLASHSIZE="8MB"
CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y
CONFIG_ESPTOOLPY_BEFORE_RESET=y CONFIG_ESPTOOLPY_BEFORE_RESET=y
# CONFIG_ESPTOOLPY_BEFORE_NORESET is not set # CONFIG_ESPTOOLPY_BEFORE_NORESET is not set
@ -355,7 +355,7 @@ CONFIG_ADC_CAL_LUT_ENABLE=y
CONFIG_ESP_ERR_TO_NAME_LOOKUP=y CONFIG_ESP_ERR_TO_NAME_LOOKUP=y
CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32 CONFIG_ESP_SYSTEM_EVENT_QUEUE_SIZE=32
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2304 CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=2304
CONFIG_ESP_MAIN_TASK_STACK_SIZE=16384 CONFIG_ESP_MAIN_TASK_STACK_SIZE=20480
CONFIG_ESP_IPC_TASK_STACK_SIZE=1024 CONFIG_ESP_IPC_TASK_STACK_SIZE=1024
CONFIG_ESP_IPC_USES_CALLERS_PRIORITY=y CONFIG_ESP_IPC_USES_CALLERS_PRIORITY=y
CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048 CONFIG_ESP_MINIMAL_SHARED_STACK_SIZE=2048
@ -567,7 +567,7 @@ CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y
# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE is not set # CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE is not set
# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL is not set # CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL is not set
CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y
# CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK is not set CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y
CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y
CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1 CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=1
CONFIG_FREERTOS_ASSERT_FAIL_ABORT=y CONFIG_FREERTOS_ASSERT_FAIL_ABORT=y
@ -884,7 +884,7 @@ CONFIG_OPENSSL_ASSERT_DO_NOTHING=y
# PThreads # PThreads
# #
CONFIG_PTHREAD_TASK_PRIO_DEFAULT=5 CONFIG_PTHREAD_TASK_PRIO_DEFAULT=5
CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 CONFIG_PTHREAD_TASK_STACK_SIZE_DEFAULT=8192
CONFIG_PTHREAD_STACK_MIN=768 CONFIG_PTHREAD_STACK_MIN=768
CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY=y CONFIG_PTHREAD_DEFAULT_CORE_NO_AFFINITY=y
# CONFIG_PTHREAD_DEFAULT_CORE_0 is not set # CONFIG_PTHREAD_DEFAULT_CORE_0 is not set

Binary file not shown.

After

Width:  |  Height:  |  Size: 807 KiB

Some files were not shown because too many files have changed in this diff Show More