-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Entscheider
committed
May 18, 2016
1 parent
5042d38
commit 55661f7
Showing
52 changed files
with
5,168 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
cmake_minimum_required(VERSION 2.8.4) | ||
project(RSlic) | ||
|
||
include(CheckCXXCompilerFlag) | ||
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11) | ||
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X) | ||
|
||
if(COMPILER_SUPPORTS_CXX11) | ||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") | ||
elseif(COMPILER_SUPPORTS_CXX0X) | ||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") | ||
else() | ||
message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") | ||
endif() | ||
|
||
add_subdirectory(apps) | ||
add_subdirectory(lib) | ||
|
||
configure_file( | ||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" | ||
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" | ||
IMMEDIATE @ONLY) | ||
|
||
add_custom_target(uninstall | ||
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
# Overview | ||
RSlic is a library written in C++ for computing Superpixel and Supervoxel using OpenCV. It based on the Slic-Algorithmus (http://ivrg.epfl.ch/research/superpixels). | ||
|
||
# Features | ||
- Compute Superpixel and Supervoxel | ||
- Support for the zero parameter version of the SLIC algorithm (SLICO) | ||
- Support for custom metrics | ||
- Ability to save any iteration while computing (e.g. SuperPixelGUI makes use of it) | ||
|
||
# Dependency | ||
To build RSlic you need: | ||
- OpenCV | ||
- CMake | ||
- optional: ccmake or cmake-gui for a configuration interface | ||
- C++11 Compiler (e.g. gcc or clang) | ||
- Qt4 or Qt5 for GUI-Apps | ||
|
||
# Installing | ||
Go into the source directory and run: | ||
|
||
``` | ||
$ mkdir build && cd build | ||
$ cmake .. | ||
$ make | ||
$ make install | ||
``` | ||
|
||
Or run *ccmake* if you want to configure somethings before building. (E.g. you can disable thread usage. Or prefer Qt4 over Qt5) | ||
|
||
# Create a project | ||
## CMakeLists | ||
Create a CMakeLists.txt for your project. If your project has the name myproj, the CMakeLists.txt should contains something like: | ||
|
||
``` | ||
find_package(RSlic REQUIRED) | ||
include_directories(${RSLIC_INCLUDE_DIRS}) | ||
add_executable(myproj main.cpp ...) | ||
target_link_libraries(myproj ${RSLIC_LIB}) | ||
``` | ||
|
||
By the way: Your project will (and have to) use C++11 now. | ||
|
||
## Including the files | ||
If you would like to use Superpixel the simplest way would be to import RSlic/RSlic2H.h: | ||
|
||
```cpp | ||
#include <RSlic/RSlic2H.h> | ||
``` | ||
|
||
and if you want to use Supervoxel: | ||
|
||
```cpp | ||
#include <RSlic/RSlic3H.h> | ||
``` | ||
Of course you can use Superpixel and Supervoxel at the same time. | ||
|
||
## Simple introduction RSlic | ||
Executing the Slic-Algorithmus is very simple. Let's say you have a gray image img, want n Superpixel with a special stiffness. Then: | ||
|
||
```cpp | ||
#include <RSlic/RSlic2H.h> | ||
using namespace RSlic::Pixel; | ||
.... | ||
Mat grad = buildGrad(img); //Build the gradient for the algorithm | ||
int w = m.cols; | ||
int h = m.rows; | ||
int step = sqrt(w * h * 1.0 / n); //Calc the step-width | ||
Slic2P slic = Slic2::initialize(img,grad,step,stiffness); //Initialize with the parameter | ||
for (int i=0; i < 10; i++){ //Do 10 Iterations | ||
slic = slic->iterate<distanceGray>(); | ||
//slic = slic->iterateZero<distanceGray>(); //For the zero parameter version | ||
} | ||
slic = slic->finalize<distanceGray>(); | ||
``` | ||
Now you can work with *slic*. Mainly you want to use | ||
*slic->getClusters()*. See the documentation for more details. | ||
You're not sure if you have a gray image or a colorful one? | ||
```cpp | ||
#include <RSlic/RSlic2H.h> | ||
using namespace RSlic::Pixel; | ||
.... | ||
Mat grad = buildGrad(img); //Build the gradient for the algorithms | ||
int w = m.cols; | ||
int h = m.rows; | ||
int step = sqrt(w * h * 1.0 / n); //Calc the step-width | ||
Slic2P slic = Slic2::initialize(img,grad,step,stiffness); //Initialize with the parameter | ||
for (int i=0; i < 10; i++){ //Do 10 Iterations | ||
slic = iteratingHelper(slic, img.type()); | ||
// slic = iteratingHelper(slic, img.type(), true); //For the zero parameter version | ||
} | ||
slic = slic->finalize<distanceGray>(); | ||
``` | ||
|
||
You think that's not simple enough? OK, an easier version: | ||
```cpp | ||
#include <RSlic/RSlic2H.h> | ||
using namespace RSlic::Pixel; | ||
.... | ||
//10-Iterations | ||
Slic2P slic = shutUpAndTakeMyMoney(img, n, hardness, false, 10); | ||
//10-Iterations with Slico | ||
//Slic2P slic = shutUpAndTakeMyMoney(img, n, hardness, true, 10); | ||
``` | ||
Note that Slic is often intended to be applied on top of LAB images. So you may want to convert your image before using the functions above. (Use OpenCV for this) | ||
# 3rd Party Code | ||
This library uses the ThreaPool file from https://github.com/progschj/ThreadPool. | ||
The RSlic library uses threads if 'PARALLEL' is enabled in CMakeCache. | ||
# License | ||
BSD license |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
project(3DTest) | ||
|
||
find_package( OpenCV REQUIRED ) | ||
include_directories ("${3DTest_SOURCE_DIR}/../../lib") | ||
set(CMAKE_INCLUDE_CURRENT_DIR ON) | ||
|
||
set(SOURCE_FILES main.cpp parser.cpp exporter.cpp) | ||
add_executable(3DTest ${SOURCE_FILES}) | ||
|
||
target_link_libraries(3DTest rslic ${OpenCV_LIBS}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# 3DTest | ||
|
||
3DTest is a program which creates a point cloud from several images with Supervoxel. | ||
The export format is ply. | ||
|
||
Additionally, a window appears which shows the result in pictures. | ||
The following keys help navigate through these pictures: | ||
|
||
- a Go a picture backward | ||
- s Go a picture forward | ||
- t Toggle between showing contour in z-direction | ||
- d Show some debug information | ||
- q Close the window | ||
|
||
The following arguments are allowed on the command line: | ||
|
||
- -c Number of Supervoxel (optional) | ||
- -m Stiffness (optional) | ||
- -t Number of threads to be used (optional) | ||
- -0 Use Slico (optional) | ||
- -h Show some help and exit | ||
- -o Output filename for the point cloud. (optional). The points cloud will only exported if a filename is set. | ||
- pictures | ||
|
||
Some command can like this: | ||
|
||
` | ||
./3DTest -c 39000 -m 40 -i 10 -o out.ply pic001.tif pic002.tif | ||
` | ||
|
||
` | ||
./3DTest -0 -o out.ply img/*.tif | ||
` | ||
|
||
or without exporting: | ||
|
||
` | ||
./3DTest img/*.tif | ||
` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
#include "exporter.h" | ||
#include <iostream> | ||
#include <fstream> | ||
using namespace std; | ||
using namespace RSlic::Voxel; | ||
|
||
// Return coordinates of points which are between clusters | ||
// mask.empty => ignore mask | ||
vector<Vec3i> contourVertex(Slic3P p, const Mat &mask) { | ||
Mat_<ClusterInt> clusters = p->getClusters().getClusterLabel(); | ||
int w = clusters.size[1]; | ||
int h = clusters.size[0]; | ||
int d = clusters.size[2]; | ||
vector<Vec3i> res; | ||
for (int x = 0; x < w - 1; x++) { | ||
for (int y = 0; y < h - 1; y++) { | ||
for (int t = 0; t < d - 1; t++) { | ||
if (clusters.at<ClusterInt>(y, x, t) != clusters.at<ClusterInt>(y, x, t + 1) | ||
|| clusters.at<ClusterInt>(y, x, t) != clusters.at<ClusterInt>(y, x + 1, t) | ||
|| clusters.at<ClusterInt>(y, x, t) != clusters.at<ClusterInt>(y + 1, x, t)){ | ||
if (!mask.empty() && mask.at<uint8_t>(y,x,t) == 0) continue; | ||
res.push_back(Vec3i(x, y, t)); | ||
} | ||
} | ||
} | ||
} | ||
return res; | ||
} | ||
|
||
void exportPLY(const vector<Vec3i> &vertex, const string &filename,RSlic::Voxel::MovieCacheP img, const string & comments) { | ||
ofstream out; | ||
out.open(filename); | ||
if (out.fail()) { | ||
cout << "[ERROR] Opening " << filename << " failed" << endl; | ||
return; | ||
} | ||
out << "ply" << endl; | ||
if (!comments.empty()) | ||
out << "comment " <<comments << endl; | ||
out << "format ascii 1.0 " << endl; | ||
out << "element vertex " << vertex.size() << endl; | ||
//out<<"property list uchar int vertex_index"<<endl; | ||
out << "property int x" << endl | ||
<< "property int y" << endl | ||
<< "property int z" << endl | ||
<< "property uchar red "<<endl | ||
<< "property uchar green"<<endl | ||
<<"property uchar blue"<<endl; | ||
out << "end_header" << endl; | ||
for (const Vec3i &vec: vertex) { | ||
int x = vec[0]; | ||
int y = vec[1]; | ||
int z = vec[2]; | ||
Vec3b color(0,0,0); | ||
if (img->type() == CV_8UC1) color = Vec3b::all(img->at<uint8_t>(y,x,z)); | ||
else if (img->type()==CV_8UC3) color = img->at<Vec3b>(y,x,z); | ||
int r = color[1] , g = color[0],b = color[2]; | ||
out << x << ' ' << y << ' ' << z | ||
<< ' ' << r <<' ' << g << ' ' << b <<endl; | ||
} | ||
out.close(); | ||
} | ||
|
||
|
||
|
||
|
||
#include <opencv2/highgui/highgui.hpp> | ||
template <typename T> | ||
void showNrIntern(cv::Mat labels, int i, bool tIgnore, Mat &img, T value){ | ||
for (int x = 1; x < img.cols - 1; x++) { | ||
for (int y = 1; y < img.rows - 1; y++) { | ||
if (labels.at<ClusterInt>(y, x, i) < 0){ | ||
std::cout<<"Fail"; | ||
continue; | ||
} | ||
if ((labels.at<ClusterInt>(y, x, i) != labels.at<ClusterInt>(y, x + 1, i) | ||
|| labels.at<ClusterInt>(y, x, i) != labels.at<ClusterInt>(y, x - 1, i) | ||
|| labels.at<ClusterInt>(y, x, i) != labels.at<ClusterInt>(y + 1, x, i) | ||
|| labels.at<ClusterInt>(y, x, i) != labels.at<ClusterInt>(y - 1, x, i)) | ||
&& (tIgnore || (labels.at<ClusterInt>(y, x, i) == labels.at<ClusterInt>(y, x, i-1) | ||
&& labels.at<ClusterInt>(y, x, i) == labels.at<ClusterInt>(y, x, i+1) | ||
)) | ||
) | ||
img.at<T>(y, x) = value; | ||
} | ||
} | ||
} | ||
|
||
// Get a 2-D image visualization | ||
// tIgnore: ignore time-dimension for cluster contour | ||
void showNr(Slic3P p, int i, bool tIgnore) { | ||
auto img = p->getImg()->matAt(i).clone(); | ||
auto labels = p->getClusters().getClusterLabel(); | ||
if (img.type()==CV_8UC3){ | ||
cv::cvtColor(img, img, cv::COLOR_Lab2BGR); | ||
showNrIntern<Vec3b>(labels,i,tIgnore,img,Vec3b(255,255,255)); | ||
}else{ | ||
showNrIntern<uint8_t>(labels,i,tIgnore,img,255); | ||
} | ||
|
||
imshow("Hi", img); | ||
} | ||
#include <unordered_set> | ||
|
||
// Show first image | ||
// and handling for key events | ||
void showFirst(Slic3P p) { | ||
int i = 0; | ||
const int d = p->getImg()->duration(); | ||
bool tIgnore(false); | ||
showNr(p, i, tIgnore); | ||
char c; | ||
do { | ||
c = waitKey(-1); | ||
if (c == 's') { | ||
i = min(i + 1, d - 1); | ||
showNr(p, i, tIgnore); | ||
} | ||
else if (c == 't'){ | ||
tIgnore = !tIgnore; | ||
showNr(p,i,tIgnore); | ||
} | ||
else if (c == 'a') { | ||
i = max(i - 1, 0); | ||
showNr(p, i, tIgnore); | ||
}else if (c=='d'){ | ||
auto labels = p->getClusters().getClusterLabel(); | ||
std::cout<<"Nr. "<<i<<std::endl; | ||
std::unordered_set<ClusterInt> set; | ||
auto img = p->getImg()->matAt(i); | ||
for (int x = 1; x < img.cols - 1; x++) { | ||
for (int y = 1; y < img.rows - 1; y++) { | ||
set.insert(labels.at<ClusterInt>(y,x,i)); | ||
} | ||
} | ||
for (ClusterInt c : set){ | ||
std::cout<<c<<","; | ||
} | ||
std::cout<<std::endl; | ||
} | ||
} while (c != 'q'); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
#ifndef EXPORTER_H | ||
#define EXPORTER_H | ||
|
||
#include <Voxel/RSlic3.h> | ||
#include <vector> | ||
|
||
void exportPLY(const std::vector<Vec3i> &vertex, const std::string &filename, RSlic::Voxel::MovieCacheP img, const string &comments = string()); | ||
|
||
std::vector<Vec3i> contourVertex(RSlic::Voxel::Slic3P p, const Mat & mask = Mat()); | ||
|
||
|
||
void showNr(RSlic::Voxel::Slic3P p, int i, bool tIgnore); | ||
|
||
void showFirst(RSlic::Voxel::Slic3P p); | ||
|
||
#endif // EXPORTER_H |
Oops, something went wrong.