Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender-addons.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Leger <stephen@3dservices.ch>2017-04-15 19:22:52 +0300
committerStephen Leger <stephen@3dservices.ch>2017-04-17 14:38:05 +0300
commit5641a9e0d61951714afeed609a2e787d0a2c1068 (patch)
tree61d1fa7c33435cf92231f2361a425d2722807f15 /space_clip_editor_refine_solution.py
parente924519f44a16cabf6c17a0e7852ed07c3907175 (diff)
Initial release
Diffstat (limited to 'space_clip_editor_refine_solution.py')
-rw-r--r--space_clip_editor_refine_solution.py197
1 files changed, 197 insertions, 0 deletions
diff --git a/space_clip_editor_refine_solution.py b/space_clip_editor_refine_solution.py
new file mode 100644
index 00000000..baed13fc
--- /dev/null
+++ b/space_clip_editor_refine_solution.py
@@ -0,0 +1,197 @@
+# -*- coding:utf-8 -*-
+
+# ***** GPL LICENSE BLOCK *****
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+# All rights reserved.
+# ***** GPL LICENSE BLOCK *****
+
+bl_info = {
+ "name": "Refine tracking solution",
+ "author": "Stephen Leger",
+ "license": "GPL",
+ "version": (1, 1, 1),
+ "blender": (2, 7, 8),
+ "location": "Clip Editor > Tools > Solve > Refine Solution",
+ "description": "Refine motion solution by setting track weight according reprojection error",
+ "warning": "",
+ "wiki_url": "https://github.com/s-leger/blenderTracking/wiki",
+ "tracker_url": "https://github.com/s-leger/blenderTracking/issues",
+ "support": "COMMUNITY",
+ "category": "Tools",
+}
+
+import bpy
+import math
+from mathutils import Vector
+
+class OP_Tracking_refine_solution(bpy.types.Operator):
+ """Set track weight by error and solve camera motion"""
+ bl_idname = "tracking.refine_solution"
+ bl_label = "Refine"
+ bl_options = {"UNDO"}
+
+ @classmethod
+ def poll(cls, context):
+ return (context.area.spaces.active.clip is not None)
+
+ def execute(self, context):
+ error = context.window_manager.TrackingTargetError
+ smooth = context.window_manager.TrackingSmooth
+ clip = context.area.spaces.active.clip
+ try:
+ tracking = clip.tracking
+ tracks = tracking.tracks
+ winx = float(clip.size[0])
+ winy = float(clip.size[1])
+ aspy = 1.0 / tracking.camera.pixel_aspect
+ start = tracking.reconstruction.cameras[0].frame
+ end = tracking.reconstruction.cameras[-1].frame
+ except:
+ return {'CANCELED'}
+
+ marker_position = Vector()
+
+ for frame in range(start, end):
+ camera = tracking.reconstruction.cameras.find_frame(frame)
+ if camera is not None:
+ imat = camera.matrix.inverted()
+ projection_matrix = imat.transposed()
+ else:
+ continue
+
+ for track in tracking.tracks:
+ marker = track.markers.find_frame(frame)
+ if marker is None:
+ continue
+
+ # weight incomplete tracks on start and end
+ if frame > start + smooth and frame < end - smooth:
+ for m in track.markers:
+ if not m.mute:
+ tstart = m.frame
+ break
+ for m in reversed(track.markers):
+ if not m.mute:
+ tend = m.frame
+ break
+ dt = min(0.5 * (tend - tstart), smooth)
+ if dt > 0:
+ t0 = min(1.0, (frame - tstart) / dt)
+ t1 = min(1.0, (tend - frame) / dt)
+ tw = min(t0, t1)
+ else:
+ tw = 0.0
+ else:
+ tw = 1.0
+
+ reprojected_position = track.bundle * projection_matrix
+ if reprojected_position.z == 0:
+ track.weight = 0
+ track.keyframe_insert("weight", frame=frame)
+ continue
+ reprojected_position = reprojected_position / -reprojected_position.z * tracking.camera.focal_length_pixels
+ reprojected_position = Vector((tracking.camera.principal[0] + reprojected_position[0],tracking.camera.principal[1] * aspy + reprojected_position[1], 0))
+
+ marker_position[0] = (marker.co[0] + track.offset[0]) * winx
+ marker_position[1] = (marker.co[1] + track.offset[1]) * winy * aspy
+
+ dp = marker_position - reprojected_position
+ if dp.length == 0:
+ track.weight = 1.0
+ else:
+ track.weight = min(1.0, tw * error / dp.length)
+ track.keyframe_insert("weight", frame=frame)
+
+
+ bpy.ops.clip.solve_camera()
+ return{'FINISHED'}
+
+class OP_Tracking_reset_solution(bpy.types.Operator):
+ """Reset track weight and solve camera motion"""
+ bl_idname = "tracking.reset_solution"
+ bl_label = "Reset"
+ bl_options = {"UNDO"}
+
+ @classmethod
+ def poll(cls, context):
+ return (context.area.spaces.active.clip is not None)
+
+ def execute(self, context):
+ clip = context.area.spaces.active.clip
+ try:
+ tracking = clip.tracking
+ tracks = tracking.tracks
+ start = tracking.reconstruction.cameras[0].frame
+ end = tracking.reconstruction.cameras[-1].frame
+ except:
+ return {'CANCELED'}
+ start = tracking.reconstruction.cameras[0].frame
+ end = tracking.reconstruction.cameras[-1].frame
+ for frame in range(start, end):
+ camera = tracking.reconstruction.cameras.find_frame(frame)
+ if camera is None:
+ continue
+ for track in tracking.tracks:
+ marker = track.markers.find_frame(frame)
+ if marker is None:
+ continue
+ track.weight = 1.0
+ track.keyframe_insert("weight", frame=frame)
+ bpy.ops.clip.solve_camera()
+ return{'FINISHED'}
+
+class RefineMotionTrackingPanel(bpy.types.Panel):
+ bl_label = "Refine solution"
+ bl_space_type = "CLIP_EDITOR"
+ bl_region_type = "TOOLS"
+ bl_category = "Solve"
+
+ @classmethod
+ def poll(cls, context):
+ return (context.area.spaces.active.clip is not None)
+
+ def draw(self, context):
+ layout = self.layout
+ box = layout.box()
+ row = box.row(align=True)
+ row.label("Refine")
+ row = box.row(align=True)
+ row.prop(context.window_manager, "TrackingTargetError", text="Target error")
+ row = box.row(align=True)
+ row.prop(context.window_manager, "TrackingSmooth", text="Smooth transition")
+ row = box.row(align=True)
+ row.operator("tracking.refine_solution")
+ row.operator("tracking.reset_solution")
+
+def register():
+ bpy.types.WindowManager.TrackingTargetError = bpy.props.FloatProperty(
+ name="error",
+ description="Refine motion track target error",
+ default=0.3,
+ min=0.01)
+ bpy.types.WindowManager.TrackingSmooth = bpy.props.FloatProperty(
+ name="Smooth transition",
+ description="Smooth weight transition on start and end of incomplete tracks",
+ default=25,
+ min=1)
+ bpy.utils.register_module(__name__)
+
+def unregister():
+ bpy.utils.unregister_module(__name__)
+ del bpy.types.WindowManager.TrackingTargetError
+ del bpy.types.WindowManager.TrackingSmooth
+
+if __name__ == "__main__":
+ register() \ No newline at end of file