├── .gitignore ├── .gitmodules ├── .travis.yml ├── CMakeLists.txt ├── README.md ├── bin └── .gitignore ├── cis_cli ├── CMakeLists.txt └── main.cpp ├── crs_cli ├── CMakeLists.txt └── main.cpp ├── ers_cli ├── CMakeLists.txt └── main.cpp ├── fh_cli ├── CMakeLists.txt └── main.cpp ├── lib └── .gitignore ├── lib_cis ├── CMakeLists.txt ├── README.md ├── superpixels.h └── vlib │ └── CMakeLists.txt ├── lib_crs ├── AGaussianFeature.h ├── CMakeLists.txt ├── ColorFeature.h ├── CompactnessFeature.h ├── ContourRelaxation.h ├── DepthFeature.h ├── FeatureType.h ├── GrayvalueFeature.h ├── IFeature.h ├── InitializationFunctions.h ├── LICENSE.txt ├── LabelStatisticsGauss.h ├── README.md ├── README.txt ├── TraversionGenerator.h ├── VisualizationHelper.h ├── contourRelaxedSuperpixels.cpp └── globalConstants.h ├── lib_ers ├── CMakeLists.txt ├── Edge.h ├── Image.h ├── ImageIO.h ├── MERCCInput.cpp ├── MERCClustering.h ├── MERCDisjointSet.cpp ├── MERCDisjointSet.h ├── MERCEdge.h ├── MERCFunctions.cpp ├── MERCFunctions.h ├── MERCInput.h ├── MERCInputImage.h ├── MERCLazyGreedy.cpp ├── MERCLazyGreedy.h ├── MERCOutput.cpp ├── MERCOutput.h ├── MERCOutputImage.h ├── MHeap.h ├── MList.h ├── MMFunctions.h ├── MSubmodularHeap.h ├── README.md ├── README.txt └── mex_ers.cpp ├── lib_fh ├── CMakeLists.txt ├── LiICENSE.txt ├── README.md ├── README.txt ├── convolve.h ├── disjoint-set.h ├── filter.h ├── image.h ├── imconv.h ├── imutil.h ├── misc.h ├── pnmfile.h ├── segment-graph.h ├── segment-image-labels.h ├── segment-image.h └── segment.cpp ├── lib_pb ├── CMakeLists.txt ├── Elimination │ ├── CMakeLists.txt │ ├── Elimination+SSE.h │ ├── Elimination+SSE.txx │ ├── Elimination.cc │ ├── Elimination.h │ ├── Elimination.txx │ ├── Elimination_dcl.h │ ├── LazyElimination.cc │ ├── LazyElimination.h │ ├── LazyElimination.txx │ ├── LazyElimination_dcl.h │ ├── Project.suo │ ├── exampleElimination.cc │ └── matrix.h ├── MaxFlow │ ├── CMakeLists.txt │ ├── Makefile │ ├── QPBO_Elim.cc │ ├── QPBO_Elim.h │ ├── QPBO_Elim_dcl.h │ ├── QPBO_Generic.h │ ├── QPBO_LazyElim.cc │ ├── QPBO_LazyElim.h │ ├── QPBO_MaxFlow.cc │ ├── QPBO_MaxFlow.h │ ├── README.TXT │ ├── block.h │ ├── energy.h │ ├── example.cpp │ ├── graph.h │ ├── graph.txx │ ├── instances.cxx │ └── maxflow.txx ├── README.md ├── README.txt ├── SuperPB.cpp └── step-by-step.txt ├── lib_seeds ├── CMakeLists.txt ├── LICENSE.txt ├── README.md ├── README.txt ├── seeds2.cpp └── seeds2.h ├── lib_slic ├── CMakeLists.txt ├── LICENSE.txt ├── README.md ├── README.txt ├── SLIC.cpp ├── SLIC.h └── USAGE_SLIC.txt ├── pb_cli ├── CMakeLists.txt └── main.cpp ├── screenshot.png ├── seeds_cli ├── CMakeLists.txt └── main.cpp ├── slic_cli ├── CMakeLists.txt └── main.cpp └── vlfeat_slic_cli ├── CMakeLists.txt └── main.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | nbproject 2 | build 3 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "lib_seeds_revised"] 2 | path = lib_seeds_revised 3 | url = ../seeds-revised 4 | [submodule "lib_vlfeat"] 5 | path = lib_vlfeat 6 | url = ../../vlfeat/vlfeat 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | 3 | compiler: 4 | - gcc 5 | 6 | before_script: 7 | - sudo apt-get install build-essential 8 | - sudo apt-get install cmake 9 | - sudo apt-get install libboost-all-dev 10 | - sudo apt-get install libopencv-dev 11 | - mkdir build 12 | - cd build 13 | - cmake .. 14 | 15 | script: make -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 2.8) 2 | 3 | set(CMAKE_CXX_FLAGS "-O4 -fpermissive") 4 | 5 | set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib) 6 | set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/lib) 7 | set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin) 8 | 9 | # 10 | # To build the project, install CMake, then change into 'build' and 11 | # call 'cmake ../'. 12 | # 13 | 14 | include_directories(lib_seeds_revised/lib) 15 | 16 | # SEEDS Revised 17 | add_subdirectory(lib_seeds_revised) 18 | 19 | # Constant Intensity Superpixels/Compact Superpixels 20 | # Remove comments after installing the library as described in 21 | # lib_cli/README.md! 22 | #add_subdirectory(lib_cis) 23 | #add_subdirectory(cis_cli) 24 | 25 | # Entropy Rate Superpixels 26 | add_subdirectory(lib_ers) 27 | add_subdirectory(ers_cli) 28 | 29 | # Contour Relaxed Superpixels 30 | add_subdirectory(lib_crs) 31 | add_subdirectory(crs_cli) 32 | 33 | # Felzenswalb & Huttenlocher 34 | add_subdirectory(lib_fh) 35 | add_subdirectory(fh_cli) 36 | 37 | # Pseudo Boolean Superpixels 38 | add_subdirectory(lib_pb) 39 | add_subdirectory(pb_cli) 40 | 41 | # SEEDS 42 | add_subdirectory(lib_seeds) 43 | add_subdirectory(seeds_cli) 44 | 45 | # SLIC 46 | add_subdirectory(lib_slic) 47 | add_subdirectory(slic_cli) 48 | 49 | # VLFeat SLIC 50 | add_subdirectory(vlfeat_slic_cli) 51 | -------------------------------------------------------------------------------- /bin/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | -------------------------------------------------------------------------------- /cis_cli/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../lib_cis/ ../lib_cis/vlib/include/) 2 | 3 | find_package(Boost COMPONENTS system filesystem program_options REQUIRED) 4 | find_package(OpenCV REQUIRED) 5 | 6 | include_directories(${EIGEN_INCLUDE_DIRS}) 7 | 8 | add_executable(cis_cli main.cpp) 9 | target_link_libraries(cis_cli ${Boost_LIBRARIES} ${OpenCV_LIBS} ${PCL_LIBRARIES} seeds_revised cis vlib) 10 | -------------------------------------------------------------------------------- /crs_cli/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../lib_seeds_revised/ ../lib_crs/) 2 | 3 | find_package(Boost COMPONENTS system filesystem program_options REQUIRED) 4 | find_package(OpenCV REQUIRED) 5 | 6 | include_directories(${EIGEN_INCLUDE_DIRS}) 7 | 8 | add_executable(crs_cli main.cpp) 9 | target_link_libraries(crs_cli ${Boost_LIBRARIES} ${OpenCV_LIBS} seeds_revised) 10 | -------------------------------------------------------------------------------- /ers_cli/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../lib_seeds_revised/ ../lib_ers/) 2 | 3 | find_package(Boost COMPONENTS system filesystem program_options REQUIRED) 4 | find_package(OpenCV REQUIRED) 5 | 6 | include_directories(${EIGEN_INCLUDE_DIRS}) 7 | 8 | add_executable(ers_cli main.cpp) 9 | target_link_libraries(ers_cli ${Boost_LIBRARIES} ${OpenCV_LIBS} seeds_revised ers) 10 | -------------------------------------------------------------------------------- /fh_cli/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../lib_seeds_revised/ ../lib_fh/ .) 2 | 3 | find_package(Boost COMPONENTS system filesystem program_options REQUIRED) 4 | find_package(OpenCV REQUIRED) 5 | 6 | include_directories(${EIGEN_INCLUDE_DIRS}) 7 | 8 | add_executable(fh_cli main.cpp) 9 | target_link_libraries(fh_cli ${Boost_LIBRARIES} ${OpenCV_LIBS} seeds_revised) 10 | -------------------------------------------------------------------------------- /lib/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | -------------------------------------------------------------------------------- /lib_cis/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(vlib) 2 | 3 | include_directories(vlib/include/) 4 | add_library(cis maxflow.cpp graph.cpp superpixels.cpp) 5 | target_link_libraries(cis vlib) 6 | -------------------------------------------------------------------------------- /lib_cis/README.md: -------------------------------------------------------------------------------- 1 | # Constant Intensity Superpixels 2 | 3 | Unfortunately, the code from Constant Intensity Superpixels/Compact Superpixels [1] cannot be shipped with this library due to the restrictive license of the corresponding code. Therefore, only a command line tool in `cis_cli/` is provided. 4 | 5 | [3] O. Veksler, Y. Boykov, P. Mehrani. 6 | Superpixels and supervoxels in an energy optimization framework. 7 | European Conference on Computer Vision, pages 211–224, 2010. 8 | 9 | Installation instructions: 10 | 11 | Go to [http://www.csd.uwo.ca/faculty/olga/](http://www.csd.uwo.ca/faculty/olga/) and download the code. 12 | 13 | Extract the archive into `lib_cis` in order to obtaint he following directory structure (where the `CMakeLists.txt` files are provided by this library): 14 | 15 | lib_cis 16 | |- vlib 17 | |- include 18 | |- utils 19 | |- CMakeLists.txt 20 | |- README.txt (original README) 21 | |- README.md 22 | |- maxflow.cpp 23 | |- ... 24 | |- superpixels.h (provided by this library, not included in the download described above) 25 | |- CMakeLists.txt 26 | 27 | Comment out the `main` function in `superpixels.cpp`. 28 | 29 | Either change the declaration of `loadEdges` inf `superpixels.cpp` to 30 | 31 | void loadEdges(vector &weights,int num_pixels,int width,int height, 32 | Value lambda, char *name) 33 | 34 | or use `-fpermissive` (default). 35 | 36 | Depending on the operating system, some changes in energy.h` are required: Change occurrences of 37 | 38 | add_tweights(y, 0, C); 39 | add_edge(x, y, B+C, 0); 40 | 41 | to 42 | 43 | this->add_tweights(y, 0, C); 44 | this->add_edge(x, y, B+C, 0); 45 | 46 | **Documentation on the command line tool can be found in `cis_cli/main.cpp`!** 47 | -------------------------------------------------------------------------------- /lib_cis/superpixels.h: -------------------------------------------------------------------------------- 1 | #ifndef SUPERPIXELS_H 2 | #define SUPERPIXELS_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include "graph.h" 18 | #include "energy.h" 19 | #include 20 | #include 21 | #include 22 | 23 | using namespace std; 24 | using namespace vlib; 25 | 26 | #define NUM_COLORS 255 27 | #define MULTIPLIER_VAR 1.5 28 | #define sq(x) ((x)*(x)) 29 | 30 | typedef int Value; 31 | typedef int TotalValue; 32 | typedef int Var; 33 | 34 | void check_error(int boolE, const char *error_message); 35 | void PlaceSeeds(image *I,int width,int height, 36 | int num_pixels, vector &Seeds,int *numSeeds, int PATCH_SIZE); 37 | void MoveSeedsFromEdges(image *I,int width,int height,int num_pixels, 38 | vector &Seeds, int numSeeds, int PATCH_SIZE); 39 | int computeEnergy(vector &labeling,int width,int height,int num_pixels, 40 | vector &horizWeights,vector &vertWeights, 41 | vector &diag1Weights,vector &diag2Weights, 42 | vector &Seeds, image *I,int TYPE); 43 | void getBounds(int width,int height,vector &Seeds,int *seedX,int *seedY, 44 | int *startX,int *startY,int *endX,int *endY,int label, int PATCH_SIZE); 45 | void expandOnLabel(int label,int width,int height,int num_pixels, 46 | vector &Seeds,int numSeeds, vector &labeling, 47 | vector &horizWeights,vector &vertWeights,Value lambda, 48 | vector &diag1Weights,vector &diag2Weights,int PATCH_SIZE, 49 | vector &changeMask, vector &changeMaskNew,image *I, 50 | int TYPE,float variance); 51 | void initializeLabeling(vector &labeling,int width,int height, 52 | vector &Seeds,int numSeeds, int PATCH_SIZE); 53 | float computeImageVariance(image *I,int width,int height); 54 | void loadEdges(vector &weights,int num_pixels,int width,int height, 55 | Value lambda, char *name); 56 | void computeWeights(vector &weights,int num_pixels,int width, 57 | int height,Value lambda, float variance, 58 | int incrX,int incrY, image *I, 59 | int TYPE); 60 | int saveSegmentationColor(vector &labeling,int width,int height,int num_pixels, 61 | image *I, int numSeeds, char *name); 62 | void purturbSeeds(vector &order,int numSeeds); 63 | void check_input_arguments(int argc); 64 | 65 | #endif /* SUPERPIXELS_H */ 66 | -------------------------------------------------------------------------------- /lib_cis/vlib/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(./include/) 2 | 3 | add_library(vlib utils/canny.cpp 4 | utils/dilate.cpp 5 | utils/dt.cpp 6 | utils/grad.cpp 7 | utils/pyramid.cpp 8 | utils/smooth.cpp) -------------------------------------------------------------------------------- /lib_crs/CMakeLists.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidstutz/superpixels-revisited/f14e9e0b063741e5a9eb6544a3d6c2f44cdfc9e4/lib_crs/CMakeLists.txt -------------------------------------------------------------------------------- /lib_crs/DepthFeature.h: -------------------------------------------------------------------------------- 1 | /* 2 | * File: DepthFeature.h 3 | * Author: david 4 | * 5 | * Created on August 10, 2014, 9:02 PM 6 | */ 7 | 8 | #pragma once 9 | 10 | #include "IFeature.h" 11 | #include "AGaussianFeature.h" 12 | #include "LabelStatisticsGauss.h" 13 | #include "globalConstants.h" 14 | 15 | #include 16 | #include 17 | 18 | 19 | /** 20 | * @class ColorFeature 21 | * @brief Feature of three independently Gaussian-distributed channels, intended for use with color images in YUV space. 22 | */ 23 | template 24 | class DepthFeature : public AGaussianFeature 25 | { 26 | private: 27 | 28 | typedef unsigned short TDepthData; ///< the type of the used image channels 29 | 30 | std::vector labelStatistics; ///< Gaussian label statistics of the first channel 31 | cv::Mat depth; ///< observed data of the first channel 32 | 33 | 34 | public: 35 | 36 | void setData(cv::Mat const& depth); 37 | 38 | void initializeStatistics(cv::Mat const& labelImage); 39 | 40 | double calculateCost(cv::Point2i const& curPixelCoords, 41 | TLabelImage const& oldLabel, TLabelImage const& pretendLabel, std::vector const& neighbourLabels) const; 42 | 43 | void updateStatistics(cv::Point2i const& curPixelCoords, TLabelImage const& oldLabel, TLabelImage const& newLabel); 44 | 45 | void generateRegionMeanImage(cv::Mat const& labelImage, cv::Mat& out_regionMeanImage) const; 46 | }; 47 | 48 | 49 | /** 50 | * @brief Assign new data to the feature object. 51 | * @param colorChannel1 observed data of channel 1 52 | * @param colorChannel2 observed data of channel 2 53 | * @param colorChannel3 observed data of channel 3 54 | */ 55 | template 56 | void DepthFeature::setData(cv::Mat const& depth) 57 | { 58 | assert(depth.type() == cv::DataType::type); 59 | 60 | depth.copyTo(this->depth); 61 | } 62 | 63 | 64 | /** 65 | * @brief Estimate the label statistics of all labels in the given label image, using the observed data saved in the feature object. 66 | * @param labelImage label identifiers of all pixels 67 | */ 68 | template 69 | void DepthFeature::initializeStatistics(cv::Mat const& labelImage) 70 | { 71 | // Use the provided initialization method for gaussian statistics from AGaussianFeature. 72 | this->template initializeGaussianStatistics(labelImage, depth, labelStatistics); 73 | } 74 | 75 | 76 | /** 77 | * @brief Calculate the total cost of all labels in the 8-neighbourhood of a pixel, assuming the pixel would change its label. 78 | * @param curPixelCoords coordinates of the regarded pixel 79 | * @param oldLabel old label of the regarded pixel 80 | * @param pretendLabel assumed new label of the regarded pixel 81 | * @param neighbourLabels all labels found in the 8-neighbourhood of the regarded pixel, including the old label of the pixel itself 82 | * @return total negative log-likelihood (or cost) of all labels in the neighbourhood, assuming the label change 83 | */ 84 | template 85 | double DepthFeature::calculateCost(cv::Point2i const& curPixelCoords, 86 | TLabelImage const& oldLabel, TLabelImage const& pretendLabel, std::vector const& neighbourLabels) const 87 | { 88 | // Use the provided cost calculation method for gaussian statistics from AGaussianFeature. 89 | double cost = this->template calculateGaussianCost(curPixelCoords, oldLabel, pretendLabel, 90 | neighbourLabels, this->labelStatistics, this->depth); 91 | 92 | return cost; 93 | } 94 | 95 | 96 | /** 97 | * @brief Update the saved label statistics to reflect a label change of the given pixel. 98 | * @param curPixelCoords coordinates of the pixel whose label changes 99 | * @param oldLabel old label of the changing pixel 100 | * @param newLabel new label of the changing pixel 101 | */ 102 | template 103 | void DepthFeature::updateStatistics(cv::Point2i const& curPixelCoords, TLabelImage const& oldLabel, 104 | TLabelImage const& newLabel) 105 | { 106 | this->template updateGaussianStatistics(curPixelCoords, this->labelStatistics[oldLabel], 107 | this->labelStatistics[newLabel], this->depth); 108 | } 109 | 110 | 111 | /** 112 | * @brief Create a representation of the current image visualizing each pixel with the mean color value of its assigned label. 113 | * @param labelImage label identifier of each pixel 114 | * @param out_regionMeanImage will be (re)allocated if necessary and filled with the described visualization 115 | */ 116 | template 117 | void DepthFeature::generateRegionMeanImage(cv::Mat const& labelImage, cv::Mat& out_regionMeanImage) const 118 | { 119 | assert(labelImage.size() == this->depth.size()); 120 | assert(labelImage.type() == cv::DataType::type); 121 | 122 | // Generate an image which represents all pixels by the mean color value of their label. 123 | // Channels will be filled separately and later on merged, since accessing multi-channel 124 | // matrices is not quite straightforward. 125 | cv::Mat out_depth(this->depth.size(), cv::DataType::type); 126 | 127 | for (int row = 0; row < out_depth.rows; ++row) 128 | { 129 | TDepthData* const out_depthRowPtr = out_depth.ptr(row); 130 | TLabelImage const* const labelImRowPtr = labelImage.ptr(row); 131 | 132 | for (int col = 0; col < out_depth.cols; ++col) 133 | { 134 | out_depthRowPtr[col] = this->labelStatistics[labelImRowPtr[col]].valueSum 135 | / this->labelStatistics[labelImRowPtr[col]].pixelCount; 136 | } 137 | } 138 | } 139 | 140 | 141 | -------------------------------------------------------------------------------- /lib_crs/FeatureType.h: -------------------------------------------------------------------------------- 1 | // Copyright 2013 Visual Sensorics and Information Processing Lab, Goethe University, Frankfurt 2 | // 3 | // This file is part of Contour-relaxed Superpixels. 4 | // 5 | // Contour-relaxed Superpixels is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU Lesser General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Contour-relaxed Superpixels is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU Lesser General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU Lesser General Public License 16 | // along with Contour-relaxed Superpixels. If not, see . 17 | 18 | 19 | #pragma once 20 | 21 | /** 22 | * @file FeatureType.h 23 | * @brief Header file containing the definition of the FeatureType enum. 24 | */ 25 | 26 | 27 | /** 28 | * @enum FeatureType 29 | * @brief Enum for encoding the different types of features so we can pass around which features we want to use. 30 | */ 31 | enum FeatureType 32 | { 33 | Grayvalue, 34 | Color, 35 | Compactness, 36 | Depth 37 | }; 38 | -------------------------------------------------------------------------------- /lib_crs/GrayvalueFeature.h: -------------------------------------------------------------------------------- 1 | // Copyright 2013 Visual Sensorics and Information Processing Lab, Goethe University, Frankfurt 2 | // 3 | // This file is part of Contour-relaxed Superpixels. 4 | // 5 | // Contour-relaxed Superpixels is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU Lesser General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Contour-relaxed Superpixels is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU Lesser General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU Lesser General Public License 16 | // along with Contour-relaxed Superpixels. If not, see . 17 | 18 | 19 | #pragma once 20 | 21 | #include "IFeature.h" 22 | #include "AGaussianFeature.h" 23 | #include "LabelStatisticsGauss.h" 24 | #include "globalConstants.h" 25 | 26 | #include 27 | #include 28 | 29 | 30 | /** 31 | * @class GrayvalueFeature 32 | * @brief Feature of one Gaussian-distributed channel, intended for use with grayvalue images. 33 | */ 34 | template 35 | class GrayvalueFeature : public AGaussianFeature 36 | { 37 | private: 38 | 39 | typedef uchar TGrayvalueData; ///< the type of the used grayvalue images 40 | 41 | std::vector labelStatistics; ///< Gaussian label statistics of the grayvalue image 42 | cv::Mat grayvalImage; ///< the observed grayvalue data 43 | 44 | 45 | public: 46 | 47 | void setData(cv::Mat const& grayvalueImage); 48 | 49 | void initializeStatistics(cv::Mat const& labelImage); 50 | 51 | double calculateCost(cv::Point2i const& curPixelCoords, 52 | TLabelImage const& oldLabel, TLabelImage const& pretendLabel, std::vector const& neighbourLabels) const; 53 | 54 | void updateStatistics(cv::Point2i const& curPixelCoords, TLabelImage const& oldLabel, TLabelImage const& newLabel); 55 | 56 | void generateRegionMeanImage(cv::Mat const& labelImage, cv::Mat& out_regionMeanImage) const; 57 | }; 58 | 59 | 60 | /** 61 | * @brief Assign new data to the feature object. 62 | * @param grayvalueImage observed grayvalue data 63 | */ 64 | template 65 | void GrayvalueFeature::setData(cv::Mat const& grayvalueImage) 66 | { 67 | assert(grayvalueImage.type() == cv::DataType::type); 68 | 69 | grayvalueImage.copyTo(grayvalImage); 70 | } 71 | 72 | 73 | /** 74 | * @brief Estimate the label statistics of all labels in the given label image, using the observed data saved in the feature object. 75 | * @param labelImage label identifiers of all pixels 76 | */ 77 | template 78 | void GrayvalueFeature::initializeStatistics(cv::Mat const& labelImage) 79 | { 80 | // Use the provided initialization method for gaussian statistics from AGaussianFeature. 81 | this->template initializeGaussianStatistics(labelImage, grayvalImage, labelStatistics); 82 | } 83 | 84 | 85 | /** 86 | * @brief Calculate the total cost of all labels in the 8-neighbourhood of a pixel, assuming the pixel would change its label. 87 | * @param curPixelCoords coordinates of the regarded pixel 88 | * @param oldLabel old label of the regarded pixel 89 | * @param pretendLabel assumed new label of the regarded pixel 90 | * @param neighbourLabels all labels found in the 8-neighbourhood of the regarded pixel, including the old label of the pixel itself 91 | * @return total negative log-likelihood (or cost) of all labels in the neighbourhood, assuming the label change 92 | */ 93 | template 94 | double GrayvalueFeature::calculateCost(cv::Point2i const& curPixelCoords, 95 | TLabelImage const& oldLabel, TLabelImage const& pretendLabel, std::vector const& neighbourLabels) const 96 | { 97 | // Use the provided cost calculation method for gaussian statistics from AGaussianFeature. 98 | return this->template calculateGaussianCost(curPixelCoords, oldLabel, pretendLabel, 99 | neighbourLabels, labelStatistics, grayvalImage); 100 | } 101 | 102 | 103 | /** 104 | * @brief Update the saved label statistics to reflect a label change of the given pixel. 105 | * @param curPixelCoords coordinates of the pixel whose label changes 106 | * @param oldLabel old label of the changing pixel 107 | * @param newLabel new label of the changing pixel 108 | */ 109 | template 110 | void GrayvalueFeature::updateStatistics(cv::Point2i const& curPixelCoords, TLabelImage const& oldLabel, 111 | TLabelImage const& newLabel) 112 | { 113 | // Use the provided update method for gaussian statistics from AGaussianFeature. 114 | this->template updateGaussianStatistics(curPixelCoords, labelStatistics[oldLabel], 115 | labelStatistics[newLabel], grayvalImage); 116 | } 117 | 118 | 119 | /** 120 | * @brief Create a representation of the current image visualizing each pixel with the mean grayvalue of its assigned label. 121 | * @param labelImage label identifier of each pixel 122 | * @param out_regionMeanImage will be (re)allocated if necessary and filled with the described visualization 123 | */ 124 | template 125 | void GrayvalueFeature::generateRegionMeanImage(cv::Mat const& labelImage, cv::Mat& out_regionMeanImage) const 126 | { 127 | assert(labelImage.size() == grayvalImage.size()); 128 | assert(labelImage.type() == cv::DataType::type); 129 | 130 | // Generate an image which represents all pixels by the mean grayvalue of their label. 131 | // cv::Mat::create only reallocates memory if necessary, so this is no slowdown. 132 | // We don't care about initialization of out_regionMeanImage since we will set all pixels anyway. 133 | out_regionMeanImage.create(grayvalImage.size(), cv::DataType::type); 134 | 135 | for (int row = 0; row < out_regionMeanImage.rows; ++row) 136 | { 137 | TGrayvalueData* const out_rmiRowPtr = out_regionMeanImage.ptr(row); 138 | TLabelImage const* const labelImRowPtr = labelImage.ptr(row); 139 | 140 | for (int col = 0; col < out_regionMeanImage.cols; ++col) 141 | { 142 | out_rmiRowPtr[col] = labelStatistics[labelImRowPtr[col]].valueSum / labelStatistics[labelImRowPtr[col]].pixelCount; 143 | } 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /lib_crs/IFeature.h: -------------------------------------------------------------------------------- 1 | // Copyright 2013 Visual Sensorics and Information Processing Lab, Goethe University, Frankfurt 2 | // 3 | // This file is part of Contour-relaxed Superpixels. 4 | // 5 | // Contour-relaxed Superpixels is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU Lesser General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Contour-relaxed Superpixels is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU Lesser General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU Lesser General Public License 16 | // along with Contour-relaxed Superpixels. If not, see . 17 | 18 | 19 | #pragma once 20 | 21 | #include 22 | 23 | 24 | /** 25 | * @class IFeature 26 | * @brief Interface for feature classes. Defines the functions a feature class must implement so that it can be used in the Contour Relaxation framework. 27 | */ 28 | template 29 | class IFeature 30 | { 31 | public: 32 | 33 | /** 34 | * @brief Provide a virtual destructor so instances of derived classes can be safely destroyed through a pointer or reference of type IFeature. 35 | */ 36 | virtual ~IFeature() {} 37 | 38 | /** 39 | * @brief Compute the internal label statistics for all labels in the given label image. 40 | * @param labelImage the current label image, contains one label identifier per pixel 41 | */ 42 | virtual void initializeStatistics(cv::Mat const& labelImage) = 0; 43 | 44 | /** 45 | * @brief Calculate the total cost of all labels in the 8-neighbourhood of a pixel, assuming the pixel would change its label. 46 | * @param curPixelCoords coordinates of the regarded pixel 47 | * @param oldLabel old label of the regarded pixel 48 | * @param pretendLabel assumed new label of the regarded pixel 49 | * @param neighbourLabels all labels found in the 8-neighbourhood of the regarded pixel, including the old label of the pixel itself 50 | * @return total negative log-likelihood (or cost) of all labels in the neighbourhood, assuming the label change 51 | */ 52 | virtual double calculateCost(cv::Point2i const& curPixelCoords, 53 | TLabelImage const& oldLabel, TLabelImage const& pretendLabel, 54 | std::vector const& neighbourLabels) const = 0; 55 | 56 | /** 57 | * @brief Update the saved label statistics to reflect a label change of the given pixel. 58 | * @param curPixelCoords coordinates of the pixel whose label changes 59 | * @param oldLabel old label of the changing pixel 60 | * @param newLabel new label of the changing pixel 61 | */ 62 | virtual void updateStatistics(cv::Point2i const& curPixelCoords, TLabelImage const& oldLabel, TLabelImage const& newLabel) = 0; 63 | }; 64 | -------------------------------------------------------------------------------- /lib_crs/InitializationFunctions.h: -------------------------------------------------------------------------------- 1 | // Copyright 2013 Visual Sensorics and Information Processing Lab, Goethe University, Frankfurt 2 | // 3 | // This file is part of Contour-relaxed Superpixels. 4 | // 5 | // Contour-relaxed Superpixels is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU Lesser General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Contour-relaxed Superpixels is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU Lesser General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU Lesser General Public License 16 | // along with Contour-relaxed Superpixels. If not, see . 17 | 18 | 19 | #pragma once 20 | 21 | /** 22 | * @file InitializationFunctions.h 23 | * @brief Header file providing some initialization functions for label images. These can be used for generating a starting point for superpixel generation with Contour Relaxation. 24 | */ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | 32 | /** 33 | * @brief Create a label image initialization of rectangular blocks of the given size. 34 | * @param imageSize the size of the label image which will be created 35 | * @param blockWidth the width of one rectangular block 36 | * @param blockHeight the height of one rectangular block 37 | * @return a label image of the given size, constructed by blocks of the given size, with each block being a single, unique label 38 | */ 39 | template 40 | cv::Mat createBlockInitialization(cv::Size const& imageSize, int const& blockWidth, int const& blockHeight) 41 | { 42 | assert(imageSize.width > 0 && imageSize.height > 0); 43 | assert(blockWidth > 0 && blockHeight > 0); 44 | assert(imageSize.width >= blockWidth && imageSize.height >= blockHeight); 45 | 46 | cv::Mat out_labelImage(imageSize, cv::DataType::type); 47 | 48 | // Find out how many blocks there will be in each direction. If image size is not a multiple of block size, 49 | // we need to round upwards because there will be one additional (smaller) block. 50 | int const numBlocksX = ceil(static_cast(imageSize.width) / blockWidth); 51 | int const numBlocksY = ceil(static_cast(imageSize.height) / blockHeight); 52 | 53 | // Counter for the label of the current block. 54 | TLabelImage curLabel = 0; 55 | 56 | for (int blockYi = 0; blockYi < numBlocksY; ++blockYi) 57 | { 58 | // Get the y-limits of all blocks in the current row of blocks. 59 | // End is tricky because of a possibly smaller last block. 60 | int const blockYStart = blockYi * blockHeight; 61 | int const blockYEnd = std::min((blockYi + 1) * blockHeight, imageSize.height); 62 | 63 | for (int blockXi = 0; blockXi < numBlocksX; ++blockXi) 64 | { 65 | // Get the x-limits of the current block. 66 | // End is tricky because of a possibly smaller last block. 67 | int const blockXStart = blockXi * blockWidth; 68 | int const blockXEnd = std::min((blockXi + 1) * blockWidth, imageSize.width); 69 | 70 | // Get a rectangle of the current blocksize and at the current block position. 71 | cv::Rect const curBlock(blockXStart, blockYStart, blockXEnd - blockXStart, blockYEnd - blockYStart); 72 | // Get a matrix header to the current block in the label image. 73 | cv::Mat curBlockInLabelImage = out_labelImage(curBlock); 74 | 75 | // Assign current label to block, increase label counter. 76 | curBlockInLabelImage = curLabel; 77 | 78 | ++curLabel; 79 | } 80 | } 81 | 82 | return out_labelImage; 83 | } 84 | 85 | 86 | /** 87 | * @brief Create a label image initialization of diamonds / rotated rectangular blocks of the given size. 88 | * @param imageSize the size of the label image which will be created 89 | * @param sideLength the width and height of one rectangular block which will be rotated by 45 degrees to form a diamond 90 | * @return a label image of the given size, constructed by diamonds of the given size, with each diamond being a single, unique label 91 | */ 92 | template 93 | cv::Mat createDiamondInitialization(cv::Size const& imageSize, int const& sideLength) 94 | { 95 | assert(imageSize.width > 0 && imageSize.height > 0); 96 | assert(sideLength > 0); 97 | assert(imageSize.width >= sideLength && imageSize.height >= sideLength); 98 | 99 | // For creating the bigger labels, we use the bigger dimension for both so we won't get into trouble after rotation. 100 | int const maxDimSize = std::max(imageSize.width, imageSize.height); 101 | 102 | // Create a block initialization of twice the size, which ensures we can pick our labels from the center 103 | // after rotation without getting border effects. 104 | cv::Mat const bigBlockLabels = createBlockInitialization(cv::Size(2 * maxDimSize, 2 * maxDimSize), 105 | sideLength, sideLength); 106 | 107 | // Create a rotation matrix which rotates around the center of bigBlockLabels, for 45 degrees ccw, with scale 1. 108 | cv::Mat const rotationMatrix = cv::getRotationMatrix2D(cv::Point2f(maxDimSize, maxDimSize), 45, 1); 109 | cv::Mat rotatedLabels; 110 | 111 | // Rotate the big label image. Destination image shall have the same size and interpolation shall be NN 112 | // so that no new labels are created. 113 | // Type of rotatedLabels will be the same as of bigBlockLabels. 114 | cv::warpAffine(bigBlockLabels, rotatedLabels, rotationMatrix, bigBlockLabels.size(), cv::INTER_NEAREST); 115 | 116 | // Pick the upper left corner of the region we want to use as result. 117 | // This ensures we pick our result from the center of the rotated labels. 118 | int const xStart = maxDimSize - (imageSize.width / 2); 119 | int const yStart = maxDimSize - (imageSize.height / 2); 120 | 121 | // Copy the labels into a new matrix and return it. 122 | cv::Rect const roi(xStart, yStart, imageSize.width, imageSize.height); 123 | cv::Mat roiLabels = rotatedLabels(roi); 124 | 125 | cv::Mat out_labelImage; 126 | roiLabels.copyTo(out_labelImage); 127 | 128 | return out_labelImage; 129 | } 130 | -------------------------------------------------------------------------------- /lib_crs/LabelStatisticsGauss.h: -------------------------------------------------------------------------------- 1 | // Copyright 2013 Visual Sensorics and Information Processing Lab, Goethe University, Frankfurt 2 | // 3 | // This file is part of Contour-relaxed Superpixels. 4 | // 5 | // Contour-relaxed Superpixels is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU Lesser General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Contour-relaxed Superpixels is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU Lesser General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU Lesser General Public License 16 | // along with Contour-relaxed Superpixels. If not, see . 17 | 18 | 19 | #pragma once 20 | 21 | #include 22 | 23 | 24 | /** 25 | * @struct LabelStatisticsGauss 26 | * @brief Struct containing the sufficient statistics needed to compute label likelihoods of a Gaussian-distributed feature channel. 27 | */ 28 | struct LabelStatisticsGauss 29 | { 30 | boost::uint_fast32_t pixelCount; ///< the number of pixels assigned to the label 31 | double valueSum; ///< the sum of values of all pixels assigned to the label 32 | double squareValueSum; ///< the sum of squared values of all pixels assigned to the label 33 | 34 | /** 35 | * @brief Default constructor to ensure that all members are initialized to sensible values. 36 | */ 37 | LabelStatisticsGauss() : pixelCount(0), valueSum(0), squareValueSum(0) {} 38 | }; 39 | -------------------------------------------------------------------------------- /lib_crs/README.md: -------------------------------------------------------------------------------- 1 | # Contour Relaxed Superpixels 2 | 3 | Code for Contour Relaxed Superpixels [1]: 4 | 5 | [1] C. Conrad, M. Mertz, R. Mester. 6 | Contour-relaxed superpixels. 7 | Energy Minimization Methods in Computer Vision and Pattern Recognition, 8 | volume 8081 of Lecture Notes in Computer Science, pages 280–293, 2013. 9 | 10 | The corresponding command line tool can befound in `crs_cli/main.cpp`, including documentation. 11 | 12 | License can be found in `LICENSE.txt`, the original README can be found in `README.txt`. -------------------------------------------------------------------------------- /lib_crs/README.txt: -------------------------------------------------------------------------------- 1 | --- 2 | 3 | Contour-relaxed Superpixels 4 | 5 | Version 0.1-r2, 05.08.2013 6 | 7 | Copyright 2013 Visual Sensorics and Information Processing Lab, Goethe University, Frankfurt 8 | 9 | http://www.vsi.cs.uni-frankfurt.de/ 10 | 11 | --- 12 | 13 | This file is part of Contour-relaxed Superpixels. 14 | 15 | Contour-relaxed Superpixels is free software: you can redistribute it and/or modify 16 | it under the terms of the GNU Lesser General Public License as published by 17 | the Free Software Foundation, either version 3 of the License, or 18 | (at your option) any later version. 19 | 20 | Contour-relaxed Superpixels is distributed in the hope that it will be useful, 21 | but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | GNU Lesser General Public License for more details. 24 | 25 | You should have received a copy of the GNU Lesser General Public License 26 | along with Contour-relaxed Superpixels. If not, see . 27 | 28 | --- 29 | 30 | If you use this software for research purposes, please cite the following 31 | in any resulting publication: 32 | 33 | Contour-relaxed Superpixels 34 | Christian Conrad, Matthias Mertz, and Rudolf Mester 35 | LNCS: 9th Intl. Conf. on Energy Minimization Methods in Computer Vision and Pattern Recognition (EMMCVPR), 2013 36 | 37 | --- 38 | 39 | Build information: 40 | 41 | Contour-relaxed Superpixels can be most comfortably built using CMake. 42 | Additionally, you need to have a C++ compiler (e.g. GCC) as well as the OpenCV and Boost libraries 43 | and their header files installed. 44 | 45 | The program has been successfully built and tested with the following versions: 46 | 47 | CMake 2.8.7 48 | GCC 4.6.3 49 | OpenCV 2.3.1 50 | Boost 1.46.1 51 | 52 | In order to build the program in the packed build directory, after unpacking the whole archive, 53 | execute the following two commands from within the build directory: 54 | 55 | cmake ../src 56 | make 57 | 58 | Additionally, you can then execute "make doc" to build the Doxygen documentation of the source code, 59 | provided you have Doxygen installed. 60 | 61 | --- 62 | 63 | Using Contour-relaxed Superpixels: 64 | 65 | After the program has been successfully built, you can run the executable contourRelaxedSuperpixels 66 | with the following command: 67 | 68 | ./contourRelaxedSuperpixels inputImage [blockWidth = 20] [blockHeight = 20] [directCliqueCost = 0.3] [compactnessWeight = 0.045 (color) / 0.015 (grayscale)] 69 | 70 | Required parameters: 71 | - inputImage: absolute or relative path to the input image file (1 (gray) or 3 (color) channels, must be readable by OpenCV) 72 | 73 | Optional parameters: 74 | - blockWidth: width of the rectangular blocks that are used to initialize the label image, default value = 20 75 | - blockHeight: height of the rectangular blocks that are used to initialize the label image, default value = 20 76 | - directCliqueCost: Markov clique cost for vertical and horizontal cliques, default value = 0.3 77 | - compactnessWeight: weight of the compactness feature, default value = 0.045 for color images, 0.015 for grayscale images 78 | 79 | For a detailed explanation of the optional parameters, and some other parameters you can modify 80 | in the source code, see the EMMCVPR 2013 publication mentioned above. 81 | 82 | The program will not generate any output, neither text nor graphics, in case everything goes well. 83 | The results will be written to image files in the current working directory. 84 | 85 | With inFile.ext being the input image file specified in the program call, the following output files 86 | will be generated: 87 | 88 | - inFile_labelImage.png: 16bit PNG image containing the label identifiers for each pixel. 89 | Can be opened with other software to retrieve the labels for further processing. 90 | 91 | - inFile_regionMean.png: Region-mean image, replacing each pixel with the mean color / gray value of its label. 92 | 93 | - inFile_boundaryImage.png: Black image overlayed with the label boundaries in white. 94 | 95 | - inFile_boundaryOverlay.png: Input image overlayed with the label boundaries in red. 96 | 97 | --- 98 | 99 | If you want to make changes to the source code, consider switching to a debug build to activate 100 | assertions. This can be very useful should you run into problems. You can do so by replacing 101 | the line 102 | 103 | set (CMAKE_BUILD_TYPE Release) 104 | 105 | with 106 | 107 | set (CMAKE_BUILD_TYPE Debug) 108 | 109 | in src/CMakeLists.txt. 110 | 111 | --- 112 | 113 | -------------------------------------------------------------------------------- /lib_crs/globalConstants.h: -------------------------------------------------------------------------------- 1 | // Copyright 2013 Visual Sensorics and Information Processing Lab, Goethe University, Frankfurt 2 | // 3 | // This file is part of Contour-relaxed Superpixels. 4 | // 5 | // Contour-relaxed Superpixels is free software: you can redistribute it and/or modify 6 | // it under the terms of the GNU Lesser General Public License as published by 7 | // the Free Software Foundation, either version 3 of the License, or 8 | // (at your option) any later version. 9 | // 10 | // Contour-relaxed Superpixels is distributed in the hope that it will be useful, 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | // GNU Lesser General Public License for more details. 14 | // 15 | // You should have received a copy of the GNU Lesser General Public License 16 | // along with Contour-relaxed Superpixels. If not, see . 17 | 18 | 19 | #pragma once 20 | 21 | /** 22 | * @file globalConstants.h 23 | * @brief Header file containing some global constant definitions. 24 | */ 25 | 26 | 27 | /** 28 | * @brief The threshold for minimum variance. 29 | * 30 | * Minimum variance > 0 is necessary to prevent labels with only one pixel from staying alive forever. 31 | * Value is arbitrary but works. As long as it is not too large, the exact value does not influence the 32 | * results much, so this is not needed as a parameter. 33 | */ 34 | double const featuresMinVariance = 1.0 / 12.0; 35 | -------------------------------------------------------------------------------- /lib_ers/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(ers MERCCInput.cpp 2 | MERCDisjointSet.cpp 3 | MERCFunctions.cpp 4 | MERCLazyGreedy.cpp 5 | MERCOutput.cpp) 6 | -------------------------------------------------------------------------------- /lib_ers/Edge.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011, Ming-Yu Liu 3 | 4 | All Rights Reserved 5 | 6 | Permission to use, copy, modify, and distribute this software and 7 | its documentation for any non-commercial purpose is hereby granted 8 | without fee, provided that the above copyright notice appear in 9 | all copies and that both that copyright notice and this permission 10 | notice appear in supporting documentation, and that the name of 11 | the author not be used in advertising or publicity pertaining to 12 | distribution of the software without specific, written prior 13 | permission. 14 | 15 | THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16 | INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 | ANY PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 18 | ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 20 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 21 | OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 | */ 23 | #ifndef _edge_h_ 24 | #define _edge_h_ 25 | 26 | class Edge 27 | { 28 | public: 29 | int a_; 30 | int b_; 31 | double w_; 32 | double gain_; 33 | inline Edge &operator=(const Edge &rhs); 34 | inline bool operator==(const Edge &other) const; 35 | inline bool operator!=(const Edge &other) const; 36 | inline bool operator>=(const Edge &other) const; 37 | inline bool operator<=(const Edge &other) const; 38 | inline bool operator>(const Edge &other) const; 39 | inline bool operator<(const Edge &other) const; 40 | }; 41 | #endif 42 | 43 | Edge &Edge::operator=(const Edge &rhs) 44 | { 45 | a_ = rhs.a_; 46 | b_ = rhs.b_; 47 | w_ = rhs.w_; 48 | gain_ = rhs.gain_; 49 | return *this; 50 | } 51 | 52 | bool Edge::operator==(const Edge &other) const 53 | { 54 | return w_ == other.w_; 55 | } 56 | 57 | bool Edge::operator!=(const Edge &other) const 58 | { 59 | return w_ != other.w_; 60 | } 61 | 62 | bool Edge::operator>=(const Edge &other) const 63 | { 64 | return w_ >= other.w_; 65 | } 66 | 67 | bool Edge::operator<=(const Edge &other) const 68 | { 69 | return w_ <= other.w_; 70 | } 71 | 72 | bool Edge::operator>(const Edge &other) const 73 | { 74 | return w_ > other.w_; 75 | } 76 | 77 | bool Edge::operator<(const Edge &other) const 78 | { 79 | return w_ < other.w_; 80 | } -------------------------------------------------------------------------------- /lib_ers/Image.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011, Ming-Yu Liu 3 | 4 | All Rights Reserved 5 | 6 | Permission to use, copy, modify, and distribute this software and 7 | its documentation for any non-commercial purpose is hereby granted 8 | without fee, provided that the above copyright notice appear in 9 | all copies and that both that copyright notice and this permission 10 | notice appear in supporting documentation, and that the name of 11 | the author not be used in advertising or publicity pertaining to 12 | distribution of the software without specific, written prior 13 | permission. 14 | 15 | THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16 | INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 | ANY PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 18 | ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 20 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 21 | OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 | */ 23 | 24 | #ifndef _image_h_ 25 | #define _image_h_ 26 | 27 | #include 28 | #include 29 | #include 30 | typedef unsigned char uchar; 31 | 32 | /* use imRef to access Image data. */ 33 | #define imRef(im, x, y) (im->access[y][x]) 34 | 35 | /* use imPtr to get pointer to Image data. */ 36 | #define imPtr(im, x, y) &(im->access[y][x]) 37 | 38 | class RGBMap 39 | { 40 | public: 41 | RGBMap(uchar r,uchar g,uchar b): r_(r),g_(g),b_(b) {}; 42 | RGBMap() {}; 43 | uchar r_, g_, b_; 44 | inline RGBMap& operator=(const RGBMap &rhs); 45 | inline double operator-(const RGBMap &other) const; 46 | }; 47 | 48 | double RGBMap::operator-(const RGBMap &other) const 49 | { 50 | double diff = 0; 51 | diff += abs(1.0*r_ - other.r_); 52 | diff += abs(1.0*g_ - other.g_); 53 | diff += abs(1.0*b_ - other.b_); 54 | return diff; 55 | 56 | // double diff = 0; 57 | // diff += (r_ - other.r_)*(r_ - other.r_); 58 | // diff += (g_ - other.g_)*(g_ - other.g_); 59 | // diff += (b_ - other.b_)*(b_ - other.b_); 60 | // return std::sqrt(diff); 61 | } 62 | 63 | RGBMap& RGBMap::operator=(const RGBMap &rhs) 64 | { 65 | r_ = rhs.r_, g_ = rhs.g_, b_ = rhs.b_; 66 | return (*this); 67 | } 68 | 69 | 70 | template 71 | class Image 72 | { 73 | public: 74 | 75 | // constructor 76 | inline Image(); 77 | 78 | /* create an Image */ 79 | inline Image(const int width, const int height, const bool init = true); 80 | 81 | /* delete an Image */ 82 | inline ~Image(); 83 | 84 | /* release current image if any */ 85 | inline void Release(); 86 | 87 | inline void Resize(const int width,const int height, const bool init = true); 88 | 89 | 90 | 91 | /* init an Image */ 92 | inline void Init(const T &val); 93 | 94 | /* copy an Image */ 95 | inline Image *Copy() const; 96 | 97 | /* get the width of an Image. */ 98 | inline int width() const { return w; } 99 | 100 | /* get the height of an Image. */ 101 | inline int height() const { return h; } 102 | 103 | // returning a reference to the parituclar location. 104 | inline T& Access(int x,int y) {return access[y][x];}; 105 | 106 | 107 | /* Image data. */ 108 | T *data; 109 | 110 | /* row pointers. */ 111 | T **access; 112 | 113 | 114 | 115 | private: 116 | int w, h; 117 | }; 118 | 119 | 120 | template 121 | Image::Image() 122 | { 123 | w = 0; 124 | h = 0; 125 | data = NULL; 126 | access = NULL; 127 | } 128 | 129 | 130 | template 131 | Image::Image(const int width, const int height, const bool init) 132 | { 133 | w = width; 134 | h = height; 135 | data = new T[w * h]; // allocate space for Image data 136 | access = new T*[h]; // allocate space for row pointers 137 | 138 | // initialize row pointers 139 | for (int i = 0; i < h; i++) 140 | access[i] = data + (i * w); 141 | 142 | if (init) 143 | memset(data, 0, w * h * sizeof(T)); 144 | } 145 | 146 | template 147 | Image::~Image() 148 | { 149 | Release(); 150 | } 151 | 152 | template 153 | void Image::Release() 154 | { 155 | if(data) 156 | delete [] data; 157 | if(access) 158 | delete [] access; 159 | 160 | h = 0; 161 | w = 0; 162 | } 163 | 164 | 165 | template 166 | void Image::Resize(const int width, const int height, const bool init) 167 | { 168 | Release(); 169 | w = width; 170 | h = height; 171 | data = new T[w * h]; // allocate space for Image data 172 | access = new T*[h]; // allocate space for row pointers 173 | 174 | // initialize row pointers 175 | for (int i = 0; i < h; i++) 176 | access[i] = data + (i * w); 177 | 178 | if (init) 179 | memset(data, 0, w * h * sizeof(T)); 180 | } 181 | 182 | template 183 | void Image::Init(const T &val) 184 | { 185 | T *ptr = imPtr(this, 0, 0); 186 | T *end = imPtr(this, w-1, h-1); 187 | while (ptr <= end) 188 | *ptr++ = val; 189 | } 190 | 191 | 192 | template 193 | Image *Image::Copy() const 194 | { 195 | Image *im = new Image(w, h, false); 196 | memcpy(im->data, data, w * h * sizeof(T)); 197 | return im; 198 | } 199 | 200 | #endif 201 | 202 | -------------------------------------------------------------------------------- /lib_ers/MERCCInput.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011, Ming-Yu Liu 3 | 4 | All Rights Reserved 5 | 6 | Permission to use, copy, modify, and distribute this software and 7 | its documentation for any non-commercial purpose is hereby granted 8 | without fee, provided that the above copyright notice appear in 9 | all copies and that both that copyright notice and this permission 10 | notice appear in supporting documentation, and that the name of 11 | the author not be used in advertising or publicity pertaining to 12 | distribution of the software without specific, written prior 13 | permission. 14 | 15 | THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16 | INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 | ANY PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 18 | ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 20 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 21 | OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 | */ 23 | #include "MERCInput.h" 24 | #include 25 | 26 | MERCInput::MERCInput() 27 | { 28 | edges_ = NULL; 29 | } 30 | 31 | MERCInput::~MERCInput() 32 | { 33 | Release(); 34 | } 35 | 36 | void MERCInput::Release() 37 | { 38 | if(edges_) 39 | delete [] edges_; 40 | edges_ = NULL; 41 | } 42 | 43 | void MERCInput::ReadFromMatlab(double *pI,double *pJ,double *pW,int nEdges,int nNodes) 44 | { 45 | nEdges_ = nEdges; 46 | nNodes_ = nNodes; 47 | edges_ = new Edge [nEdges_]; 48 | for(int i=0;i> nNodes_; 67 | file >> nEdges_; 68 | edges_ = new Edge [nEdges_]; 69 | for(int i=0;i>edges_[i].a_>>edges_[i].b_>>edges_[i].w_; 71 | file.close(); 72 | } 73 | 74 | 75 | void MERCInput::Write(const char* filename) 76 | { 77 | std::ofstream file; 78 | file.open(filename); 79 | file.precision(6); 80 | file< 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | using namespace std; 39 | 40 | 41 | class MERCClustering 42 | { 43 | public: 44 | 45 | void ClusteringTreeIF(int nVertices,MERCInput &edges,int kernel,double sigma,double lambda,int nC) 46 | { 47 | disjointSet_ = ClusteringTree(nVertices,edges,kernel,sigma,lambda,nC); 48 | }; 49 | 50 | virtual MERCDisjointSet* ClusteringTree(int nVertices,MERCInput &edges,int kernel,double sigma,double lambda,int nC) = 0; 51 | 52 | MERCClustering() 53 | { 54 | disjointSet_ = NULL; 55 | }; 56 | 57 | ~MERCClustering() 58 | { 59 | Release(); 60 | }; 61 | 62 | void Release() 63 | { 64 | if(disjointSet_) 65 | delete disjointSet_; 66 | }; 67 | 68 | MERCDisjointSet *disjointSet_; 69 | 70 | }; 71 | 72 | #endif -------------------------------------------------------------------------------- /lib_ers/MERCDisjointSet.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011, Ming-Yu Liu 3 | 4 | All Rights Reserved 5 | 6 | Permission to use, copy, modify, and distribute this software and 7 | its documentation for any non-commercial purpose is hereby granted 8 | without fee, provided that the above copyright notice appear in 9 | all copies and that both that copyright notice and this permission 10 | notice appear in supporting documentation, and that the name of 11 | the author not be used in advertising or publicity pertaining to 12 | distribution of the software without specific, written prior 13 | permission. 14 | 15 | THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16 | INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 | ANY PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 18 | ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 20 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 21 | OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 | */ 23 | #include "MERCDisjointSet.h" 24 | 25 | 26 | MERCDisjointSet::MERCDisjointSet(int nElements) 27 | { 28 | nElements_ = nElements; 29 | nVertices_ = nElements_; 30 | p_ = new int [nElements_]; 31 | size_ = new int [nElements_]; 32 | lists_ = new MList [nElements_]; 33 | 34 | 35 | int reservedSize = (int)std::sqrt( 1.0*nElements ); 36 | // Initialization with the cluster size and id 37 | for (int i = 0; i < nElements; i++) 38 | { 39 | p_[i] = i; 40 | size_[i] = 1; 41 | lists_[i].PushBack(i); 42 | } 43 | } 44 | 45 | MERCDisjointSet::~MERCDisjointSet() 46 | { 47 | Release(); 48 | } 49 | 50 | void MERCDisjointSet::Release() 51 | { 52 | delete [] p_; 53 | delete [] size_; 54 | delete [] lists_; 55 | p_ = NULL; 56 | size_ = NULL; 57 | lists_ = NULL; 58 | 59 | } 60 | 61 | void MERCDisjointSet::Set(int x,int l) 62 | { 63 | p_[x] = l; 64 | } 65 | 66 | int MERCDisjointSet::Find(int x) 67 | { 68 | // return the cluster ID 69 | return p_[x]; 70 | } 71 | 72 | int MERCDisjointSet::Join(int x, int y) 73 | { 74 | int aID = Find(x); 75 | int bID = Find(y); 76 | 77 | // The size is only maintained for cluster ID. 78 | int aSize = size_[aID]; 79 | int bSize = size_[bID]; 80 | 81 | 82 | int newID,delID; 83 | if( bSize < aSize ) 84 | { 85 | newID = aID; 86 | delID = bID; 87 | } 88 | else 89 | { 90 | newID = bID; 91 | delID = aID; 92 | } 93 | 94 | size_[newID] = aSize+bSize; 95 | size_[delID] = 0; 96 | 97 | MListNode *iter; 98 | for(iter=lists_[delID].first_;iter!=NULL;iter=iter->next_) 99 | p_[iter->data_] = newID; 100 | lists_[newID].Append(lists_[delID]); 101 | 102 | nElements_--; 103 | return newID; 104 | } -------------------------------------------------------------------------------- /lib_ers/MERCDisjointSet.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011, Ming-Yu Liu 3 | 4 | All Rights Reserved 5 | 6 | Permission to use, copy, modify, and distribute this software and 7 | its documentation for any non-commercial purpose is hereby granted 8 | without fee, provided that the above copyright notice appear in 9 | all copies and that both that copyright notice and this permission 10 | notice appear in supporting documentation, and that the name of 11 | the author not be used in advertising or publicity pertaining to 12 | distribution of the software without specific, written prior 13 | permission. 14 | 15 | THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16 | INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 | ANY PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 18 | ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 20 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 21 | OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 | */ 23 | #ifndef m_disjoint_set_h_ 24 | #define m_disjoint_set_h_ 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include "MList.h" 31 | 32 | 33 | class MERCDisjointSet 34 | { 35 | public: 36 | MERCDisjointSet(int nElements); 37 | ~MERCDisjointSet(); 38 | virtual void Release(); 39 | 40 | // set the pixel x with label l 41 | virtual void Set(int x,int l); 42 | 43 | // find the cluster ID for a given vertex 44 | virtual int Find(int x); 45 | 46 | // joint the cluster contains vertex y and the cluster contains vertex x 47 | virtual int Join(int x,int y); 48 | 49 | // return the cluster size containing the vertex x 50 | int rSize(int x) {return size_[Find(x)];}; 51 | 52 | // return the number of connected components in the set 53 | int rNumSets() const {return nElements_;}; 54 | 55 | // return the total number of vertices in the set 56 | int rNumVertices() const {return nVertices_;}; 57 | 58 | private: 59 | 60 | int *p_; 61 | int *size_; 62 | MList *lists_; 63 | int nElements_; 64 | int nVertices_; 65 | }; 66 | 67 | 68 | 69 | 70 | #endif 71 | 72 | -------------------------------------------------------------------------------- /lib_ers/MERCEdge.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011, Ming-Yu Liu 3 | 4 | All Rights Reserved 5 | 6 | Permission to use, copy, modify, and distribute this software and 7 | its documentation for any non-commercial purpose is hereby granted 8 | without fee, provided that the above copyright notice appear in 9 | all copies and that both that copyright notice and this permission 10 | notice appear in supporting documentation, and that the name of 11 | the author not be used in advertising or publicity pertaining to 12 | distribution of the software without specific, written prior 13 | permission. 14 | 15 | THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16 | INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 | ANY PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 18 | ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 20 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 21 | OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 | */ 23 | #ifndef _m_erc_edge_h_ 24 | #define _m_erc_edge_h_ 25 | 26 | #include 27 | #include 28 | 29 | using namespace std; 30 | 31 | class MERCEdge 32 | { 33 | public: 34 | int a_; 35 | int b_; 36 | double w_; 37 | double gain_; 38 | 39 | inline MERCEdge &operator=(const MERCEdge &rhs); 40 | inline bool operator==(const MERCEdge &other) const; 41 | inline bool operator!=(const MERCEdge &other) const; 42 | inline bool operator>=(const MERCEdge &other) const; 43 | inline bool operator<=(const MERCEdge &other) const; 44 | inline bool operator>(const MERCEdge &other) const; 45 | inline bool operator<(const MERCEdge &other) const; 46 | 47 | inline friend ostream &operator<<(ostream &output,MERCEdge &e); 48 | }; 49 | 50 | 51 | 52 | ostream &operator<<(ostream &output,MERCEdge &e) 53 | { 54 | output<< "(" << e.a_ <<", " << e.b_ <<", " << e.w_ <<", " << e.gain_ <<")"; 55 | return output; 56 | } 57 | 58 | 59 | MERCEdge &MERCEdge::operator=(const MERCEdge &rhs) 60 | { 61 | a_ = rhs.a_; 62 | b_ = rhs.b_; 63 | w_ = rhs.w_; 64 | gain_ = rhs.gain_; 65 | return *this; 66 | } 67 | 68 | bool MERCEdge::operator==(const MERCEdge &other) const 69 | { 70 | return gain_ == other.gain_; 71 | } 72 | 73 | bool MERCEdge::operator!=(const MERCEdge &other) const 74 | { 75 | return gain_ != other.gain_; 76 | } 77 | 78 | bool MERCEdge::operator>=(const MERCEdge &other) const 79 | { 80 | return gain_ >= other.gain_; 81 | } 82 | 83 | bool MERCEdge::operator<=(const MERCEdge &other) const 84 | { 85 | return gain_ <= other.gain_; 86 | } 87 | 88 | bool MERCEdge::operator>(const MERCEdge &other) const 89 | { 90 | return gain_ > other.gain_; 91 | } 92 | 93 | bool MERCEdge::operator<(const MERCEdge &other) const 94 | { 95 | return gain_ < other.gain_; 96 | } 97 | 98 | #endif -------------------------------------------------------------------------------- /lib_ers/MERCFunctions.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011, Ming-Yu Liu 3 | 4 | All Rights Reserved 5 | 6 | Permission to use, copy, modify, and distribute this software and 7 | its documentation for any non-commercial purpose is hereby granted 8 | without fee, provided that the above copyright notice appear in 9 | all copies and that both that copyright notice and this permission 10 | notice appear in supporting documentation, and that the name of 11 | the author not be used in advertising or publicity pertaining to 12 | distribution of the software without specific, written prior 13 | permission. 14 | 15 | THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16 | INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 | ANY PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 18 | ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 20 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 21 | OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 | */ 23 | #include "MERCFunctions.h" 24 | 25 | using namespace std; 26 | 27 | double MERCFunctions::ComputeERGain(double wij,double ci,double cj) 28 | { 29 | double er = ((wij+ci)*log(wij+ci) + (wij+cj)*log(wij+cj) - ci*log(ci) - cj*log(cj) - 2*wij*log(wij) )/log(2.0); 30 | if( er!=er ) 31 | return 0; 32 | else 33 | return er; 34 | } 35 | 36 | double MERCFunctions::ComputeBGain(int nVertices, int si,int sj) 37 | { 38 | double Si = si*1.0/nVertices; 39 | double Sj = sj*1.0/nVertices; 40 | double b = (-(Si+Sj)*log(Si+Sj) + Si*log(Si) + Sj*log(Sj))/log(2.0) + 1.0; 41 | return b; 42 | } 43 | 44 | void MERCFunctions::NormalizeEdgeWeight(MERCInput &edges,double *loop,double wT) 45 | { 46 | int nEdges = edges.nEdges_; 47 | int nVertices = edges.nNodes_; 48 | for(int i=0;i 28 | #include 29 | 30 | // Note the potential numerical error. Don't use a very small sigma value. 31 | class MERCFunctions 32 | { 33 | public: 34 | 35 | // compute the similarity scores 36 | static void ComputeSimilarity(MERCInput &edges,double sigma,int kernel=0); 37 | 38 | // compute the similarity scores with the Gaussian kernel. 39 | static void ComputeSimilarityGaussian(MERCInput &edges,double sigma); 40 | 41 | // compute the initial loop weight 42 | static double* ComputeLoopWeight(int nVertices,MERCInput &edges); 43 | 44 | // compute the total weight in the graph 45 | static double ComputeTotalWeight(double *loop,int nVertices); 46 | 47 | // normalize the edge similarity scores 48 | static void NormalizeEdgeWeight(MERCInput &edges,double *loop,double wT); 49 | 50 | // compute the edge gain in the entropy rate 51 | static double ComputeERGain(double wij,double ci,double cj); 52 | 53 | // compute the edge gain in the balancing term 54 | static double ComputeBGain(int nVertices, int si,int sj); 55 | 56 | }; 57 | 58 | #endif -------------------------------------------------------------------------------- /lib_ers/MERCInput.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011, Ming-Yu Liu 3 | 4 | All Rights Reserved 5 | 6 | Permission to use, copy, modify, and distribute this software and 7 | its documentation for any non-commercial purpose is hereby granted 8 | without fee, provided that the above copyright notice appear in 9 | all copies and that both that copyright notice and this permission 10 | notice appear in supporting documentation, and that the name of 11 | the author not be used in advertising or publicity pertaining to 12 | distribution of the software without specific, written prior 13 | permission. 14 | 15 | THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16 | INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 | ANY PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 18 | ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 20 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 21 | OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 | */ 23 | #ifndef _m_erc_input_h_ 24 | #define _m_erc_input_h_ 25 | 26 | #include 27 | #include 28 | #include "Edge.h" 29 | 30 | using namespace std; 31 | 32 | class MERCInput 33 | { 34 | public: 35 | MERCInput(); 36 | ~MERCInput(); 37 | void Release(); 38 | void Write(const char* filename); 39 | void Read(const char* filename); 40 | void ReadFromMatlab(double *pI,double *pJ,double *pW,int nEdges,int nNodes); 41 | 42 | public: 43 | Edge *edges_; 44 | int nEdges_; 45 | int nNodes_; 46 | 47 | }; 48 | 49 | #endif -------------------------------------------------------------------------------- /lib_ers/MERCInputImage.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011, Ming-Yu Liu 3 | 4 | All Rights Reserved 5 | 6 | Permission to use, copy, modify, and distribute this software and 7 | its documentation for any non-commercial purpose is hereby granted 8 | without fee, provided that the above copyright notice appear in 9 | all copies and that both that copyright notice and this permission 10 | notice appear in supporting documentation, and that the name of 11 | the author not be used in advertising or publicity pertaining to 12 | distribution of the software without specific, written prior 13 | permission. 14 | 15 | THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16 | INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 | ANY PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 18 | ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 20 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 21 | OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 | */ 23 | #ifndef _m_erc_input_image_h_ 24 | #define _m_erc_input_image_h_ 25 | 26 | #include "MERCInput.h" 27 | #include "Image.h" 28 | #include 29 | 30 | using namespace std; 31 | 32 | template 33 | class MERCInputImage: public MERCInput 34 | { 35 | public: 36 | void ReadImage(Image *inputImage, int conn8=1); 37 | 38 | int width_; 39 | int height_; 40 | }; 41 | 42 | template 43 | void MERCInputImage::ReadImage(Image *inputImage, int conn8) 44 | { 45 | width_ = inputImage->width(); 46 | height_ = inputImage->height(); 47 | nNodes_ = width_*height_; 48 | 49 | //cout<Access(x,y) - inputImage->Access(x+1,y))); 66 | num++; 67 | } 68 | 69 | if (y < height_-1) 70 | { 71 | edges_[num].a_ = y * width_ + x; 72 | edges_[num].b_ = (y+1) * width_ + x; 73 | //edges_[num].w_ = DiffGrayImage(image, x, y, x, y+1); 74 | edges_[num].w_ = abs(1.0*(inputImage->Access(x,y) - inputImage->Access(x,y+1))); 75 | num++; 76 | } 77 | 78 | if(conn8==1) 79 | { 80 | if ((x < width_-1) && (y < height_-1)) 81 | { 82 | edges_[num].a_ = y * width_ + x; 83 | edges_[num].b_ = (y+1) * width_ + (x+1); 84 | //edges_[num].w_ = std::sqrt(2.0)*DiffGrayImage(image, x, y, x+1, y+1); 85 | edges_[num].w_ = sqrt(2.0)*abs(1.0*(inputImage->Access(x,y) - inputImage->Access(x+1,y+1))); 86 | num++; 87 | } 88 | 89 | if ((x < width_-1) && (y > 0)) 90 | { 91 | edges_[num].a_ = y * width_ + x; 92 | edges_[num].b_ = (y-1) * width_ + (x+1); 93 | //edges_[num].w_ = std::sqrt(2.0)*DiffGrayImage(image, x, y, x+1, y-1); 94 | edges_[num].w_ = sqrt(2.0)*abs(1.0*(inputImage->Access(x,y) - inputImage->Access(x+1,y-1))); 95 | num++; 96 | } 97 | } 98 | } 99 | } 100 | nEdges_ = num; 101 | } 102 | 103 | #endif -------------------------------------------------------------------------------- /lib_ers/MERCLazyGreedy.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011, Ming-Yu Liu 3 | 4 | All Rights Reserved 5 | 6 | Permission to use, copy, modify, and distribute this software and 7 | its documentation for any non-commercial purpose is hereby granted 8 | without fee, provided that the above copyright notice appear in 9 | all copies and that both that copyright notice and this permission 10 | notice appear in supporting documentation, and that the name of 11 | the author not be used in advertising or publicity pertaining to 12 | distribution of the software without specific, written prior 13 | permission. 14 | 15 | THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16 | INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 | ANY PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 18 | ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 20 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 21 | OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 | */ 23 | #include "MERCLazyGreedy.h" 24 | 25 | MERCDisjointSet* MERCLazyGreedy::ClusteringTree(int nVertices,MERCInput &edges,int kernel,double sigma,double lambda,int nC) 26 | { 27 | //LARGE_INTEGER t1, t2, f; 28 | //QueryPerformanceFrequency(&f); 29 | //QueryPerformanceCounter(&t1); 30 | 31 | 32 | int nEdges = edges.nEdges_; 33 | MERCDisjointSet *u = new MERCDisjointSet(nVertices); 34 | 35 | MERCFunctions::ComputeSimilarity(edges,sigma,kernel); 36 | double *loop = MERCFunctions::ComputeLoopWeight(nVertices,edges); 37 | double wT = MERCFunctions::ComputeTotalWeight(loop,nVertices); 38 | MERCFunctions::NormalizeEdgeWeight(edges,loop,wT); 39 | 40 | // 41 | // Compute initial gain and decide the weighting on the balancing term 42 | // 43 | double *erGainArr = new double [nEdges];// gain in entropy rate term 44 | double *bGainArr = new double [nEdges]; // gain in balancing term 45 | double maxERGain=0,maxBGain=1e-20; 46 | for(int i=0;iFind( edges.edges_[i].a_ ); 53 | int b = u->Find( edges.edges_[i].b_ ); 54 | if(a!=b) 55 | bGainArr[i] = MERCFunctions::ComputeBGain(nVertices, u->rSize(a), u->rSize(b) ); 56 | else 57 | bGainArr[i] = 0; 58 | if(erGainArr[i]>maxERGain) 59 | maxERGain = erGainArr[i]; 60 | if(bGainArr[i]>maxBGain) 61 | maxBGain = bGainArr[i]; 62 | } 63 | double balancing = lambda*maxERGain/std::abs(maxBGain); 64 | //double balancing = lambda* log( 1.0*nVertices )/ log( 1.0*nC ); 65 | 66 | /* 67 | std::cout.precision(8); 68 | std::cout.setf(ios::fixed,ios::floatfield); 69 | std::cout<<"maxERGain = "<Find( bestEdge.a_ ); 108 | b = u->Find( bestEdge.b_ ); 109 | 110 | if(a!=b) 111 | { 112 | u->Join(a,b); 113 | cc--; 114 | loop[bestEdge.a_] -= bestEdge.w_; 115 | loop[bestEdge.b_] -= bestEdge.w_; 116 | } 117 | 118 | heap.EasyPartialUpdateTree(u,balancing,loop); 119 | } 120 | 121 | 122 | delete [] loop; 123 | //QueryPerformanceCounter(&t2); 124 | //std::cout.precision(6); 125 | //std::cout< &label,const char *filename) 26 | { 27 | std::ofstream file; 28 | file.open(filename); 29 | 30 | for(int i=0;i MERCOutput::DisjointSetToLabel(MERCDisjointSet *u) 39 | { 40 | int nSegments=0; 41 | int segIndex = 0; 42 | int nVertices = u->rNumVertices(); 43 | std::vector *sarray = new std::vector [nVertices]; 44 | vector labeling(nVertices); 45 | 46 | for (int k=0; kFind(k); 49 | sarray[comp].push_back(k); 50 | } 51 | 52 | for(int k=0;k 0) 55 | { 56 | nSegments++; 57 | } 58 | } 59 | 60 | for(int k=0;k 0) 63 | { 64 | for(unsigned int j=0;j 27 | #include 28 | #include 29 | #include "MERCDisjointSet.h" 30 | using namespace std; 31 | 32 | class MERCOutput 33 | { 34 | public: 35 | 36 | // Convert disjoint the set structure to a label array 37 | static vector DisjointSetToLabel(MERCDisjointSet *u); 38 | 39 | // Store the clustering map 40 | static void StoreClusteringMap(vector &label,const char *filename); 41 | }; 42 | 43 | 44 | 45 | #endif -------------------------------------------------------------------------------- /lib_ers/MERCOutputImage.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011, Ming-Yu Liu 3 | 4 | All Rights Reserved 5 | 6 | Permission to use, copy, modify, and distribute this software and 7 | its documentation for any non-commercial purpose is hereby granted 8 | without fee, provided that the above copyright notice appear in 9 | all copies and that both that copyright notice and this permission 10 | notice appear in supporting documentation, and that the name of 11 | the author not be used in advertising or publicity pertaining to 12 | distribution of the software without specific, written prior 13 | permission. 14 | 15 | THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16 | INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 | ANY PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 18 | ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 20 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 21 | OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 | */ 23 | #ifndef _m_erc_output_image_h_ 24 | #define _m_erc_output_image_h_ 25 | 26 | #include "MERCOutput.h" 27 | #include "Image.h" 28 | #include "ImageIO.h" 29 | 30 | using namespace std; 31 | 32 | class MERCOutputImage: public MERCOutput 33 | { 34 | public: 35 | static void StoreSegmentationMap(vector &label,int width,int height,const char *filename); 36 | 37 | 38 | }; 39 | 40 | void MERCOutputImage::StoreSegmentationMap(vector &label,int width,int height,const char *filename) 41 | { 42 | Image outputImage(width,height); 43 | 44 | RGBMap *color = new RGBMap[width*height]; 45 | 46 | for(int i=0; i 27 | class MListNode 28 | { 29 | public: 30 | T data_; 31 | MListNode *next_; 32 | }; 33 | 34 | 35 | template 36 | class MList 37 | { 38 | 39 | public: 40 | MList() { 41 | size_ = 0; 42 | first_ = NULL; 43 | last_ = NULL; 44 | }; 45 | ~MList() 46 | { 47 | Clear(); 48 | }; 49 | 50 | // Clear everything in the list 51 | void Clear(); 52 | 53 | // Push a new node to the end of the list 54 | void PushBack(T &data); 55 | 56 | // Append a list to the end of this list 57 | void Append(MList &other); 58 | //void Append(MList *other); 59 | 60 | // Return the number of elements in the list 61 | unsigned int rSize() {return size_;}; 62 | 63 | // Copy the list 64 | inline MList &operator=(const MList &rhs); 65 | 66 | 67 | MListNode *first_; 68 | MListNode *last_; 69 | unsigned int size_; 70 | }; 71 | 72 | template 73 | MList& MList::operator=(const MList &rhs) 74 | { 75 | MListNode *tmp; 76 | for(tmp=rhs.first_;tmp!=NULL;tmp=tmp->next_) 77 | { 78 | this->PushBack(tmp->data_); 79 | } 80 | return *this; 81 | } 82 | 83 | template 84 | void MList::Append(MList &other) 85 | { 86 | if(size_==0) 87 | { 88 | size_ = other.size_; 89 | first_ = other.first_; 90 | last_ = other.last_; 91 | } 92 | else 93 | { 94 | size_ += other.rSize(); 95 | last_->next_ = other.first_; 96 | last_ = other.last_; 97 | } 98 | 99 | // We should not release the dynamic memory at this place 100 | // since they are appended to the end of the other list. 101 | other.first_ = NULL; 102 | other.last_ = NULL; 103 | other.size_ = 0; 104 | } 105 | 106 | 107 | template 108 | void MList::Clear() 109 | { 110 | if(size_ == 0 ) 111 | return; 112 | 113 | MListNode *node = first_; 114 | while(node!=NULL) 115 | { 116 | // pointer to the next 117 | MListNode *tmp = node->next_; 118 | // delete the current one 119 | delete node; 120 | // link to the next 121 | node = tmp; 122 | } 123 | 124 | first_ = NULL; 125 | last_ = NULL; 126 | size_ = 0; 127 | } 128 | 129 | template 130 | void MList::PushBack(T &data) 131 | { 132 | // copy the content 133 | MListNode *node = new MListNode [1]; 134 | node->data_ = data; 135 | node->next_ = NULL; 136 | 137 | // if the list is empty 138 | if(last_==NULL) 139 | { 140 | // update the first node 141 | first_ = node; 142 | // update the last node 143 | last_ = node; 144 | // increase the size by one 145 | size_++; 146 | } 147 | else 148 | { 149 | // insert to the end of the list 150 | last_->next_ = node; 151 | // update the last node 152 | last_ = node; 153 | // increase the size by one 154 | size_++; 155 | } 156 | } 157 | 158 | 159 | #endif -------------------------------------------------------------------------------- /lib_ers/MSubmodularHeap.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011, Ming-Yu Liu 3 | 4 | All Rights Reserved 5 | 6 | Permission to use, copy, modify, and distribute this software and 7 | its documentation for any non-commercial purpose is hereby granted 8 | without fee, provided that the above copyright notice appear in 9 | all copies and that both that copyright notice and this permission 10 | notice appear in supporting documentation, and that the name of 11 | the author not be used in advertising or publicity pertaining to 12 | distribution of the software without specific, written prior 13 | permission. 14 | 15 | THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16 | INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 | ANY PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 18 | ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 20 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 21 | OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 | */ 23 | #ifndef _m_submodular_heap_h_ 24 | #define _m_submodular_heap_h_ 25 | #include "MMFunctions.h" 26 | #include "MHeap.h" 27 | #include "MERCDisjointSet.h" 28 | #include "MERCFunctions.h" 29 | 30 | using namespace std; 31 | 32 | template 33 | class MSubmodularHeap: public MHeap 34 | { 35 | public: 36 | 37 | MSubmodularHeap(int length); 38 | MSubmodularHeap(T *inarr,int length); 39 | 40 | // An easy update version for tree structure 41 | void EasyPartialUpdateTree(MERCDisjointSet *u,double balancingTerm,double *loop); 42 | 43 | 44 | private: 45 | 46 | MERCDisjointSet *u_; 47 | double *loop_; 48 | double balancingTerm_; 49 | 50 | // An easy update version for tree structure 51 | int EasyUpdateValueTree(int i); 52 | void EasySubmodularMaxHeapifyTree(); 53 | 54 | }; 55 | 56 | 57 | template 58 | MSubmodularHeap::MSubmodularHeap(int length): MHeap(length) {} 59 | 60 | template 61 | MSubmodularHeap::MSubmodularHeap(T *inarr,int length): MHeap(inarr,length) {} 62 | 63 | //============================================================================== 64 | // Fast update for tree structure 65 | //============================================================================== 66 | template 67 | void MSubmodularHeap::EasyPartialUpdateTree(MERCDisjointSet *u,double balancingTerm,double *loop) 68 | { 69 | // access to the disjoint set structure 70 | u_ = u; 71 | // keep track the loop value 72 | loop_ = loop; 73 | // copy the balancing parameter value. 74 | balancingTerm_ = balancingTerm; 75 | 76 | // A special heap update structure that utilize the submodular property. 77 | EasySubmodularMaxHeapifyTree(); 78 | } 79 | 80 | template 81 | void MSubmodularHeap::EasySubmodularMaxHeapifyTree() 82 | { 83 | //If the root node value is not updated, then update it 84 | //If the root node value is updated, then it is the maximum value in the current heap. 85 | //We don't need to update the other nodes because the dimnishing return property guarantees that the value can only be smaller. 86 | while(EasyUpdateValueTree(1)==0) 87 | { 88 | // If the edge form a loop, remove it from the loop and update the heap. 89 | if(this->array_[1].gain_ == 0) 90 | this->HeapExtractMax(); 91 | // Let insert the value into some correct place in the heap. 92 | else 93 | this->MaxHeapify(1); // find the maximum one through maxheapify 94 | } 95 | } 96 | 97 | 98 | template 99 | int MSubmodularHeap::EasyUpdateValueTree(int i) 100 | { 101 | double erGain,bGain; 102 | // store the old gain 103 | double oldGain = this->array_[i].gain_; 104 | 105 | int a,b; 106 | a = u_->Find( this->array_[i].a_ ); 107 | b = u_->Find( this->array_[i].b_ ); 108 | 109 | 110 | 111 | // If the edge forms a cycle, makes the gain zero. 112 | // Later, we will remove the zero edges from the heap. 113 | if( a==b ) 114 | { 115 | this->array_[i].gain_ = 0; 116 | } 117 | else 118 | { 119 | // recompute the entropy rate gain 120 | erGain = MERCFunctions::ComputeERGain( this->array_[i].w_, loop_[this->array_[i].a_]-this->array_[i].w_, loop_[this->array_[i].b_]-this->array_[i].w_); 121 | 122 | // recomptue the balancing gain 123 | bGain = MERCFunctions::ComputeBGain(u_->rNumVertices(), u_->rSize(a), u_->rSize(b) ); 124 | 125 | 126 | // compute the overall gain 127 | this->array_[i].gain_ = erGain+balancingTerm_*bGain; 128 | //array_[i].erGain_ = erGain; 129 | //array_[i].bGain_ = bGain; 130 | } 131 | 132 | // If the value is uptodate, we return one. (It will exit the while loop.) 133 | if(oldGain==this->array_[i].gain_) 134 | return 1; 135 | 136 | // If it is not, then we return zero. (It will trigger another MaxHeapify.) 137 | return 0; 138 | } 139 | 140 | 141 | 142 | #endif -------------------------------------------------------------------------------- /lib_ers/README.md: -------------------------------------------------------------------------------- 1 | # Entropy Rate Superpixels 2 | 3 | Code for Entropy Rate Superpixels [1]: 4 | 5 | [1] M. Y. Lui, O. Tuzel, S. Ramalingam, R. Chellappa. 6 | Entropy rate superpixel segmentation. 7 | Conference on Computer Vision and Pattern Recognition, pages 2097–2104, 2011. 8 | 9 | The corresponding command line tool can befound in `ers_cli/main.cpp`, including documentation. 10 | 11 | The original README can be found in `README.txt`. -------------------------------------------------------------------------------- /lib_ers/README.txt: -------------------------------------------------------------------------------- 1 | /******************************************************************** 2 | * Entropy Rate Superpixel Segmentation code * 3 | * * 4 | * Ming-Yu Liu (UMD), Oncel Tuzel (MERL), * 5 | * Srikumar Ramalingam (c) and Rama Chellappa (UMD) * 6 | * * 7 | /******************************************************************** 8 | 9 | /* Copyright 2011, Ming-Yu Liu 10 | 11 | All Rights Reserved 12 | 13 | Permission to use, copy, modify, and distribute this software and 14 | its documentation for any non-commercial purpose is hereby granted 15 | without fee, provided that the above copyright notice appear in 16 | all copies and that both that copyright notice and this permission 17 | notice appear in supporting documentation, and that the name of 18 | the author not be used in advertising or publicity pertaining to 19 | distribution of the software without specific, written prior 20 | permission. 21 | 22 | THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 23 | INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 24 | ANY PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 25 | ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 26 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 27 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 28 | OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 29 | */ 30 | 31 | /******************************************************************** 32 | * General information * 33 | /******************************************************************** 34 | Thanks for your interest in our work. This is a MATLAB wrapper for the 35 | Entropy Rate Superpixel Segmentation algorithm. For more detail about 36 | the algorithm please refer to the project webpage 37 | http://www.umiacs.umd.edu/~mingyliu 38 | or the following paper 39 | 40 | Ming-Yu Liu, Oncel Tuzel, Srikumar Ramalingam, and Rama Chellappa 41 | "Entropy Rate Superpixel Segmentation" Proceedings of the IEEE 42 | Conference on Computer Vision and Pattern Recognition(CVPR), 43 | Colorado Spring, June 2011. 44 | 45 | If you use this software, you should cite 46 | the aforementioned paper in any resulting publication. 47 | 48 | If you have any questions regarding the code please contact 49 | Ming-Yu Liu via . 50 | 51 | /******************************************************************** 52 | * Installation and usage * 53 | /******************************************************************** 54 | 55 | 1) Unzipped the files to $HOME_DIR 56 | 57 | 2) We have provided pre-compiled mex functions. You may not need to 58 | recompile the mex files again. If you need to recompile the codes. 59 | In the matlab command prompt, type >>make. This should do the job. 60 | 61 | 3) Type demo to see a demonstration of the usage of the code. 62 | 63 | mex_ers.mex : compute the superpixel segmentation for an input image. 64 | usage: 65 | [labels] = mex_ers(image,nC); 66 | [labels] = mex_ers(image,nC,lambda,sigma); 67 | [labels] = mex_ers(image,nC,lambda,sigma,conn8); 68 | Input: 69 | image : the input grey scale image or color image 70 | nC : the number of desired superpixels 71 | lambda : the balancing parameter ( default = 0.5; ) 72 | sigma : the kernel bandwidth ( default = 5.0; ) 73 | conn8 : the flag of using 8-connected grid graph structure ( default = 1 ) 74 | if set to 0, the algorithm will use 4-connected graph instead. 75 | Output: 76 | labels : the output image. Each pixel is labeled with the label 77 | of the superpixel it belongs to. Note that the labeling 78 | begins from 0 to nC-1 79 | 80 | /******************************************************************** 81 | * Revision History: * 82 | /******************************************************************** 83 | August 26, 2011; - Fixed two bugs causing compiling errors in Linux environment. 84 | August 11, 2011; - Enable the input of color images. 85 | August 11, 2011; - Enable the use of 4-connected grid graph structure. 86 | July 1, 2011; - First version for the general public 87 | 88 | -------------------------------------------------------------------------------- /lib_ers/mex_ers.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2011, Ming-Yu Liu 3 | 4 | All Rights Reserved 5 | 6 | Permission to use, copy, modify, and distribute this software and 7 | its documentation for any non-commercial purpose is hereby granted 8 | without fee, provided that the above copyright notice appear in 9 | all copies and that both that copyright notice and this permission 10 | notice appear in supporting documentation, and that the name of 11 | the author not be used in advertising or publicity pertaining to 12 | distribution of the software without specific, written prior 13 | permission. 14 | 15 | THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16 | INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 | ANY PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 18 | ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN 20 | AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 21 | OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22 | */ 23 | 24 | // Entropy Rate Superpixel Segmentation 25 | #include "mex.h" 26 | #include "matrix.h" 27 | #include "MERCLazyGreedy.h" 28 | #include "MERCInputImage.h" 29 | #include "MERCOutputImage.h" 30 | 31 | #include "Image.h" 32 | #include "ImageIO.h" 33 | #include 34 | #include 35 | 36 | using namespace std; 37 | 38 | void mexFunction(int nlhs, mxArray *plhs[ ],int nrhs, const mxArray *prhs[ ]) 39 | { 40 | double lambda,sigma; 41 | int nC,kernel = 0; 42 | int row,col; 43 | int conn8; 44 | double *pLambda,*pSigma,*pNC; 45 | double *data; 46 | double *out; 47 | double *pConn8; 48 | //size_t width,height; 49 | MERCLazyGreedy merc; 50 | 51 | mexPrintf("Entropy Rate Superpixel Segmentation Version 0.2!!!\n"); 52 | 53 | if(!(nrhs==2||nrhs==4||nrhs==5)) 54 | { 55 | mexPrintf("Syntax Error!!!\n"); 56 | mexPrintf("[labels] = mex_ers(image,nC)\n"); 57 | mexPrintf("[labels] = mex_ers(image,nC,lambda,sigma)\n"); 58 | mexErrMsgTxt("[labels] = mex_ers(image,nC,lambda,sigma,conn8)\n"); 59 | } 60 | 61 | //if(nlhs > 1) 62 | //{ 63 | // mexErrMsgTxt("Too many output arguments."); 64 | //} 65 | 66 | /* Check data type of input argument */ 67 | if (!(mxIsDouble(prhs[0]))) 68 | { 69 | mexErrMsgTxt("Input argument must be of type double."); 70 | } 71 | 72 | //width = mxGetN(prhs[0]); 73 | //height = mxGetM(prhs[0]); 74 | data = mxGetPr(prhs[0]); 75 | 76 | if(nrhs==2) 77 | { 78 | pNC = mxGetPr(prhs[1]); 79 | lambda = 0.5; 80 | sigma = 5.0; 81 | conn8 = 1; 82 | } 83 | 84 | if(nrhs==4) 85 | { 86 | pNC = mxGetPr(prhs[1]); 87 | pLambda = mxGetPr(prhs[2]); 88 | pSigma = mxGetPr(prhs[3]); 89 | lambda = *pLambda; 90 | sigma = *pSigma; 91 | conn8 = 1; 92 | } 93 | 94 | if(nrhs==5) 95 | { 96 | pNC = mxGetPr(prhs[1]); 97 | pLambda = mxGetPr(prhs[2]); 98 | pSigma = mxGetPr(prhs[3]); 99 | pConn8 = mxGetPr(prhs[4]); 100 | lambda = *pLambda; 101 | sigma = *pSigma; 102 | conn8 = (int)(*pConn8); 103 | } 104 | 105 | nC = (int)(*pNC); 106 | 107 | 108 | int nDims = (int)mxGetNumberOfDimensions(prhs[0]); 109 | if(nDims == 3) 110 | { 111 | int width = mxGetN(prhs[0])/nDims; 112 | int height = mxGetM(prhs[0]); 113 | //mexPrintf("Size = ( %d , %d ); Dimension = %d\n",width,height,nDims); 114 | Image inputImage; 115 | MERCInputImage input; 116 | // Create Iamge 117 | inputImage.Resize(width,height,false); 118 | // Read the image from MATLAB 119 | for (col=0; col < width; col++) 120 | { 121 | for (row=0; row < height; row++) 122 | { 123 | RGBMap color( 124 | (int)mxGetPr(prhs[0])[row+col*height+0*width*height], 125 | (int)mxGetPr(prhs[0])[row+col*height+1*width*height], 126 | (int)mxGetPr(prhs[0])[row+col*height+2*width*height]); 127 | inputImage.Access(col,row) = color; 128 | 129 | } 130 | } 131 | // Read the image for segmentation 132 | input.ReadImage(&inputImage,conn8); 133 | 134 | // Entropy rate superpixel segmentation 135 | merc.ClusteringTreeIF(input.nNodes_,input,kernel,sigma*nDims,lambda*1.0*nC,nC); 136 | vector label = MERCOutputImage::DisjointSetToLabel(merc.disjointSet_); 137 | // Allocate memory for the labeled image. 138 | plhs[0] = mxCreateDoubleMatrix(height, width, mxREAL); 139 | out = mxGetPr(plhs[0]); 140 | // Fill in the labeled image 141 | for (col=0; col < width; col++) 142 | for (row=0; row < height; row++) 143 | out[row+col*height] = (double)label[col+row*width]; 144 | } 145 | else 146 | { 147 | int width = mxGetN(prhs[0]); 148 | int height = mxGetM(prhs[0]); 149 | Image inputImage; 150 | MERCInputImage input; 151 | // Create Iamge 152 | inputImage.Resize(width,height,false); 153 | // Read the image from MATLAB 154 | for (col=0; col < mxGetN(prhs[0]); col++) 155 | for (row=0; row < mxGetM(prhs[0]); row++) 156 | inputImage.Access(col,row) = (uchar)mxGetPr(prhs[0])[row+col*mxGetM(prhs[0])]; 157 | // Read the image for segmentation 158 | input.ReadImage(&inputImage,conn8); 159 | 160 | // Entropy rate superpixel segmentation 161 | merc.ClusteringTreeIF(input.nNodes_,input,kernel,sigma,lambda*1.0*nC,nC); 162 | vector label = MERCOutputImage::DisjointSetToLabel(merc.disjointSet_); 163 | 164 | // Allocate memory for the labeled image. 165 | plhs[0] = mxCreateDoubleMatrix(height, width, mxREAL); 166 | out = mxGetPr(plhs[0]); 167 | // Fill in the labeled image 168 | for (col=0; col < width; col++) 169 | for (row=0; row < height; row++) 170 | out[row+col*height] = (double)label[col+row*width]; 171 | } 172 | 173 | return; 174 | } 175 | -------------------------------------------------------------------------------- /lib_fh/CMakeLists.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidstutz/superpixels-revisited/f14e9e0b063741e5a9eb6544a3d6c2f44cdfc9e4/lib_fh/CMakeLists.txt -------------------------------------------------------------------------------- /lib_fh/README.md: -------------------------------------------------------------------------------- 1 | # Felzenswalb & Huttenlocher Segmentation 2 | 3 | Code for the segmentation algorithm by Felzenswalb & Huttenlocher [1]: 4 | 5 | [1] P. F. Felzenswalb, D. P. Huttenlocher. 6 | Efficient graph-based image segmentation. 7 | International Journal of Computer Vision, 59(2), 2004. 8 | 9 | The corresponding command line tool can befound in `fh_cli/main.cpp`, including documentation. 10 | 11 | The original README can be found in `README.txt`, the license can befound in `LICENSE.txt`. -------------------------------------------------------------------------------- /lib_fh/README.txt: -------------------------------------------------------------------------------- 1 | Implementation of the segmentation algorithm described in: 2 | 3 | Efficient Graph-Based Image Segmentation 4 | Pedro F. Felzenszwalb and Daniel P. Huttenlocher 5 | International Journal of Computer Vision, 59(2) September 2004. 6 | 7 | The program takes a color image (PPM format) and produces a segmentation 8 | with a random color assigned to each region. 9 | 10 | 1) Type "make" to compile "segment". 11 | 12 | 2) Run "segment sigma k min input output". 13 | 14 | The parameters are: (see the paper for details) 15 | 16 | sigma: Used to smooth the input image before segmenting it. 17 | k: Value for the threshold function. 18 | min: Minimum component size enforced by post-processing. 19 | input: Input image. 20 | output: Output image. 21 | 22 | Typical parameters are sigma = 0.5, k = 500, min = 20. 23 | Larger values for k result in larger components in the result. 24 | -------------------------------------------------------------------------------- /lib_fh/convolve.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 Pedro Felzenszwalb 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | */ 18 | 19 | /* convolution */ 20 | 21 | #ifndef CONVOLVE_H 22 | #define CONVOLVE_H 23 | 24 | #include 25 | #include 26 | #include 27 | #include "image.h" 28 | 29 | /* convolve src with mask. dst is flipped! */ 30 | static void convolve_even(image *src, image *dst, 31 | std::vector &mask) { 32 | int width = src->width(); 33 | int height = src->height(); 34 | int len = mask.size(); 35 | 36 | for (int y = 0; y < height; y++) { 37 | for (int x = 0; x < width; x++) { 38 | float sum = mask[0] * imRef(src, x, y); 39 | for (int i = 1; i < len; i++) { 40 | sum += mask[i] * 41 | (imRef(src, std::max(x-i,0), y) + 42 | imRef(src, std::min(x+i, width-1), y)); 43 | } 44 | imRef(dst, y, x) = sum; 45 | } 46 | } 47 | } 48 | 49 | /* convolve src with mask. dst is flipped! */ 50 | static void convolve_odd(image *src, image *dst, 51 | std::vector &mask) { 52 | int width = src->width(); 53 | int height = src->height(); 54 | int len = mask.size(); 55 | 56 | for (int y = 0; y < height; y++) { 57 | for (int x = 0; x < width; x++) { 58 | float sum = mask[0] * imRef(src, x, y); 59 | for (int i = 1; i < len; i++) { 60 | sum += mask[i] * 61 | (imRef(src, std::max(x-i,0), y) - 62 | imRef(src, std::min(x+i, width-1), y)); 63 | } 64 | imRef(dst, y, x) = sum; 65 | } 66 | } 67 | } 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /lib_fh/disjoint-set.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 Pedro Felzenszwalb 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | */ 18 | 19 | #ifndef DISJOINT_SET 20 | #define DISJOINT_SET 21 | 22 | // disjoint-set forests using union-by-rank and path compression (sort of). 23 | 24 | typedef struct { 25 | int rank; 26 | int p; 27 | int size; 28 | } uni_elt; 29 | 30 | class universe { 31 | public: 32 | universe(int elements); 33 | ~universe(); 34 | int find(int x); 35 | void join(int x, int y); 36 | int size(int x) const { return elts[x].size; } 37 | int num_sets() const { return num; } 38 | 39 | private: 40 | uni_elt *elts; 41 | int num; 42 | }; 43 | 44 | universe::universe(int elements) { 45 | elts = new uni_elt[elements]; 46 | num = elements; 47 | for (int i = 0; i < elements; i++) { 48 | elts[i].rank = 0; 49 | elts[i].size = 1; 50 | elts[i].p = i; 51 | } 52 | } 53 | 54 | universe::~universe() { 55 | delete [] elts; 56 | } 57 | 58 | int universe::find(int x) { 59 | int y = x; 60 | while (y != elts[y].p) 61 | y = elts[y].p; 62 | elts[x].p = y; 63 | return y; 64 | } 65 | 66 | void universe::join(int x, int y) { 67 | if (elts[x].rank > elts[y].rank) { 68 | elts[y].p = x; 69 | elts[x].size += elts[y].size; 70 | } else { 71 | elts[x].p = y; 72 | elts[y].size += elts[x].size; 73 | if (elts[x].rank == elts[y].rank) 74 | elts[y].rank++; 75 | } 76 | num--; 77 | } 78 | 79 | #endif 80 | -------------------------------------------------------------------------------- /lib_fh/filter.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 Pedro Felzenszwalb 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | */ 18 | 19 | /* simple filters */ 20 | 21 | #ifndef FILTER_H 22 | #define FILTER_H 23 | 24 | #include 25 | #include 26 | #include "image.h" 27 | #include "misc.h" 28 | #include "convolve.h" 29 | #include "imconv.h" 30 | 31 | #define WIDTH 4.0 32 | 33 | /* normalize mask so it integrates to one */ 34 | static void normalize(std::vector &mask) { 35 | int len = mask.size(); 36 | float sum = 0; 37 | for (int i = 1; i < len; i++) { 38 | sum += fabs(mask[i]); 39 | } 40 | sum = 2*sum + fabs(mask[0]); 41 | for (int i = 0; i < len; i++) { 42 | mask[i] /= sum; 43 | } 44 | } 45 | 46 | /* make filters */ 47 | #define MAKE_FILTER(name, fun) \ 48 | static std::vector make_ ## name (float sigma) { \ 49 | sigma = std::max(sigma, 0.01F); \ 50 | int len = (int)ceil(sigma * WIDTH) + 1; \ 51 | std::vector mask(len); \ 52 | for (int i = 0; i < len; i++) { \ 53 | mask[i] = fun; \ 54 | } \ 55 | return mask; \ 56 | } 57 | 58 | MAKE_FILTER(fgauss, exp(-0.5*square(i/sigma))); 59 | 60 | /* convolve image with gaussian filter */ 61 | static image *smooth(image *src, float sigma) { 62 | std::vector mask = make_fgauss(sigma); 63 | normalize(mask); 64 | 65 | image *tmp = new image(src->height(), src->width(), false); 66 | image *dst = new image(src->width(), src->height(), false); 67 | convolve_even(src, tmp, mask); 68 | convolve_even(tmp, dst, mask); 69 | 70 | delete tmp; 71 | return dst; 72 | } 73 | 74 | /* convolve image with gaussian filter */ 75 | image *smooth(image *src, float sigma) { 76 | image *tmp = imageUCHARtoFLOAT(src); 77 | image *dst = smooth(tmp, sigma); 78 | delete tmp; 79 | return dst; 80 | } 81 | 82 | /* compute laplacian */ 83 | static image *laplacian(image *src) { 84 | int width = src->width(); 85 | int height = src->height(); 86 | image *dst = new image(width, height); 87 | 88 | for (int y = 1; y < height-1; y++) { 89 | for (int x = 1; x < width-1; x++) { 90 | float d2x = imRef(src, x-1, y) + imRef(src, x+1, y) - 91 | 2*imRef(src, x, y); 92 | float d2y = imRef(src, x, y-1) + imRef(src, x, y+1) - 93 | 2*imRef(src, x, y); 94 | imRef(dst, x, y) = d2x + d2y; 95 | } 96 | } 97 | return dst; 98 | } 99 | 100 | #endif 101 | -------------------------------------------------------------------------------- /lib_fh/image.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 Pedro Felzenszwalb 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | */ 18 | 19 | /* a simple image class */ 20 | 21 | #ifndef IMAGE_H 22 | #define IMAGE_H 23 | 24 | #include 25 | 26 | template 27 | class image { 28 | public: 29 | /* create an image */ 30 | image(const int width, const int height, const bool init = true); 31 | 32 | /* delete an image */ 33 | ~image(); 34 | 35 | /* init an image */ 36 | void init(const T &val); 37 | 38 | /* copy an image */ 39 | image *copy() const; 40 | 41 | /* get the width of an image. */ 42 | int width() const { return w; } 43 | 44 | /* get the height of an image. */ 45 | int height() const { return h; } 46 | 47 | /* image data. */ 48 | T *data; 49 | 50 | /* row pointers. */ 51 | T **access; 52 | 53 | private: 54 | int w, h; 55 | }; 56 | 57 | /* use imRef to access image data. */ 58 | #define imRef(im, x, y) (im->access[y][x]) 59 | 60 | /* use imPtr to get pointer to image data. */ 61 | #define imPtr(im, x, y) &(im->access[y][x]) 62 | 63 | template 64 | image::image(const int width, const int height, const bool init) { 65 | w = width; 66 | h = height; 67 | data = new T[w * h]; // allocate space for image data 68 | access = new T*[h]; // allocate space for row pointers 69 | 70 | // initialize row pointers 71 | for (int i = 0; i < h; i++) 72 | access[i] = data + (i * w); 73 | 74 | if (init) 75 | memset(data, 0, w * h * sizeof(T)); 76 | } 77 | 78 | template 79 | image::~image() { 80 | delete [] data; 81 | delete [] access; 82 | } 83 | 84 | template 85 | void image::init(const T &val) { 86 | T *ptr = imPtr(this, 0, 0); 87 | T *end = imPtr(this, w-1, h-1); 88 | while (ptr <= end) 89 | *ptr++ = val; 90 | } 91 | 92 | 93 | template 94 | image *image::copy() const { 95 | image *im = new image(w, h, false); 96 | memcpy(im->data, data, w * h * sizeof(T)); 97 | return im; 98 | } 99 | 100 | #endif 101 | 102 | -------------------------------------------------------------------------------- /lib_fh/imconv.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 Pedro Felzenszwalb 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | */ 18 | 19 | /* image conversion */ 20 | 21 | #ifndef CONV_H 22 | #define CONV_H 23 | 24 | #include 25 | #include "image.h" 26 | #include "imutil.h" 27 | #include "misc.h" 28 | 29 | #define RED_WEIGHT 0.299 30 | #define GREEN_WEIGHT 0.587 31 | #define BLUE_WEIGHT 0.114 32 | 33 | static image *imageRGBtoGRAY(image *input) { 34 | int width = input->width(); 35 | int height = input->height(); 36 | image *output = new image(width, height, false); 37 | 38 | for (int y = 0; y < height; y++) { 39 | for (int x = 0; x < width; x++) { 40 | imRef(output, x, y) = (uchar) 41 | (imRef(input, x, y).r * RED_WEIGHT + 42 | imRef(input, x, y).g * GREEN_WEIGHT + 43 | imRef(input, x, y).b * BLUE_WEIGHT); 44 | } 45 | } 46 | return output; 47 | } 48 | 49 | static image *imageGRAYtoRGB(image *input) { 50 | int width = input->width(); 51 | int height = input->height(); 52 | image *output = new image(width, height, false); 53 | 54 | for (int y = 0; y < height; y++) { 55 | for (int x = 0; x < width; x++) { 56 | imRef(output, x, y).r = imRef(input, x, y); 57 | imRef(output, x, y).g = imRef(input, x, y); 58 | imRef(output, x, y).b = imRef(input, x, y); 59 | } 60 | } 61 | return output; 62 | } 63 | 64 | static image *imageUCHARtoFLOAT(image *input) { 65 | int width = input->width(); 66 | int height = input->height(); 67 | image *output = new image(width, height, false); 68 | 69 | for (int y = 0; y < height; y++) { 70 | for (int x = 0; x < width; x++) { 71 | imRef(output, x, y) = imRef(input, x, y); 72 | } 73 | } 74 | return output; 75 | } 76 | 77 | static image *imageINTtoFLOAT(image *input) { 78 | int width = input->width(); 79 | int height = input->height(); 80 | image *output = new image(width, height, false); 81 | 82 | for (int y = 0; y < height; y++) { 83 | for (int x = 0; x < width; x++) { 84 | imRef(output, x, y) = imRef(input, x, y); 85 | } 86 | } 87 | return output; 88 | } 89 | 90 | static image *imageFLOATtoUCHAR(image *input, 91 | float min, float max) { 92 | int width = input->width(); 93 | int height = input->height(); 94 | image *output = new image(width, height, false); 95 | 96 | if (max == min) 97 | return output; 98 | 99 | float scale = UCHAR_MAX / (max - min); 100 | for (int y = 0; y < height; y++) { 101 | for (int x = 0; x < width; x++) { 102 | uchar val = (uchar)((imRef(input, x, y) - min) * scale); 103 | imRef(output, x, y) = bound(val, (uchar)0, (uchar)UCHAR_MAX); 104 | } 105 | } 106 | return output; 107 | } 108 | 109 | static image *imageFLOATtoUCHAR(image *input) { 110 | float min, max; 111 | min_max(input, &min, &max); 112 | return imageFLOATtoUCHAR(input, min, max); 113 | } 114 | 115 | static image *imageUCHARtoLONG(image *input) { 116 | int width = input->width(); 117 | int height = input->height(); 118 | image *output = new image(width, height, false); 119 | 120 | for (int y = 0; y < height; y++) { 121 | for (int x = 0; x < width; x++) { 122 | imRef(output, x, y) = imRef(input, x, y); 123 | } 124 | } 125 | return output; 126 | } 127 | 128 | static image *imageLONGtoUCHAR(image *input, long min, long max) { 129 | int width = input->width(); 130 | int height = input->height(); 131 | image *output = new image(width, height, false); 132 | 133 | if (max == min) 134 | return output; 135 | 136 | float scale = UCHAR_MAX / (float)(max - min); 137 | for (int y = 0; y < height; y++) { 138 | for (int x = 0; x < width; x++) { 139 | uchar val = (uchar)((imRef(input, x, y) - min) * scale); 140 | imRef(output, x, y) = bound(val, (uchar)0, (uchar)UCHAR_MAX); 141 | } 142 | } 143 | return output; 144 | } 145 | 146 | static image *imageLONGtoUCHAR(image *input) { 147 | long min, max; 148 | min_max(input, &min, &max); 149 | return imageLONGtoUCHAR(input, min, max); 150 | } 151 | 152 | static image *imageSHORTtoUCHAR(image *input, 153 | short min, short max) { 154 | int width = input->width(); 155 | int height = input->height(); 156 | image *output = new image(width, height, false); 157 | 158 | if (max == min) 159 | return output; 160 | 161 | float scale = UCHAR_MAX / (float)(max - min); 162 | for (int y = 0; y < height; y++) { 163 | for (int x = 0; x < width; x++) { 164 | uchar val = (uchar)((imRef(input, x, y) - min) * scale); 165 | imRef(output, x, y) = bound(val, (uchar)0, (uchar)UCHAR_MAX); 166 | } 167 | } 168 | return output; 169 | } 170 | 171 | static image *imageSHORTtoUCHAR(image *input) { 172 | short min, max; 173 | min_max(input, &min, &max); 174 | return imageSHORTtoUCHAR(input, min, max); 175 | } 176 | 177 | #endif 178 | -------------------------------------------------------------------------------- /lib_fh/imutil.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 Pedro Felzenszwalb 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | */ 18 | 19 | /* some image utilities */ 20 | 21 | #ifndef IMUTIL_H 22 | #define IMUTIL_H 23 | 24 | #include "image.h" 25 | #include "misc.h" 26 | 27 | /* compute minimum and maximum value in an image */ 28 | template 29 | void min_max(image *im, T *ret_min, T *ret_max) { 30 | int width = im->width(); 31 | int height = im->height(); 32 | 33 | T min = imRef(im, 0, 0); 34 | T max = imRef(im, 0, 0); 35 | for (int y = 0; y < height; y++) { 36 | for (int x = 0; x < width; x++) { 37 | T val = imRef(im, x, y); 38 | if (min > val) 39 | min = val; 40 | if (max < val) 41 | max = val; 42 | } 43 | } 44 | 45 | *ret_min = min; 46 | *ret_max = max; 47 | } 48 | 49 | /* threshold image */ 50 | template 51 | image *threshold(image *src, int t) { 52 | int width = src->width(); 53 | int height = src->height(); 54 | image *dst = new image(width, height); 55 | 56 | for (int y = 0; y < height; y++) { 57 | for (int x = 0; x < width; x++) { 58 | imRef(dst, x, y) = (imRef(src, x, y) >= t); 59 | } 60 | } 61 | 62 | return dst; 63 | } 64 | 65 | #endif 66 | 67 | -------------------------------------------------------------------------------- /lib_fh/misc.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 Pedro Felzenszwalb 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | */ 18 | 19 | /* random stuff */ 20 | 21 | #ifndef MISC_H 22 | #define MISC_H 23 | 24 | #include 25 | 26 | #ifndef M_PI 27 | #define M_PI 3.141592653589793 28 | #endif 29 | 30 | typedef unsigned char uchar; 31 | 32 | typedef struct { uchar r, g, b; } rgb; 33 | 34 | inline bool operator==(const rgb &a, const rgb &b) { 35 | return ((a.r == b.r) && (a.g == b.g) && (a.b == b.b)); 36 | } 37 | 38 | template 39 | inline T abs(const T &x) { return (x > 0 ? x : -x); }; 40 | 41 | template 42 | inline int sign(const T &x) { return (x >= 0 ? 1 : -1); }; 43 | 44 | template 45 | inline T square(const T &x) { return x*x; }; 46 | 47 | template 48 | inline T bound(const T &x, const T &min, const T &max) { 49 | return (x < min ? min : (x > max ? max : x)); 50 | } 51 | 52 | template 53 | inline bool check_bound(const T &x, const T&min, const T &max) { 54 | return ((x < min) || (x > max)); 55 | } 56 | 57 | inline int vlib_round(float x) { return (int)(x + 0.5F); } 58 | 59 | inline int vlib_round(double x) { return (int)(x + 0.5); } 60 | 61 | inline double gaussian(double val, double sigma) { 62 | return exp(-square(val/sigma)/2)/(sqrt(2*M_PI)*sigma); 63 | } 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /lib_fh/pnmfile.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 Pedro Felzenszwalb 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | */ 18 | 19 | /* basic image I/O */ 20 | 21 | #ifndef PNM_FILE_H 22 | #define PNM_FILE_H 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include "image.h" 29 | #include "misc.h" 30 | 31 | #define BUF_SIZE 256 32 | 33 | class pnm_error { }; 34 | 35 | static void read_packed(unsigned char *data, int size, std::ifstream &f) { 36 | unsigned char c = 0; 37 | 38 | int bitshift = -1; 39 | for (int pos = 0; pos < size; pos++) { 40 | if (bitshift == -1) { 41 | c = f.get(); 42 | bitshift = 7; 43 | } 44 | data[pos] = (c >> bitshift) & 1; 45 | bitshift--; 46 | } 47 | } 48 | 49 | static void write_packed(unsigned char *data, int size, std::ofstream &f) { 50 | unsigned char c = 0; 51 | 52 | int bitshift = 7; 53 | for (int pos = 0; pos < size; pos++) { 54 | c = c | (data[pos] << bitshift); 55 | bitshift--; 56 | if ((bitshift == -1) || (pos == size-1)) { 57 | f.put(c); 58 | bitshift = 7; 59 | c = 0; 60 | } 61 | } 62 | } 63 | 64 | /* read PNM field, skipping comments */ 65 | static void pnm_read(std::ifstream &file, char *buf) { 66 | char doc[BUF_SIZE]; 67 | char c; 68 | 69 | file >> c; 70 | while (c == '#') { 71 | file.getline(doc, BUF_SIZE); 72 | file >> c; 73 | } 74 | file.putback(c); 75 | 76 | file.width(BUF_SIZE); 77 | file >> buf; 78 | file.ignore(); 79 | } 80 | 81 | static image *loadPBM(const char *name) { 82 | char buf[BUF_SIZE]; 83 | 84 | /* read header */ 85 | std::ifstream file(name, std::ios::in | std::ios::binary); 86 | pnm_read(file, buf); 87 | if (strncmp(buf, "P4", 2)) 88 | throw pnm_error(); 89 | 90 | pnm_read(file, buf); 91 | int width = atoi(buf); 92 | pnm_read(file, buf); 93 | int height = atoi(buf); 94 | 95 | /* read data */ 96 | image *im = new image(width, height); 97 | for (int i = 0; i < height; i++) 98 | read_packed(imPtr(im, 0, i), width, file); 99 | 100 | return im; 101 | } 102 | 103 | static void savePBM(image *im, const char *name) { 104 | int width = im->width(); 105 | int height = im->height(); 106 | std::ofstream file(name, std::ios::out | std::ios::binary); 107 | 108 | file << "P4\n" << width << " " << height << "\n"; 109 | for (int i = 0; i < height; i++) 110 | write_packed(imPtr(im, 0, i), width, file); 111 | } 112 | 113 | static image *loadPGM(const char *name) { 114 | char buf[BUF_SIZE]; 115 | 116 | /* read header */ 117 | std::ifstream file(name, std::ios::in | std::ios::binary); 118 | pnm_read(file, buf); 119 | if (strncmp(buf, "P5", 2)) 120 | throw pnm_error(); 121 | 122 | pnm_read(file, buf); 123 | int width = atoi(buf); 124 | pnm_read(file, buf); 125 | int height = atoi(buf); 126 | 127 | pnm_read(file, buf); 128 | if (atoi(buf) > UCHAR_MAX) 129 | throw pnm_error(); 130 | 131 | /* read data */ 132 | image *im = new image(width, height); 133 | file.read((char *)imPtr(im, 0, 0), width * height * sizeof(uchar)); 134 | 135 | return im; 136 | } 137 | 138 | static void savePGM(image *im, const char *name) { 139 | int width = im->width(); 140 | int height = im->height(); 141 | std::ofstream file(name, std::ios::out | std::ios::binary); 142 | 143 | file << "P5\n" << width << " " << height << "\n" << UCHAR_MAX << "\n"; 144 | file.write((char *)imPtr(im, 0, 0), width * height * sizeof(uchar)); 145 | } 146 | 147 | static image *loadPPM(const char *name) { 148 | char buf[BUF_SIZE], doc[BUF_SIZE]; 149 | 150 | /* read header */ 151 | std::ifstream file(name, std::ios::in | std::ios::binary); 152 | pnm_read(file, buf); 153 | if (strncmp(buf, "P6", 2)) 154 | throw pnm_error(); 155 | 156 | pnm_read(file, buf); 157 | int width = atoi(buf); 158 | pnm_read(file, buf); 159 | int height = atoi(buf); 160 | 161 | pnm_read(file, buf); 162 | if (atoi(buf) > UCHAR_MAX) 163 | throw pnm_error(); 164 | 165 | /* read data */ 166 | image *im = new image(width, height); 167 | file.read((char *)imPtr(im, 0, 0), width * height * sizeof(rgb)); 168 | 169 | return im; 170 | } 171 | 172 | static void savePPM(image *im, const char *name) { 173 | int width = im->width(); 174 | int height = im->height(); 175 | std::ofstream file(name, std::ios::out | std::ios::binary); 176 | 177 | file << "P6\n" << width << " " << height << "\n" << UCHAR_MAX << "\n"; 178 | file.write((char *)imPtr(im, 0, 0), width * height * sizeof(rgb)); 179 | } 180 | 181 | template 182 | void load_image(image **im, const char *name) { 183 | char buf[BUF_SIZE]; 184 | 185 | /* read header */ 186 | std::ifstream file(name, std::ios::in | std::ios::binary); 187 | pnm_read(file, buf); 188 | if (strncmp(buf, "VLIB", 9)) 189 | throw pnm_error(); 190 | 191 | pnm_read(file, buf); 192 | int width = atoi(buf); 193 | pnm_read(file, buf); 194 | int height = atoi(buf); 195 | 196 | /* read data */ 197 | *im = new image(width, height); 198 | file.read((char *)imPtr((*im), 0, 0), width * height * sizeof(T)); 199 | } 200 | 201 | template 202 | void save_image(image *im, const char *name) { 203 | int width = im->width(); 204 | int height = im->height(); 205 | std::ofstream file(name, std::ios::out | std::ios::binary); 206 | 207 | file << "VLIB\n" << width << " " << height << "\n"; 208 | file.write((char *)imPtr(im, 0, 0), width * height * sizeof(T)); 209 | } 210 | 211 | #endif 212 | -------------------------------------------------------------------------------- /lib_fh/segment-graph.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 Pedro Felzenszwalb 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | */ 18 | 19 | #ifndef SEGMENT_GRAPH 20 | #define SEGMENT_GRAPH 21 | 22 | #include 23 | #include 24 | #include "disjoint-set.h" 25 | 26 | // threshold function 27 | #define THRESHOLD(size, c) (c/size) 28 | 29 | typedef struct { 30 | float w; 31 | int a, b; 32 | } edge; 33 | 34 | bool operator<(const edge &a, const edge &b) { 35 | return a.w < b.w; 36 | } 37 | 38 | /* 39 | * Segment a graph 40 | * 41 | * Returns a disjoint-set forest representing the segmentation. 42 | * 43 | * num_vertices: number of vertices in graph. 44 | * num_edges: number of edges in graph 45 | * edges: array of edges. 46 | * c: constant for treshold function. 47 | */ 48 | universe *segment_graph(int num_vertices, int num_edges, edge *edges, 49 | float c) { 50 | // sort edges by weight 51 | std::sort(edges, edges + num_edges); 52 | 53 | // make a disjoint-set forest 54 | universe *u = new universe(num_vertices); 55 | 56 | // init thresholds 57 | float *threshold = new float[num_vertices]; 58 | for (int i = 0; i < num_vertices; i++) 59 | threshold[i] = THRESHOLD(1,c); 60 | 61 | // for each edge, in non-decreasing weight order... 62 | for (int i = 0; i < num_edges; i++) { 63 | edge *pedge = &edges[i]; 64 | 65 | // components conected by this edge 66 | int a = u->find(pedge->a); 67 | int b = u->find(pedge->b); 68 | if (a != b) { 69 | if ((pedge->w <= threshold[a]) && 70 | (pedge->w <= threshold[b])) { 71 | u->join(a, b); 72 | a = u->find(a); 73 | threshold[a] = pedge->w + THRESHOLD(u->size(a), c); 74 | } 75 | } 76 | } 77 | 78 | // free up 79 | delete threshold; 80 | return u; 81 | } 82 | 83 | #endif 84 | -------------------------------------------------------------------------------- /lib_fh/segment-image-labels.h: -------------------------------------------------------------------------------- 1 | #ifndef SEGMENT_IMAGE_LABELS_H 2 | #define SEGMENT_IMAGE_LABELS_H 3 | 4 | #include "image.h" 5 | #include "misc.h" 6 | #include "filter.h" 7 | #include "segment-graph.h" 8 | #include "segment-image.h" 9 | 10 | /* 11 | * Segment an image and return and image containing the labels 12 | * instead of random colors. 13 | * 14 | * Returns a color image representing the segmentation. 15 | * 16 | * im: image to segment. 17 | * sigma: to smooth the image. 18 | * c: constant for treshold function. 19 | * min_size: minimum component size (enforced by post-processing stage). 20 | * num_ccs: number of connected components in the segmentation. 21 | */ 22 | image *segment_image_labels(image *im, float sigma, float c, int min_size, 23 | int *num_ccs) { 24 | int width = im->width(); 25 | int height = im->height(); 26 | 27 | image *r = new image(width, height); 28 | image *g = new image(width, height); 29 | image *b = new image(width, height); 30 | 31 | // smooth each color channel 32 | for (int y = 0; y < height; y++) { 33 | for (int x = 0; x < width; x++) { 34 | imRef(r, x, y) = imRef(im, x, y).r; 35 | imRef(g, x, y) = imRef(im, x, y).g; 36 | imRef(b, x, y) = imRef(im, x, y).b; 37 | } 38 | } 39 | image *smooth_r = smooth(r, sigma); 40 | image *smooth_g = smooth(g, sigma); 41 | image *smooth_b = smooth(b, sigma); 42 | delete r; 43 | delete g; 44 | delete b; 45 | 46 | // build graph 47 | edge *edges = new edge[width*height*4]; 48 | int num = 0; 49 | for (int y = 0; y < height; y++) { 50 | for (int x = 0; x < width; x++) { 51 | if (x < width-1) { 52 | edges[num].a = y * width + x; 53 | edges[num].b = y * width + (x+1); 54 | edges[num].w = diff(smooth_r, smooth_g, smooth_b, x, y, x+1, y); 55 | num++; 56 | } 57 | 58 | if (y < height-1) { 59 | edges[num].a = y * width + x; 60 | edges[num].b = (y+1) * width + x; 61 | edges[num].w = diff(smooth_r, smooth_g, smooth_b, x, y, x, y+1); 62 | num++; 63 | } 64 | 65 | if ((x < width-1) && (y < height-1)) { 66 | edges[num].a = y * width + x; 67 | edges[num].b = (y+1) * width + (x+1); 68 | edges[num].w = diff(smooth_r, smooth_g, smooth_b, x, y, x+1, y+1); 69 | num++; 70 | } 71 | 72 | if ((x < width-1) && (y > 0)) { 73 | edges[num].a = y * width + x; 74 | edges[num].b = (y-1) * width + (x+1); 75 | edges[num].w = diff(smooth_r, smooth_g, smooth_b, x, y, x+1, y-1); 76 | num++; 77 | } 78 | } 79 | } 80 | delete smooth_r; 81 | delete smooth_g; 82 | delete smooth_b; 83 | 84 | // segment 85 | universe *u = segment_graph(width*height, num, edges, c); 86 | 87 | // post process small components 88 | for (int i = 0; i < num; i++) { 89 | int a = u->find(edges[i].a); 90 | int b = u->find(edges[i].b); 91 | if ((a != b) && ((u->size(a) < min_size) || (u->size(b) < min_size))) 92 | u->join(a, b); 93 | } 94 | delete [] edges; 95 | *num_ccs = u->num_sets(); 96 | 97 | image *output = new image(width, height); 98 | 99 | for (int y = 0; y < height; y++) { 100 | for (int x = 0; x < width; x++) { 101 | int comp = u->find(y * width + x); 102 | imRef(output, x, y) = comp; 103 | } 104 | } 105 | 106 | delete u; 107 | 108 | return output; 109 | } 110 | 111 | #endif /* SEGMENT_IMAGE_LABELS_H */ 112 | 113 | -------------------------------------------------------------------------------- /lib_fh/segment-image.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 Pedro Felzenszwalb 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | */ 18 | 19 | #ifndef SEGMENT_IMAGE 20 | #define SEGMENT_IMAGE 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include "segment-graph.h" 27 | 28 | // random color 29 | rgb random_rgb(){ 30 | rgb c; 31 | double r; 32 | 33 | c.r = (uchar)random(); 34 | c.g = (uchar)random(); 35 | c.b = (uchar)random(); 36 | 37 | return c; 38 | } 39 | 40 | // dissimilarity measure between pixels 41 | static inline float diff(image *r, image *g, image *b, 42 | int x1, int y1, int x2, int y2) { 43 | return sqrt(square(imRef(r, x1, y1)-imRef(r, x2, y2)) + 44 | square(imRef(g, x1, y1)-imRef(g, x2, y2)) + 45 | square(imRef(b, x1, y1)-imRef(b, x2, y2))); 46 | } 47 | 48 | /* 49 | * Segment an image 50 | * 51 | * Returns a color image representing the segmentation. 52 | * 53 | * im: image to segment. 54 | * sigma: to smooth the image. 55 | * c: constant for treshold function. 56 | * min_size: minimum component size (enforced by post-processing stage). 57 | * num_ccs: number of connected components in the segmentation. 58 | */ 59 | image *segment_image(image *im, float sigma, float c, int min_size, 60 | int *num_ccs) { 61 | int width = im->width(); 62 | int height = im->height(); 63 | 64 | image *r = new image(width, height); 65 | image *g = new image(width, height); 66 | image *b = new image(width, height); 67 | 68 | // smooth each color channel 69 | for (int y = 0; y < height; y++) { 70 | for (int x = 0; x < width; x++) { 71 | imRef(r, x, y) = imRef(im, x, y).r; 72 | imRef(g, x, y) = imRef(im, x, y).g; 73 | imRef(b, x, y) = imRef(im, x, y).b; 74 | } 75 | } 76 | image *smooth_r = smooth(r, sigma); 77 | image *smooth_g = smooth(g, sigma); 78 | image *smooth_b = smooth(b, sigma); 79 | delete r; 80 | delete g; 81 | delete b; 82 | 83 | // build graph 84 | edge *edges = new edge[width*height*4]; 85 | int num = 0; 86 | for (int y = 0; y < height; y++) { 87 | for (int x = 0; x < width; x++) { 88 | if (x < width-1) { 89 | edges[num].a = y * width + x; 90 | edges[num].b = y * width + (x+1); 91 | edges[num].w = diff(smooth_r, smooth_g, smooth_b, x, y, x+1, y); 92 | num++; 93 | } 94 | 95 | if (y < height-1) { 96 | edges[num].a = y * width + x; 97 | edges[num].b = (y+1) * width + x; 98 | edges[num].w = diff(smooth_r, smooth_g, smooth_b, x, y, x, y+1); 99 | num++; 100 | } 101 | 102 | if ((x < width-1) && (y < height-1)) { 103 | edges[num].a = y * width + x; 104 | edges[num].b = (y+1) * width + (x+1); 105 | edges[num].w = diff(smooth_r, smooth_g, smooth_b, x, y, x+1, y+1); 106 | num++; 107 | } 108 | 109 | if ((x < width-1) && (y > 0)) { 110 | edges[num].a = y * width + x; 111 | edges[num].b = (y-1) * width + (x+1); 112 | edges[num].w = diff(smooth_r, smooth_g, smooth_b, x, y, x+1, y-1); 113 | num++; 114 | } 115 | } 116 | } 117 | delete smooth_r; 118 | delete smooth_g; 119 | delete smooth_b; 120 | 121 | // segment 122 | universe *u = segment_graph(width*height, num, edges, c); 123 | 124 | // post process small components 125 | for (int i = 0; i < num; i++) { 126 | int a = u->find(edges[i].a); 127 | int b = u->find(edges[i].b); 128 | if ((a != b) && ((u->size(a) < min_size) || (u->size(b) < min_size))) 129 | u->join(a, b); 130 | } 131 | delete [] edges; 132 | *num_ccs = u->num_sets(); 133 | 134 | image *output = new image(width, height); 135 | 136 | // pick random colors for each component 137 | rgb *colors = new rgb[width*height]; 138 | for (int i = 0; i < width*height; i++) 139 | colors[i] = random_rgb(); 140 | 141 | for (int y = 0; y < height; y++) { 142 | for (int x = 0; x < width; x++) { 143 | int comp = u->find(y * width + x); 144 | imRef(output, x, y) = colors[comp]; 145 | } 146 | } 147 | 148 | delete [] colors; 149 | delete u; 150 | 151 | return output; 152 | } 153 | 154 | #endif 155 | -------------------------------------------------------------------------------- /lib_fh/segment.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (C) 2006 Pedro Felzenszwalb 3 | 4 | This program is free software; you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation; either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include "segment-image.h" 25 | 26 | int main(int argc, char **argv) { 27 | if (argc != 6) { 28 | fprintf(stderr, "usage: %s sigma k min input(ppm) output(ppm)\n", argv[0]); 29 | return 1; 30 | } 31 | 32 | float sigma = atof(argv[1]); 33 | float k = atof(argv[2]); 34 | int min_size = atoi(argv[3]); 35 | 36 | printf("loading input image.\n"); 37 | image *input = loadPPM(argv[4]); 38 | 39 | printf("processing\n"); 40 | int num_ccs; 41 | image *seg = segment_image(input, sigma, k, min_size, &num_ccs); 42 | savePPM(seg, argv[5]); 43 | 44 | printf("got %d components\n", num_ccs); 45 | printf("done! uff...thats hard work.\n"); 46 | 47 | return 0; 48 | } 49 | 50 | -------------------------------------------------------------------------------- /lib_pb/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_subdirectory(Elimination) 2 | add_subdirectory(MaxFlow) 3 | -------------------------------------------------------------------------------- /lib_pb/Elimination/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../) 2 | 3 | add_library(pb_elimination Elimination.h Elimination.txx Elimination.cc LazyElimination.h LazyElimination.cc) 4 | -------------------------------------------------------------------------------- /lib_pb/Elimination/Elimination+SSE.h: -------------------------------------------------------------------------------- 1 | #ifndef Elimination_SSE_h_ 2 | #define Elimination_SSE_h_ 3 | 4 | #define ELIMINATION_SSE 0 5 | 6 | 7 | 8 | // If SSE optimizations are enabled via the above #define, make sure the 9 | // hardware/compiler has support for SSE instructions. If so, we need to 10 | // define a cross platform macro to align variables to sixteen byte multiple 11 | // addresses (for i/o efficiency between the SSE registers). 12 | 13 | #if ELIMINATION_SSE && defined( __SSE__ ) 14 | #ifdef __GNUC__ 15 | #define ELIMINATION_SSE_ALIGN __attribute__((__aligned__(16))) 16 | #endif 17 | 18 | #ifdef _WIN32 19 | #define ELIMINATION_SSE_ALIGN __declspec(align(16)) 20 | #endif 21 | #else 22 | #define ELIMINATION_SSE_ALIGN 23 | #endif 24 | 25 | 26 | 27 | 28 | #endif // Elimination_SSE_h_ 29 | -------------------------------------------------------------------------------- /lib_pb/Elimination/Elimination+SSE.txx: -------------------------------------------------------------------------------- 1 | #ifndef Elimination_SSE_txx_ 2 | #define Elimination_SSE_txx_ 3 | 4 | #include "Elimination+SSE.h" 5 | 6 | #if ELIMINATION_SSE 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | #define _mm_splat_ps( v, i ) _mm_shuffle_ps( v, v, _MM_SHUFFLE(i,i,i,i) ) 17 | 18 | 19 | template<> 20 | void Elimination< float >::compute_coefficients( 21 | const float *a, float * newvals ) const 22 | { 23 | //printf( "SSE Optimized Routine\n" ); 24 | 25 | // At the input, a is a matrix consisting of the values of the 26 | // cost function in a 4-neighbourhood. 27 | // newvals will be returned as the values of the terms in the 28 | // reduced function. 29 | 30 | // We fill out the vector. This gives the values 31 | // of the function for all possible assignments to the variables x_i 32 | 33 | __m128 values[4]; 34 | __m128 a4 = _mm_set_ps1( a[4] ); 35 | 36 | values[0] = _mm_add_ps( _mm_add_ps( _mm_set_ps1( a[0] ), 37 | _mm_set_ps( a[1], 0.0f, a[1], 0.0f ) ), 38 | _mm_set_ps( a[2], a[2], 0.0f, 0.0f ) ); 39 | values[1] = _mm_add_ps( values[0], _mm_set_ps1( a[3] ) ); 40 | values[2] = _mm_add_ps( values[0], a4 ); 41 | values[3] = _mm_add_ps( values[1], a4 ); 42 | 43 | // New values for the variables 44 | __m128 newvals1 = _mm_setzero_ps(); 45 | __m128 newvals2 = _mm_setzero_ps(); 46 | 47 | // For registry i/o efficiency, each row of matrix A needs to be sixteen 48 | // byte aligned. Fortunately, the matrix is eight columns wide, so 49 | // we only need to ensure the first element is sixteen byte aligned. 50 | // Furthermore, since these values never change, we can take the one-time 51 | // performance hit to re-copy the data to memory aligned addresses. 52 | // Otherwise, we might be better off to use the less efficient non-aligned 53 | // i/o commands. 54 | 55 | static 56 | ELIMINATION_SSE_ALIGN 57 | float coefficients[8*16]; 58 | 59 | static bool initialized = false; 60 | 61 | if ( initialized == false ) 62 | { 63 | // _aligned_malloc(8*16*sizeof(float),16) 64 | //coefficients = (float *)malloc( 8 * 16 * sizeof( float ) ); 65 | 66 | // why isn't memcpy working? 67 | for ( int i = 0; i < 16; ++i ) 68 | for ( int j = 0; j < 8; ++j ) 69 | coefficients[i*8+j] = this->APseudoInverseTranspose_[i][j]; 70 | 71 | initialized = true; 72 | } 73 | 74 | // To compute the new values, we iterate over the rows of A. If the 75 | // corresponding element of val is less than zero, then we multiply 76 | // the entire row by val[i] and add it to newvals. 77 | // 78 | // For efficiency, we partially unroll the loop to handle four rows 79 | // at a time. This allow the "if ( val[i] < 0 )" test to be conducted 80 | // on four elements simultaneously. 81 | 82 | ELIMINATION_SSE_ALIGN 83 | const float * pRow = coefficients; 84 | 85 | for ( int i = 0; i < 4; ++i ) 86 | { 87 | // Derivative values which are zero or greater than zero result in a 88 | // product of zero. Therefore, we only really need to worry about 89 | // function values less than zero. Here, we get a bit mask indicating 90 | // which rows in the current set of four need to be multiplied by the 91 | // corresponding val[i] and added to newvals. 92 | 93 | register int approxMask = 94 | _mm_movemask_ps( _mm_cmplt_ps( values[i], _mm_setzero_ps() ) ); 95 | 96 | // For each row that needs to be multiplied, we break the row into 97 | // two chunks of for floats. Each chunk is multiplied by the constant 98 | // val[i] and then added to the corresponding chunk of newvals. 99 | 100 | //-------------------------------------------------- 101 | 102 | if ( approxMask & 1 ) 103 | { 104 | __m128 c = _mm_splat_ps( values[i], 0 ); 105 | newvals1 = _mm_add_ps( newvals1, _mm_mul_ps( c, _mm_load_ps( pRow ))); 106 | pRow += 4; 107 | newvals2 = _mm_add_ps( newvals2, _mm_mul_ps( c, _mm_load_ps( pRow ))); 108 | pRow += 4; 109 | } 110 | 111 | else 112 | { 113 | pRow += 8; 114 | } 115 | 116 | //-------------------------------------------------- 117 | 118 | if ( approxMask & 2 ) 119 | { 120 | __m128 c = _mm_splat_ps( values[i], 1 ); 121 | newvals1 = _mm_add_ps( newvals1, _mm_mul_ps( c, _mm_load_ps( pRow ))); 122 | pRow += 4; 123 | newvals2 = _mm_add_ps( newvals2, _mm_mul_ps( c, _mm_load_ps( pRow ))); 124 | pRow += 4; 125 | } 126 | 127 | else 128 | { 129 | pRow += 8; 130 | } 131 | 132 | //-------------------------------------------------- 133 | 134 | if ( approxMask & 4 ) 135 | { 136 | __m128 c = _mm_splat_ps( values[i], 2 ); 137 | newvals1 = _mm_add_ps( newvals1, _mm_mul_ps( c, _mm_load_ps( pRow ))); 138 | pRow += 4; 139 | newvals2 = _mm_add_ps( newvals2, _mm_mul_ps( c, _mm_load_ps( pRow ))); 140 | pRow += 4; 141 | } 142 | 143 | else 144 | { 145 | pRow += 8; 146 | } 147 | 148 | //-------------------------------------------------- 149 | 150 | if ( approxMask & 8 ) 151 | { 152 | __m128 c = _mm_splat_ps( values[i], 3 ); 153 | newvals1 = _mm_add_ps( newvals1, _mm_mul_ps( c, _mm_load_ps( pRow ))); 154 | pRow += 4; 155 | newvals2 = _mm_add_ps( newvals2, _mm_mul_ps( c, _mm_load_ps( pRow ))); 156 | pRow += 4; 157 | } 158 | 159 | else 160 | { 161 | pRow += 8; 162 | } 163 | } 164 | 165 | _mm_storeu_ps( newvals, newvals1 ); 166 | _mm_storeu_ps( newvals + 4, newvals2 ); 167 | } 168 | 169 | #endif // SSE 170 | 171 | #endif // Elimination_SSE_txx_ 172 | -------------------------------------------------------------------------------- /lib_pb/Elimination/Elimination.cc: -------------------------------------------------------------------------------- 1 | #include "Elimination.txx" 2 | //#include "Elimination+SSE.txx" 3 | 4 | template class Elimination< float >; 5 | template class Elimination< double >; 6 | 7 | -------------------------------------------------------------------------------- /lib_pb/Elimination/Elimination.h: -------------------------------------------------------------------------------- 1 | #ifndef Elimination_h_ 2 | #define Elimination_h_ 3 | 4 | #include "matrix.h" 5 | #include "Elimination+SSE.h" 6 | 7 | template< typename T > 8 | class Elimination 9 | { 10 | protected: 11 | // The pseudo-inverse for the least squares problem is really a 12 | // 9x16 matrix. However, we don't care what the value of the constant 13 | // is in the approximated expression. So we don't need to calculate 14 | // it, which means we can remove one row of the matrix. 15 | FixedMatrix< T, 16, 8 > APseudoInverseTranspose_; 16 | 17 | const bool verbose_; 18 | 19 | protected: 20 | 21 | void 22 | initialize(); 23 | 24 | void 25 | traverse1( const PaddedMatrix< T >& A, 26 | const PaddedMatrix< T >& B_right, 27 | const PaddedMatrix< T >& B_down, 28 | PaddedMatrix< T >& A2, 29 | PaddedMatrix< T >& B2_dr, 30 | PaddedMatrix< T >& B2_ur ); 31 | 32 | void 33 | traverse2( const PaddedMatrix< T >& A, 34 | const PaddedMatrix< T >& B_dr, 35 | const PaddedMatrix< T >& B_ur, 36 | PaddedMatrix< T >& Anew, 37 | PaddedMatrix< T >& B_right, 38 | PaddedMatrix< T >& B_down ); 39 | 40 | void 41 | optimize( const PaddedMatrix< T >& A, 42 | const PaddedMatrix< T >& B_right, 43 | const PaddedMatrix< T >& B_down, 44 | PaddedMatrix< unsigned char >& X_star ); 45 | public: 46 | 47 | Elimination() : 48 | verbose_( false ) 49 | { 50 | this->initialize(); 51 | } 52 | 53 | void 54 | compute_coefficients( const T * a, T * newvals ) const; 55 | 56 | static void 57 | solve( const Matrix< T >& A, 58 | const Matrix< T >& B_right, 59 | const Matrix< T >& B_down, 60 | Matrix< unsigned char >& X_star ); 61 | }; 62 | 63 | #endif // Elimination_h_ 64 | -------------------------------------------------------------------------------- /lib_pb/Elimination/Elimination_dcl.h: -------------------------------------------------------------------------------- 1 | #ifndef Elimination_cc 2 | #define Elimination_cc 3 | #include 4 | 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /lib_pb/Elimination/LazyElimination.cc: -------------------------------------------------------------------------------- 1 | #include "LazyElimination.txx" 2 | 3 | template class LazyElimination< float >; 4 | template class LazyElimination< double >; 5 | -------------------------------------------------------------------------------- /lib_pb/Elimination/LazyElimination.h: -------------------------------------------------------------------------------- 1 | #ifndef LazyElimination_h_ 2 | #define LazyElimination_h_ 3 | 4 | #include "Elimination.h" 5 | #include "MaxFlow/graph.h" 6 | 7 | template< typename T > 8 | class LazyElimination : public Elimination< T > 9 | { 10 | protected: 11 | // Define the dimensions of the problem 12 | const int idim_; 13 | const int jdim_; 14 | 15 | Matrix< T >& A_; // Unary terms 16 | Matrix< T >& U_; // Binary term - Up 17 | Matrix< T >& R_; // Binary term - Right 18 | Matrix< T >& D_; // Binary term - Down 19 | Matrix< T >& L_; // Binary term - Left 20 | 21 | typedef Graph< T, T, T> GraphType; 22 | GraphType * g_; 23 | 24 | Matrix< bool > eliminated_; // Tells if a node is alive 25 | Matrix< unsigned char > levels_; // Determines the level of nodes 26 | 27 | // Flag to control lazy elimination or not 28 | const bool lazy_elimination_; 29 | 30 | protected: 31 | 32 | // Accessing these nodes 33 | void addA( int i, int j, T val ) 34 | { 35 | if ( i < 0 || i >= this->idim_ || 36 | j < 0 || j >= this->jdim_ ) return; 37 | A_[i][j] += val; 38 | } 39 | 40 | void addU( int i, int j, T val ) 41 | { 42 | if ( i < 0 || i >= this->idim_ || 43 | j < 0 || j >= this->jdim_ ) return; 44 | U_[i][j] += val; 45 | } 46 | 47 | void addR( int i, int j, T val ) 48 | { 49 | if ( i < 0 || i >= this->idim_ || 50 | j < 0 || j >= this->jdim_ ) return; 51 | R_[i][j] += val; 52 | } 53 | 54 | void addD( int i, int j, T val ) 55 | { 56 | if ( i < 0 || i >= this->idim_ || 57 | j < 0 || j >= this->jdim_ ) return; 58 | D_[i][j] += val; 59 | } 60 | 61 | void addL( int i, int j, T val) 62 | { 63 | if ( i < 0 || i >= this->idim_ || 64 | j < 0 || j >= this->jdim_ ) return; 65 | L_[i][j] += val; 66 | } 67 | 68 | // Main methods 69 | void eliminate_node (int i, int j, int level, bool lazily ); 70 | void switch_binary_terms (); 71 | 72 | inline bool node_exists (int i, int j) const 73 | { 74 | return ( i >=0 && i < this->idim_ && 75 | j >=0 && j < this->jdim_ && 76 | !this->eliminated_[i][j] ); 77 | } 78 | 79 | void define_graph (); 80 | 81 | unsigned char back_substitute( 82 | Matrix< unsigned char >& xStar, int i, int j ); 83 | 84 | void init_levels (); 85 | 86 | //--------------------------------------------------------------------- 87 | // Interface to the Boykov maxflow code 88 | void init_graphcuts(); 89 | 90 | inline int nodenum( int i, int j ) const 91 | { 92 | return j + jdim_ * i; 93 | } 94 | 95 | inline void add_tweights (int i, int j, T val) const 96 | { 97 | g_->add_tweights( nodenum(i, j), val, (T)0 ); 98 | } 99 | 100 | inline void add_edge(int i1, int j1, int i2, int j2, T val) const 101 | { 102 | g_->add_edge( nodenum(i1, j1), nodenum(i2, j2), (T)0, val ); 103 | } 104 | 105 | // How to get the level of a node 106 | unsigned char level_of_node (int i, int j) const 107 | { 108 | return levels_[i][j]; 109 | } 110 | 111 | public: 112 | 113 | LazyElimination( Matrix< T >& A, 114 | Matrix< T >& U, 115 | Matrix< T >& R, 116 | Matrix< T >& D, 117 | Matrix< T >& L, 118 | bool lazy_elimination = true ) : 119 | idim_( A.rows() ), 120 | jdim_( A.cols() ), 121 | A_( A ), 122 | U_( U ), 123 | R_( R ), 124 | D_( D ), 125 | L_( L ), 126 | g_( NULL ), 127 | eliminated_( A.rows(), A.cols() ), 128 | levels_( A.rows(), A.cols() ), 129 | lazy_elimination_ (lazy_elimination) 130 | 131 | { 132 | // Initialize the levels array 133 | this->init_levels(); 134 | 135 | // And the "isEliminated" flags 136 | this->eliminated_.fill( false ); 137 | } 138 | 139 | virtual ~LazyElimination() 140 | { 141 | if (g_) delete g_; 142 | } 143 | 144 | void segment( Matrix< unsigned char >& X_Star ); 145 | 146 | // The static interface 147 | static void solve( 148 | const Matrix< T >& A, 149 | const Matrix< T >& B_right, 150 | const Matrix< T >& B_down, 151 | Matrix< unsigned char >& X_star ); 152 | 153 | }; 154 | 155 | #endif // LazyElimination_h_ 156 | -------------------------------------------------------------------------------- /lib_pb/Elimination/LazyElimination_dcl.h: -------------------------------------------------------------------------------- 1 | #ifndef LazyElimination_cc 2 | #define LazyElimination_cc 3 | #include 4 | 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /lib_pb/Elimination/Project.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidstutz/superpixels-revisited/f14e9e0b063741e5a9eb6544a3d6c2f44cdfc9e4/lib_pb/Elimination/Project.suo -------------------------------------------------------------------------------- /lib_pb/Elimination/exampleElimination.cc: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | int main (int argc, char *argv[]) 6 | { 7 | (void)argc; 8 | (void)argv; 9 | 10 | float a[5]; 11 | float v[8]; 12 | 13 | a[0] = 30.0f; 14 | a[1] = 0.0f; 15 | a[2] = -20.0f; 16 | a[3] = -20.0f; 17 | a[4] = -20.0f; 18 | 19 | Elimination< float > eliminator; 20 | 21 | eliminator.compute_coefficients( a, v ); 22 | 23 | for ( int i = 0; i < 8; ++i ) 24 | printf( "%f\n", v[i] ); 25 | 26 | // Finished 27 | return 0; 28 | } 29 | -------------------------------------------------------------------------------- /lib_pb/Elimination/matrix.h: -------------------------------------------------------------------------------- 1 | #ifndef Matrix_h_ 2 | #define Matrix_h_ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | template< typename T > 12 | class Matrix 13 | { 14 | protected: 15 | 16 | const int rows_; 17 | const int cols_; 18 | T * data_; 19 | 20 | public: 21 | 22 | Matrix( int rows, int cols ) : 23 | rows_( rows ), 24 | cols_( cols ) 25 | { 26 | if ( rows <= 0 || cols <= 0 ) 27 | throw std::invalid_argument("invalid matrix dimensions"); 28 | 29 | this->data_ = (T*)calloc( 30 | static_cast< size_t >( this->rows_ ) * 31 | static_cast< size_t >( this->cols_ ), sizeof( T ) ); 32 | 33 | if ( this->data_ == NULL ) throw std::bad_alloc(); 34 | } 35 | 36 | Matrix( const Matrix< T >& that ) : 37 | rows_( that.rows_ ), 38 | cols_( that.cols_ ) 39 | { 40 | this->data_ = (T*)malloc( this->rows_ * this->cols_ * sizeof( T ) ); 41 | if ( this->data_ == NULL ) throw std::bad_alloc(); 42 | 43 | memcpy( this->data_, that.data_, 44 | static_cast< size_t >( this->rows_ ) * 45 | static_cast< size_t >( this->cols_ ) * sizeof( T ) ); 46 | } 47 | 48 | ~Matrix() 49 | { 50 | free( this->data_ ); 51 | } 52 | 53 | int rows() const 54 | { 55 | return this->rows_; 56 | } 57 | 58 | int cols() const 59 | { 60 | return this->cols_; 61 | } 62 | 63 | T* operator[]( int row ) 64 | { 65 | assert( row < this->rows_ ); 66 | return this->data_ + row * this->cols_; 67 | } 68 | 69 | const T* operator[]( int row ) const 70 | { 71 | assert( row < this->rows_ ); 72 | return this->data_ + row * this->cols_; 73 | } 74 | 75 | void fill( const T value ) 76 | { 77 | for ( int i = 0; i < this->rows_; ++i ) 78 | for ( int j = 0; j < this->cols_; ++j ) 79 | (*this)[i][j] = value; 80 | } 81 | }; 82 | 83 | template< typename T, int rowsT, int colsT > 84 | class FixedMatrix 85 | { 86 | protected: 87 | 88 | T data_[rowsT * colsT]; 89 | 90 | public: 91 | 92 | FixedMatrix() 93 | { 94 | memset( data_, 0, 95 | static_cast< size_t >( rowsT ) * 96 | static_cast< size_t >( colsT ) * sizeof( T ) ); 97 | } 98 | 99 | FixedMatrix( const T* const data ) 100 | { 101 | memcpy( this->data_, data, sizeof(T) * 102 | static_cast< size_t >( rowsT ) * 103 | static_cast< size_t >( colsT ) ); 104 | } 105 | 106 | int rows() const 107 | { 108 | return rowsT; 109 | } 110 | 111 | int cols() const 112 | { 113 | return colsT; 114 | } 115 | 116 | T* operator[]( int row ) 117 | { 118 | assert( row < rowsT ); 119 | return this->data_ + row * colsT; 120 | } 121 | 122 | const T* operator[]( int row ) const 123 | { 124 | assert( row < rowsT ); 125 | return this->data_ + row * colsT; 126 | } 127 | }; 128 | 129 | template< typename T > 130 | class PaddedMatrix 131 | { 132 | // 133 | // Avoids boundary checking by adding extra elements at the beginning 134 | // and end of each row and column. 135 | // It's okay to read from these locations (they are all zero), 136 | // but your code really shouldn't be writing to them. 137 | // 138 | 139 | protected: 140 | 141 | const int rows_; 142 | const int cols_; 143 | T* data_; 144 | 145 | public: 146 | 147 | PaddedMatrix( int rows, int cols ) : 148 | rows_( rows ), 149 | cols_( cols ) 150 | { 151 | if ( rows <= 0 || cols <= 0 ) 152 | throw std::invalid_argument("invalid matrix dimensions"); 153 | 154 | this->data_ = (T*)calloc( 155 | ( static_cast< size_t >( this->rows_ ) + 2 ) * 156 | ( static_cast< size_t >( this->cols_ ) + 2 ), sizeof( T ) ); 157 | 158 | if ( this->data_ == NULL ) throw std::bad_alloc(); 159 | } 160 | 161 | PaddedMatrix( const PaddedMatrix< T >& that ) : 162 | rows_( that.rows_ ), 163 | cols_( that.cols_ ) 164 | { 165 | this->data_ = (T*)calloc( 166 | ( this->rows_ + 2 ) * ( this->cols_ + 2 ) , sizeof( T ) ); 167 | 168 | if ( this->data_ == NULL ) throw std::bad_alloc(); 169 | 170 | memcpy( this->data_, that.data_, 171 | ( this->rows_ + 2 ) * ( this->cols_ + 2 ) * sizeof( T ) ); 172 | } 173 | 174 | PaddedMatrix( const Matrix< T >& that ) : 175 | rows_( that.rows() ), 176 | cols_( that.cols() ) 177 | { 178 | this->data_ = (T*)calloc( 179 | ( static_cast< size_t >( this->rows_ ) + 2 ) * 180 | ( static_cast< size_t >( this->cols_ ) + 2 ), 181 | sizeof( T ) ); 182 | 183 | if ( this->data_ == NULL ) throw std::bad_alloc(); 184 | 185 | for ( int row = 0; row < this->rows_; ++row ) 186 | for ( int col = 0; col < this->cols_; ++col ) 187 | (*this)[row][col] = that[row][col]; 188 | } 189 | 190 | ~PaddedMatrix() 191 | { 192 | free( this->data_ ); 193 | } 194 | 195 | PaddedMatrix< T >& 196 | operator = ( const PaddedMatrix< T >& that ) 197 | { 198 | assert( this->rows_ == that.rows_ ); 199 | assert( this->cols_ == that.cols_ ); 200 | 201 | memcpy( this->data_, that.data_, 202 | ( static_cast< size_t >( this->rows_ ) + 2 ) * 203 | ( static_cast< size_t >( this->cols_ ) + 2 ) * 204 | sizeof( T ) ); 205 | 206 | return *this; 207 | } 208 | 209 | int rows() const 210 | { 211 | return this->rows_; 212 | } 213 | 214 | int cols() const 215 | { 216 | return this->cols_; 217 | } 218 | 219 | void fill( const T value ) 220 | { 221 | for ( unsigned int i = 0; i < this->rows_; ++i ) 222 | for ( unsigned int j = 0; j < this->cols_; ++j ) 223 | (*this)[i][j] = value; 224 | } 225 | 226 | T* operator[]( int row ) 227 | { 228 | assert( row >= -1 ); 229 | assert( row <= this->rows_ ); 230 | return this->data_ + ( row + 1 ) * ( this->cols_ + 2 ) + 1; 231 | } 232 | 233 | const T* operator[]( int row ) const 234 | { 235 | assert( row >= -1 ); 236 | assert( row <= this->rows_ ); 237 | return this->data_ + ( row + 1 ) * ( this->cols_ + 2 ) + 1; 238 | } 239 | }; 240 | 241 | 242 | #endif // Matrix_h_ 243 | -------------------------------------------------------------------------------- /lib_pb/MaxFlow/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../) 2 | 3 | add_library(pb_maxflow instances.cxx QPBO_Elim.cc QPBO_LazyElim.cc QPBO_MaxFlow.cc) 4 | -------------------------------------------------------------------------------- /lib_pb/MaxFlow/QPBO_Elim.cc: -------------------------------------------------------------------------------- 1 | #include "QPBO_Elim.h" 2 | 3 | #include "Elimination/Elimination.h" 4 | 5 | ElimQPBO::ElimQPBO( const Matrix< float >& A, 6 | const Matrix< float >& B_right, 7 | const Matrix< float >& B_down, 8 | Matrix< unsigned char >& X ) : 9 | GenericQPBO( A, B_right, B_down, X ) 10 | { 11 | Elimination< float >::solve( A, B_right, B_down, X ); 12 | } 13 | 14 | 15 | -------------------------------------------------------------------------------- /lib_pb/MaxFlow/QPBO_Elim.h: -------------------------------------------------------------------------------- 1 | #ifndef QPBO_Elim_h_ 2 | #define QPBO_Elim_h_ 3 | 4 | // Solves a Quadratic Pseudo Boolean Optimization problem defined over a 5 | // four-connect lattice using the Elimination algorithm. 6 | 7 | #include "QPBO_Generic.h" 8 | 9 | class ElimQPBO : public GenericQPBO 10 | { 11 | public: 12 | // See QPBO_Generic.h for details about these parameters. 13 | ElimQPBO( const Matrix< float >& A, 14 | const Matrix< float >& B_right, 15 | const Matrix< float >& B_down, 16 | Matrix< unsigned char >& X ); 17 | }; 18 | 19 | #endif // QPBO_Elim_h_ 20 | -------------------------------------------------------------------------------- /lib_pb/MaxFlow/QPBO_Elim_dcl.h: -------------------------------------------------------------------------------- 1 | #ifndef QPBO_Elim_cc 2 | #define QPBO_Elim_cc 3 | #include 4 | 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /lib_pb/MaxFlow/QPBO_Generic.h: -------------------------------------------------------------------------------- 1 | #ifndef QPBO_Generic_h_ 2 | #define QPBO_Generic_h_ 3 | 4 | // Generic Quadartic Pseduo Boolean Optimization Algorithm for a 4-connect 5 | // lattice of variables. This file doesn't actually do anything, except 6 | // specify the generic interface to any optimization algorithm (such as 7 | // max-flow, roof dual, elimination ("basic") and lazy elimination). 8 | // 9 | // *** Do not confuse this with Kolmogorov's "QPBO" library *** 10 | 11 | #include "Elimination/matrix.h" 12 | 13 | class GenericQPBO 14 | { 15 | public: 16 | // The main interface to any optimization technique. 17 | // A contains the coefficients of the variables x_{i,j} 18 | // B_right contains the coefficients of x_{i,j} . x_{i,j+1} 19 | // B_down contains the coefficients of the x_{i,j} . x_{i+1,j} 20 | // X is the (sub)optimal labelling. It will be resized to m x n 21 | // and each element will be set to either 0 or 1. 22 | GenericQPBO( const Matrix< float >& A, 23 | const Matrix< float >& B_right, 24 | const Matrix< float >& B_down, 25 | Matrix< unsigned char >& X ) 26 | { 27 | const unsigned int rows = A.rows(); 28 | const unsigned int cols = A.cols(); 29 | 30 | assert( B_right.rows() == rows ); 31 | assert( B_right.cols() == cols ); 32 | assert( B_down.rows() == rows ); 33 | assert( B_down.cols() == cols ); 34 | } 35 | }; 36 | 37 | #endif // QPBO_Generic_h_ 38 | -------------------------------------------------------------------------------- /lib_pb/MaxFlow/QPBO_LazyElim.cc: -------------------------------------------------------------------------------- 1 | #include "QPBO_LazyElim.h" 2 | 3 | #include "Elimination/LazyElimination.h" 4 | 5 | LazyElimQPBO::LazyElimQPBO( 6 | const Matrix< float >& A, 7 | const Matrix< float >& B_right, 8 | const Matrix< float >& B_down, 9 | Matrix< unsigned char >& X_star ) : 10 | GenericQPBO( A, B_right, B_down, X_star ) 11 | { 12 | LazyElimination< float >::solve( A, B_right, B_down, X_star ); 13 | } 14 | 15 | 16 | -------------------------------------------------------------------------------- /lib_pb/MaxFlow/QPBO_LazyElim.h: -------------------------------------------------------------------------------- 1 | #ifndef QPBO_LazyElim_h_ 2 | #define QPBO_LazyElim_h_ 3 | 4 | // Solves a Quadratic Pseudo Boolean Optimization problem defined over a 5 | // four-connect lattice using the LazyElimination algorithm. 6 | 7 | #include "QPBO_Generic.h" 8 | 9 | class LazyElimQPBO : public GenericQPBO 10 | { 11 | public: 12 | // See QPBO_Generic.h for details about these parameters. 13 | LazyElimQPBO( const Matrix< float >& A, 14 | const Matrix< float >& B_right, 15 | const Matrix< float >& B_down, 16 | Matrix< unsigned char >& X_star ); 17 | }; 18 | 19 | #endif // QPBO_LazyElim_h_ 20 | -------------------------------------------------------------------------------- /lib_pb/MaxFlow/QPBO_MaxFlow.cc: -------------------------------------------------------------------------------- 1 | #include "QPBO_MaxFlow.h" 2 | 3 | #include "MaxFlow/graph.h" 4 | 5 | 6 | 7 | MaxFlowQPBO::MaxFlowQPBO( const Matrix< float >& A, 8 | const Matrix< float >& B_right, 9 | const Matrix< float >& B_down, 10 | Matrix< unsigned char >& Seg ) : 11 | GenericQPBO( A, B_right, B_down, Seg ), 12 | idim_( A.rows() ), 13 | jdim_( A.cols() ) 14 | { 15 | // Run a multilabel segment 16 | // First, initialize the segmentation 17 | //Seg.Init (0, this->idim_-1, 0, this->jdim_-1); 18 | Seg.fill(0); 19 | 20 | // Create a graph 21 | typedef Graph< float, float, float > GraphType; 22 | GraphType g( this->idim_ * this->jdim_, 23 | this->idim_ * ( this->jdim_ - 1 ) + 24 | this->jdim_ * ( this->idim_ - 1 ) ); 25 | 26 | // Add a node for each variable 27 | g.add_node( this->idim_ * this->jdim_ ); 28 | 29 | // The unary terms are represented as edges from the source to the node, 30 | // or from the node to the sink, depending on whether the element of A 31 | // is positive or negative. Although the API deals with negative 32 | // coefficients, it's fairly straightforward to do this ourselves. 33 | for (int i=0; iidim_; ++i) 34 | for (int j=0; jjdim_; ++j) 35 | { 36 | // a_{i,j} x_{i,j} = a_{i,j} \bar{0} . x_{i,j} when a_{i,j} >= 0 37 | if ( A[i][j] >= 0.0f ) g.add_tweights( this->node(i,j), A[i][j], 0.0f ); 38 | else g.add_tweights( this->node(i,j), 0.0f, -A[i][j] ); 39 | } 40 | 41 | // The binary terms are represented as edges between two nodes. 42 | // However, every term x_{i,j} . x_{p,q} must be converted into the form 43 | // \bar{x}_{i,j} . x_{p,q} so that it can be associated with an edge from 44 | // x_{i,j} to x_{p,q}. When doing this conversion, we generate a term 45 | // -x_{p,q}. This is why we do the binary terms first. Otherwise, we 46 | // would have to update the unary terms after already setting them once. 47 | 48 | // right 49 | for (int i=0; iidim_; ++i) 50 | for (int j=0; jjdim_-1; ++j) 51 | { 52 | // if the coefficient is not negative, then the function is 53 | // not submodular, and all we can do is truncate the function. 54 | if ( B_right[i][j] >= 0.0f ) 55 | { 56 | //printf( "Truncating\n" ); 57 | continue; 58 | } 59 | 60 | // switch x_{i,j} to \bar{x}_{i,j} 61 | // Now the term corresponds to an edge from x_{i,j} to x_{i,j+1} 62 | 63 | g.add_edge( this->node( i, j ), this->node( i, j + 1 ), 64 | -B_right[i][j], 0.0f ); 65 | 66 | // and update the unary terms 67 | g.add_tweights( this->node(i,j+1), B_right[i][j], 0.0f ); 68 | } 69 | 70 | // down 71 | for (int i=0; iidim_-1; ++i) 72 | for (int j=0; jjdim_; ++j) 73 | { 74 | // if the coefficient is not negative, then the function is 75 | // not submodular, and all we can do is truncate the function. 76 | if ( B_down[i][j] >= 0.0f ) 77 | { 78 | //printf( "Truncating\n" ); 79 | continue; 80 | } 81 | 82 | // switch x_{i,j} to \bar{x}_{i,j} 83 | // Now the term corresponds to an edge from x_{i,j} to x_{i+1,j} 84 | 85 | g.add_edge( this->node( i, j ), this->node( i + 1, j ), 86 | -B_down[i][j], 0.0f ); 87 | 88 | // and update the unary terms 89 | g.add_tweights( this->node(i+1,j), B_down[i][j], 0.0f ); 90 | } 91 | 92 | 93 | 94 | // solve 95 | g.maxflow(); 96 | 97 | // record the answer 98 | for (int i=0; iidim_; ++i) 99 | for (int j=0; jjdim_; ++j) 100 | Seg[i][j] = g.what_segment( this->node(i,j) ); 101 | } 102 | 103 | 104 | -------------------------------------------------------------------------------- /lib_pb/MaxFlow/QPBO_MaxFlow.h: -------------------------------------------------------------------------------- 1 | #ifndef QPBO_MaxFlow_h_ 2 | #define QPBO_MaxFlow_h_ 3 | 4 | // Solves a Quadratic Pseudo Boolean Optimization problem defined over a 5 | // four-connect lattice using Max-Flow. The coefficients of the quadratic 6 | // terms must be negative for a valid flow graph representation. If positive 7 | // coefficients are encountered, the method will simply ignore them. 8 | 9 | #include "QPBO_Generic.h" 10 | 11 | class MaxFlowQPBO : public GenericQPBO 12 | { 13 | protected: 14 | const int idim_; 15 | const int jdim_; 16 | 17 | int 18 | node( int i, int j ) 19 | { 20 | return i * this->jdim_ + j; 21 | } 22 | 23 | public: 24 | // See QPBO_Generic.h for details about these parameters. 25 | MaxFlowQPBO( const Matrix< float >& A, 26 | const Matrix< float >& B_right, 27 | const Matrix< float >& B_down, 28 | Matrix< unsigned char >& Seg ); 29 | }; 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /lib_pb/MaxFlow/README.TXT: -------------------------------------------------------------------------------- 1 | ################################################################### 2 | # # 3 | # MAXFLOW - software for computing mincut/maxflow in a graph # 4 | # Version 3.0 # 5 | # http://www.cs.adastral.ucl.ac.uk/~vnk/software.html # 6 | # # 7 | # Yuri Boykov (yuri@csd.uwo.ca) # 8 | # Vladimir Kolmogorov (vnk@adastral.ucl.ac.uk) # 9 | # 2001-2006 # 10 | # # 11 | ################################################################### 12 | 13 | 1. Introduction. 14 | 15 | This software library implements the maxflow algorithm described in 16 | 17 | "An Experimental Comparison of Min-Cut/Max-Flow Algorithms for Energy Minimization in Vision." 18 | Yuri Boykov and Vladimir Kolmogorov. 19 | In IEEE Transactions on Pattern Analysis and Machine Intelligence (PAMI), 20 | September 2004 21 | 22 | This algorithm was developed by Yuri Boykov and Vladimir Kolmogorov 23 | at Siemens Corporate Research. To make it available for public use, 24 | it was later reimplemented by Vladimir Kolmogorov based on open publications. 25 | 26 | If you use this software for research purposes, you should cite 27 | the aforementioned paper in any resulting publication. 28 | 29 | ---------------------------------------------------------------------- 30 | 31 | REUSING TREES: 32 | 33 | Starting with version 3.0, there is a also an option of reusing search 34 | trees from one maxflow computation to the next, as described in 35 | 36 | "Efficiently Solving Dynamic Markov Random Fields Using Graph Cuts." 37 | Pushmeet Kohli and Philip H.S. Torr 38 | International Conference on Computer Vision (ICCV), 2005 39 | 40 | If you use this option, you should cite 41 | the aforementioned paper in any resulting publication. 42 | 43 | Tested under windows, Visual C++ 6.0 compiler and unix (SunOS 5.8 44 | and RedHat Linux 7.0, GNU c++ compiler). 45 | 46 | ################################################################## 47 | 48 | 2. License & disclaimer. 49 | 50 | Copyright 2001 Vladimir Kolmogorov (vnk@adastral.ucl.ac.uk), Yuri Boykov (yuri@csd.uwo.ca). 51 | 52 | This software can be used for research purposes only. 53 | 54 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 55 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 56 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 57 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 58 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 59 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 60 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 61 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 62 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 63 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 64 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 65 | 66 | ################################################################## 67 | 68 | 3. Example usage. 69 | 70 | This section shows how to use the library to compute 71 | a minimum cut on the following graph: 72 | 73 | SOURCE 74 | / \ 75 | 1/ \2 76 | / 3 \ 77 | node0 -----> node1 78 | | <----- | 79 | | 4 | 80 | \ / 81 | 5\ /6 82 | \ / 83 | SINK 84 | 85 | /////////////////////////////////////////////////// 86 | 87 | #include 88 | #include "graph.h" 89 | 90 | int main() 91 | { 92 | typedef Graph GraphType; 93 | GraphType *g = new GraphType(/*estimated # of nodes*/ 2, /*estimated # of edges*/ 1); 94 | 95 | g -> add_node(); 96 | g -> add_node(); 97 | 98 | g -> add_tweights( 0, /* capacities */ 1, 5 ); 99 | g -> add_tweights( 1, /* capacities */ 2, 6 ); 100 | g -> add_edge( 0, 1, /* capacities */ 3, 4 ); 101 | 102 | int flow = g -> maxflow(); 103 | 104 | printf("Flow = %d\n", flow); 105 | printf("Minimum cut:\n"); 106 | if (g->what_segment(0) == GraphType::SOURCE) 107 | printf("node0 is in the SOURCE set\n"); 108 | else 109 | printf("node0 is in the SINK set\n"); 110 | if (g->what_segment(1) == GraphType::SOURCE) 111 | printf("node1 is in the SOURCE set\n"); 112 | else 113 | printf("node1 is in the SINK set\n"); 114 | 115 | delete g; 116 | 117 | return 0; 118 | } 119 | 120 | 121 | /////////////////////////////////////////////////// 122 | -------------------------------------------------------------------------------- /lib_pb/MaxFlow/example.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "graph.h" 3 | 4 | /*------------------------------------------------------------ 5 | This example shows how to use the library to compute 6 | a minimum cut on the following graph: 7 | 8 | SOURCE 9 | / \ 10 | 1/ \2 11 | / 3 \ 12 | node0 -----> node1 13 | | <----- | 14 | | 4 | 15 | \ / 16 | 5\ /6 17 | \ / 18 | SINK 19 | -------------------------------------------------------------*/ 20 | 21 | int main() 22 | { 23 | typedef Graph GraphType; 24 | GraphType *g = new GraphType(/*estimated # of nodes*/ 2, /*estimated # of edges*/ 1); 25 | 26 | g -> add_node(); 27 | g -> add_node(); 28 | 29 | g -> add_tweights( 0, /* capacities */ 1, 5 ); 30 | g -> add_tweights( 1, /* capacities */ 2, 6 ); 31 | g -> add_edge( 0, 1, /* capacities */ 3, 4 ); 32 | 33 | int flow = g -> maxflow(); 34 | 35 | printf("Flow = %d\n", flow); 36 | printf("Minimum cut:\n"); 37 | if (g->what_segment(0) == GraphType::SOURCE) 38 | printf("node0 is in the SOURCE set\n"); 39 | else 40 | printf("node0 is in the SINK set\n"); 41 | if (g->what_segment(1) == GraphType::SOURCE) 42 | printf("node1 is in the SOURCE set\n"); 43 | else 44 | printf("node1 is in the SINK set\n"); 45 | 46 | delete g; 47 | 48 | return 0; 49 | } 50 | -------------------------------------------------------------------------------- /lib_pb/MaxFlow/graph.txx: -------------------------------------------------------------------------------- 1 | /* graph.cpp */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include "graph.h" 7 | 8 | template 9 | Graph::Graph 10 | ( 11 | int node_num_max, 12 | int edge_num_max, 13 | void (*err_function)(char *) 14 | ) 15 | 16 | : node_num(0), 17 | nodeptr_block(NULL), 18 | error_function(err_function) 19 | 20 | { 21 | if (node_num_max < 16) node_num_max = 16; 22 | if (edge_num_max < 16) edge_num_max = 16; 23 | 24 | nodes = (node*) malloc(node_num_max*sizeof(node)); 25 | arcs = (arc*) malloc(2*edge_num_max*sizeof(arc)); 26 | if (!nodes || !arcs) 27 | { 28 | if (error_function) (*error_function)("Not enough memory!"); 29 | exit(1); 30 | } 31 | 32 | node_last = nodes; 33 | node_max = nodes + node_num_max; 34 | arc_last = arcs; 35 | arc_max = arcs + 2*edge_num_max; 36 | 37 | maxflow_iteration = 0; 38 | flow = 0; 39 | } 40 | 41 | template 42 | Graph::~Graph() 43 | { 44 | if (nodeptr_block) 45 | { 46 | delete nodeptr_block; 47 | nodeptr_block = NULL; 48 | } 49 | free(nodes); 50 | free(arcs); 51 | } 52 | 53 | template 54 | void Graph::reset() 55 | { 56 | node_last = nodes; 57 | arc_last = arcs; 58 | node_num = 0; 59 | 60 | if (nodeptr_block) 61 | { 62 | delete nodeptr_block; 63 | nodeptr_block = NULL; 64 | } 65 | 66 | maxflow_iteration = 0; 67 | flow = 0; 68 | } 69 | 70 | template 71 | void Graph::reallocate_nodes(int num) 72 | { 73 | int node_num_max = (int)(node_max - nodes); 74 | node* nodes_old = nodes; 75 | 76 | node_num_max += node_num_max / 2; 77 | if (node_num_max < node_num + num) node_num_max = node_num + num; 78 | nodes = (node*) realloc(nodes_old, node_num_max*sizeof(node)); 79 | if (!nodes) 80 | { 81 | if (error_function) (*error_function)("Not enough memory!"); exit(1); 82 | } 83 | 84 | node_last = nodes + node_num; 85 | node_max = nodes + node_num_max; 86 | 87 | if (nodes != nodes_old) 88 | { 89 | arc* a; 90 | for (a=arcs; ahead = (node*) ((char*)a->head + 93 | (((char*) nodes) - ((char*) nodes_old))); 94 | } 95 | } 96 | } 97 | 98 | template 99 | void Graph::reallocate_arcs() 100 | { 101 | int arc_num_max = (int)(arc_max - arcs); 102 | int arc_num = (int)(arc_last - arcs); 103 | arc* arcs_old = arcs; 104 | 105 | arc_num_max += arc_num_max / 2; if (arc_num_max & 1) arc_num_max ++; 106 | arcs = (arc*) realloc(arcs_old, arc_num_max*sizeof(arc)); 107 | if (!arcs) 108 | { 109 | if (error_function) (*error_function)("Not enough memory!"); 110 | exit(1); 111 | } 112 | 113 | arc_last = arcs + arc_num; 114 | arc_max = arcs + arc_num_max; 115 | 116 | if (arcs != arcs_old) 117 | { 118 | node* i; 119 | arc* a; 120 | for (i=nodes; ifirst) 123 | i->first = (arc*) ((char*)i->first + 124 | (((char*) arcs) - ((char*) arcs_old))); 125 | } 126 | for (a=arcs; anext) 129 | a->next = (arc*) ((char*)a->next + 130 | (((char*) arcs) - ((char*) arcs_old))); 131 | a->sister = (arc*) ((char*)a->sister + 132 | (((char*) arcs) - ((char*) arcs_old))); 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /lib_pb/MaxFlow/instances.cxx: -------------------------------------------------------------------------------- 1 | #include "graph.h" 2 | #include "graph.txx" 3 | #include "maxflow.txx" 4 | 5 | #ifdef _MSC_VER 6 | #pragma warning(disable: 4661) 7 | #endif 8 | 9 | // Instantiations: 10 | // IMPORTANT: 11 | // flowtype should be 'larger' than tcaptype 12 | // tcaptype should be 'larger' than captype 13 | 14 | template class Graph; 15 | template class Graph; 16 | template class Graph; 17 | template class Graph; 18 | 19 | -------------------------------------------------------------------------------- /lib_pb/README.md: -------------------------------------------------------------------------------- 1 | # Pseudo Boolean Superpixels 2 | 3 | Code for Pseudo Boolean Superpixels [1]: 4 | 5 | [1] Superpixels via pseudo-boolean optimization. 6 | Y. Zhang, R. Hartley, J. Mashford, and S. Burn. 7 | In International Conference on Computer Vision, 2011. 8 | 9 | [2] Minimizing energy functions on 4-connected lattices using elimination. 10 | Peter Carr, Richard Hartley 11 | In International Conference on Computer Vision, 2009. 12 | 13 | [3] An Experimental Comparison of Min-Cut/Max-Flow Algorithms for Energy Minimization in Vision. 14 | Yuri Boykov and Vladimir Kolmogorov. 15 | In IEEE Transactions on Pattern Analysis and Machine Intelligence (PAMI), September 2004 16 | 17 | The algorithm is based on work by Carr et al. and Boykov et al., see the original README in `README.txt`. Note that the superpixelcodeby Zhang et al. can be used for research purposes only. 18 | 19 | The corresponding command line tool can befound in `pb_cli/main.cpp`, including documentation. -------------------------------------------------------------------------------- /lib_pb/README.txt: -------------------------------------------------------------------------------- 1 | ################################################################### 2 | # # 3 | # Superpixels via Pseudo-Boolean Optimization # 4 | # # 5 | # v2.0 # 6 | # # 7 | # http://yuhang.rsise.anu.edu.au/yuhang/ # 8 | # # 9 | # Yuhang Zhang(yuhang.zhang@anu.edu.au) # 10 | # Research School of Computer Science # 11 | # The Australian National University # 12 | # # 13 | ################################################################### 14 | 15 | 1. This code can only be used for none commercial purpose. 16 | 17 | 2. If you are using it for research, please cite paper [1] below. Depends on the optimization algorithm you choose, you might cite [2] or [3] as well. 18 | 19 | 3. CMakeLists.txt files have been provided to simplify the compiling. Users unfamiliar with CMake are recommended to read the step-by-step.txt file. 20 | 21 | 4. To compile the code properly, a third party library named VXL is needed. Please download it from http://sourceforge.net/projects/vxl/ and unzip the downloaded file under the given directory SuperPB. In this case the unzipped files should be delivered into the empty folder "vxl-1.14.0". Then please build VXL under "vxl-1.14.0/bin". This will keep the consistency with the CMakeLists.txt. If you prefer to install VXL at another place or are using a version different from 1.14.0, please modify the corresponding lines in CMakeLists.txt 22 | 23 | 5. The executable file can be launched with the following command: 24 | 25 | >SuperPB.exe imagename hsize vsize sigma algorithm 26 | 27 | imagename: the input image, e.g. test.jpg 28 | hsize: the width of the initial vertical strips, controlling the width of superpixels, e.g. 20 29 | vsize: the height of the initial horizontal strips, controlling the height of superpixels, e.g. 20 30 | sigma: balancing the weight between regular shape and accurate edge, e.g. 20 31 | algorithm: 0: maxflow; 1: Elimination, e.g. 1 32 | 33 | Elimination runs faster than maxflow. The superpixels produced by the two optimization algorithms are both accurate but usually different. 34 | 35 | 6. If you have any questions about the code or the algorithm, please write to yuhang.zhang@anu.edu.au. 36 | 37 | [1]Superpixels via pseudo-boolean optimization. 38 | Y. Zhang, R. Hartley, J. Mashford, and S. Burn. 39 | In International Conference on Computer Vision, 2011. 40 | 41 | [2]Minimizing energy functions on 4-connected lattices using elimination. 42 | Peter Carr, Richard Hartley 43 | In International Conference on Computer Vision, 2009. 44 | 45 | [3]An Experimental Comparison of Min-Cut/Max-Flow Algorithms for Energy Minimization in Vision. 46 | Yuri Boykov and Vladimir Kolmogorov. 47 | In IEEE Transactions on Pattern Analysis and Machine Intelligence (PAMI), September 2004 48 | -------------------------------------------------------------------------------- /lib_pb/SuperPB.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include 7 | #include 8 | 9 | struct scost 10 | { 11 | float h00; 12 | float h01; 13 | float h10; 14 | float h11; 15 | float v00; 16 | float v01; 17 | float v10; 18 | float v11; 19 | }; 20 | 21 | int myfloor(float t) 22 | { 23 | return int(t)>t? int(t)-1:int(t); 24 | } 25 | 26 | template 27 | void smoothcost(vil_image_view & im, int i1, int i2, int j1, int j2, int hsize, int vsize, float sigma, scost *sc) 28 | { 29 | float temp; 30 | float colordiff=0; 31 | 32 | temp = im(i1,j1,0); 33 | temp-= im(i2,j2,0); 34 | colordiff += fabs(temp); 35 | 36 | temp = im(i1,j1,1); 37 | temp-= im(i2,j2,1); 38 | colordiff += fabs(temp); 39 | 40 | temp = im(i1,j1,2); 41 | temp-= im(i2,j2,2); 42 | colordiff += fabs(temp); 43 | 44 | colordiff = exp(-colordiff/sigma); 45 | 46 | 47 | sc->h01 = colordiff; 48 | sc->h10 = colordiff; 49 | sc->v01 = colordiff; 50 | sc->v10 = colordiff; 51 | 52 | 53 | 54 | if(myfloor(float(i1)/hsize)!=myfloor(float(i2)/hsize)) 55 | { 56 | sc->h00 = colordiff; 57 | } 58 | else 59 | { 60 | sc->h00 = 0; 61 | } 62 | 63 | if(myfloor(float(i1-hsize/2)/hsize)!=myfloor(float(i2-hsize/2)/hsize)) 64 | { 65 | sc->h11 = colordiff; 66 | } 67 | else 68 | { 69 | sc->h11 = 0; 70 | } 71 | 72 | 73 | if(myfloor(float(j1)/vsize)!=myfloor(float(j2)/vsize)) 74 | { 75 | sc->v00 = colordiff; 76 | } 77 | else 78 | { 79 | sc->v00 = 0; 80 | } 81 | 82 | if(myfloor(float(j1-vsize/2)/vsize)!=myfloor(float(j2-vsize/2)/vsize)) 83 | { 84 | sc->v11 = colordiff; 85 | } 86 | else 87 | { 88 | sc->v11 = 0; 89 | } 90 | 91 | 92 | 93 | return; 94 | } 95 | 96 | //exe inputimage hsize vsize sigma algorithm(0/1) 97 | int main(int argc, char* argv[]) 98 | { 99 | vil_image_view< vxl_byte > im = vil_load(argv[1]); 100 | 101 | int width = im.ni(); 102 | int height= im.nj(); 103 | int hsize = atoi(argv[2]); 104 | int vsize = atoi(argv[3]); 105 | float sigma = atof(argv[4]); 106 | int algo = atoi(argv[5]); 107 | 108 | Matrix U1(height,width),U2(height,width);//to hold data cost 109 | Matrix Bh1(height,width),Bh2(height,width);//horizontal smooth cost 110 | Matrix Bv1(height,width),Bv2(height,width);//vertical smooth cost 111 | Matrix< unsigned char > solution1(height,width),solution2(height,width); 112 | 113 | struct scost *sc = (struct scost*)malloc(sizeof(struct scost)); 114 | 115 | U1.fill(0); 116 | Bh1.fill(0); 117 | Bv1.fill(0); 118 | U2.fill(0); 119 | Bh2.fill(0); 120 | Bv2.fill(0); 121 | 122 | for(int i=0;ih00-sc->h01-sc->h10+sc->h11; 130 | U1[j][i] += sc->h10-sc->h00; 131 | U1[j][i+1] += sc->h01-sc->h00; 132 | Bh2[j][i] = sc->v00-sc->v01-sc->v10+sc->v11; 133 | U2[j][i] += sc->v10-sc->v00; 134 | U2[j][i+1] += sc->v01-sc->v00; 135 | } 136 | 137 | if(jh00-sc->h01-sc->h10+sc->h11; 142 | U1[j][i] += sc->h10-sc->h00; 143 | U1[j+1][i] += sc->h01-sc->h00; 144 | Bv2[j][i] = sc->v00-sc->v01-sc->v10+sc->v11; 145 | U2[j][i] += sc->v10-sc->v00; 146 | U2[j+1][i] += sc->v01-sc->v00; 147 | } 148 | } 149 | } 150 | 151 | if(algo==0) 152 | { 153 | MaxFlowQPBO solve1(U1,Bh1,Bv1,solution1); 154 | MaxFlowQPBO solve2(U2,Bh2,Bv2,solution2); 155 | } 156 | else 157 | { 158 | Elimination< float >::solve(U1, Bh1, Bv1, solution1); 159 | Elimination< float >::solve(U2, Bh2, Bv2, solution2); 160 | } 161 | 162 | vil_image_view< int > imh(width,height); 163 | vil_image_view< int > imv(width,height); 164 | 165 | for(int i=0;idevenv /Build "Release|Win32" vxl.sln 24 | 25 | You may change the option to 64bit. If your computer does not recognize devenv, find it in your visual studio directory and add the directory into PATH, e.g. 26 | 27 | >set PATH=YOURPATH\Microsoft Visual Studio 8\Common7\IDE;%PATH% 28 | 29 | It should take a long while to compile, when the number at the beginning of each line approaches 500, it is about to finish. 30 | 31 | 4. Compile the superpixel code. 32 | 33 | My code uses the Elimination algorithm by Peter Carr and Richard Hartley ICCV09. Their code uses the Maxflow by Yuri Boykov. So, you will see a single .cpp file by the side of two heavier folders. But do not worry, use CMake again, you will obtain another solution file, SuperPB.sln, easily. Compile it under visual studio. If everything goes smoothly, you now have the exe file of my code. 34 | 35 | 5. If you still have any problem or question, drop me a mail: 36 | 37 | yuhang.zhang@anu.edu.au 38 | 39 | Cheers, 40 | 41 | Yuhang 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /lib_seeds/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(seeds seeds2.cpp) 2 | -------------------------------------------------------------------------------- /lib_seeds/README.md: -------------------------------------------------------------------------------- 1 | # Superpixels Extracted via Energy-Driven Sampling (SEEDS) 2 | 3 | Original implementation of SEEDS Superpixels[1]: 4 | 5 | [1] M. van den Bergh, X. Boix, G. Roig, B. de Capitani, L. van Gool. 6 | SEEDS: Superpixels extracted via energy-driven sampling. 7 | European Conference on Computer Vision, pages 13–26, 2012. 8 | 9 | The corresponding command line tool can befound in `seeds_cli/main.cpp`, including documentation. 10 | 11 | The original README can be found in `README.txt`, the license can befound in `LICENSE.txt`. -------------------------------------------------------------------------------- /lib_seeds/README.txt: -------------------------------------------------------------------------------- 1 | 2 | This is the source code to SEEDS superpixels, as described in M. Van den Bergh, X. Boix, G. Roig, B. de Capitani and L. Van Gool, "SEEDS: Superpixels Extracted via Energy-Driven Sampling", ECCV 2012. 3 | 4 | The SEEDS class is defined in seeds.h and seeds2.cpp. The method can be run on an RGB image (stored in an UINT* array) by using the following constructor, initialization and iteration methods: 5 | 6 | SEEDS(int width, int height, int nr_channels, int nr_bins, int min_size); 7 | void initialize(UINT* image, int seeds_w, int seeds_h, int nr_levels); 8 | void iterate(); 9 | 10 | The initial size of the superpixels is independent from the image size, and defined by the following 3 parameters: , and . The first two define the minimum block size in the SEEDS algorithm. The defines the number of times this block size is doubled to reach the superpixel size. The superpixel size (width x height) is defined as follows: (seed_width*2^(nr_levels-1) x seed_height*2^(nr_levels-1)). 11 | 12 | For example, if (seed_width x seed_height) = (3x4) and nr_levels = 4, then the initial superpixels will be rectangular and of size (3*2^3 x 4*2^3) = (24x32). Provided an image of size (480x320), this results in 20*10 = 200 superpixels. 13 | 14 | 15 | Two usage examples are provided: 16 | 17 | 18 | 1. Evaluation demo (superpixel_test.cpp) 19 | 20 | This example is intended for use on the BSD300 or BSD500 dataset (http://www.eecs.berkeley.edu/Research/Projects/CS/vision/bsds/). 21 | 22 | Usage: bin/superpixel_test.cpp image_name [number_of_superpixels] 23 | 24 | A bash script is provided to run through a series of images (batch_process). 25 | 26 | 27 | 2. Live demo (demo.cpp) 28 | 29 | This examples takes images from a webcam and segments them independently and in real-time. 30 | 31 | 32 | 33 | Furthermore, a mex file is provided for use in Matlab. 34 | 35 | 36 | Disclaimer: the author of the code or ETH Zurich are not responsible for any damages that may result from using this code. 37 | Copyright (c) 2012 Michael Van den Bergh (ETH Zurich). All rights reserved. 38 | -------------------------------------------------------------------------------- /lib_seeds/seeds2.h: -------------------------------------------------------------------------------- 1 | // ****************************************************************************** 2 | // SEEDS Superpixels 3 | // ****************************************************************************** 4 | // Author: Michael Van den Bergh 5 | // Contact: vamichae@vision.ee.ethz.ch 6 | // 7 | // This code implements the superpixel method described in: 8 | // M. Van den Bergh, X. Boix, G. Roig, B. de Capitani and L. Van Gool, 9 | // "SEEDS: Superpixels Extracted via Energy-Driven Sampling", 10 | // ECCV 2012 11 | // 12 | // Copyright (c) 2012 Michael Van den Bergh (ETH Zurich). All rights reserved. 13 | // ****************************************************************************** 14 | 15 | #if !defined(_SEEDS_H_INCLUDED_) 16 | #define _SEEDS_H_INCLUDED_ 17 | 18 | #include 19 | #include 20 | 21 | using namespace std; 22 | 23 | typedef unsigned int UINT; 24 | 25 | 26 | class SEEDS 27 | { 28 | public: 29 | SEEDS(int width, int height, int nr_channels, int nr_bins, int min_size); 30 | ~SEEDS(); 31 | 32 | // initialize with an image 33 | void initialize(UINT* image, int seeds_w, int seeds_h, int nr_levels); 34 | void initialize(const cv::Mat &image, int seeds_w, int seeds_h, int nr_levels); 35 | 36 | // go through iterations 37 | void iterate(int iterations); 38 | 39 | // output labels 40 | UINT** labels; 41 | 42 | // evaluation 43 | int count_superpixels(); 44 | void SaveLabels_Text(string filename); 45 | void SaveLabels_CSV(string filename); 46 | 47 | // mean colors 48 | void compute_mean_map(); 49 | UINT* means; 50 | 51 | private: 52 | 53 | int current_nr_superpixels; 54 | bool initialized; 55 | 56 | // seeds 57 | int seeds_w; 58 | int seeds_h; 59 | int seeds_nr_levels; 60 | int seeds_top_level; 61 | int seeds_current_level; 62 | 63 | // image processing 64 | float* image_l; 65 | float* image_a; 66 | float* image_b; 67 | UINT* image_bins; 68 | float* edge_h; 69 | float* edge_w; 70 | float* bin_cutoff1; 71 | float* bin_cutoff2; 72 | float* bin_cutoff3; 73 | 74 | // keep one labeling for each level 75 | UINT* nr_labels; 76 | UINT** parent; 77 | UINT** nr_partitions; 78 | int** T; 79 | int go_down_one_level(); 80 | 81 | // initialization 82 | void assign_labels(); 83 | void compute_histograms(int until_level = -1); 84 | void compute_histograms_ex(); 85 | void compute_means(); 86 | void compute_edges(); 87 | void lab_get_histogram_cutoff_values(UINT* image); 88 | void lab_get_histogram_cutoff_values(const cv::Mat &image); 89 | 90 | // color conversion and histograms 91 | int RGB2HSV(const int& r, const int& g, const int& b, float* hval, float* sval, float* vval); 92 | int RGB2LAB(const int& r, const int& g, const int& b, float* lval, float* aval, float* bval); 93 | int LAB2bin(float l, float a, float b); 94 | int RGB2LAB_special(int r, int g, int b, float* lval, float* aval, float* bval); 95 | int RGB2LAB_special(int r, int g, int b, int* bin_l, int* bin_a, int* bin_b); 96 | void LAB2RGB(float L, float a, float b, int* R, int* G, int* B); 97 | 98 | int histogram_size; 99 | int*** histogram; 100 | //int** subhistogram; 101 | 102 | 103 | void update(int level, int label_new, int x, int y); 104 | void add_pixel(int level, int label, int x, int y); 105 | void add_pixel_m(int level, int label, int x, int y); 106 | void delete_pixel(int level, int label, int x, int y); 107 | void delete_pixel_m(int level, int label, int x, int y); 108 | void add_block(int level, int label, int sublevel, int sublabel); 109 | void delete_block(int level, int label, int sublevel, int sublabel); 110 | void update_labels(int level); 111 | 112 | 113 | // probability computation 114 | bool probability(int color, int label1, int label2, int prior1, int prior2, float edge1, float edge2); 115 | bool probability_means(float L, float a, float b, int label1, int label2, int prior1, int prior2, float edge1, float edge2); 116 | 117 | int threebythree(int x, int y, int label); 118 | int threebyfour(int x, int y, int label); 119 | int fourbythree(int x, int y, int lacompute_mean_mapbel); 120 | 121 | 122 | // block updating 123 | void update_blocks(int level, float req_confidence = 0.0); 124 | float merge_threshold; 125 | float intersection(int level1, int label1, int level2, int label2); 126 | float geometric_distance(int label1, int label2); 127 | int min_size; 128 | 129 | // border updating 130 | void update_pixels(); 131 | void update_pixels_means(); 132 | bool forwardbackward; 133 | int threebythree_upperbound; 134 | int threebythree_lowerbound; 135 | 136 | bool check_split(int a11, int a12, int a13, int a21, int a22, int a23, int a31, int a32, int a33, bool horizontal, bool forward); 137 | 138 | int nr_comp; 139 | float step_h; 140 | float step_w; 141 | float substep_h; 142 | float substep_w; 143 | int nr_label_h; 144 | int nr_label_w; 145 | int* nr_w; 146 | int* nr_h; 147 | 148 | int* x_position; 149 | int* y_position; 150 | float* L_channel; 151 | float* A_channel; 152 | float* B_channel; 153 | float* L_subchannel; 154 | float* A_subchannel; 155 | float* B_subchannel; 156 | int width, height, nr_channels, nr_bins; 157 | 158 | int iteration; 159 | int step; 160 | }; 161 | 162 | 163 | 164 | 165 | #endif // !defined(_SEEDS_H_INCLUDED_) 166 | -------------------------------------------------------------------------------- /lib_slic/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_library(slic SLIC.cpp) 2 | -------------------------------------------------------------------------------- /lib_slic/README.md: -------------------------------------------------------------------------------- 1 | # Simple Linear Iterative Clustering (SLIC) 2 | 3 | Original implementation of SLIC [1]: 4 | 5 | [1] R. Achanta, A. Shaji, K. Smith, A. Lucchi, P. Fua, S. Süsstrunk. 6 | SLIC superpixels. 7 | Technical report, École Polytechnique Fédérale de Lausanne, 2010. 8 | 9 | The corresponding command line tool can befound in `slic_cli/main.cpp`, including documentation. 10 | 11 | The original README can be found in `README.txt`, the license can befound in `LICENSE.txt`. -------------------------------------------------------------------------------- /lib_slic/README.txt: -------------------------------------------------------------------------------- 1 | ================================================================================ 2 | MICROSOFT FOUNDATION CLASS LIBRARY : SLICSuperpixels Project Overview 3 | =============================================================================== 4 | 5 | The application wizard has created this SLICSuperpixels application for 6 | you. This application not only demonstrates the basics of using the Microsoft 7 | Foundation Classes but is also a starting point for writing your application. 8 | 9 | This file contains a summary of what you will find in each of the files that 10 | make up your SLICSuperpixels application. 11 | 12 | SLICSuperpixels.vcproj 13 | This is the main project file for VC++ projects generated using an application wizard. 14 | It contains information about the version of Visual C++ that generated the file, and 15 | information about the platforms, configurations, and project features selected with the 16 | application wizard. 17 | 18 | SLICSuperpixels.h 19 | This is the main header file for the application. It includes other 20 | project specific headers (including Resource.h) and declares the 21 | CSLICSuperpixelsApp application class. 22 | 23 | SLICSuperpixels.cpp 24 | This is the main application source file that contains the application 25 | class CSLICSuperpixelsApp. 26 | 27 | SLICSuperpixels.rc 28 | This is a listing of all of the Microsoft Windows resources that the 29 | program uses. It includes the icons, bitmaps, and cursors that are stored 30 | in the RES subdirectory. This file can be directly edited in Microsoft 31 | Visual C++. Your project resources are in 1033. 32 | 33 | res\SLICSuperpixels.ico 34 | This is an icon file, which is used as the application's icon. This 35 | icon is included by the main resource file SLICSuperpixels.rc. 36 | 37 | res\SLICSuperpixels.rc2 38 | This file contains resources that are not edited by Microsoft 39 | Visual C++. You should place all resources not editable by 40 | the resource editor in this file. 41 | 42 | 43 | ///////////////////////////////////////////////////////////////////////////// 44 | 45 | The application wizard creates one dialog class: 46 | 47 | SLICSuperpixelsDlg.h, SLICSuperpixelsDlg.cpp - the dialog 48 | These files contain your CSLICSuperpixelsDlg class. This class defines 49 | the behavior of your application's main dialog. The dialog's template is 50 | in SLICSuperpixels.rc, which can be edited in Microsoft Visual C++. 51 | 52 | 53 | ///////////////////////////////////////////////////////////////////////////// 54 | 55 | Other standard files: 56 | 57 | StdAfx.h, StdAfx.cpp 58 | These files are used to build a precompiled header (PCH) file 59 | named SLICSuperpixels.pch and a precompiled types file named StdAfx.obj. 60 | 61 | Resource.h 62 | This is the standard header file, which defines new resource IDs. 63 | Microsoft Visual C++ reads and updates this file. 64 | 65 | ///////////////////////////////////////////////////////////////////////////// 66 | 67 | Other notes: 68 | 69 | The application wizard uses "TODO:" to indicate parts of the source code you 70 | should add to or customize. 71 | 72 | If your application uses MFC in a shared DLL, you will need 73 | to redistribute the MFC DLLs. If your application is in a language 74 | other than the operating system's locale, you will also have to 75 | redistribute the corresponding localized resources MFC90XXX.DLL. 76 | For more information on both of these topics, please see the section on 77 | redistributing Visual C++ applications in MSDN documentation. 78 | 79 | ///////////////////////////////////////////////////////////////////////////// 80 | -------------------------------------------------------------------------------- /lib_slic/USAGE_SLIC.txt: -------------------------------------------------------------------------------- 1 | 2 | SLIC class declaration and implementation files are provided. The files provide the code to perform superpixel segmentation as explained in the paper: 3 | 4 | "SLIC Superpixels", Radhakrishna Achanta, Appu Shaji, Kevin Smith, Aurelien Lucchi, Pascal Fua, and Sabine Susstrunk. 5 | EPFL Technical Report no. 149300, June 2010. 6 | 7 | The code in addition provides the extension to supervoxels as well! Usage can be seen in the demo function DoSupervoxelVideoSegmentation() in the SLICSuperpixelsDlg.cpp file. 8 | 9 | The usage is quite straight forward. One has to instantiate an object of the SLIC class and call the various methods on it. Here is an example main() file: 10 | 11 | 12 | #include 13 | #include "SLIC.h" 14 | 15 | int main() 16 | { 17 | int width(0), height(0); 18 | // unsigned int (32 bits) to hold a pixel in ARGB format as follows: 19 | // from left to right, 20 | // the first 8 bits are for the alpha channel (and are ignored) 21 | // the next 8 bits are for the red channel 22 | // the next 8 bits are for the green channel 23 | // the last 8 bits are for the blue channel 24 | unsigned int* pbuff = new UINT[sz]; 25 | ReadImage(pbuff, width, height);//YOUR own function to read an image into the ARGB format 26 | 27 | //---------------------------------- 28 | // Initialize parameters 29 | //---------------------------------- 30 | int k = 200;//Desired number of superpixels. 31 | double m = 20;//Compactness factor. use a value ranging from 10 to 40 depending on your needs. Default is 10 32 | int* klabels = NULL; 33 | int numlabels(0); 34 | string filename = "yourfilename.jpg"; 35 | string savepath = "yourpathname"; 36 | //---------------------------------- 37 | // Perform SLIC on the image buffer 38 | //---------------------------------- 39 | SLIC segment; 40 | segment.DoSuperpixelSegmentation_ForGivenNumberOfSuperpixels(pbuff, width, height, klabels, numlabels, k, m); 41 | // Alternately one can also use the function DoSuperpixelSegmentation_ForGivenStepSize() for a desired superpixel size 42 | //---------------------------------- 43 | // Save the labels to a text file 44 | //---------------------------------- 45 | segment.SaveSuperpixelLabels(klabels, width, height, filename, savepath); 46 | //---------------------------------- 47 | // Draw boundaries around segments 48 | //---------------------------------- 49 | segment.DrawContoursAroundSegments(pbuff, klabels, width, height, 0xff0000); 50 | //---------------------------------- 51 | // Save the image with segment boundaries. 52 | //---------------------------------- 53 | SaveSegmentedImageFile(pbuff, width, height);//YOUR own function to save an ARGB buffer as an image 54 | //---------------------------------- 55 | // Clean up 56 | //---------------------------------- 57 | if(pbuff) delete [] pbuff; 58 | if(klabels) delete [] klabels; 59 | 60 | return 0; 61 | } 62 | 63 | As a disclaimer, the author of the code or EPFL are not responsible for any damages that may result from using this code. 64 | 65 | 66 | -------------------------------------------------------------------------------- /pb_cli/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../lib_pb ../lib_seeds_revised/) 2 | 3 | find_package(Boost COMPONENTS system filesystem program_options REQUIRED) 4 | find_package(OpenCV REQUIRED) 5 | 6 | include_directories(${EIGEN_INCLUDE_DIRS}) 7 | 8 | add_executable(pb_cli main.cpp) 9 | target_link_libraries(pb_cli ${Boost_LIBRARIES} ${OpenCV_LIBS} seeds_revised pb_elimination pb_maxflow) -------------------------------------------------------------------------------- /screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/davidstutz/superpixels-revisited/f14e9e0b063741e5a9eb6544a3d6c2f44cdfc9e4/screenshot.png -------------------------------------------------------------------------------- /seeds_cli/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../lib_seeds_revised/ ../lib_seeds/) 2 | 3 | find_package(Boost COMPONENTS system filesystem program_options REQUIRED) 4 | find_package(OpenCV REQUIRED) 5 | 6 | include_directories(${EIGEN_INCLUDE_DIRS}) 7 | 8 | add_executable(seeds_cli main.cpp) 9 | target_link_libraries(seeds_cli ${Boost_LIBRARIES} ${OpenCV_LIBS} seeds_revised seeds) 10 | -------------------------------------------------------------------------------- /slic_cli/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../lib_seeds_revised/ ../lib_slic/) 2 | 3 | find_package(Boost COMPONENTS system filesystem program_options REQUIRED) 4 | find_package(OpenCV REQUIRED) 5 | 6 | include_directories(${EIGEN_INCLUDE_DIRS}) 7 | 8 | add_executable(slic_cli main.cpp) 9 | target_link_libraries(slic_cli ${Boost_LIBRARIES} ${OpenCV_LIBS} seeds_revised slic) 10 | -------------------------------------------------------------------------------- /vlfeat_slic_cli/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories(../lib_seeds_revised/ ../lib_vlfeat/vl/) 2 | 3 | set(CMAKE_THREAD_PREFER_PTHREAD TRUE) 4 | find_package(Threads REQUIRED) 5 | 6 | find_package(Boost COMPONENTS system filesystem program_options REQUIRED) 7 | find_package(OpenCV REQUIRED) 8 | 9 | include_directories(${EIGEN_INCLUDE_DIRS}) 10 | 11 | 12 | add_library(vlfeat 13 | ../lib_vlfeat/vl/generic.c 14 | ../lib_vlfeat/vl/mathop.c 15 | ../lib_vlfeat/vl/aib.c 16 | ../lib_vlfeat/vl/array.c 17 | ../lib_vlfeat/vl/covdet.c 18 | ../lib_vlfeat/vl/dsift.c 19 | ../lib_vlfeat/vl/fisher.c 20 | ../lib_vlfeat/vl/getopt_long.c 21 | ../lib_vlfeat/vl/gmm.c 22 | ../lib_vlfeat/vl/hikmeans.c 23 | ../lib_vlfeat/vl/hog.c 24 | ../lib_vlfeat/vl/homkermap.c 25 | ../lib_vlfeat/vl/host.c 26 | ../lib_vlfeat/vl/ikmeans.c 27 | ../lib_vlfeat/vl/ikmeans_elkan.tc 28 | ../lib_vlfeat/vl/ikmeans_init.tc 29 | ../lib_vlfeat/vl/ikmeans_lloyd.tc 30 | ../lib_vlfeat/vl/imopv.c 31 | ../lib_vlfeat/vl/kdtree.c 32 | ../lib_vlfeat/vl/kmeans.c 33 | ../lib_vlfeat/vl/lbp.c 34 | ../lib_vlfeat/vl/liop.c 35 | ../lib_vlfeat/vl/mathop.c 36 | ../lib_vlfeat/vl/mser.c 37 | ../lib_vlfeat/vl/pgm.c 38 | ../lib_vlfeat/vl/quickshift.c 39 | ../lib_vlfeat/vl/random.c 40 | ../lib_vlfeat/vl/rodrigues.c 41 | ../lib_vlfeat/vl/scalespace.c 42 | ../lib_vlfeat/vl/sift.c 43 | ../lib_vlfeat/vl/slic.c 44 | ../lib_vlfeat/vl/stringop.c 45 | ../lib_vlfeat/vl/svm.c 46 | ../lib_vlfeat/vl/svmdataset.c 47 | ../lib_vlfeat/vl/vlad.c) 48 | 49 | add_executable(vlfeat_slic_cli main.cpp) 50 | target_link_libraries(vlfeat_slic_cli ${Boost_LIBRARIES} ${OpenCV_LIBS} vlfeat seeds_revised ${CMAKE_THREAD_LIBS_INIT}) 51 | --------------------------------------------------------------------------------