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;
 			}
 		}
 	}