[PYTHON] Add-on that sketches the range specified by the annotation of the image editor

In the previous article Script about Blender camera operation A script that makes the specified range of the image displayed in the image editor a sketch of the camera I organized it a little and made it an add-on. Annotation to bound panel is added to the image tab. image.png Can you see that the area where the annotation line is drawn is the sketch of the camera? The rendering resolution is also specified in the specified range of resolutions.

This is a very niche feature in itself If you apply it, you may be able to use it in an interesting way.

CropBG_Annotate.py


bl_info = {
    "name" : "Crop image from Annotation",
    "author" : "Yukimituki",
    "description" : "",
    "blender" : (2, 80, 0),
    "version" : (0, 0, 1),
    "location" : "",
    "warning" : "",
    "category" : "Generic"
}

import bpy
import os
from bpy.types import (
        PropertyGroup,
        )

class IMAGE_PT_Annotatebound(bpy.types.Panel):
    bl_idname = "annotation_to_bound.panel"
    bl_label = "Annotation to bound"
    bl_space_type = "IMAGE_EDITOR"
    bl_region_type = "UI"
    bl_category = "Image"
    #Definition of drawing
    def draw(self, context):
        layout = self.layout
        row = layout.row()
        row.operator("action.crop_stroke_bound")

class IMAGE_OT_Stroke(bpy.types.Operator):
    '''Crop the range specified by the annotation'''
    bl_idname = "action.crop_stroke_bound"
    bl_label = "get_stroke"
    def execute(self, context):
        scene = context.scene
        #Get annotation line
        strokes = context.annotation_data.layers.active.active_frame.strokes
        #Annotations are filtered because some are used for 3D views and some are used for 3D views.
        strokes_2d = [ s for s in strokes if s.display_mode == '2DSPACE']
        bbox_2d = self.get_stroke_bound( strokes_2d )

        #Get information on the displayed image
        img = context.space_data.image
        #Set the sketch image of the camera
        crop_size = self.set_cameraBG(context, img, bbox_2d)
        #Rendering image size settings
        scene.render.resolution_x = crop_size[0]
        scene.render.resolution_y = crop_size[1]
        return {'FINISHED'}
        
    def get_stroke_bound(self, strokes):
        '''Get a range of annotations'''
        x_list = []
        y_list = []
        for stroke in strokes:
            x_list += [pos.co[0] for pos in stroke.points]
            y_list += [pos.co[1] for pos in stroke.points]
        bbox = [min(x_list),min(y_list), max(x_list), max(y_list)]
        return(bbox)
    def set_cameraBG(self, context, image_object, bbox):
        '''Set camera background'''
        #Get camera information
        camera = context.scene.camera
        camera.data.show_background_images = True

        #Sketch image settings
        bg_image = camera.data.background_images.new()
        bg_image.image = image_object
        bg_size = image_object.size

        #Setting the display range of the sketch
        bg_image.frame_method = 'CROP'
        crop_size = [(bbox[2] -bbox[0])*bg_size[0], (bbox[3] -bbox[1])*bg_size[1]]
        #Cut out the background trim by putting it in the frame based on the larger one compared to the ratio of the background image.
        if bg_size[0] * crop_size[0] > bg_size[1] * crop_size[1]:
            bg_scale = bg_size[0] / crop_size[0]
        else:
            bg_scale = bg_size[1] / crop_size[1]
        bg_image.scale = bg_scale
        #Set the center position of the sketch
        bg_image.offset = ((bbox[0] + bbox[2] -1) *-0.5 *bg_scale, (bbox[1]+ bbox[3] -1) *-0.5 *bg_scale) 
        return( crop_size )

classes = (
    IMAGE_PT_Annotatebound,
    IMAGE_OT_Stroke,
    )

#####################################
def register():
    for cls in classes:
        bpy.utils.register_class(cls)
    #bpy.app.translations.register(__name__, translation_dict)   #Dictionary registration


def unregister():
    #bpy.app.translations.unregister(__name__)   #Delete dictionary
    for cls in reversed(classes):
        bpy.utils.unregister_class(cls)


if __name__ == "__main__":
    register()
#######################################

Recommended Posts

Add-on that sketches the range specified by the annotation of the image editor
[Python] Specify the range from the image by dragging the mouse
Get the image of "Suzu Hirose" by Google image search.
Judging the victory or defeat of Shadowverse by image recognition
A story that is a little addicted to the authority of the directory specified by expdp (for beginners)
[Image recognition] How to read the result of automatic annotation with VoTT
The result of making the first thing that works with Python (image recognition)