Forum

Author Topic: Render Image from KeyFrame (moved from Camera Calibration folder)  (Read 6270 times)

Paulo

  • Hero Member
  • *****
  • Posts: 1350
    • View Profile
Hello all,

i am trying to adapt Render_fotos_for_cameras script so as to render from Keyframes present in an animation...

When I run script I get Error: expected Calibration object.

Since a keyframe has no sensor.calibration object, I create a simulated calibration (with 50 mm focal on full format camera).

However, when i use command chunk.model.renderImage(camera.transform, calibration), I get the error that calibration is not Calibration object....

Code: [Select]
def get_cameras(chunk):

    selected_cameras = [camera for camera in chunk.cameras if camera.transform and camera.selected and camera.type == PhotoScan.Camera.Type.Keyframe]


    if len(selected_cameras) > 0:

        return selected_cameras

    else:

        return [camera for camera in chunk.cameras if camera.transform and camera.type == PhotoScan.Camera.Type.Keyframe]

def render_cameras():

    print("Script started...")
   
    # simulates a 50 mm focal 36 mm format camera
   
    sensor = Metashape.Sensor
    sensor.height = 4000
    sensor.width = 6000
    sensor.type = Metashape.Sensor.Type.Frame
    sensor.focal_length = 50
    sensor.pixwl_size = Metashape.Vector( (0.006, 0.006) )
    calibration = Metashape.Calibration
    calibration.f = 50 / 0.006
    calibration.cx = 0
    calibration.cy = 0
    calibration.b1 = 0
    calibration.b2 = 0   
    calibration.k1 = 0
    calibration.k2 = 0
    calibration.k3 = 0
    calibration.k4 = 0
    calibration.p1 = 0
    calibration.p2 = 0
    calibration.width = 4000
    calibration.height = 6000
    calibration.type = Metashape.Sensor.Type.Frame

    doc = PhotoScan.app.document
    chunk = PhotoScan.app.document.chunk

    if not chunk.model:

        raise Exception("No model!")

    num = 0

    for camera in get_cameras(chunk):
   
        render = chunk.model.renderImage(camera.transform, calibration)

        doc_dir = os.path.dirname(doc.path)

        render_filename = "Keyframe" + str(num) + "_render.jpg"

        num += 1

        render.save(os.path.join(doc_dir, render_filename))


    print("Script finished!")

Any help will be welcome!
« Last Edit: July 15, 2019, 05:16:38 PM by Paulo »
Best Regards,
Paul Pelletier,
Surveyor

Paulo

  • Hero Member
  • *****
  • Posts: 1350
    • View Profile
Render Image from KeyFrame (moved from Camera Calibration folder)
« Reply #1 on: July 15, 2019, 06:09:42 PM »
Hello all,

i am trying to adapt Render_fotos_for_cameras script so as to render from Keyframes present in an animation...

When I run script I get Error: expected Calibration object.

Since a keyframe has no sensor.calibration object, I create a simulated calibration (with 50 mm focal on full format camera).

However, when i use command chunk.model.renderImage(camera.transform, calibration), I get the error that calibration is not Calibration object....

Code: [Select]
def get_cameras(chunk):

    selected_cameras = [camera for camera in chunk.cameras if camera.transform and camera.selected and camera.type == PhotoScan.Camera.Type.Keyframe]


    if len(selected_cameras) > 0:

        return selected_cameras

    else:

        return [camera for camera in chunk.cameras if camera.transform and camera.type == PhotoScan.Camera.Type.Keyframe]

def render_cameras():

    print("Script started...")
   
    # simulates a 50 mm focal 36 mm format camera
   
    sensor = Metashape.Sensor
    sensor.height = 4000
    sensor.width = 6000
    sensor.type = Metashape.Sensor.Type.Frame
    sensor.focal_length = 50
    sensor.pixwl_size = Metashape.Vector( (0.006, 0.006) )
    calibration = Metashape.Calibration
    calibration.f = 50 / 0.006
    calibration.cx = 0
    calibration.cy = 0
    calibration.b1 = 0
    calibration.b2 = 0   
    calibration.k1 = 0
    calibration.k2 = 0
    calibration.k3 = 0
    calibration.k4 = 0
    calibration.p1 = 0
    calibration.p2 = 0
    calibration.width = 4000
    calibration.height = 6000
    calibration.type = Metashape.Sensor.Type.Frame

    doc = PhotoScan.app.document
    chunk = PhotoScan.app.document.chunk

    if not chunk.model:

        raise Exception("No model!")

    num = 0

    for camera in get_cameras(chunk):
   
        render = chunk.model.renderImage(camera.transform, calibration)

        doc_dir = os.path.dirname(doc.path)

        render_filename = "Keyframe" + str(num) + "_render.jpg"

        num += 1

        render.save(os.path.join(doc_dir, render_filename))


    print("Script finished!")

Any help will be welcome!
Best Regards,
Paul Pelletier,
Surveyor

Alexey Pasumansky

  • Agisoft Technical Support
  • Hero Member
  • *****
  • Posts: 14968
    • View Profile
Re: Render Image from KeyFrame (moved from Camera Calibration folder)
« Reply #2 on: July 15, 2019, 08:15:47 PM »
Hello Paul,

Does it help if you modify the line of "calibration" variable assignment as following:
Code: [Select]
calibration = Metashape.Calibration()
Also you can remove the lines related to "sensor" variable right before calibration assignment.
Best regards,
Alexey Pasumansky,
Agisoft LLC

Paulo

  • Hero Member
  • *****
  • Posts: 1350
    • View Profile
Re: Render Image from KeyFrame (moved from Camera Calibration folder)
« Reply #3 on: July 15, 2019, 10:59:44 PM »
Alexey,

thanks, now it does create a rendered image from selected keyframe shown in previous screen capture.

However the image is completely black (all r,g,b are 0,0,0)

Attached is rendered image....

Code: [Select]
def render_cameras():

    print("Script started...")
   
    # simulates a 50 mm focal 36 mm format camera
   
    calibration = Metashape.Calibration()
    calibration.f = 50 / 0.006
    calibration.cx = 0
    calibration.cy = 0
    calibration.b1 = 0
    calibration.b2 = 0   
    calibration.k1 = 0
    calibration.k2 = 0
    calibration.k3 = 0
    calibration.k4 = 0
    calibration.p1 = 0
    calibration.p2 = 0
    calibration.width = 6000
    calibration.height = 4000
    calibration.type = Metashape.Sensor.Type.Frame

    doc = PhotoScan.app.document
    chunk = PhotoScan.app.document.chunk

    if not chunk.model:

        raise Exception("No model!")


    for camera in get_cameras(chunk):
   
        render = chunk.model.renderImage(camera.transform, calibration)

        doc_dir = os.path.dirname(doc.path)

        render_filename = "Keyframe" + str(camera.key) + "_render.jpg"

        render.save(os.path.join(doc_dir, render_filename))


    print("Script finished!")
Best Regards,
Paul Pelletier,
Surveyor

Paulo

  • Hero Member
  • *****
  • Posts: 1350
    • View Profile
Re: Render Image from KeyFrame (moved from Camera Calibration folder)
« Reply #4 on: July 16, 2019, 06:15:24 AM »
I got it!, Alexey,

it seems that for keyframe transform, you need to multiply it by Metashape.Matrix().Diag([1, -1, -1, 1]) before applying the transform to RenderImage command as in:

Code: [Select]
    for camera in get_cameras(chunk):

        M = camera.transform * Metashape.Matrix().Diag([1, -1, -1, 1])
 
        render = chunk.model.renderImage(M, calibration)

        doc_dir = os.path.dirname(doc.path)

        render_filename = "Keyframe" + str(camera.key) + "_render.jpg"

        render.save(os.path.join(doc_dir, render_filename))

see attached screen capture...

I think that contrary to normal camera transforms, the Y and Z axis do not have to be inverted when dealing with Keyframe type
« Last Edit: July 16, 2019, 06:40:04 AM by Paulo »
Best Regards,
Paul Pelletier,
Surveyor

jkova96

  • Full Member
  • ***
  • Posts: 146
    • View Profile
Re: Render Image from KeyFrame (moved from Camera Calibration folder)
« Reply #5 on: August 27, 2023, 09:59:10 PM »
Hi, to all of you.
I have Agisoft, version 1.8 and here's script suitable for task:
Code: [Select]
# Script save model renders for selected cameras (or all aligned cameras if no aligned cameras selected)
# to the same folder where the source photos are present with the "_render" suffix.
#
# This is python script for Metashape Pro. Scripts repository: https://github.com/agisoft-llc/metashape-scripts

import Metashape
import os

# Checking compatibility
compatible_major_version = "1.8"
found_major_version = ".".join(Metashape.app.version.split('.')[:2])
if found_major_version != compatible_major_version:
    raise Exception("Incompatible Metashape version: {} != {}".format(found_major_version, compatible_major_version))


def get_cameras(chunk):
    selected_cameras = [camera for camera in chunk.cameras if camera.transform and camera.selected and camera.type == Metashape.Camera.Type.Regular]

    if len(selected_cameras) > 0:
        return selected_cameras
    else:
        return [camera for camera in chunk.cameras if camera.transform and camera.type == Metashape.Camera.Type.Regular]


def render_cameras():
    print("Script started...")

    chunk = Metashape.app.document.chunk
    if not chunk.model:
        raise Exception("No model!")

    for camera in get_cameras(chunk):
        if not camera.type == Metashape.Camera.Type.Regular: #skip camera track, if any
            continue

        render = chunk.model.renderImage(camera.transform, camera.sensor.calibration)

        photo_dir = os.path.dirname(camera.photo.path)
        photo_filename = os.path.basename(camera.photo.path)
        render_filename = os.path.splitext(photo_filename)[0] + "_render.jpg"

        render.save(os.path.join(photo_dir, render_filename))

    print("Script finished!")


label = "Scripts/Render photos for cameras"
Metashape.app.addMenuItem(label, render_cameras)
print("To execute this script press {}".format(label))

You can change to 2.0 if you have that version.
I found this useful code on github, here's the link: https://github.com/agisoft-llc/metashape-scripts/blob/master/src/render_photos_for_cameras.py

Bye :)