Skip to content

Commit

Permalink
Change segment to abstract class
Browse files Browse the repository at this point in the history
  • Loading branch information
hgaiser committed Sep 23, 2014
1 parent f29de0d commit 2833186
Show file tree
Hide file tree
Showing 9 changed files with 238 additions and 169 deletions.
6 changes: 2 additions & 4 deletions random/src/connection.h
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
#pragma once

#include "segment.h"

class Connection
{
public:
Connection(const Segment & a_, const Segment & b_, uint8_t flags, const cv::Mat & weights) :
a(a_.id), b(b_.id), similarity(exp(Segment::computeSimilarity(a_, b_, flags, weights)))
Connection(int a_, int b_, float sim) :
a(a_), b(b_), similarity(exp(sim))
{
}

Expand Down
154 changes: 154 additions & 0 deletions random/src/features_segment.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
#pragma once

#include <vector>
#include <opencv2/opencv.hpp>
#include "segment.h"

enum {
COLOR_SIMILARITY = 0x1,
TEXTURE_SIMILARITY = 0x2,
SIZE_SIMILARITY = 0x4,
BBOX_SIMILARITY = 0x8,
};

#define HIST_SIZE 25
#define HIST_STEP int(255 / HIST_SIZE)

class FeaturesSegment: public Segment
{
public:
FeaturesSegment(int id, int nchannels, cv::Size size, uint8_t f, const cv::Mat & w) :
Segment(id, size),
nchannels(nchannels),
flags(f),
weights(w)
{
color_hist.assign(nchannels * HIST_SIZE, 0.f);
texture_hist.assign(HIST_SIZE, 0.f);
}

virtual void addPoint(const cv::Mat & image, const cv::Mat & texture, cv::Point point) override {
Segment::addPoint(image, texture, point);
size++;
if (nchannels == 1) {
cv::Vec<uint8_t, 1> color = image.at<cv::Vec<uint8_t, 1>>(point);
for (int i = 0; i < nchannels; i++)
color_hist[i*HIST_SIZE + color[i] / HIST_STEP]++;
} else if (nchannels == 3) {
cv::Vec<uint8_t, 3> color = image.at<cv::Vec<uint8_t, 3>>(point);
for (int i = 0; i < nchannels; i++)
color_hist[i*HIST_SIZE + color[i] / HIST_STEP]++;
}
uint8_t text = texture.at<uint8_t>(point);
texture_hist[text / HIST_STEP]++;
}

virtual void finalizeSetup() override {
cv::normalize(color_hist, color_hist, 1, 0, cv::NORM_L1);
cv::normalize(texture_hist, texture_hist, 1, 0, cv::NORM_L1);
}

virtual float computeSimilarity(const Segment * b_) override {
const FeaturesSegment * b = dynamic_cast<const FeaturesSegment *>(b_);
if (weights.type() != CV_32FC1) {
std::cerr << "Error! Weights are not one channel float " << weights << std::endl;
return 0.f;
}
if (weights.total() != 5) {
std::cerr << "Error! Not enough weights: " << weights << std::endl;
return 0.f;
}
if (im_size != b->im_size) {
std::cerr << "Error! Segments are from different images?" << std::endl;
return 0.f;
}
if (size == 0 || b->size == 0) {
std::cout << "Warning! Invalid segment." << std::endl;
return 0.f;
}
if (color_hist.size() != b->color_hist.size() || texture_hist.size() != b->texture_hist.size()) {
std::cout << "Error! Segments histograms don't match!" << std::endl;
return 0.f;
}

float color_similarity = 0.f;
if (flags & COLOR_SIMILARITY) {
for (uint64_t i = 0; i < color_hist.size(); i++)
color_similarity += weights.at<float>(0) * std::min(color_hist[i], b->color_hist[i]);
}

float texture_similarity = 0.f;
if (flags & TEXTURE_SIMILARITY) {
for (uint64_t i = 0; i < texture_hist.size(); i++)
texture_similarity += weights.at<float>(1) * std::min(texture_hist[i], b->texture_hist[i]);
}

float size_similarity = 0.f;
if (flags & SIZE_SIMILARITY) {
size_similarity += weights.at<float>(2) * (1.f - float(size + b->size) / im_size);
}

float bbox_similarity = 0.f;
if (flags & BBOX_SIMILARITY) {
cv::Point combined_min(std::min(min_p.x, b->min_p.x), std::min(min_p.y, b->min_p.y));
cv::Point combined_max(std::max(max_p.x, b->max_p.x), std::max(max_p.y, b->max_p.y));
int bbox_size = (combined_max.x - combined_min.x) * (combined_max.y - combined_min.y);
bbox_similarity += weights.at<float>(3) * (1.f - float(bbox_size - size - b->size) / im_size);
}

return color_similarity + texture_similarity + size_similarity + bbox_similarity + weights.at<float>(4);
}

std::unique_ptr<Segment> merge(const Segment * b_) override {
const FeaturesSegment * b = dynamic_cast<const FeaturesSegment *>(b_);
std::unique_ptr<Segment> s_(new FeaturesSegment(-1, nchannels, im_size_cv, flags, weights));
FeaturesSegment * s = dynamic_cast<FeaturesSegment *>(s_.get());
s->size = size + b->size;
#ifdef DEBUG
cv::bitwise_or(mask, b->mask, s->mask);
#endif

s->min_p = cv::Point(std::min(min_p.x, b->min_p.x), std::min(min_p.y, b->min_p.y));
s->max_p = cv::Point(std::max(max_p.x, b->max_p.x), std::max(max_p.y, b->max_p.y));

if (color_hist.size() != b->color_hist.size() || texture_hist.size() != b->texture_hist.size())
return s_;

for (uint64_t i = 0; i < color_hist.size(); i++) {
s->color_hist[i] = (color_hist[i] * size + b->size * b->color_hist[i]) / s->size;
}

for (uint64_t i = 0; i < texture_hist.size(); i++)
s->texture_hist[i] = (size * texture_hist[i] + b->size * b->texture_hist[i]) / s->size;
//s->texture_hist = (size * texture_hist + b->size * b->texture_hist) / s->size;


s->history.insert(history.begin(), history.end());
s->history.insert(b->history.begin(), b->history.end());

s->neighbours.insert(neighbours.begin(), neighbours.end());
s->neighbours.insert(b->neighbours.begin(), b->neighbours.end());

for (const auto & h: s->history)
s->neighbours.erase(h);

return s_;
}

std::ostream & output(std::ostream & out) const {
out << "<id: " << id << "; size: " << size << "; im_size: " << im_size << "; bbox: " << bbox() << "; neighbours: [";
for (auto n: neighbours)
out << n << ", ";
return out << "]>";
}

inline cv::Rect bbox() const {
return cv::Rect(min_p, max_p);
}

std::vector<float> color_hist;
std::vector<float> texture_hist;
int nchannels;
uint8_t flags;
const cv::Mat & weights;
};
12 changes: 7 additions & 5 deletions random/src/location_prior.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,27 @@ const float deviation = 4.f;

class LocationPrior : public SelectionPrior {
public:
virtual SelectionPriorMap computeSelectionPrior(const cv::Mat & image, const std::vector<Segment> & segments) {
virtual SelectionPriorMap computeSelectionPrior(const cv::Mat & image, const std::vector<std::unique_ptr<Segment>> & segments) {
SelectionPriorMap prior;

uint32_t radius = (image.cols*image.cols + image.rows*image.rows) / 4;
cv::Point center = cv::Point(image.cols / 2, image.rows / 2);
float sum = 0.f;

for (const auto s: segments) {
if (s.empty())
for (const auto & s: segments) {
if (s->empty())
continue;

cv::Point diff = (s.min_p + s.max_p) * 0.5 - center;
cv::Point diff = (s->min_p + s->max_p) * 0.5 - center;
float likelihood = exp(-diff.dot(diff) / float(radius) * deviation);
sum += likelihood;
prior.insert({s.id, likelihood});
prior.insert({s->id, likelihood});
std::cout << "size: " << prior.size() << " id: " << s->id << std::endl;
}

for (auto & p: prior) {
p.second /= sum;
std::cout << "likelihood: " << p.second << std::endl;
}

return prior;
Expand Down
75 changes: 47 additions & 28 deletions random/src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
#define DEBUG 1

//#include "CVBoostConverter.hpp"
#include <random>
#include <stdint.h>
#include <functional>
#include "conversion.h"
#include <boost/python.hpp>

#include "features_segment.h"
#include "connection.h"
#include "adjacency.h"
#include "uniform_prior.h"
#include "location_prior.h"
#include "objectness_prior.h"
#include "objectness_location_prior.h"

#include "random_stopping_criterion.h"

using namespace boost::python;
Expand All @@ -27,12 +33,12 @@ cv::Mat get_bboxes_(const cv::Mat & image, const cv::Mat & seg, const cv::Mat &
cv::minMaxIdx(seg, nullptr, &max_id_);
int max_id = max_id_;

std::vector<Segment> segments;
std::vector<std::unique_ptr<Segment>> segments;
segments.reserve(max_id);
int nchannels = image.channels();
cv::Size size = image.size();
for (int i = 0; i <= max_id; i++) {
segments.push_back(Segment(i, nchannels, size));
segments.push_back(std::unique_ptr<Segment>(new FeaturesSegment(i, nchannels, size, flags, weights)));
}

{
Expand All @@ -41,26 +47,23 @@ cv::Mat get_bboxes_(const cv::Mat & image, const cv::Mat & seg, const cv::Mat &
for (int j = 0; j < image.cols; j++) {
cv::Point p(j, i);
uint16_t id = seg.at<uint16_t>(p);
if (nchannels == 1)
segments[id].addPoint(image.at<cv::Vec<uint8_t, 1>>(p), edge.at<uint8_t>(p), p);
else if (nchannels == 3)
segments[id].addPoint(image.at<cv::Vec3b>(p), edge.at<uint8_t>(p), p);
segments[id]->addPoint(image, edge, p);

if (i < image.rows - 1) {
uint16_t n = seg.at<uint16_t>(i+1, j);
if (n != id && adjacency.get(id, n) == false) {
adjacency.get(id, n) = true;
segments[id].addNeighbour(n);
segments[n].addNeighbour(id);
segments[id]->addNeighbour(n);
segments[n]->addNeighbour(id);
}
}

if (j < image.cols - 1) {
uint16_t n = seg.at<uint16_t>(i, j+1);
if (n != id && adjacency.get(id, n) == false) {
adjacency.get(id, n) = true;
segments[id].addNeighbour(n);
segments[n].addNeighbour(id);
segments[id]->addNeighbour(n);
segments[n]->addNeighbour(id);
}
}
}
Expand All @@ -70,13 +73,13 @@ cv::Mat get_bboxes_(const cv::Mat & image, const cv::Mat & seg, const cv::Mat &
cv::Mat bboxes;
float similarity_sum = 0.f;
for (auto & s: segments) {
s.normalizeHistogram();
s->finalizeSetup();

cv::Mat bbox = cv::Mat(1, 4, CV_32SC1);
bbox.at<int>(0) = s.min_p.x;
bbox.at<int>(1) = s.min_p.y;
bbox.at<int>(2) = s.max_p.x;
bbox.at<int>(3) = s.max_p.y;
bbox.at<int>(0) = s->min_p.x;
bbox.at<int>(1) = s->min_p.y;
bbox.at<int>(2) = s->max_p.x;
bbox.at<int>(3) = s->max_p.y;
if (bboxes.empty())
bboxes = bbox;
else
Expand Down Expand Up @@ -108,25 +111,31 @@ cv::Mat get_bboxes_(const cv::Mat & image, const cv::Mat & seg, const cv::Mat &
cv::namedWindow("SelectionLikelihood", cv::WINDOW_AUTOSIZE);
#endif

Segment s;
for (uint32_t i = 0; i < n; i++) {
s = segments[prior.poll()];
std::unique_ptr<Segment> & s = segments[prior.poll()];
RandomStoppingCriterion stop;
cv::Rect r(s.min_p, s.max_p);
cv::Rect r(s->min_p, s->max_p);

while (stop.stop(image, r) == false) {
#ifdef DEBUG
cv::Mat red = edge * 0.5;
cv::Mat green;
s.mask.copyTo(green);
s->mask.copyTo(green);
green *= 255;
std::cout << "history:" << std::endl;
for (const auto & h: s->history)
std::cout << h << ", ";
std::cout << std::endl;
#endif
float sum = 0.f;
std::vector<Connection> connections;
for (auto n: s.neighbours) {
connections.push_back(Connection(s, segments[n], flags, weights));
std::cout << "neighbours:" << std::endl;
for (auto n: s->neighbours) {
connections.push_back(Connection(s->id, n, s->computeSimilarity(segments[n].get())));
sum += (connections.end() - 1)->similarity;
std::cout << n << ", ";
}
std::cout << std::endl;

#ifdef DEBUG
cv::Mat blue = cv::Mat::zeros(seg.size(), CV_8UC1);
Expand All @@ -136,9 +145,19 @@ cv::Mat get_bboxes_(const cv::Mat & image, const cv::Mat & seg, const cv::Mat &
max_sim = c.similarity;
}
for (auto & c: connections) {
blue += segments[c.b].mask * 255 * (c.similarity / max_sim);
blue += segments[c.b]->mask * 255 * (c.similarity / max_sim);
std::cout << c.similarity << std::endl;
}

for (int i = 0; i < blue.total(); i++) {
if (blue.at<uint8_t>(i) && green.at<uint8_t>(i)) {
// std::cout << "blue: " << (int)blue.at<uint8_t>(i) << " green: " << (int)green.at<uint8_t>(i) << std::endl;
for (auto & c: connections) {
if (segments[c.b]->mask.at<uint8_t>(i))
std::cout << "<<<<<<<<<<<<<<<<<<< " << c.b << " <<<<<<<<<<<<<<<<<<<<<" << std::endl;
}
}
}
std::cout << std::endl;
cv::Mat visualization;
cv::merge({blue, green, red}, visualization);
Expand All @@ -153,17 +172,17 @@ cv::Mat get_bboxes_(const cv::Mat & image, const cv::Mat & seg, const cv::Mat &
for (auto & c: connections) {
sum += c.similarity;
if (sum >= rnd) {
s = Segment::merge(s, segments[c.b]);
s = s->merge(segments[c.b].get());
break;
}
}
}

cv::Mat bbox = cv::Mat(1, 4, CV_32SC1);
bbox.at<int>(0) = s.min_p.x;
bbox.at<int>(1) = s.min_p.y;
bbox.at<int>(2) = s.max_p.x;
bbox.at<int>(3) = s.max_p.y;
bbox.at<int>(0) = s->min_p.x;
bbox.at<int>(1) = s->min_p.y;
bbox.at<int>(2) = s->max_p.x;
bbox.at<int>(3) = s->max_p.y;
if (bboxes.empty())
bboxes = bbox;
else
Expand All @@ -176,7 +195,7 @@ cv::Mat get_bboxes_(const cv::Mat & image, const cv::Mat & seg, const cv::Mat &
cv::cvtColor(draw, draw, cv::COLOR_BGR2GRAY);
cv::Rect r(cv::Point(bboxes.at<int>(0), bboxes.at<int>(1)), cv::Point(bboxes.at<int>(2), bboxes.at<int>(3)));
cv::rectangle(draw, r, cv::Scalar(255));
cv::addWeighted(draw, 0.5, s.mask * 255, 0.5, 0.0, draw);
cv::addWeighted(draw, 0.5, segments[n - 1]->mask * 255, 0.5, 0.0, draw);
cv::imshow("Image", draw);

std::cout << bboxes << std::endl;
Expand Down
Loading

0 comments on commit 2833186

Please sign in to comment.