[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [58872] branches/soc-2011-tomato/source/ blender/compositor: Replace crappy custom sampler with EWA one

Sergey Sharybin sergey.vfx at gmail.com
Sat Aug 3 21:53:24 CEST 2013


Revision: 58872
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=58872
Author:   nazgul
Date:     2013-08-03 19:53:24 +0000 (Sat, 03 Aug 2013)
Log Message:
-----------
Replace crappy custom sampler with EWA one

Our sampler could be useful for more general usage,
like simpler downsampling in scale node, but it needs
to be improved before it's really useful.

It was giving lots of jittering artifacts which isn't
good for motion tracking. So now image wrap operation
used EWA filtering.

For now, it uses copy-pasted dx/dy calculation which
came from MapUV operation. Ideally we need to get
rid of duplicated code, but it's not so trivial for
now because of UV coordinates are calculating in
different ways. Not a big deal to have duplicated
code for a while.

Modified Paths:
--------------
    branches/soc-2011-tomato/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cpp
    branches/soc-2011-tomato/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.h
    branches/soc-2011-tomato/source/blender/compositor/operations/COM_DownsampleOperation.cpp
    branches/soc-2011-tomato/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.cpp

Modified: branches/soc-2011-tomato/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cpp
===================================================================
--- branches/soc-2011-tomato/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cpp	2013-08-03 19:53:16 UTC (rev 58871)
+++ branches/soc-2011-tomato/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.cpp	2013-08-03 19:53:24 UTC (rev 58872)
@@ -36,58 +36,11 @@
 	#include "BKE_tracking.h"
 }
 
-static int getLengthInPixels(float v1[2], float v2[2], int width, int height)
-{
-	float dx = fabsf(v2[0] - v1[0]) * width;
-	float dy = fabsf(v2[1] - v1[1]) * height;
-
-	return sqrtf(dx * dx + dy * dy);
-}
-
 PlaneTrackDeformNode::PlaneTrackDeformNode(bNode *editorNode) : Node(editorNode)
 {
 	/* pass */
 }
 
-bool PlaneTrackDeformNode::getDownsampleDimensions(MovieClip *movieClip, NodePlaneTrackDeformData *data, int frame_number,
-                                                   float *downsample_width_r, float *downsample_height_r)
-{
-	bool do_downsample = false;
-
-	*downsample_width_r = 0.0f;
-	*downsample_height_r = 0.0f;
-
-	if (movieClip) {
-		MovieTracking *tracking = &movieClip->tracking;
-		MovieTrackingObject *object = BKE_tracking_object_get_named(tracking, data->tracking_object);
-		if (object) {
-			MovieTrackingPlaneTrack *plane_track =
-				BKE_tracking_plane_track_get_named(tracking, object, data->plane_track_name);
-
-			if (plane_track) {
-				MovieClipUser user = {0};
-				int width, height;
-				int clip_framenr = BKE_movieclip_remap_scene_to_clip_frame(movieClip, frame_number);
-				MovieTrackingPlaneMarker *plane_marker =
-					BKE_tracking_plane_marker_get(plane_track, clip_framenr);
-
-				BKE_movieclip_user_set_frame(&user, frame_number);
-				BKE_movieclip_get_size(movieClip, &user, &width, &height);
-
-				*downsample_width_r = max_ff(getLengthInPixels(plane_marker->corners[0], plane_marker->corners[1], width, height),
-				                             getLengthInPixels(plane_marker->corners[2], plane_marker->corners[3], width, height));
-				*downsample_height_r = max_ff(getLengthInPixels(plane_marker->corners[1], plane_marker->corners[2], width, height),
-				                              getLengthInPixels(plane_marker->corners[0], plane_marker->corners[3], width, height));
-
-				/* Only do downsample if both dimensions are smaller */
-				do_downsample = *downsample_width_r < width && *downsample_height_r < height;
-			}
-		}
-	}
-
-	return do_downsample;
-}
-
 void PlaneTrackDeformNode::convertToOperations(ExecutionSystem *graph, CompositorContext *context)
 {
 	InputSocket *input_image = this->getInputSocket(0);
@@ -112,21 +65,7 @@
 		warp_image_operation->setPlaneTrackName(data->plane_track_name);
 		warp_image_operation->setFramenumber(frame_number);
 
-		float downsample_width, downsample_height;
-		if (getDownsampleDimensions(clip, data, frame_number, &downsample_width, &downsample_height)) {
-			DownsampleOperation *downsample_operation = new DownsampleOperation();
-			downsample_operation->setNewWidth(downsample_width);
-			downsample_operation->setNewHeight(downsample_height);
-			downsample_operation->setKeepAspect(true);
-
-			input_image->relinkConnections(downsample_operation->getInputSocket(0), 0, graph);
-			addLink(graph, downsample_operation->getOutputSocket(), warp_image_operation->getInputSocket(0));
-			graph->addOperation(downsample_operation);
-		}
-		else {
-			input_image->relinkConnections(warp_image_operation->getInputSocket(0), 0, graph);
-		}
-
+		input_image->relinkConnections(warp_image_operation->getInputSocket(0), 0, graph);
 		output_warped_image->relinkConnections(warp_image_operation->getOutputSocket());
 
 		graph->addOperation(warp_image_operation);

Modified: branches/soc-2011-tomato/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.h
===================================================================
--- branches/soc-2011-tomato/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.h	2013-08-03 19:53:16 UTC (rev 58871)
+++ branches/soc-2011-tomato/source/blender/compositor/nodes/COM_PlaneTrackDeformNode.h	2013-08-03 19:53:24 UTC (rev 58872)
@@ -32,10 +32,6 @@
  * @ingroup Node
  */
 class PlaneTrackDeformNode : public Node {
-protected:
-	bool getDownsampleDimensions(MovieClip *movieClip, NodePlaneTrackDeformData *data, int frame_number,
-	                             float *downsample_width_r, float *downsample_height_r);
-
 public:
 	PlaneTrackDeformNode(bNode *editorNode);
 	void convertToOperations(ExecutionSystem *graph, CompositorContext *context);

Modified: branches/soc-2011-tomato/source/blender/compositor/operations/COM_DownsampleOperation.cpp
===================================================================
--- branches/soc-2011-tomato/source/blender/compositor/operations/COM_DownsampleOperation.cpp	2013-08-03 19:53:16 UTC (rev 58871)
+++ branches/soc-2011-tomato/source/blender/compositor/operations/COM_DownsampleOperation.cpp	2013-08-03 19:53:24 UTC (rev 58872)
@@ -103,8 +103,9 @@
 {
 	rcti newInput;
 
-	float width_ratio = (float) readOperation->getWidth() / this->m_newWidth,
-	      height_ratio = (float) readOperation->getHeight() / this->m_newHeight;
+	/* TODO(sergey): This might be wrong, in some tests tiles were missing. */
+	float width_ratio = (float) readOperation->getWidth() / this->getWidth(),
+	      height_ratio = (float) readOperation->getHeight() / this->getHeight();
 
 	newInput.xmin = input->xmin * width_ratio - 1;
 	newInput.ymin = input->ymin * height_ratio - 1;

Modified: branches/soc-2011-tomato/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.cpp
===================================================================
--- branches/soc-2011-tomato/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.cpp	2013-08-03 19:53:16 UTC (rev 58871)
+++ branches/soc-2011-tomato/source/blender/compositor/operations/COM_PlaneTrackWarpImageOperation.cpp	2013-08-03 19:53:24 UTC (rev 58872)
@@ -34,11 +34,34 @@
 	#include "BKE_tracking.h"
 }
 
+BLI_INLINE bool isPointInsideQuad(const float x, const float y, const float corners[4][2])
+{
+	float point[2];
+
+	point[0] = x;
+	point[1] = y;
+
+	return isect_point_tri_v2(point, corners[0], corners[1], corners[2]) ||
+	       isect_point_tri_v2(point, corners[0], corners[2], corners[3]);
+}
+
+BLI_INLINE void resolveUV(const float x, const float y, const float corners[4][2], float uv[2])
+{
+	float point[2];
+
+	point[0] = x;
+	point[1] = y;
+
+	/* Use reverse bilinear to get UV coordinates within original frame */
+	resolve_quad_uv(uv, point, corners[0], corners[1], corners[2], corners[3]);
+}
+
 PlaneTrackWarpImageOperation::PlaneTrackWarpImageOperation() : PlaneTrackCommonOperation()
 {
 	this->addInputSocket(COM_DT_COLOR, COM_SC_NO_RESIZE);
 	this->addOutputSocket(COM_DT_COLOR);
 	this->m_pixelReader = NULL;
+	this->setComplex(true);
 }
 
 void PlaneTrackWarpImageOperation::initExecution()
@@ -55,7 +78,6 @@
 
 void PlaneTrackWarpImageOperation::executePixel(float output[4], float x, float y, PixelSampler sampler)
 {
-	float point[2];
 	float frame_space_corners[4][2];
 
 	for (int i = 0; i < 4; i++) {
@@ -63,23 +85,62 @@
 		frame_space_corners[i][1] = this->m_corners[i][1] * this->getHeight();
 	}
 
-	point[0] = x;
-	point[1] = y;
+	if (isPointInsideQuad(x, y, frame_space_corners)) {
+		float inputUV[2];
+		float uv_a[2], uv_b[2];
+		float u, v;
 
-	if (isect_point_tri_v2(point, frame_space_corners[0], frame_space_corners[1], frame_space_corners[2]) ||
-	    isect_point_tri_v2(point, frame_space_corners[0], frame_space_corners[2], frame_space_corners[3]))
-	{
-		/* Use reverse bilinear to get UV coordinates within original frame
-		 * Shall we consider using inverse homography transform here?
-		 */
-		float uv[2];
-		resolve_quad_uv(uv, point, frame_space_corners[0], frame_space_corners[1], frame_space_corners[2], frame_space_corners[3]);
+		float dx, dy;
+		float uv_l, uv_r;
+		float uv_u, uv_d;
 
-		float source_x = uv[0] * this->m_pixelReader->getWidth(),
-		      source_y = uv[1] * this->m_pixelReader->getHeight();
+		resolveUV(x, y, frame_space_corners, inputUV);
 
-		/* Force to bilinear filtering */
-		this->m_pixelReader->read(output, source_x, source_y, COM_PS_BILINEAR);
+		/* adaptive sampling, red (U) channel */
+		resolveUV(x - 1, y, frame_space_corners, uv_a);
+		resolveUV(x + 1, y, frame_space_corners, uv_b);
+		uv_l = fabsf(inputUV[0] - uv_a[0]);
+		uv_r = fabsf(inputUV[0] - uv_b[0]);
+
+		dx = 0.5f * (uv_l + uv_r);
+
+		/* adaptive sampling, green (V) channel */
+		resolveUV(x, y - 1, frame_space_corners, uv_a);
+		resolveUV(x, y + 1, frame_space_corners, uv_b);
+		uv_u = fabsf(inputUV[1] - uv_a[1]);
+		uv_d = fabsf(inputUV[1] - uv_b[1]);
+
+		dy = 0.5f * (uv_u + uv_d);
+
+		/* more adaptive sampling, red and green (UV) channels */
+		resolveUV(x - 1, y - 1, frame_space_corners, uv_a);
+		resolveUV(x - 1, y + 1, frame_space_corners, uv_b);
+		uv_l = fabsf(inputUV[0] - uv_a[0]);
+		uv_r = fabsf(inputUV[0] - uv_b[0]);
+		uv_u = fabsf(inputUV[1] - uv_a[1]);
+		uv_d = fabsf(inputUV[1] - uv_b[1]);
+
+		dx += 0.25f * (uv_l + uv_r);
+		dy += 0.25f * (uv_u + uv_d);
+
+		resolveUV(x + 1, y - 1, frame_space_corners, uv_a);
+		resolveUV(x + 1, y + 1, frame_space_corners, uv_b);
+		uv_l = fabsf(inputUV[0] - uv_a[0]);
+		uv_r = fabsf(inputUV[0] - uv_b[0]);
+		uv_u = fabsf(inputUV[1] - uv_a[1]);
+		uv_d = fabsf(inputUV[1] - uv_b[1]);
+
+		dx += 0.25f * (uv_l + uv_r);
+		dy += 0.25f * (uv_u + uv_d);
+
+		/* should use mipmap */
+		dx = min(dx, 0.2f);
+		dy = min(dy, 0.2f);
+
+		u = inputUV[0] * this->m_pixelReader->getWidth();
+		v = inputUV[1] * this->m_pixelReader->getHeight();
+
+		this->m_pixelReader->read(output, u, v, dx, dy, COM_PS_NEAREST);
 	}
 	else {
 		zero_v4(output);




More information about the Bf-blender-cvs mailing list