[Bf-extensions-cvs] [e924519] master: Initial release

Stephen Leger noreply at git.blender.org
Mon Apr 17 13:38:32 CEST 2017


Commit: e924519f44a16cabf6c17a0e7852ed07c3907175
Author: Stephen Leger
Date:   Sat Apr 15 18:16:41 2017 +0200
Branches: master
https://developer.blender.org/rBAe924519f44a16cabf6c17a0e7852ed07c3907175

Initial release

===================================================================

A	space_clip_editor_autotracker.py

===================================================================

diff --git a/space_clip_editor_autotracker.py b/space_clip_editor_autotracker.py
new file mode 100644
index 0000000..56c2bca
--- /dev/null
+++ b/space_clip_editor_autotracker.py
@@ -0,0 +1,348 @@
+bl_info = {
+    "name": "Autotrack",
+    "author": "Miika Puustinen, Matti Kaihola",
+    "version": (0, 0, 95),
+    "blender": (2, 78, 0),
+    "location": "Movie clip Editor > Tools Panel > Autotrack",
+    "description": "Motion Tracking with automatic feature detection.",
+    "warning": "",
+    "wiki_url": "https://github.com/miikapuustinen/blender_autotracker",
+    "category": "Motion Tracking",
+    }
+
+
+import bpy
+import math
+
+
+class AutotrackerOperator(bpy.types.Operator):
+    """Autotrack. Esc to cancel."""
+    bl_idname = "wm.modal_timer_operator"
+    bl_label = "Modal Timer Operator"
+
+    limits = bpy.props.IntProperty(default=0)
+    _timer = None
+
+    def active_clip(self):
+        area = [i for i in bpy.context.screen.areas if i.type == 'CLIP_EDITOR'][0]
+        clip = area.spaces.active.clip.name
+        return clip
+
+    # DETECT FEATURES
+    def auto_features(self, delete_threshold, limits):
+        tracks = []
+        selected = []
+        old = []
+        to_delete = []
+
+        bpy.ops.clip.select_all(action='DESELECT')
+
+        # Detect Features
+        bpy.ops.clip.detect_features(
+            threshold=bpy.context.scene.autotracker_props.df_threshold,
+            min_distance=bpy.context.scene.autotracker_props.df_distance,
+            margin=bpy.context.scene.autotracker_props.df_margin,
+            placement=bpy.context.scene.autotracker_props.placement_list
+            )
+
+        current_frame = bpy.context.scene.frame_current
+
+        tracks = bpy.data.movieclips[self.active_clip()].tracking.tracks
+        for track in tracks:
+            if track.markers.find_frame(current_frame) is not None:
+                if track.select is not True and track.hide is False and track.markers.find_frame(current_frame).mute is False:
+                    old.append(track)
+                if track.select is True:
+                    selected.append(track)
+
+        # Select overlapping new markers
+        for i in selected:
+            for j in old:
+                i_marker = i.markers.find_frame(current_frame)
+                j_marker = j.markers.find_frame(current_frame)
+                distance = math.sqrt(((i_marker.co[0] - j_marker.co[0])**2) + ((i_marker.co[1] - j_marker.co[1])**2))
+
+                if distance < delete_threshold:
+                    to_delete.append(i)
+                    break
+
+        # delete short tracks
+        for track in tracks:
+            muted = []
+            active = []
+            # print(track)
+            for marker in track.markers:
+                if marker.mute is True:
+                    muted.append(marker)
+                else:
+                    active.append(marker)
+            if len(muted) > 3 and len(active) < 1:
+                to_delete.append(track)
+
+            if len(track.markers) > 1 and len(active) == 0:
+                to_delete.append(track)
+
+        # Delete Overlapping Markers
+        bpy.ops.clip.select_all(action='DESELECT')
+        for track in tracks:
+            if track in to_delete:
+                track.select = True
+
+        bpy.ops.clip.delete_track()
+
+        print(str(len(selected)) + "/" + str(len(tracks)) + " tracks tracking.")
+
+    # AUTOTRACK FRAMES
+    def track_frames_backward(self):
+        bpy.ops.clip.track_markers(backwards=True, sequence=False)
+
+    def track_frames_forward(self):
+        bpy.ops.clip.track_markers(backwards=False, sequence=False)
+
+    # REMOVE BAD MARKERS
+    def remove_extra(self, jump_cut, track_backwards):
+        trackers = []
+
+        if track_backwards is True:
+            one_frame = -1
+            two_frames = -2
+        else:
+            one_frame = 1
+            two_frames = 2
+
+        if self.limits >= 3:
+            trackers = bpy.data.movieclips[self.active_clip()].tracking.tracks
+
+            for i in trackers:
+                if len(i.markers) > 5:
+                    current_frame = bpy.context.scene.frame_current
+
+                    if (i.markers.find_frame(current_frame) is not None and
+                        i.markers.find_frame(current_frame - one_frame) is not None and
+                       i.markers.find_frame(current_frame - two_frames) is not None):
+
+                        key_frame = i.markers.find_frame(current_frame).co
+                        prev_frame = i.markers.find_frame(current_frame - one_frame).co
+                        distance = math.sqrt(((key_frame[0] - prev_frame[0])**2) + ((key_frame[1] - prev_frame[1])**2))
+                        # Jump Cut threshold
+                        if distance > jump_cut:
+                            if (i.markers.find_frame(current_frame) is not None and
+                               i.markers.find_frame(current_frame - one_frame) is not None):
+
+                                # create new track to new pos
+                                new_track = \
+                                    bpy.data.movieclips[self.active_clip()].tracking.tracks.new(frame=current_frame)
+                                new_track.markers[0].co = i.markers.find_frame(current_frame).co
+                                i.markers.find_frame(current_frame).mute = True
+                                i.markers.find_frame(current_frame - one_frame).mute = True
+
+    def modal(self, context, event):
+        scene = bpy.context.scene
+        if (event.type in {'ESC'} or scene.frame_current == scene.frame_end + 1 or
+           scene.frame_current == scene.frame_start - 1):
+            self.limits = 0
+            self.cancel(context)
+            return {'FINISHED'}
+
+        if event.type == 'TIMER':
+
+            # PROP VARIABLES
+            delete_threshold = bpy.context.scene.autotracker_props.delete_threshold
+            endframe = bpy.context.scene.frame_end
+            start_frame = bpy.context.scene.frame_start
+            frame_separate = bpy.context.scene.autotracker_props.frame_separation
+            margin = bpy.context.scene.autotracker_props.df_margin
+            distance = bpy.context.scene.autotracker_props.df_distance
+            threshold = bpy.context.scene.autotracker_props.df_threshold
+            jump_cut = bpy.context.scene.autotracker_props.jump_cut
+            track_backwards = bpy.context.scene.autotracker_props.track_backwards
+
+            # Auto features every frame separate step
+            if bpy.context.scene.frame_current % frame_separate == 0 or self.limits == 0:
+                limits = self.limits
+                self.auto_features(delete_threshold, limits)
+
+            # Select all trackers for tracking
+            select_all = bpy.ops.clip.select_all(action='SELECT')
+            tracks = bpy.data.movieclips[self.active_clip()].tracking.tracks
+            active_tracks = []
+            for track in tracks:
+                if track.lock is True:
+                    track.select = False
+                else:
+                    active_tracks.append(track)
+
+            # Forwards or backwards tracking
+            if track_backwards is True:
+                if len(active_tracks) == 0:
+                    print("No new tracks created. Doing nothing.")
+                    self.limits = 0
+                    self.cancel(context)
+                    return {'FINISHED'}
+                else:
+                    self.track_frames_backward()
+            else:
+                if len(active_tracks) == 0:
+                    print("No new tracks created. Doing nothing.")
+                    self.limits = 0
+                    self.cancel(context)
+                    return {'FINISHED'}
+                else:
+                    self.track_frames_forward()
+
+            # Remove bad tracks
+            self.remove_extra(jump_cut, track_backwards)
+
+            self.limits += 1
+
+        return {'PASS_THROUGH'}
+
+    def execute(self, context):
+        wm = context.window_manager
+        self._timer = wm.event_timer_add(time_step=0.5, window=context.window)
+        wm.modal_handler_add(self)
+        return {'RUNNING_MODAL'}
+
+    def cancel(self, context):
+        wm = context.window_manager
+        wm.event_timer_remove(self._timer)
+
+
+# UI CREATION #
+
+class Autotracker_UI(bpy.types.Panel):
+    """Creates a Panel in the Render Layer properties window"""
+    bl_label = "Autotrack"
+    bl_idname = "autotrack"
+    bl_space_type = 'CLIP_EDITOR'
+    bl_region_type = 'TOOLS'
+    bl_category = "Track"
+
+    # Draw UI
+    def draw(self, context):
+        layout = self.layout
+
+        row = layout.row(align=True)
+        row.scale_y = 1.5
+
+        props = row.operator("wm.modal_timer_operator", text="Autotrack!     ", icon='PLAY')
+
+        row = layout.row(align=True)
+        row.prop(context.scene.autotracker_props, "track_backwards")
+
+        row = layout.row(align=True)  # make next row
+        row.prop(context.scene.autotracker_props, "delete_threshold")
+
+        row = layout.row(align=True)
+        row.prop(context.scene.autotracker_props, "frame_separation", text="Frame Separation")
+
+        row = layout.row(align=True)
+        row.prop(context.scene.autotracker_props, "jump_cut", text="Jump Threshold")
+
+        row = layout.row(align=True)
+        row.label(text="Detect Features Settings:")
+
+        row = layout.row(align=True)
+        row.prop(context.scene.autotracker_props, "df_margin", text="Margin:")
+
+        row = layout.row(align=True)
+        row.prop(context.scene.autotracker_props, "df_threshold", text="Threshold:")
+
+        row = layout.row(align=True)
+        row.prop(context.scene.autotracker_props, "df_distance", text="Distance:")
+
+        row = layout.row(align=True)
+        row.label(text="Feature Placement:")
+
+        row = layout.row(align=True)
+        row.prop(context.scene.autotracker_props, "placement_list")
+
+
+class AutotrackerSettings(bpy.types.PropertyGroup):
+    """Create properties"""
+    df_margin = bpy.props.IntProp

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-extensions-cvs mailing list