diff --git a/cv-node/src/algorithms/nick1.cu b/cv-node/src/algorithms/nick1.cu
index 7c7702b7fad61bb37c15c678758f945c0907cc20..8858dcecc2f14ee51413ad6e026b9f23028fe72b 100644
--- a/cv-node/src/algorithms/nick1.cu
+++ b/cv-node/src/algorithms/nick1.cu
@@ -161,6 +161,8 @@ __global__ void filter_kernel(cudaTextureObject_t t, cudaTextureObject_t d,
 	}
 }
 
+
+/* Use Prewitt operator */
 __global__ void edge_invar1_kernel(cudaTextureObject_t t, ftl::cuda::TextureObject<float2> o) {
 	for (STRIDE_Y(v,o.height())) {
 		for (STRIDE_X(u,o.width())) {
@@ -175,11 +177,73 @@ __global__ void edge_invar1_kernel(cudaTextureObject_t t, ftl::cuda::TextureObje
 			float a = atan2(gy,gx);
 			
 			// TODO adapt threshold using histeresis
-			o(u,v) = (g > 10.0f) ? make_float2(g,a) : make_float2(NAN,NAN);
+			o(u,v) = (g > 10.0f) ? make_float2(g,abs(a)) : make_float2(NAN,NAN);
 		}	
 	}
 }
 
+__device__ void edge_follow(float &sum, int &count, cudaTextureObject_t i1, int u, int v, int sign) {
+	int u2 = u;
+	int v2 = v;
+	int n = 0;
+	float sumchange = 0.0f;
+	float2 pixel_i1 = tex2D<float2>(i1,u,v);
+
+	for (int j=0; j<10; j++) {
+		// Vertical edge = 0, so to follow it don't move in x
+		int dx = ((pixel_i1.y >= 0.785 && pixel_i1.y <= 2.356) ) ? 0 : 1;
+		int dy = (dx == 1) ? 0 : 1;
+
+		// Check perpendicular to edge to find strongest gradient
+		//if (tex2D<float2>(i1, u2+dy, v2+dx).x < pixel_i1.x && tex2D<float2>(i1, u2-dy, v2-dx).x < pixel_i1.x) {
+			//o(u,v) = pixel_i1.y*81.0f;
+		//} else {
+		//	break;
+		//}
+		//continue;
+		
+		float2 next_pix;
+		next_pix.x = NAN;
+		next_pix.y = NAN;
+		float diff = 10000.0f;
+		int nu, nv;
+		
+		for (int i=-5; i<=5; i++) {
+			float2 pix = tex2D<float2>(i1,u2+dx*i+dy*1, v2+dy*i+dx*1);
+			if (isnan(pix.x)) continue;
+			
+			float d = abs(pix.x-pixel_i1.x)*abs(pix.y-pixel_i1.y);
+			if (d < diff) {
+				nu = u2+dx*i+dy*sign;
+				nv = v2+dy*i+dx*sign;
+				next_pix = pix;
+				diff = d;
+			}
+		}
+		
+		if (!isnan(next_pix.x) && diff < 10.0f) {
+			float change = abs(pixel_i1.y - next_pix.y);
+
+			// Corner or edge change.
+			//if (change > 0.785f) break;
+			if (change > 1.0f) break;
+
+			u2 = nu;
+			v2 = nv;
+			sumchange += change;
+			pixel_i1 = next_pix;
+			n++;
+		} else {
+			//o(u,v) = NAN;
+			break;
+		}
+	}
+
+	//if (n == 0) sum = 0.0f;
+	sum = sumchange;
+	count = n;
+}
+
 __global__ void edge_invar2_kernel(cudaTextureObject_t i1, ftl::cuda::TextureObject<float> o) {
 	for (STRIDE_Y(v,o.height())) {
 		for (STRIDE_X(u,o.width())) {
@@ -189,31 +253,31 @@ __global__ void edge_invar2_kernel(cudaTextureObject_t i1, ftl::cuda::TextureObj
 				o(u,v) = NAN;
 				continue;
 			}
-			
-			int dx = ((pixel_i1.y >= 0.785 && pixel_i1.y <= 2.356) ) ? 0 : 1;
+
+			int dx = ((pixel_i1.y >= 0.785 && pixel_i1.y <= 2.356) ) ? 1 : 0;
 			int dy = (dx == 1) ? 0 : 1;
-			
-			float2 next_pix;
-			next_pix.x = NAN;
-			next_pix.y = NAN;
-			float diff = 10000.0f;
-			
-			for (int i=-10; i<=10; i++) {
-				float2 pix = tex2D<float2>(i1,u+dx*i+dy*2, v+dy*i+dx*2);
-				if (isnan(pix.x)) continue;
-				
-				float d = abs(pix.x-pixel_i1.x)*abs(pix.y-pixel_i1.y);
-				if (d < diff) {
-					next_pix = pix;
-					diff = d;
-				}
+
+			// Check perpendicular to edge to find strongest gradient
+			if (tex2D<float2>(i1, u+dy, v+dx).x < pixel_i1.x && tex2D<float2>(i1, u-dy, v-dx).x < pixel_i1.x) {
+				//o(u,v) = pixel_i1.y*81.0f;
+			} else {
+				o(u,v) = NAN;
+				continue;
 			}
+
+			float sum_a, sum_b;
+			int count_a, count_b;
+			edge_follow(sum_a, count_a, i1, u, v, 1);
+			edge_follow(sum_b, count_b, i1, u, v, -1);
 			
-			if (!isnan(next_pix.x) && diff < 2.0f) {
-				o(u,v) = abs(pixel_i1.y - next_pix.y)*81.0f;
+
+			// Output length of edge
+			if (count_a+count_b > 5) {
+				o(u,v) = ((sum_a+sum_b) / (float)(count_a+count_b)) * 300.0f + 50.0f;
 			} else {
-				o(u,v) = NAN;
+				o(u,v) = 200.0f;
 			}
+			//o(u,v) = (sumchange / (float)(j-1))*100.0f;
 			
 			// Search in two directions for next edge pixel
 			// Calculate curvature by monitoring gradient angle change