diff --git a/lib/libstereo/include/stereo.hpp b/lib/libstereo/include/stereo.hpp
index 4c802da27d7e98228436bde624e1724501fe5492..4070a0d2716f575d1b1cb3c8b32e75950226580c 100644
--- a/lib/libstereo/include/stereo.hpp
+++ b/lib/libstereo/include/stereo.hpp
@@ -77,6 +77,7 @@ public:
 					AggregationDirections::VERTICAL |
 					AggregationDirections::DIAGONAL;
 		bool debug = false;
+		CensusPattern pattern = CensusPattern::STANDARD;
 	};
 	Parameters params;
 
@@ -87,7 +88,8 @@ private:
 
 /**
  * Mean reference pixel. Doesn't work since detail is lost form reference
- * 
+ *
+ * @see "Froba, B., Ernst, A. "Face detection with the modified census transform," In: Sixth IEEE International Conference on Automatic Face and Gesture Recognition. IEEE Computer Society Press, Los Alamitos (2004)."
  * @see "A robust local census-based stereo matching insensitive to illumination changes" (2012)
  * @see "A stereo matching algorithm based on four-moded census and relative confidence plane fitting" (2015)
  * @see "Stereo matching based on improved census transform" (2018)
@@ -218,6 +220,7 @@ public:
 		/** variance window size */
 		int var_window = 9;
 		bool debug = false;
+		CensusPattern pattern = CensusPattern::STANDARD;
 	};
 	Parameters params;
 
diff --git a/lib/libstereo/include/stereo_types.hpp b/lib/libstereo/include/stereo_types.hpp
index fc57ddcf960f647c2bae5d356a29963d37fdde9d..6eb259b9d447432178e7fb731b127ef592053df3 100644
--- a/lib/libstereo/include/stereo_types.hpp
+++ b/lib/libstereo/include/stereo_types.hpp
@@ -18,4 +18,10 @@ enum AggregationDirections : int {
 	ALL = HORIZONTAL+VERTICAL+DIAGONAL,
 };
 
+enum class CensusPattern {
+	STANDARD,
+	GENERALISED,
+	STAR
+};
+
 #endif
diff --git a/lib/libstereo/middlebury/main.cpp b/lib/libstereo/middlebury/main.cpp
index ec40c620eda82d7bff143da3a7fa82f2c96a9e75..40cd2ec4ab92b134ac92dece58f75204d9f8fd48 100644
--- a/lib/libstereo/middlebury/main.cpp
+++ b/lib/libstereo/middlebury/main.cpp
@@ -27,6 +27,20 @@ static void run_censussgm(MiddleburyData &data, cv::Mat &disparity) {
 	stereo.compute(data.imL, data.imR, disparity);
 }
 
+static void run_gcensussgm(MiddleburyData &data, cv::Mat &disparity) {
+	auto stereo = StereoCensusSgm();
+	stereo.params.P1 = 12;
+	stereo.params.P2 = 32;
+
+	stereo.params.d_min = data.calib.vmin;
+	stereo.params.d_max = data.calib.vmax;
+	stereo.params.subpixel = 1;
+	stereo.params.lr_consistency = true;
+	stereo.params.debug = false;
+	stereo.params.pattern = CensusPattern::GENERALISED;
+	stereo.compute(data.imL, data.imR, disparity);
+}
+
 static void run_meancensussgm(MiddleburyData &data, cv::Mat &disparity) {
 	auto stereo = StereoMeanCensusSgm();
 	stereo.params.P1 = 12;
@@ -79,6 +93,20 @@ static void run_hcensussgm(MiddleburyData &data, cv::Mat &disparity) {
 	stereo.compute(data.imL, data.imR, disparity);
 }
 
+static void run_hgcensussgm(MiddleburyData &data, cv::Mat &disparity) {
+	auto stereo = StereoHierCensusSgm();
+	stereo.params.P1 = 12*3;
+	stereo.params.P2 = 32*3;
+
+	stereo.params.d_min = data.calib.vmin;
+	stereo.params.d_max = data.calib.vmax;
+	stereo.params.subpixel = 1;
+	stereo.params.lr_consistency = true;
+	stereo.params.debug = false;
+	stereo.params.pattern = CensusPattern::GENERALISED;
+	stereo.compute(data.imL, data.imR, disparity);
+}
+
 static void run_cpcensussgm(MiddleburyData &data, cv::Mat &disparity) {
 	auto stereo = StereoCPCensusSgm();
 	stereo.params.P1 = 12;
@@ -207,6 +235,8 @@ static const std::map<std::string, std::function<void(MiddleburyData&, cv::Mat&)
 	{ "wcensussgm", run_wcensussgm },
 	{ "brefcensus", run_brefcensussgm },
 	{ "mcensussgm", run_meancensussgm },
+	{ "gcensussgm", run_gcensussgm },
+	{ "hgcensussgm", run_hgcensussgm },
 	//{ "misgm", run_misgm },
 	{ "varcensus", run_varcensus },
 	{ "stablesgm", run_stablesgm },
diff --git a/lib/libstereo/src/algorithms/censussgm.cu b/lib/libstereo/src/algorithms/censussgm.cu
index 8661ec3a994809e31081cb1e176280aa9cedb9f2..fb229bf668d0b60f40dcad82d9f616a720cf451e 100644
--- a/lib/libstereo/src/algorithms/censussgm.cu
+++ b/lib/libstereo/src/algorithms/censussgm.cu
@@ -25,6 +25,7 @@ void StereoCensusSgm::compute(cv::InputArray l, cv::InputArray r, cv::OutputArra
 
 	mat2gray(l, impl_->l);
 	mat2gray(r, impl_->r);
+	impl_->cost.setPattern(params.pattern);
 	impl_->cost.set(impl_->l, impl_->r);
 
 	cudaSafeCall(cudaDeviceSynchronize());
diff --git a/lib/libstereo/src/algorithms/hcensussgm.cu b/lib/libstereo/src/algorithms/hcensussgm.cu
index 27b61fd3d58c7952948fae1ae58b206ca4316661..e8c8b000b890a9256413436ca90b1cf7fc579676 100644
--- a/lib/libstereo/src/algorithms/hcensussgm.cu
+++ b/lib/libstereo/src/algorithms/hcensussgm.cu
@@ -4,6 +4,7 @@
 #include "../costs/dual.hpp"
 #include <opencv2/cudawarping.hpp>
 #include <opencv2/cudafilters.hpp>
+#include <opencv2/highgui.hpp>
 
 typedef MultiCostsWeighted<CensusMatchingCost,3> MatchingCost;
 
@@ -104,6 +105,10 @@ void StereoHierCensusSgm::compute(cv::InputArray l, cv::InputArray r, cv::Output
     variance_mask(coarse_l.toGpuMat(), var_coarse, params.var_window);
     cv::cuda::normalize(var_coarse, var_coarse, params.alpha, params.beta, cv::NORM_MINMAX, -1);
 
+    cv::Mat tmp;
+    var_fine.download(tmp);
+    cv::imshow("Var", tmp);
+
 	// CT
     impl_->cost_fine.set(impl_->l, impl_->r);
     impl_->cost_medium.set(impl_->l, impl_->r, medium_l, medium_r);
diff --git a/lib/libstereo/src/costs/census.cu b/lib/libstereo/src/costs/census.cu
index 0ede41478453ca1fb06f646a3525652f17707c13..60cdfbaff3026bc5da73f639bf7b052e7118c5fa 100644
--- a/lib/libstereo/src/costs/census.cu
+++ b/lib/libstereo/src/costs/census.cu
@@ -180,13 +180,25 @@ namespace algorithms {
 }
 
 void CensusMatchingCost::set(const Array2D<uchar> &l, const Array2D<uchar> &r) {
-	parallel2D<algorithms::CensusTransformRowMajor<9,7>>({l.data(), ct_l_.data()}, l.width, l.height);
-	parallel2D<algorithms::CensusTransformRowMajor<9,7>>({r.data(), ct_r_.data()}, r.width, r.height);
+	if (pattern_ == CensusPattern::STANDARD) {
+		parallel2D<algorithms::CensusTransformRowMajor<9,7>>({l.data(), ct_l_.data()}, l.width, l.height);
+		parallel2D<algorithms::CensusTransformRowMajor<9,7>>({r.data(), ct_r_.data()}, r.width, r.height);
+	} else if (pattern_ == CensusPattern::GENERALISED) {
+		parallel2D<algorithms::GCensusTransformRowMajor<9,7>>({l.data(), ct_l_.data()}, l.width, l.height);
+		parallel2D<algorithms::GCensusTransformRowMajor<9,7>>({r.data(), ct_r_.data()}, r.width, r.height);
+	} else {
+		// TODO: 
+	}
 }
 
 void CensusMatchingCost::set(const Array2D<uchar> &l, const Array2D<uchar> &r, const Array2D<uchar> &hl, const Array2D<uchar> &hr) {
-	parallel2D<algorithms::HCensusTransformRowMajor<9,7>>({l.data(), hl.data(), ct_l_.data(), {ushort(hl.width), ushort(hl.height)}}, l.width, l.height);
-	parallel2D<algorithms::HCensusTransformRowMajor<9,7>>({r.data(), hr.data(), ct_r_.data(), {ushort(hr.width), ushort(hr.height)}}, r.width, r.height);
+	if (pattern_ == CensusPattern::STANDARD) {
+		parallel2D<algorithms::HCensusTransformRowMajor<9,7>>({l.data(), hl.data(), ct_l_.data(), {ushort(hl.width), ushort(hl.height)}}, l.width, l.height);
+		parallel2D<algorithms::HCensusTransformRowMajor<9,7>>({r.data(), hr.data(), ct_r_.data(), {ushort(hr.width), ushort(hr.height)}}, r.width, r.height);
+	} else if (pattern_ == CensusPattern::GENERALISED) {
+		parallel2D<algorithms::HGCensusTransformRowMajor<9,7>>({l.data(), hl.data(), ct_l_.data(), {ushort(hl.width), ushort(hl.height)}}, l.width, l.height);
+		parallel2D<algorithms::HGCensusTransformRowMajor<9,7>>({r.data(), hr.data(), ct_r_.data(), {ushort(hr.width), ushort(hr.height)}}, r.width, r.height);
+	}
 }
 
 void CensusMatchingCost::set(cv::InputArray l, cv::InputArray r) {
diff --git a/lib/libstereo/src/costs/census.hpp b/lib/libstereo/src/costs/census.hpp
index 24f6364ec21630f9653dc4cbbaceeba2bf3e972d..2b811923133653a95bbbf58585fabd473fad3db9 100644
--- a/lib/libstereo/src/costs/census.hpp
+++ b/lib/libstereo/src/costs/census.hpp
@@ -4,6 +4,7 @@
 #include <opencv2/core/core.hpp>
 #include "array2d.hpp"
 #include "dsbase.hpp"
+#include <stereo_types.hpp>
 
 #include <cuda_runtime.h>
 namespace impl {
@@ -162,6 +163,8 @@ public:
 			data().r = ct_r_.data();
 		}
 
+	inline void setPattern(CensusPattern p) { pattern_ = p; }
+
 	void set(cv::InputArray l, cv::InputArray r);
 	void set(const Array2D<uchar>& l, const Array2D<uchar>& r);
 	void set(const Array2D<uchar> &l, const Array2D<uchar> &r, const Array2D<uchar> &hl, const Array2D<uchar> &hr);
@@ -170,6 +173,7 @@ public:
 protected:
 	Array2D<uint64_t> ct_l_;
 	Array2D<uint64_t> ct_r_;
+	CensusPattern pattern_ = CensusPattern::STANDARD;
 };
 
 class WeightedCensusMatchingCost : public DSBase<impl::WeightedCensusMatchingCost<11, 5>> {