chore: add files
63
BUILD.md
Normal file
|
@ -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=<opencv install path> ..`
|
||||
|
||||
Replace `<opencv install path>` 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**)
|
||||
|
||||
|
17
CMakeLists.txt
Normal file
|
@ -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)
|
79
DEP_LINUX.md
Normal file
|
@ -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.
|
62
DEP_OSX.md
Normal file
|
@ -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.
|
89
DEP_WINDOWS.md
Normal file
|
@ -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`
|
BIN
data/images/HappyFish.png
Normal file
After Width: | Height: | Size: 42 KiB |
BIN
data/images/cat.jpg
Normal file
After Width: | Height: | Size: 64 KiB |
BIN
data/images/texture11.png
Normal file
After Width: | Height: | Size: 137 KiB |
BIN
data/images/texture11_VT.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
data/images/texture3.png
Normal file
After Width: | Height: | Size: 111 KiB |
BIN
data/images/texture3_VT.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
data/images/texture8.png
Normal file
After Width: | Height: | Size: 145 KiB |
BIN
data/images/texture8_VT.png
Normal file
After Width: | Height: | Size: 16 KiB |
2
src/CMakeLists.txt
Normal file
|
@ -0,0 +1,2 @@
|
|||
add_subdirectory(tp)
|
||||
add_subdirectory(tutorials)
|
9
src/tp/CMakeLists.txt
Normal file
|
@ -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} )
|
507
src/tp/main.cpp
Normal file
|
@ -0,0 +1,507 @@
|
|||
#include "ocv_utils.hpp"
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/imgcodecs.hpp>
|
||||
#include <opencv2/highgui.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
#include <opencv2/imgcodecs.hpp>
|
||||
#include <iostream>
|
||||
#include <omp.h>
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
// ------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
void printHelp(const string &progName)
|
||||
{
|
||||
cout << "Usage:\n\t " << progName << " <image_file> <K_num_of_clusters> [<image_ground_truth>]" << 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<float>(i, 0);
|
||||
int G = centers.at<float>(i, 1);
|
||||
int B = centers.at<float>(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<Vec3f>(i) = vect.at<Vec3f>(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<Vec3f>(i);
|
||||
int closest = closestCenter(color, prevCenters);
|
||||
centers.at<Vec3f>(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<Vec3f>(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<Vec3f>(s_i, s_j);
|
||||
Vec3f dest = matIMG->at<Vec3f>(d_i, d_j);
|
||||
|
||||
// seuil chromatique
|
||||
float dist = cv::norm(dest - centre);
|
||||
if (dist < hc)
|
||||
{
|
||||
matMOY->at<Vec3f>(s_i, s_j) += dest;
|
||||
matMOY->at<Vec3f>(d_i, d_j) += centre;
|
||||
|
||||
matCOUNT->at<float>(s_i, s_j)++;
|
||||
matCOUNT->at<float>(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<Vec3f>(i, j) = matMOY.at<Vec3f>(i, j) / matCOUNT.at<float>(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<Vec3b>(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<Vec3b>(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<Vec3f>(0);
|
||||
centers.at<Vec3f>(0) = centers.at<Vec3f>(1);
|
||||
centers.at<Vec3f>(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<Vec3b>(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<Vec3b>(i, j) = colorMaj;
|
||||
}
|
||||
else if (useTrust && closest == 1)
|
||||
{
|
||||
resultMatrix.at<Vec3b>(i, j) = colorMin;
|
||||
}
|
||||
else
|
||||
{
|
||||
resultMatrix.at<Vec3b>(i, j) = centers.at<Vec3b>(closest);
|
||||
}
|
||||
|
||||
// Increment counters for the quality evaluations
|
||||
if (useTrust)
|
||||
{
|
||||
if (trustMatrix.at<Vec3b>(i, j) != resultMatrix.at<Vec3b>(i, j))
|
||||
{
|
||||
diffMatrix.at<Vec3b>(i, j) = trustMatrix.at<Vec3b>(i, j) == colorMaj ? red : blue;
|
||||
|
||||
if (trustMatrix.at<Vec3b>(i, j) == colorMaj)
|
||||
{
|
||||
// False negative
|
||||
FN++;
|
||||
}
|
||||
else
|
||||
{
|
||||
// False positive
|
||||
FP++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (trustMatrix.at<Vec3b>(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;
|
||||
}
|
40
src/tp/ocv_utils.cpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
#include "ocv_utils.hpp"
|
||||
|
||||
#include <iostream>
|
||||
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());
|
||||
}
|
24
src/tp/ocv_utils.hpp
Normal file
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
/**
|
||||
* @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);
|
BIN
src/tp/ocv_utils.hpp.gch
Normal file
17
src/tutorials/CMakeLists.txt
Normal file
|
@ -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 )
|
37
src/tutorials/display_image.cpp
Normal file
|
@ -0,0 +1,37 @@
|
|||
#include <opencv2/core/core.hpp>
|
||||
#include <opencv2/highgui/highgui.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
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;
|
||||
}
|
45
src/tutorials/load_modify_image.cpp
Normal file
|
@ -0,0 +1,45 @@
|
|||
#include <opencv2/core/core.hpp>
|
||||
#include <opencv2/highgui/highgui.hpp>
|
||||
#include <opencv2/imgproc/imgproc.hpp>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
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;
|
||||
}
|
89
src/tutorials/mat_the_basic_image_container.cpp
Normal file
|
@ -0,0 +1,89 @@
|
|||
/* For description look into the help() function. */
|
||||
|
||||
#include "opencv2/core/core.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
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_<double>(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<float> 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<Point2f> 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;
|
||||
}
|