diff --git a/components/rgbd-sources/include/ftl/cb_segmentation.hpp b/components/rgbd-sources/include/ftl/cb_segmentation.hpp index 64e22402a18af8b8cd778689104988427c1201ab..75ec0bdc4c7c7c8c67ee77a05e808fb439961f8d 100644 --- a/components/rgbd-sources/include/ftl/cb_segmentation.hpp +++ b/components/rgbd-sources/include/ftl/cb_segmentation.hpp @@ -71,21 +71,31 @@ protected: bool brightness(CBSegmentation::Pixel &pixel, float alpha, float beta); bool depthdiff(CBSegmentation::Pixel &pixel, float sigma); - inline int freq() { return f; } + inline int freq() { return f; } inline long getLambda() { return lambda; } inline long ctime() { return p; } inline long atime() { return q; } }; - enum EntryType { EMPTY, H, M }; + enum EntryType { H, M }; - struct Entry { - EntryType type = EMPTY; - CBSegmentation::Codeword cw; + union Entry { + char size; + struct Data { + EntryType type; + CBSegmentation::Codeword cw; + } data ; }; - bool processPixel(Pixel &px, Codeword *codeword=nullptr); + struct CompareEntry{ + bool operator()(const Entry &a,const Entry &b) const{ + return !((a.data.type == M && b.data.type == H) || + (a.data.cw.f < b.data.cw.f)); + } + }; + bool processPixel(Pixel &px, Codeword *codeword=nullptr); + size_t width_; size_t height_; size_t size_; @@ -101,8 +111,7 @@ protected: private: long t_ = 1; - std::vector<Entry> cb_; - + std::vector<Entry> cb_; }; } \ No newline at end of file diff --git a/components/rgbd-sources/src/cb_segmentation.cpp b/components/rgbd-sources/src/cb_segmentation.cpp index 32f56fc82fd3397054dc68f07a7de3d1249c2bdb..f6f5fc2b2093b25fda6fd4554eb6e4bc04eef472 100644 --- a/components/rgbd-sources/src/cb_segmentation.cpp +++ b/components/rgbd-sources/src/cb_segmentation.cpp @@ -1,5 +1,6 @@ #include "ftl/cb_segmentation.hpp" +#include<algorithm> #include <math.h> using cv::Mat; @@ -72,6 +73,7 @@ bool CBSegmentation::Codeword::colordiff(CBSegmentation::Pixel &px, float epsilo // "Algorithm for codebook construction" // bool CBSegmentation::Codeword::brightness(CBSegmentation::Pixel &px, float alpha, float beta) { + return true; float i_low = alpha * i_max; float i_hi = min(beta * i_max, i_min / alpha); return (i_low <= px.i) && (px.i <= i_hi); @@ -81,30 +83,33 @@ CBSegmentation::CBSegmentation( char codebook_size, size_t width, size_t height, float alpha, float beta, float epsilon, float sigma, int T_h, int T_add, int T_del) : - size_(codebook_size), width_(width), height_(height), + size_(codebook_size + 1), width_(width), height_(height), alpha_(alpha), beta_(beta), epsilon_(epsilon), sigma_(sigma), T_h_(T_h), T_add_(T_add), T_del_(T_del) { - cb_ = vector<Entry>(width * height * codebook_size); + cb_ = vector<Entry>(width * height * size_); + for (size_t i = 0; i < cb_.size(); i += size_) { + cb_[i].size = 0; + } } bool CBSegmentation::processPixel(CBSegmentation::Pixel &px, CBSegmentation::Codeword *codeword) { - CBSegmentation::Entry *entry = &cb_[size_ * px.idx]; - CBSegmentation::Entry *const end = &cb_[size_ * px.idx + size_]; - - // pointers to where to place new entries (in preference order) - CBSegmentation::Entry *empty_entry = nullptr; - CBSegmentation::Entry *lru = nullptr; - //CBSegmentation::Entry *lru_h = nullptr; - //CBSegmentation::Entry *lru_m = nullptr; + char &size = cb_[size_ * px.idx].size; + size_t idx_begin = size_ * px.idx + 1; + + CBSegmentation::Entry::Data *start = &(cb_[idx_begin].data); + CBSegmentation::Entry::Data *entry = start; + + CBSegmentation::Entry::Data *lru = nullptr; + CBSegmentation::Entry::Data *lfu = nullptr; - // TODO: possible (micro-)optimization: keep codewords in M, H, EMPTY order + // TODO: benchmark sorting // if value is found (in M or H), loop exits early and no further maintenance - // is done. Maintenance can happen when codeword is not found and all entries + // is done. Maintenance may happen when codeword is not found and all entries // are evaluated. - for (; entry != end; entry++) { + for (int i = 0; i < size; i++) { if (entry->type == M) { // matching codeword, update and return if (entry->cw.brightness(px, alpha_, beta_) && entry->cw.colordiff(px, epsilon_)) { @@ -113,16 +118,19 @@ bool CBSegmentation::processPixel(CBSegmentation::Pixel &px, CBSegmentation::Cod return true; } - // delete if not accessed for longer time than T_del + // delete (move last to here) if not accessed for longer time than T_del if ((px.t - entry->cw.atime()) > T_del_) { - entry->type = EMPTY; - empty_entry = entry; + size--; + *entry = *(start + size); + //std::sort( cb_.begin() + idx_begin, + // cb_.begin() + idx_begin + size, + // CompareEntry()); continue; } - // update LRU - if (!lru || lru->cw.atime() > entry->cw.atime()) { - lru = entry; + // update LFU + if (!lfu || lfu->cw.freq() > entry->cw.freq()) { + lfu = entry; } } else if (entry->type == H) { @@ -133,6 +141,9 @@ bool CBSegmentation::processPixel(CBSegmentation::Pixel &px, CBSegmentation::Cod // should be moved to M? if so, move and return true if ((px.t - entry->cw.ctime()) > T_add_) { entry->type = M; + //std::sort( cb_.begin() + idx_begin, + // cb_.begin() + idx_begin + size, + // CompareEntry()); return true; } else { @@ -140,10 +151,10 @@ bool CBSegmentation::processPixel(CBSegmentation::Pixel &px, CBSegmentation::Cod } } - // delete if lambda gt T_h - if (entry->cw.getLambda() > T_del_) { - entry->type = EMPTY; - empty_entry = entry; + // delete if lambda lt T_h + if (entry->cw.getLambda() < T_h_) { + size--; + *entry = *(start + size); continue; } @@ -152,21 +163,27 @@ bool CBSegmentation::processPixel(CBSegmentation::Pixel &px, CBSegmentation::Cod lru = entry; } } - else { - empty_entry = entry; - } } - // not found, create new codeword (to empty position or lru h/m) - // TODO: should lru be used without prioritization? - if (empty_entry) { - empty_entry->type = H; - empty_entry->cw.set(px); + // not found, create new codeword (to empty position or lru h or lfu m) + // TODO: Should not prefer H codewords over M codewords? + if (size < (size_ - 1)) { + entry = start + size; + size++; + entry->type = H; + entry->cw.set(px); } - else { + else if (lru) { lru->type = H; lru->cw.set(px); } + else { + lfu->type = H; + lfu->cw.set(px); + } + + // sort anyways (frequencies may have changed during earlier iterations) + //std::sort(cb_.begin() + idx_begin, cb_.begin() + idx_begin + size, CompareEntry()); return false; } @@ -177,17 +194,20 @@ void CBSegmentation::apply(Mat &in, Mat &out) { out = Mat(height_, width_, CV_8UC1, cv::Scalar(0)); } + // TODO: thread pool, queue N rows #pragma omp parallel for for (int y = 0; y < height_; ++y) { size_t idx = y * width_; - uchar *ptr = in.ptr<uchar>(y); - for (int x = 0; x < width_; ++x, ++idx, ptr = ptr + 3) { - auto px = Pixel(idx, ptr, 0, t_); + uchar *ptr_in = in.ptr<uchar>(y); + uchar *ptr_out = out.ptr<uchar>(y); + + for (int x = 0; x < width_; ++x, ++idx, ptr_in += 3) { + auto px = Pixel(idx, ptr_in, 0, t_); if(processPixel(px)) { - out.data[idx] = 0; + ptr_out[x] = 0; } else { - out.data[idx] = 255; + ptr_out[x] = 255; } } }