commit 1662d8616db1ec08d47d7452a8a45489e1fddca3 Author: Laureηt Date: Sun Sep 18 16:51:07 2022 +0200 chore: add files diff --git a/BUILD.md b/BUILD.md new file mode 100644 index 0000000..a2b6cdf --- /dev/null +++ b/BUILD.md @@ -0,0 +1,63 @@ +# Dependencies + +This projet requires: + +* opencv >= 3.4.4 +* cmake >= 3.10 + +## Installing the dependencies + +* [Linux](DEP_LINUX.md) +* [Windows](DEP_WINDOWS.md) +* [OSx](DEP_OSX.md) + +# Building + +## Linux & OSX + +From the root of the project: + +``` +mkdir build +cd build +cmake .. -DOpenCV_DIR=${tpTIBasePath}/opencv-3.4.13/build/install/share/OpenCV/ +``` + +and then to compile + +``` +make -j$(nproc) +``` + +All the executables are placed in `build/bin` + +## Windows + +### Create the Visual Studio Solution. + +* open a Terminal and go to the directory containing the code. + +* execute: + + * `md build` + + * `cd build` + + * `cmake -G "Visual Studio 16 2019" -A x64 -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_PREFIX_PATH:PATH= ..` + + Replace `` with the location where you installed opencv (e.g. C:/User/Toto/Opencv) + + * `dir` + + > if you had a different version of VS installed (not the latest) you may need to adapt the string `Visual Studio 16 2019` to your version: e.g. Visual Studio 15 2017, Visual Studio 14 2015, Visual Studio 12 2013 + +* if everything went well you should find a file named `tpTI.sln` inside the directory. + + +### Compile, build, execute + +* open `tpTI.sln` inside VS either by double clicking on it or opening from inside VS + +* build the solution (**Build Solution** from the **Build menu**) + + diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..1cae6f5 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.10) +project(tpTI VERSION 0.1 LANGUAGES CXX) + +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +include(GNUInstallDirs) + +# set the output path for the generated files +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}) +set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR}) +set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR} ) + +find_package(OpenCV 4.0 REQUIRED) +message(STATUS "OpenCV found, version ${OpenCV_VERSION}") + +add_subdirectory(src) \ No newline at end of file diff --git a/DEP_LINUX.md b/DEP_LINUX.md new file mode 100644 index 0000000..1b21705 --- /dev/null +++ b/DEP_LINUX.md @@ -0,0 +1,79 @@ +# Linux + +These are the steps to build all you need for the TP. + + +## Prerequisites + +In order to develop in C++ some system packages are required (you may already have it installed on your machine since the opengl tp of last semester): + +``` +sudo apt-get install libglu1-mesa-dev freeglut3-dev build-essential mesa-common-dev libxi-dev libxmu-dev automake libgtk+2.0-dev pkg-config libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev libgstreamer-plugins-good1.0-dev libv4l-dev gstreamer1.0-plugins-bad ubuntu-restricted-extras +``` + +To build this code we use the CMake build system. +You can install CMake from the system package manager but you need a recent version >= 3.10. +Check the version that is provided by your linux distribution and if it is suitable usually you just need to + + + ``` + sudo apt-get install cmake + ``` + +otherwise you can install the binaries from here: https://github.com/Kitware/CMake/releases/download/v3.17.1/cmake-3.17.1-Linux-x86_64.sh + + To install: + + ``` + wget https://github.com/Kitware/CMake/releases/download/v3.17.1/cmake-3.17.1-Linux-x86_64.sh + chmod +x cmake-3.17.1-Linux-x86_64.sh + sudo cmake-3.17.1-Linux-x86_64.sh --prefix=/usr/local/ --skip-license + ``` + + +## Setting up your working environment + +* create a folder `tpTI` where you will have all the dependencies and the sources of the tp. + Please avoid paths containing spaces, weird characters or accents. + +* to make your life easier, set up an environment variable that refer to this location + + * You can define it for a single session with (e.g.) `export tpTIBasePath=/home/sgaspari/dev/tpTI` + + * or you can define it once for all by adding the previous instruction to your `~/.bashrc` (or `~/.profile`) files, so that you don't need to run the instruction for each terminal session. + + * you can verify that the variable is set with `echo ${tpTIBasePath}` + + +## opencv + +OpenCV is a computer vision library that contains some of the algorithms we are using for image processing and pose estimation. +To install it: + +* download the library from the repository https://github.com/opencv/opencv/archive/3.4.13.zip + +* unzip the file into `${tpTIBasePath}` (a folder named `opencv-3.4.13` should appear). + +* from `${tpTIBasePath}\opencv-3.4.13` create a `build` directory (`mkdir build`) + +* from the shell, go to `${tpTIBasePath}/opencv-3.4.13/build` and execute the following: + + ``` + cmake .. -DCMAKE_INSTALL_PREFIX:PATH=`pwd`/install -DCMAKE_BUILD_TYPE=Release -DWITH_CUDA:BOOL=OFF -DBUILD_PERF_TESTS:BOOL=OFF -DBUILD_TESTS:BOOL=OFF + ``` + +* then build and install the library by running + + ``` + make install -j$(nproc) + ``` + and go grab a cup of coffee or a beverage of your choice ;-) + + +* in order to run the tp code later on you have to add the built libraries to the `LD_LIBRARY_PATH` environment variable. + + ``` + export LD_LIBRARY_PATH=${tpTIBasePath}/opencv-3.4.13/build/install/lib:$LD_LIBRARY_PATH + ``` + + Again, you can add this to your `~/.bashrc` (or `~/.profile`) file so that you have it available for all shell sessions. \ No newline at end of file diff --git a/DEP_OSX.md b/DEP_OSX.md new file mode 100644 index 0000000..5e43ad2 --- /dev/null +++ b/DEP_OSX.md @@ -0,0 +1,62 @@ +# OSX + +These are the steps to build all you need for the TP. + + +## Prerequisites + +* If you do not have it already installed, you need to install XCode from the `Mac App Store`, see here for more details https://developer.apple.com/support/xcode/ + +* everything will be smoother if you have homebrew installed (https://brew.sh/): it is a package manager similar in spirit to the one you find in Linux. + + * `brew install automake cmake` will install everything you need for building the code. + + * if you don't have homebrew you can install CMake by downloading https://github.com/Kitware/CMake/releases/download/v3.17.1/cmake-3.17.1-Darwin-x86_64.dmg + +## Setting up your working environment + +* create a folder `tpTI` where you will have all the dependencies and the sources of the tp. + Please avoid paths containing spaces, weird characters or accents. + +* to make your life easier, set up an environment variable that refer to this location + + * You can define it for a single session with (e.g.) `export tpTIBasePath=/home/sgaspari/dev/tpTI` + + * or you can define it once for all by adding the previous instruction to your `~/.profile` file, so that you don't need to run the instruction for each terminal session. + + * you can verify that the variable is set with `echo ${tpTIBasePath}` + + +## opencv + +OpenCV is a computer vision library that contains some of the algorithms we are using for image processing and pose estimation. +To install it: + +* download the library from the repository https://github.com/opencv/opencv/archive/3.4.13.zip + +* unzip the file into `${tpTIBasePath}` (a folder named `opencv-3.4.13` should appear). + +* from `${tpTIBasePath}\opencv-3.4.13` create a `build` directory (`mkdir build`) + +* from the shell, go to `${tpTIBasePath}/opencv-3.4.13/build` and execute the following: + + ``` + cmake .. -DCMAKE_INSTALL_PREFIX:PATH=`pwd`/install -DCMAKE_BUILD_TYPE=Release -DWITH_CUDA:BOOL=OFF -DBUILD_PERF_TESTS:BOOL=OFF -DBUILD_TESTS:BOOL=OFF + ``` + +* then build and install the library by running + + ``` + make install -j4 + ``` + You can replace 4 with the number of threads that you machine can support, it will speed up the building. + Then go grab a cup of coffee or a beverage of your choice ;-) + + +* in order to run the tp code later on you have to add the built libraries to the `DYLD_LIBRARY_PATH` environment variable. + + ``` + export DYLD_LIBRARY_PATH=${tpTIBasePath}/opencv-3.4.13/build/install/lib:$DYLD_LIBRARY_PATH + ``` + + Again, you can add this to your `~/.profile` file so that you have it available for all shell sessions. \ No newline at end of file diff --git a/DEP_WINDOWS.md b/DEP_WINDOWS.md new file mode 100644 index 0000000..13e7b1a --- /dev/null +++ b/DEP_WINDOWS.md @@ -0,0 +1,89 @@ +# Windows + +These are the steps to build all you need for the TP. + + +## Prerequisites + +The building process requires CMake and MS Visual Studio. +You may already have it installed on your machine since the opengl tp of last semester. + +If it is not the case: + +* download and install the latest version of CMake + + * download here: https://github.com/Kitware/CMake/releases/download/v3.17.1/cmake-3.17.1-win64-x64.msi + + * !!! When installing make sure that the checkbox "ne pas ajouter cmake au PATH" is **NOT** checked + + +* if you don't have it already, download and install MS Visual Studio Community Edition (free for students): https://visualstudio.microsoft.com/downloads/ + + * install instructions here: https://docs.microsoft.com/en-us/cpp/build/vscpp-step-0-installation?view=vs-2019 + + * !!! install the "Desktop development with C++" + + * If you have VS already installed, you can go in **Tools** --> **Get Tools and Features...** to install "Desktop development with C++" if it is missing. + + +## Setting up your working environment + +* create a folder `tpTI` where you will have all the dependencies and the sources of the tp. + Please avoid paths containing spaces, weird characters or accents. + +* to make your life easier, set up an environment variable that refer to this location + + * from the prompt (`cmd.exe`) execute `c:\Windows\System32\SystemPropertiesAdvanced.exe ` + + * click `Environment Variables...` (`Variables d'environnement...`) + + * in `User Variables for ...` ( `Variables utilisateur pour...`) click `New...` and set a new variable named + `tpTIBasePath` and set its value to the full path to the working directory, e.g. `C:\Users\Simone\source\tpTI` + + * once you set it, in order to be usable at command line you need to open a new session of prompt/powershell + + * if you open the session you can check it is working by running `echo %tpTIBasePath%` in command prompt (or `$env:tpTIBasePath` in powershell) + This should display the whole path to tpTI. + + +## opencv + +OpenCV is a computer vision library that contains some of the algorithms we are using for image processing and pose estimation. +To install it: + +* download the library from the repository https://github.com/opencv/opencv/archive/3.4.13.zip + +* unzip the file into %tpTIBasePath% (a folder named `opencv-3.4.13` should appear). + +* from `%tpTIBasePath%\opencv-3.4.13` create a `build` directory (`mkdir build`) + +* from the terminal/prompt, go to `%tpTIBasePath%\opencv-3.4.13\build` and execute the following: + + ``` + cmake .. -G "Visual Studio 16 2019" -A x64 -DCMAKE_BUILD_TYPE=Release -DWITH_CUDA:BOOL=OFF -DBUILD_PERF_TESTS:BOOL=OFF -DBUILD_TESTS:BOOL=OFF + ``` + +> if you had a different version of VS installed (not the latest) you may need to adapt the string `Visual Studio 16 2019` to your version: e.g. `Visual Studio 15 2017`, `Visual Studio 14 2015`, `Visual Studio 12 2013` etc + +* then execute + + ``` + cmake --build . --config Release + ``` + + and go grab a cup of coffee or a beverage of your choice ;-) + + +## Setting up the runtime environment variables + +The last step before start working on the TP is to set up the environment variables that allows the system to find the libraries you just installed/built. + +* from the prompt execute `c:\Windows\System32\SystemPropertiesAdvanced.exe ` + + * click `Environment Variables...` (`Variables d'environnement...`) + + * in `User Variables for ...` (`Variables utilisateur pour...`), select the variable `Path` and then click `Edit...` + + * add at the bottom of the list the following paths: + + * `%tpTIBasePath%\opencv-2.4.13.4\build\bin\Release` diff --git a/data/images/HappyFish.png b/data/images/HappyFish.png new file mode 100644 index 0000000..5193089 Binary files /dev/null and b/data/images/HappyFish.png differ diff --git a/data/images/cat.jpg b/data/images/cat.jpg new file mode 100644 index 0000000..df4a907 Binary files /dev/null and b/data/images/cat.jpg differ diff --git a/data/images/texture11.png b/data/images/texture11.png new file mode 100644 index 0000000..5d60197 Binary files /dev/null and b/data/images/texture11.png differ diff --git a/data/images/texture11_VT.png b/data/images/texture11_VT.png new file mode 100644 index 0000000..543d9e4 Binary files /dev/null and b/data/images/texture11_VT.png differ diff --git a/data/images/texture3.png b/data/images/texture3.png new file mode 100644 index 0000000..34034f6 Binary files /dev/null and b/data/images/texture3.png differ diff --git a/data/images/texture3_VT.png b/data/images/texture3_VT.png new file mode 100644 index 0000000..bb23e77 Binary files /dev/null and b/data/images/texture3_VT.png differ diff --git a/data/images/texture8.png b/data/images/texture8.png new file mode 100644 index 0000000..9cdf7f0 Binary files /dev/null and b/data/images/texture8.png differ diff --git a/data/images/texture8_VT.png b/data/images/texture8_VT.png new file mode 100644 index 0000000..7461948 Binary files /dev/null and b/data/images/texture8_VT.png differ diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..835dc49 --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory(tp) +add_subdirectory(tutorials) \ No newline at end of file diff --git a/src/tp/CMakeLists.txt b/src/tp/CMakeLists.txt new file mode 100644 index 0000000..f24248b --- /dev/null +++ b/src/tp/CMakeLists.txt @@ -0,0 +1,9 @@ +find_package(OpenMP) +if (OPENMP_FOUND) + set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") + set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") + set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") +endif() + +add_executable( main main.cpp ocv_utils.cpp ocv_utils.hpp) +target_link_libraries( main ${OpenCV_LIBS} ) \ No newline at end of file diff --git a/src/tp/main.cpp b/src/tp/main.cpp new file mode 100644 index 0000000..0f7d7c4 --- /dev/null +++ b/src/tp/main.cpp @@ -0,0 +1,507 @@ +#include "ocv_utils.hpp" + +#include +#include +#include +#include +#include +#include +#include + +using namespace cv; +using namespace std; + +// ------------------------------------------------------------------------------------------------------------------------ + +void printHelp(const string &progName) +{ + cout << "Usage:\n\t " << progName << " []" << endl; +} + +int min(int a, int b) +{ + return a < b ? a : b; +} + +int max(int a, int b) +{ + return a > b ? a : b; +} + +/** + * @brief Calculate the euclidean distance between {r,it_max,b} and {R,G,B} + * + * @param r red + * @param g green + * @param b blue + * @param R Red + * @param G Green + * @param B Blue + * @return distance between {r,it_max,b} and {R,G,B} + */ +int distance(int r, int g, int b, int R, int G, int B) +{ + return sqrt((r - R) * (r - R) + (g - G) * (g - G) + (b - B) * (b - B)); +} + +/** + * @brief Calculate the index of the closest center from the color + * + * @param color + * @param centers + * @return index of the closest center + */ +int closestCenter(Vec3b color, Mat centers) +{ + // Extract r it_max b values + int r = color[0]; + int it_max = color[1]; + int b = color[2]; + + // Initialize variables + int minDistance = sqrt(3 * 255 * 255) + 1; + int closest; + + // Test each centers + for (int i = 0; i < centers.rows; i++) + { + // Extract R G B values from the current center + int R = centers.at(i, 0); + int G = centers.at(i, 1); + int B = centers.at(i, 2); + + // Replace varibales with new values if necessary + int curDistance = distance(r, it_max, b, R, G, B); + if (curDistance < minDistance) + { + minDistance = curDistance; + closest = i; + } + } + return closest; +} + +// ------------------------------------------------------------------------------------------------------------------------ + +/** + * @brief Calculate the k-means of the vect + * + * @param vect + * @param k + * @return Centers of vect + */ +Mat kmeans(Mat vect, int k) +{ + Mat centers(k, 1, CV_32FC3); + + // initialisation des centres + for (int i = 0; i < k; i++) + { + centers.at(i) = vect.at(i * vect.rows / k); + } + + int it = 0; + int it_max = 20000; + int counters[k]; + Mat prevCenters; + + do + { + // initialiser les varibales de boucle + prevCenters = centers.clone(); + for (int i = 0; i < k; i++) + { + counters[i] = 0; + } + + // compter les centres + // sommer les pixels de chaque classe + centers = Mat::zeros(k, 1, CV_32FC3); + for (int i = 0; i < vect.cols; i++) + { + Vec3f color = vect.at(i); + int closest = closestCenter(color, prevCenters); + centers.at(closest) += color; + counters[closest]++; + } + + // faire la moyennes des pixels de chaque classe + for (int i = 0; i < k; i++) + { + if (counters[i] != 0) + centers.at(i) /= counters[i]; + } + + } while (it++ < it_max && sum(centers != prevCenters) != Scalar(0, 0, 0, 0)); + cout << "kmeans terminé en " << it << " itérations." << endl << endl; + + return centers; +} + +// ------------------------------------------------------------------------------------------------------------------------ + +/** + * @brief + * + * @param s_i + * @param s_j + * @param d_i + * @param d_j + * @param matIMG + * @param matMOY + * @param matCOUNT + * @param hc + * @return float + */ +float compute(int s_i, int s_j, int d_i, int d_j, Mat *matIMG, Mat *matMOY, Mat *matCOUNT, double hc) +{ + Vec3f centre = matIMG->at(s_i, s_j); + Vec3f dest = matIMG->at(d_i, d_j); + + // seuil chromatique + float dist = cv::norm(dest - centre); + if (dist < hc) + { + matMOY->at(s_i, s_j) += dest; + matMOY->at(d_i, d_j) += centre; + + matCOUNT->at(s_i, s_j)++; + matCOUNT->at(d_i, d_j)++; + + return dist; + } + + return 0; +} + +/** + * @brief Calculate the k-means of the matIMG + * + * @param hs + * @param hc + * @param eps + * @param itMax + * @param matIMG + * @return Mat + */ +Mat meanshift(uint hs, double hc, double eps, uint itMax, Mat matIMG) +{ + Mat matMOY, matCOUNT; + float maxDist, dist; + int i, j; + + int it = 0; + + #pragma omp parallel shared(it) + + do { + #pragma omp single + { + cout << " mean-shit (" << it << "/" << itMax << ")" << endl; + + matMOY = Mat::zeros(matIMG.rows, matIMG.cols, CV_32FC3); + matCOUNT = Mat::zeros(matIMG.rows, matIMG.cols, CV_32FC1); + maxDist = 0; + it++; + } + + #pragma omp for private(i, j) + for (i = 0; i < matIMG.rows; i++) + { + for (j = 0; j < matIMG.cols; j++) + { + // pixels à droite du centre + for (int j2 = j; j2 < min(j + hs + 1, matIMG.cols); j2++) + { + dist = compute(i, j, i, j2, &matIMG, &matMOY, &matCOUNT, hc); + if (dist > maxDist) + { + maxDist = dist; + } + } + + // pixels en dessous du centre + for (int i2 = i + 1; i2 < min(i + hs + 1, matIMG.rows); i2++) + { + for (int j2 = max(j - hs, 0); j2 < min(j + hs + 1, matIMG.cols); j2++) + { + dist = compute(i, j, i2, j2, &matIMG, &matMOY, &matCOUNT, hc); + if (dist > maxDist) + { + maxDist = dist; + } + } + } + + matIMG.at(i, j) = matMOY.at(i, j) / matCOUNT.at(i, j); + } + } + // cout << "maxDist = " << maxDist << endl; + } + while (it < itMax); + + return matIMG; +} + +// ------------------------------------------------------------------------------------------------------------------------ + +/** + * @brief + * + * @param argc + * @param argv + * @return int + */ +int main(int argc, char **argv) +{ + if (argc != 3 && argc != 4) + { + cout << " Incorrect number of arguments." << endl; + printHelp(string(argv[0])); + return EXIT_FAILURE; + } + + const auto imageFilename = string(argv[1]); + const string groundTruthFilename = (argc == 4) ? string(argv[3]) : string(); + const int k = stoi(argv[2]); + + if (k < 1) + { + cout << " k must be a positive integer" << endl; + printHelp(string(argv[0])); + return EXIT_FAILURE; + } + + // trust file used ? + bool useTrust = !groundTruthFilename.empty() && k == 2; + + // just for debugging + { + cout << endl + << " Program called with the following arguments:" << endl; + cout << " \timage file: " << imageFilename << endl; + cout << " \tk: " << k << endl; + if (useTrust) + cout << " \tground truth segmentation: " << groundTruthFilename << endl + << endl; + } + + // load the color image to process from file + Mat sourceMatrix = imread(imageFilename, IMREAD_COLOR); + Mat trustMatrix = imread(groundTruthFilename, IMREAD_COLOR); + + // for debugging use the macro PRINT_MAT_INFO to print the info about the matrix, like size and type + PRINT_MAT_INFO(sourceMatrix); + + // convert the image into floats (CV_32F), for kmeans + Mat sourceMatrix32f; + sourceMatrix.convertTo(sourceMatrix32f, CV_32F); + + // reshape the image into a 1D array, for kmeans + Mat sourceMatrixReshaped = sourceMatrix32f.reshape(3, 1); + + // Call OpenCV's kmeans function + Mat labels, centers; + kmeans( + sourceMatrixReshaped, + k, + labels, + TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 10, 1.0), + 3, + KMEANS_PP_CENTERS, + centers); + + // Call ou kmeans function + centers = kmeans(sourceMatrixReshaped, k); + + // Create result matrix + Mat resultMatrix = sourceMatrix.clone(); + Mat diffMatrix = trustMatrix.clone(); + + // Some usefull colors + Vec3b white(255, 255, 255); + Vec3b black(0, 0, 0); + Vec3b red(255, 0, 0); + Vec3b blue(0, 0, 255); + + Vec3b colorMaj, colorMin; + if (useTrust) + { + // Count the number of pixel per class in the trust matrix + int n = 0, p = 0; + for (int i = 0; i < trustMatrix.rows; i++) + { + for (int j = 0; j < trustMatrix.cols; j++) + { + if (trustMatrix.at(i, j) == white) + { + n++; + } + else + { + p++; + } + } + } + + // Assign black/white to colorMaj/colorMin + if (n > p) + { + colorMaj = white; + colorMin = black; + } + else + { + colorMaj = black; + colorMin = white; + } + + // Count the number of pixel per class in the source matrix + n = 0; + p = 0; + for (int i = 0; i < resultMatrix.rows; i++) + { + for (int j = 0; j < resultMatrix.cols; j++) + { + Vec3b color = sourceMatrix.at(i, j); + int closest = closestCenter(color, centers); + if (closest == 0) + { + n++; + } + else + { + p++; + } + } + } + + // Reorganize centers to match with the trust matrix + if (n < p) + { + Vec3f tmp = centers.at(0); + centers.at(0) = centers.at(1); + centers.at(1) = tmp; + } + } + + // Quality counters + float TP = 0; + float FP = 0; + float TN = 0; + float FN = 0; + + // Loop for each pixel + for (int i = 0; i < resultMatrix.rows; i++) + { + for (int j = 0; j < resultMatrix.cols; j++) + { + Vec3b color = sourceMatrix.at(i, j); + + int closest = closestCenter(color, centers); + + // Set pixel color to the color of the closest center + // (Or black/white if we are using a trust image) + if (useTrust && closest == 0) + { + resultMatrix.at(i, j) = colorMaj; + } + else if (useTrust && closest == 1) + { + resultMatrix.at(i, j) = colorMin; + } + else + { + resultMatrix.at(i, j) = centers.at(closest); + } + + // Increment counters for the quality evaluations + if (useTrust) + { + if (trustMatrix.at(i, j) != resultMatrix.at(i, j)) + { + diffMatrix.at(i, j) = trustMatrix.at(i, j) == colorMaj ? red : blue; + + if (trustMatrix.at(i, j) == colorMaj) + { + // False negative + FN++; + } + else + { + // False positive + FP++; + } + } + else + { + if (trustMatrix.at(i, j) == colorMaj) + { + // True positive + TP++; + } + else + { + // True negative + TN++; + } + } + } + } + } + + // Trust comparison results + if (useTrust) + { + float P = TP / (TP + FP); + float S = TP / (TP + FN); + float DSC = 2 * TP / (2 * TP + FP + FN); + + cout << endl + << "counters = " << endl + << " TP = " << TP << endl + << " TN = " << TN << endl + << " FP = " << FP << endl + << " FN = " << FN << endl + << " Total (debug) = " << (TP + TN + FP + FN) << endl + << endl + << " Precision = " << P << endl + << " Sensibility = " << S << endl + << " DICE Similarity Coefficient = " << DSC << endl; + } + + // compute meanshift for the image + int hs = 2; + int hc = 10; + double eps = 1.0; + int ite = 5; + + Mat msMatrix = meanshift(hs, hc, eps, ite, sourceMatrix32f); + Mat msMatrixU; + msMatrix.convertTo(msMatrixU, CV_8U); + + // create image windows + namedWindow("Source", cv::WINDOW_AUTOSIZE); + namedWindow("Result", cv::WINDOW_AUTOSIZE); + if (useTrust) + { + namedWindow("Trust", cv::WINDOW_AUTOSIZE); + namedWindow("Diff", cv::WINDOW_AUTOSIZE); + } + namedWindow("Mean Shift", cv::WINDOW_AUTOSIZE); + + // show images + imshow("Source", sourceMatrix); + imshow("Result", resultMatrix); + if (useTrust) + { + imshow("Trust", trustMatrix); + imshow("Diff", diffMatrix); + } + imshow("Mean Shift", msMatrixU); + + // press q to end + while (waitKey(0) != 113); + + return EXIT_SUCCESS; +} diff --git a/src/tp/ocv_utils.cpp b/src/tp/ocv_utils.cpp new file mode 100644 index 0000000..a4d77d1 --- /dev/null +++ b/src/tp/ocv_utils.cpp @@ -0,0 +1,40 @@ +#include "ocv_utils.hpp" + +#include +std::string getMatType(int number) +{ + // find type + const int imgTypeInt = number % 8; + std::string imgTypeString; + + switch(imgTypeInt) + { + case 0: imgTypeString = "8U"; break; + case 1: imgTypeString = "8S"; break; + case 2: imgTypeString = "16U"; break; + case 3: imgTypeString = "16S"; break; + case 4: imgTypeString = "32S"; break; + case 5: imgTypeString = "32F"; break; + case 6: imgTypeString = "64F"; break; + default: break; + } + + // find channel + const int channel = (number / 8) + 1; + + std::stringstream type; + type << "CV_" << imgTypeString << "C" << channel; + + return type.str(); +} + +void printMatInfo(const std::string& message, const cv::Mat& m) +{ + std::cout << message << ": " << m.size() << " ch: "<< m.channels() << " type: " << getMatType(m.type()) << std::endl; +} + + +std::string getMatType(const cv::Mat& m) +{ + return getMatType(m.type()); +} \ No newline at end of file diff --git a/src/tp/ocv_utils.hpp b/src/tp/ocv_utils.hpp new file mode 100644 index 0000000..770109c --- /dev/null +++ b/src/tp/ocv_utils.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include + +#include + +/** + * @brief Print the information about the matrix (size, channels and type). + * @param message A message to print before the matrix info: the output is in the format "message: [RxC] ch: #channels type: CV_XXTCY" + * @param m The matrix. + */ +void printMatInfo(const std::string& message, const cv::Mat& m); + +/** + * @brief Print the information about a matrix with the name given by variable name. + */ +#define PRINT_MAT_INFO(mat) printMatInfo(#mat, mat) + +/** + * @brief Return the matrix type in readable string format + * @param m The matrix + * @return A string with the matrix type in string format, e.g. "CV_8UC3" + */ +std::string getMatType(const cv::Mat& m); \ No newline at end of file diff --git a/src/tp/ocv_utils.hpp.gch b/src/tp/ocv_utils.hpp.gch new file mode 100644 index 0000000..a5bcd70 Binary files /dev/null and b/src/tp/ocv_utils.hpp.gch differ diff --git a/src/tutorials/CMakeLists.txt b/src/tutorials/CMakeLists.txt new file mode 100644 index 0000000..c77865d --- /dev/null +++ b/src/tutorials/CMakeLists.txt @@ -0,0 +1,17 @@ +######################################################### +# +# OPENCV TUTORIALS +# +######################################################### + +add_executable( display_image display_image.cpp ) +target_link_libraries( display_image ${OpenCV_LIBS} ) + +add_executable( load_modify_image load_modify_image.cpp ) +target_link_libraries( load_modify_image ${OpenCV_LIBS} ) + +add_executable( mat_the_basic_image_container mat_the_basic_image_container.cpp ) +target_link_libraries( mat_the_basic_image_container ${OpenCV_LIBS} ) + + +add_custom_target( tutorials DEPENDS load_modify_image display_image mat_the_basic_image_container ) diff --git a/src/tutorials/display_image.cpp b/src/tutorials/display_image.cpp new file mode 100644 index 0000000..b06927e --- /dev/null +++ b/src/tutorials/display_image.cpp @@ -0,0 +1,37 @@ +#include +#include + +#include + +using namespace cv; +using namespace std; + +int main(int argc, char **argv) +{ + if (argc != 2) + { + cout << " Usage: display_image ImageToLoadAndDisplay" << endl; + return EXIT_FAILURE; + } + + // Read the file + Mat image = imread(argv[1], cv::IMREAD_COLOR); + + // Check for invalid input + if (image.empty()) + { + cout << "Could not open or find the image" << std::endl; + return EXIT_FAILURE; + } + + // Create a window for display. + namedWindow("Display window", cv::WINDOW_AUTOSIZE); + + // Show our image inside it. + imshow("Display window", image); + + // Wait for a keystroke in the window + waitKey(0); + + return EXIT_SUCCESS; +} \ No newline at end of file diff --git a/src/tutorials/load_modify_image.cpp b/src/tutorials/load_modify_image.cpp new file mode 100644 index 0000000..432a391 --- /dev/null +++ b/src/tutorials/load_modify_image.cpp @@ -0,0 +1,45 @@ +#include +#include +#include + +#include + +using namespace cv; +using namespace std; + +int main(int argc, char **argv) +{ + // Read the filename + char *imageName = argv[1]; + + // load image from file + Mat image = imread(imageName, IMREAD_COLOR); + + if (argc != 2 || image.empty()) + { // verify the image was correctly loaded + cerr << " No image data " << endl; + return EXIT_FAILURE; + } + + // create new Mat, for the grey image + Mat gray_image; + + // convert the loaded image to grey, and copy it to gray_image + cvtColor(image, gray_image, cv::COLOR_BGR2GRAY); + + // write greyscale image to file + imwrite("Gray_Image.jpg", gray_image); + + // create windows + namedWindow(imageName, cv::WINDOW_AUTOSIZE); + namedWindow("Gray image", cv::WINDOW_AUTOSIZE); + + // show on windows + imshow(imageName, image); + imshow("Gray image", gray_image); + + // Wait for a keystroke in the window + waitKey(0); + + return EXIT_SUCCESS; +} diff --git a/src/tutorials/mat_the_basic_image_container.cpp b/src/tutorials/mat_the_basic_image_container.cpp new file mode 100644 index 0000000..f1fb728 --- /dev/null +++ b/src/tutorials/mat_the_basic_image_container.cpp @@ -0,0 +1,89 @@ +/* For description look into the help() function. */ + +#include "opencv2/core/core.hpp" + +#include + +using namespace std; +using namespace cv; + +static void help(char *progName) +{ + cout << "\n--------------------------------------------------------------------------" << endl + << "This program shows how to create matrices(cv::Mat) in OpenCV and its serial" + << " out capabilities" << endl + << "That is, cv::Mat M(...); M.create and cout << M. " << endl + << "Shows how output can be formatted to OpenCV, python, numpy, csv and C styles." << endl + << "Usage:" << endl + << std::string(progName) << endl + << "--------------------------------------------------------------------------" << endl + << endl; +} + +int main(int, char** argv) +{ + help(argv[0]); + // create by using the constructor + Mat M(2, 2, CV_8UC3, Scalar(0, 0, 255)); + cout << "M = " << endl << " " << M << endl << endl; + + // create by using the create function() + M.create(4, 4, CV_8UC(2)); + cout << "M = " << endl << " " << M << endl << endl; + + // create multidimensional matrices + int sz[3] = {2, 2, 2}; + Mat L(3, sz, CV_8UC(1), Scalar::all(0)); + // Cannot print via operator << + + // Create using MATLAB style eye, ones or zero matrix + Mat E = Mat::eye(4, 4, CV_64F); + cout << "E = " << endl << " " << E << endl << endl; + + Mat O = Mat::ones(2, 2, CV_32F); + cout << "O = " << endl << " " << O << endl << endl; + + Mat Z = Mat::zeros(3, 3, CV_8UC1); + cout << "Z = " << endl << " " << Z << endl << endl; + + // create a 3x3 double-precision identity matrix + Mat C = (Mat_(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0); + cout << "C = " << endl << " " << C << endl << endl; + + Mat RowClone = C.row(1).clone(); + cout << "RowClone = " << endl << " " << RowClone << endl << endl; + + // Fill a matrix with random values + Mat R = Mat(3, 2, CV_8UC3); + randu(R, Scalar::all(0), Scalar::all(255)); + + // Demonstrate the output formating options +#if CV_MAJOR_VERSION < 3 + cout << "R (default) = " << endl << R << endl << endl; + cout << "R (python) = " << endl << format(R, "python") << endl << endl; + cout << "R (numpy) = " << endl << format(R, "numpy") << endl << endl; + cout << "R (csv) = " << endl << format(R, "csv") << endl << endl; + cout << "R (c) = " << endl << format(R, "C") << endl << endl; +#endif + + Point2f P(5, 1); + cout << "Point (2D) = " << P << endl << endl; + + Point3f P3f(2, 6, 7); + cout << "Point (3D) = " << P3f << endl << endl; + + vector v; + v.push_back((float)CV_PI); + v.push_back(2); + v.push_back(3.01f); + + cout << "Vector of floats via Mat = " << Mat(v) << endl << endl; + + vector vPoints(20); + for(size_t i = 0; i < vPoints.size(); ++i) + vPoints[i] = Point2f((float)(i * 5), (float)(i % 7)); + + cout << "A vector of 2D Points = " << vPoints << endl << endl; + + return EXIT_SUCCESS; +} \ No newline at end of file