Skip to content

Commit

Permalink
Implemented simple superpixel mean + a demo
Browse files Browse the repository at this point in the history
  • Loading branch information
martin-pr committed May 3, 2020
1 parent 82cfb7c commit 67cce80
Show file tree
Hide file tree
Showing 6 changed files with 529 additions and 2 deletions.
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1112,6 +1112,28 @@ SLIC (Simple Linear Iterative Clustering) is a simple adaptation of k-means clus
<div style="width:290px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div>
</td>
</tr>
<tr>
<td>
<div style="width:290px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div>
<img src="toolbars/06_opencv/91_superpixel_mean.png" style="width:70px;">
<div style="width:290px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div>
</td>
<td>

#### Superpixel Mean

Superpixel algorithms derive meaningful atomic primitives from dense grid images, which can then be used as inputs to other computer vision algorithms.

One of the simplest such algorithm is mean, averaging the values in a superpixel, leading to a "mosaic-like" look.

<sub>Achanta, Radhakrishna, et al. ["SLIC superpixels compared to state-of-the-art superpixel methods."](https://infoscience.epfl.ch/record/149300/files/SLIC_Superpixels_TR_2.pdf) IEEE transactions on pattern analysis and machine intelligence 34.11 (2012): 2274-2282.</sub>
</td>
<td>
<div style="width:290px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div>
<img src="toolbars/06_opencv/91_superpixel_mean_screenshot.png" style="width:70px;">
<div style="width:290px">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div>
</td>
</tr>
</table>

### Hdr
Expand Down
139 changes: 139 additions & 0 deletions src/plugins/opencv/nodes/superpixels/mean.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
#include <possumwood_sdk/node_implementation.h>

#include <tbb/parallel_for.h>

#include <actions/traits.h>

#include "frame.h"

namespace {

dependency_graph::InAttr<possumwood::opencv::Frame> a_in;
dependency_graph::InAttr<possumwood::opencv::Frame> a_superpixels;
dependency_graph::OutAttr<possumwood::opencv::Frame> a_out;

float getFloat(const cv::Mat& in, int row, int col, int channel) {
if(in.depth() == CV_32F)
return in.ptr<float>(row, col)[channel];
return in.ptr<double>(row, col)[channel];
}

long getLong(const cv::Mat& in, int row, int col, int channel) {
if(in.depth() == CV_8U)
return in.ptr<uint8_t>(row, col)[channel];
if(in.depth() == CV_8S)
return in.ptr<int8_t>(row, col)[channel];
if(in.depth() == CV_16U)
return in.ptr<uint16_t>(row, col)[channel];
if(in.depth() == CV_16S)
return in.ptr<int16_t>(row, col)[channel];
return in.ptr<int32_t>(row, col)[channel];
}

void setFloat(cv::Mat& in, int row, int col, int channel, float val) {
if(in.depth() == CV_32F)
in.ptr<float>(row, col)[channel] = val;
else
in.ptr<double>(row, col)[channel] = val;
}

void setLong(cv::Mat& in, int row, int col, int channel, long val) {
if(in.depth() == CV_8U)
in.ptr<uint8_t>(row, col)[channel] = val;
else if(in.depth() == CV_8S)
in.ptr<int8_t>(row, col)[channel] = val;
else if(in.depth() == CV_16U)
in.ptr<uint16_t>(row, col)[channel] = val;
else if(in.depth() == CV_16S)
in.ptr<int16_t>(row, col)[channel] = val;
else
in.ptr<int32_t>(row, col)[channel] = val;
}

dependency_graph::State compute(dependency_graph::Values& data) {
const cv::Mat& in = *data.get(a_in);
const cv::Mat& superpixels = *data.get(a_superpixels);

if(in.rows != superpixels.rows || in.cols != superpixels.cols)
throw std::runtime_error("Input and superpixel size have to match.");

if(superpixels.type() != CV_32SC1)
throw std::runtime_error("Only CV_32SC1 type supported on the superpixels input!");

// first of all, get the maximum index of the superpixels
int32_t maxIndex = 0;
for(int row=0; row<superpixels.rows; ++row)
for(int col=0; col<superpixels.cols; ++col)
maxIndex = std::max(maxIndex, superpixels.at<int32_t>(row, col));

cv::Mat out = cv::Mat::zeros(in.rows, in.cols, in.type());

if(in.depth() == CV_32F || in.depth() == CV_64F) {
// make the right sized accumulator and norm array
std::vector<std::vector<float>> vals(in.channels(), std::vector<float>(maxIndex+1, 0.0f));
std::vector<long> norm(maxIndex+1, 0);

// and accumulate the values
for(int row=0; row<in.rows; ++row)
for(int col=0; col<in.cols; ++col) {
const int32_t index = superpixels.at<int32_t>(row, col);

for(int c=0;c<in.channels();++c)
vals[c][index] += getFloat(in, row, col, c);

norm[index]++;
}

// assign the result
for(int row=0; row<in.rows; ++row)
for(int col=0; col<in.cols; ++col)
for(int c=0;c<in.channels();++c) {
const int32_t index = superpixels.at<int32_t>(row, col);
setFloat(out, row, col, c, vals[c][index] / (float)norm[index]);
}
}

else {
// make the right sized accumulator and norm array
std::vector<std::vector<long>> vals(in.channels(), std::vector<long>(maxIndex+1, 0.0f));
std::vector<long> norm(maxIndex+1, 0);

// and accumulate the values
for(int row=0; row<in.rows; ++row)
for(int col=0; col<in.cols; ++col) {
const int32_t index = superpixels.at<int32_t>(row, col);

for(int c=0;c<in.channels();++c)
vals[c][index] += getLong(in, row, col, c);

norm[index]++;
}

// assign the result
for(int row=0; row<in.rows; ++row)
for(int col=0; col<in.cols; ++col)
for(int c=0;c<in.channels();++c) {
const int32_t index = superpixels.at<int32_t>(row, col);
setLong(out, row, col, c, vals[c][index] / norm[index]);
}
}

data.set(a_out, possumwood::opencv::Frame(out));

return dependency_graph::State();
}

void init(possumwood::Metadata& meta) {
meta.addAttribute(a_in, "in", possumwood::opencv::Frame(), possumwood::AttrFlags::kVertical);
meta.addAttribute(a_superpixels, "superpixels", possumwood::opencv::Frame(), possumwood::AttrFlags::kVertical);
meta.addAttribute(a_out, "out", possumwood::opencv::Frame(), possumwood::AttrFlags::kVertical);

meta.addInfluence(a_in, a_out);
meta.addInfluence(a_superpixels, a_out);

meta.setCompute(compute);
}

possumwood::NodeImplementation s_impl("opencv/superpixels/mean", init);

}
2 changes: 0 additions & 2 deletions src/plugins/opencv/nodes/superpixels/slic.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
#include <possumwood_sdk/node_implementation.h>

#include <atomic>

#include <opencv2/opencv.hpp>
#include <tbb/parallel_for.h>

Expand Down
Binary file added toolbars/06_opencv/91_superpixel_mean.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 67cce80

Please sign in to comment.