AutoFTG-Scripts_Metashape-Pro/AutoFTG/autoftg_main.py

826 lines
30 KiB
Python
Raw Normal View History

2023-08-04 19:35:27 +02:00
# AutoFTG - Scripts for Agisoft Metashape Pro
#
# This is an assembly of python scripts for process automation, and some existing scripts from other users
#
# Scripts were written for use in work process on project 2TDK, construction of railroad tunnels in Slovenia,
# but were later modified to support any kind of project where lots of processing is needed.
#
# Author: Boris Bilc
#
# Script repository (GitHub):
# ---------------------------
# URL: https://github.com/bilkos/AutoFTG-Scripts_Metashape-Pro
#
#
# References:
# -----------
#
# Copy Bounding Box Script:
# - https://github.com/agisoft-llc/metashape-scripts/blob/master/src/copy_bounding_box_dialog.py
# Copies bounding boxes from chunk to other chunks.
#
#
# If you add or change resorces (icons, images, etc... in qtresorces.qrc), then you need to re-compile qtresorces.qrc file.
# To do that you need to navigate to script folder and run following command:
#
# pyside2-rcc -o resource.py qtresources.qrc
#
# If you are using VSCode that you can modify and compile UI elements with PySide2-VSC extension.
#
# Scripts are free to use for commercial or non-commercial use.
#
# Please use 'Issues' page in GitHub repository to report any bugs, and suggestions for improvements.
# Link to issues page: https://github.com/bilkos/AutoFTG-Scripts_Metashape-Pro/issues
import os
import pydoc
import shutil
import sys
import time
from configparser import ConfigParser
from datetime import datetime
from os import path
import Metashape
from PySide2 import QtCore, QtGui, QtWidgets
from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *
import AutoFTG.autoftg_batch
import AutoFTG.autoftg_chunkquickadd
import AutoFTG.autoftg_copyregion
import AutoFTG.autoftg_settingscamedit
import AutoFTG.autoftg_settingschunk
import AutoFTG.autoftg_settingsmain
import AutoFTG.qtresources_rc2
from AutoFTG.autoftg_batch import *
from AutoFTG.autoftg_chunkquickadd import *
from AutoFTG.autoftg_copyregion import *
from AutoFTG.autoftg_settingscamedit import *
from AutoFTG.autoftg_settingschunk import *
from AutoFTG.autoftg_settingsmain import *
from AutoFTG.qtresources_rc2 import *
# App info
app_name = "AutoFTG"
app_ver = "2.6.4"
appsettings_ver = "6"
app_author = "Author: Boris Bilc\n\n"
app_repo = "Repository URL:\nhttps://github.com/bilkos/AutoFTG-Scripts_Metashape-Pro"
ref_repo = "Agisoft GitHub repository:\nhttps://github.com/agisoft-llc/metashape-scripts"
ref_scripts = "Copy Bounding Box Script:\nhttps://github.com/agisoft-llc/metashape-scripts/blob/master/src/copy_bounding_box_dialog.py"
app_about = "Scripts for process automation in Agisoft Metashape Pro\n\nThis is an assembly of existing scripts from other users,\nand some additional scripts written for use in work process at project 2TIR, tunnel T8-KP in Slovenia."
# Check compatibility with Metashape
compatible_major_version = "2.0"
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))
projectOpened = False
settingsRebuild = False
selected_data_folder = ''
selected_camera = "No Calibration - Frame (Default)"
selected_pre = ''
selected_suf = ''
selected_menu = ''
# Load icons settings
icoCfg = ConfigParser()
icoCfgFile = 'settings_icons.ini'
icoCfgPath = os.path.expanduser('~\AppData\Local\Agisoft\Metashape Pro\scripts\AutoFTG\\').replace("\\", "/")
icoCfgFilePath = icoCfgPath + icoCfgFile
icons_list = []
def loadIcoSettings():
global icons_list
icoCfgFileExists = os.path.isfile(icoCfgFilePath) # Check if settings file exists
if icoCfgFileExists == False:
icoCfg.add_section("ICONS")
icoCfg.set("ICONS", "ico-0", "icons8-xbox-cross-96.png")
icoCfg.set("ICONS", "ico-1", "icons8-product-documents-50.png")
icoCfg.set("ICONS", "ico-2", "icons8-documents-folder-50-2.png")
icoCfg.set("ICONS", "ico-3", "icons8-documents-folder-50.png")
icoCfg.set("ICONS", "ico-4", "icons8-dossier-50.png")
icoCfg.set("ICONS", "ico-5", "icons8-pictures-folder-50-2.png")
icoCfg.set("ICONS", "ico-6", "icons8-folded-booklet-50.png")
icoCfg.set("ICONS", "ico-7", "icons8-images-folder-50.png")
icoCfg.set("ICONS", "ico-8", "icons8-full-image-50.png")
icoCfg.set("ICONS", "ico-9", "icons8-video-folder-50.png")
icoCfg.set("ICONS", "ico-10", "icons8-ftp-50.png")
icoCfg.set("ICONS", "ico-11", "icons8-web-camera-50.png")
icoCfg.set("ICONS", "ico-12", "icons8-camera-on-tripod-96.png")
icoCfg.set("ICONS", "ico-13", "icons8-sd-50.png")
icoCfg.set("ICONS", "ico-14", "icons8-quadcopter-50.png")
icoCfg.set("ICONS", "ico-15", "icons8-plane-48.png")
icoCfg.set("ICONS", "ico-16", "icons8-national-park-48.png")
icoCfg.set("ICONS", "ico-17", "icons8-ground-48.png")
icoCfg.set("ICONS", "ico-18", "icons8-country-48.png")
icoCfg.set("ICONS", "ico-19", "icons8-subway-50.png")
icoCfg.set("ICONS", "ico-20", "icons8-underground-50.png")
icoCfg.set("ICONS", "ico-21", "icons8-land-surveying-48.png")
icoCfg.set("ICONS", "ico-22", "icons8-drawing-compass-48.png")
icoCfg.set("ICONS", "ico-23", "icons8-camera-50.png")
icoCfg.set("ICONS", "ico-24", "menu_kalota-modra.png")
icoCfg.set("ICONS", "ico-25", "menu_kalota-oranzna.png")
icoCfg.set("ICONS", "ico-26", "template_kalota-modra.png")
icoCfg.set("ICONS", "ico-27", "template_kalota-oranzna.png")
icoCfg.set("ICONS", "ico-28", "template_kalota-rdeca.png")
icoCfg.set("ICONS", "ico-29", "template_kalota-vijola.png")
icoCfg.set("ICONS", "ico-30", "template_kalota-zelena.png")
icoCfg.set("ICONS", "ico-31", "template_stopnica-modra.png")
icoCfg.set("ICONS", "ico-32", "template_stopnica-oranzna.png")
icoCfg.set("ICONS", "ico-33", "template_stopnica-rdeca.png")
icoCfg.set("ICONS", "ico-34", "template_stopnica-vijola.png")
icoCfg.set("ICONS", "ico-35", "template_stopnica-zelena.png")
with open(icoCfgFilePath, 'w') as icoconfig:
camCfg.write(icoconfig)
icoCfgFileExists = True
icoCfg.read(icoCfgFilePath)
icons_list = icoCfg.options("ICONS")
print("Loading chunk definition icons... OK.")
# Load main app settings
appCfg = ConfigParser()
appCfgFile = 'settings_autoftg.ini'
appCfgPath = os.path.expanduser('~\AppData\Local\Agisoft\Metashape Pro\scripts\AutoFTG\\').replace("\\", "/")
appCfgFilePath = appCfgPath + appCfgFile
appCfgFileExists = os.path.isfile(appCfgFilePath) # Check if settings file exists
# Load custom menu settings
menuCfg = ConfigParser()
menuCfgFile = "settings_newchunk.ini"
menuCfgPath = os.path.expanduser('~\AppData\Local\Agisoft\Metashape Pro\scripts\AutoFTG').replace("\\", "/")
menuCfgFilePath = menuCfgPath + "/" + menuCfgFile
menuCfgFilePathExists = os.path.isfile(menuCfgFilePath)
chunk_sections = []
# Init configparser for camera settings. Set empty camera variables for global use.
camCfg = ConfigParser()
cam_name = ''
cam_desc = ''
cam_type = ''
cam_subtype = ''
cam_res = ''
cam_file = ''
cameraXmlSource = ''
cameraXmlDest = ''
camCfgFile = "settings_cam.ini"
camCfgPath = os.path.expanduser('~\AppData\Local\Agisoft\Metashape Pro\scripts\AutoFTG\cameras\\').replace("\\", "/")
camCfgFilePath = camCfgPath + camCfgFile
camCfgFilePathExists = os.path.isfile(camCfgFilePath)
cam_list = []
projCfg = ConfigParser() # INICALIZACIJA NASTAVITEV
def camCfgLoad():
global cam_list
if camCfgFilePathExists == False:
defcam_name = 'No Calibration - Frame (Default)'
defcam_description = 'Default Metashape camera settings for type FRAME. Calibration is calculated On-The-Fly.'
defcam_type = 'Frame'
defcam_subtype = 'Standard'
defcam_resolution = '0'
defcam_file = 'None'
defcam2_name = 'No Calibration - Fisheye'
defcam2_description = 'Default Metashape camera settings for type FISHEYE. Calibration is calculated On-The-Fly.'
defcam2_type = 'Fisheye'
defcam2_subtype = 'Standard'
defcam2_resolution = '0'
defcam2_file = 'None'
camCfg.add_section(defcam_name)
camCfg.set(defcam_name, "description", defcam_description)
camCfg.set(defcam_name, "type", defcam_type)
camCfg.set(defcam_name, "subtype", defcam_subtype)
camCfg.set(defcam_name, "resolution", defcam_resolution)
camCfg.set(defcam_name, "file", defcam_file)
camCfg.add_section(defcam2_name)
camCfg.set(defcam2_name, "description", defcam2_description)
camCfg.set(defcam2_name, "type", defcam2_type)
camCfg.set(defcam2_name, "subtype", defcam2_subtype)
camCfg.set(defcam2_name, "resolution", defcam2_resolution)
camCfg.set(defcam2_name, "file", defcam2_file)
with open(camCfgFilePath, 'w') as camconfigfile:
camCfg.write(camconfigfile)
camCfg.read(camCfgFilePath)
cam_list = camCfg.sections()
print("Camera settings loaded...")
# Read camera settings from INI config file
def readCameraSettings(cam_section):
global cam_name
global cam_desc
global cam_type
global cam_subtype
global cam_res
global cam_file
# Read settings for requested camera
cam_name = cam_section
cam_desc = camCfg.get(cam_section, "Description")
cam_type = camCfg.get(cam_section, "Type")
cam_subtype = camCfg.get(cam_section, "SubType")
cam_res = camCfg.get(cam_section, "Resolution")
cam_file = camCfg.get(cam_section, "File")
print("Using camera\n" + "Name: " + cam_name + "\nDesc.: " + cam_desc + "\nType: " + cam_type + "\nSubType: " + cam_subtype + "\nResolution: " + cam_res + "\nFile: " + cam_file)
# Called to apply camera settings when creating new chunk
def useCameraSettings():
# Init document
doc = Metashape.app.document
chunk = doc.chunk
# readCameraSettings(settings.defaultCamera)
camera_path = camCfgPath + cam_file
# Sensor to which we will apply settings
chunk_sensor = chunk.sensors[0]
# Set sensor type from camera
if cam_type == "Fisheye":
chunk_sensor.type = Metashape.Sensor.Type.Fisheye
elif cam_type == "Frame":
chunk_sensor.type = Metashape.Sensor.Type.Frame
elif cam_type == "Spherical":
chunk_sensor.type = Metashape.Sensor.Type.Spherical
elif cam_type == "Cylindrical":
chunk_sensor.type = Metashape.Sensor.Type.Cylindrical
elif cam_type == "RPC":
chunk_sensor.type = Metashape.Sensor.Type.RPC
else:
Metashape.app.messagBox("Camera Type not recognized.\nPlease check camera settings...")
# Init calibration and import settings from camera calibration file (Metashape XML)
chunk_calib = Metashape.Calibration()
if cam_file != "None":
chunk_calib.load(path=camera_path, format=Metashape.CalibrationFormatXML)
chunk_sensor.user_calib = chunk_calib
# Save document and show message with applied settings
doc.save()
# Metashape.app.messageBox("Camera settings applied.\n\nCamera: " + cam_name + "\nType: " + cam_type + "\nFilename: " + cam_file)
Metashape.app.update()
def selectCamChunk():
camCfgLoad()
diaSelectCamera()
if selected_camera == None:
print("No camera chosen. Using default camera.")
else:
readCameraSettings(selected_camera)
useCameraSettings()
print("\n\nApplied custom camera: " + selected_camera)
# Routine for adding/editing camera configuration
def saveCamConfig(camorig, camname, camdesc, camtype, camsub, camres, camfile):
if camCfg.has_section(camorig) == True:
camCfg.remove_section(camorig)
camCfg.add_section(camname)
camCfg.set(camname, "Description", camdesc)
camCfg.set(camname, "Type", camtype)
camCfg.set(camname, "SubType", camsub)
camCfg.set(camname, "Resolution", camres)
camCfg.set(camname, "File", camfile)
Metashape.app.messageBox("Camera Updated\n\n" + "Name: " + camname + "\nDesc.: " + camdesc + "\nType: " + camtype + "\nSubType: " + camsub + "\nRes.:: " + camres + " MP\nFile: " + camfile)
else:
camCfg.add_section(camname)
camCfg.set(camname, "Description", camdesc)
camCfg.set(camname, "Type", camtype)
camCfg.set(camname, "SubType", camsub)
camCfg.set(camname, "Resolution", camres)
camCfg.set(camname, "File", camfile)
Metashape.app.messageBox("Camera Created\n\n" + "Name: " + camname + "\nDesc.: " + camdesc + "\nType: " + camtype + "\nSubType: " + camsub + "\nRes.:: " + camres + " MP\nFile: " + camfile)
with open(camCfgFilePath, 'w') as configfile:
camCfg.write(configfile)
camCfgLoad()
# Routine for adding/editing camera configuration
def removeCamConfig(camname):
cam_xmlmsg = ''
if camCfg.has_section(camname) == True:
if camCfg.get(camname, "File") != "":
cameraXml = camCfgPath + camCfg.get(camname, "File")
if os.path.isfile(cameraXml):
os.remove(cameraXml)
cam_xmlmsg = "\nXML file " + cameraXml + " deleted."
camCfg.remove_section(camname)
cam_secmsg = "Camera [" + camname + "] removed from settings." + cam_xmlmsg
with open(camCfgFilePath, 'w') as configfile:
camCfg.write(configfile)
camCfgLoad()
Metashape.app.messageBox(cam_secmsg)
else:
Metashape.app.messageBox("Error! No camera named (" + str(camname) + ") was found.\n\nDid you manualy edit comaera configuration?")
def chunksCfgLoad():
global chunk_sections
if menuCfgFilePathExists == False:
menu_section_m = "GENERAL"
menuCfg.add_section(menu_section_m)
menuCfg.set(menu_section_m, "menu_icon", "ico-0")
menuCfg.set(menu_section_m, "chunk_name_format", "metashape")
menuCfg.set(menu_section_m, "chunk_name_prefix", "")
menuCfg.set(menu_section_m, "chunk_name_suffix", "")
menuCfg.set(menu_section_m, "work_folder", str(Metashape.app.getExistingDirectory("Project data folder (batch)")))
menuCfg.set(menu_section_m, "export_folder", str(Metashape.app.getExistingDirectory("Project data export folder (batch)")))
with open(menuCfgFilePath, 'w') as menuconfig:
menuCfg.write(menuconfig)
menuCfg.read(menuCfgFilePath)
chunk_sections = menuCfg.sections()
print("Custom chunk settings loaded...\nFile: " + menuCfgFile)
def appCfgLoad():
global selected_data_folder
global selected_camera
appCfgFileExists = os.path.isfile(appCfgFilePath) # Check if settings file exists
if appCfgFileExists == False:
print("\nSettings initialization...\nPlease choose data folder, and default camera.")
Metashape.app.messageBox("Settings file not found...\nPlease choose default data folder, and default camera.")
foldeData = str(Metashape.app.getExistingDirectory("Working data folder"))
#selectCamDefault()
diaSelectCamera()
appCfg.add_section('APP SETTINGS')
appCfg.set('APP SETTINGS', 'settings_version', appsettings_ver)
appCfg.set('APP SETTINGS', 'folder_data', foldeData)
appCfg.set('APP SETTINGS', 'default_camera', selected_camera)
appCfg.set('APP SETTINGS', 'default_chunk_def', "GENERAL")
# Writing our configuration file to 'example.cfg'
with open(appCfgFilePath, 'w') as configfile:
appCfg.write(configfile)
appCfg.read(appCfgFilePath)
checkSettingsVer()
selected_data_folder = appCfg.get('APP SETTINGS', 'folder_data')
selected_camera = appCfg.get('APP SETTINGS', 'default_camera')
# Project settings initialization (used when .psx project is loaded)
def projCfgLoad():
global settingsRebuild
global projDoc
global projCfgFilePath
global projCfgFilePathExists
global projCfg
global projectOpened
global selected_camera
global selected_data_folder
projDoc = Metashape.app.document
projDocFile = str(projDoc).replace("<Document '", "").replace("'>", "")
projCfgFilePath = projDocFile.replace(".psx", "_settings.ini") # Datoteka z nastavitvami projekta
projCfgFilePathExists = os.path.isfile(projCfgFilePath) # Preveri, če datoteka z projektom obstaja
if projCfgFilePathExists == False:
print("\nProject settings initialization...\nPlease choose data folder, and default camera.")
Metashape.app.messageBox("Settings initialization...\nPlease choose data folder, and default camera.")
proj_data = Metashape.app.getExistingDirectory("Project data folder")
diaSelectCamera()
if projCfg.has_section('PROJECT SETTINGS') == True:
projCfg.remove_section('PROJECT SETTINGS')
projCfg.add_section('PROJECT SETTINGS')
projCfg.set('PROJECT SETTINGS', 'settings_version', appsettings_ver)
projCfg.set('PROJECT SETTINGS', 'folder_data', str(proj_data))
projCfg.set('PROJECT SETTINGS', 'default_camera', selected_camera)
projCfg.set('PROJECT SETTINGS', 'default_chunk_def', "GENERAL")
# Writing our configuration file to 'example.cfg'
with open(projCfgFilePath, 'w') as configfile:
projCfg.write(configfile)
projCfg.read(projCfgFilePath)
checkSettingsVer()
selected_data_folder = projCfg.get('PROJECT SETTINGS', 'folder_data')
selected_camera = projCfg.get('PROJECT SETTINGS', 'default_camera')
selected_chunk_def = projCfg.get('PROJECT SETTINGS', 'default_chunk_def')
readCameraSettings(selected_camera)
projectOpened = True
Metashape.app.messageBox("Project settings loaded.\n\n"
+ "Data Folder: " + str(selected_data_folder) + "\n"
+ "Default Camera: " + str(selected_camera) + "\n"
+ "Def. Chunk Definition: " + str(selected_chunk_def))
# Check settings version
def checkSettingsVer():
global settingsRebuild
if appCfg.get("APP SETTINGS", "settings_version") != appsettings_ver:
settingsReset()
# Reset settings
def settingsReset():
if projectOpened == True:
os.remove(projCfgFilePath)
projCfgLoad()
else:
os.remove(appCfgFilePath)
appCfgLoad()
# Routine to check if project exists before initializing settings
def projectOpenedCheck():
global projectOpened
doc = Metashape.app.document
#fileDoc = str(doc).replace("<Document '", "").replace("'>", "")
if doc == "<Document ''>" or doc == None:
projectOpened = False
appCfgLoad()
Metashape.app.messageBox("Empty project?\n\nSave project first, or open an existing project. (*.psx).")
else:
projectOpened = True
projCfgLoad()
# Show progress of processing
def progress_print(p):
print('Completed: {:.2f}%'.format(p))
# Detect markers and import coords
def marker_targets():
doc = Metashape.app.document
chunk = doc.chunk
netpath = Metashape.app.document.path
netroot = path.dirname(netpath)
nadaljujem = Metashape.app.getBool("Start marker detection?")
if nadaljujem == True:
chunk.detectMarkers(target_type=Metashape.CircularTarget12bit, tolerance=98)
Metashape.app.messageBox("Marker detection finished.\n\nIn next step choose file containing marker coordinates.\n\nFile must contain header, coordinates are expected starting at line 7.")
path_ref = Metashape.app.getOpenFileName("Import coordinates " + chunk.label, netroot, "Text file (*.txt)")
chunk.importReference(path_ref, format=Metashape.ReferenceFormatCSV, columns='nxyz', delimiter=',', skip_rows=6, create_markers=True)
chunk.updateTransform()
Metashape.app.messageBox("Target coordinates imported.\n\nNext step: Workflow > Align Photos")
Metashape.app.update()
doc.save()
# Routine for finding files - used when creating new chunk
def find_files(folder, types):
return [entry.path for entry in os.scandir(folder) if (entry.is_file() and os.path.splitext(entry.name)[1].lower() in types)]
def newchunk_manual(name_prefix, name_suffix, work_folder):
global projectOpened
if projectOpened == True:
doc = Metashape.app.document
# netroot = path.dirname(netpath)
netroot = work_folder
try:
image_folder = Metashape.app.getExistingDirectory("Select data folder", netroot)
except:
print("Add Chunk cancelled...")
else:
photos = find_files(image_folder, [".jpg", ".jpeg", ".png", ".tif", ".tiff"])
chunk = doc.addChunk()
chunk_nameraw = os.path.basename(image_folder)
chunk_name = name_prefix + chunk_nameraw + name_suffix
chunk.label = Metashape.app.getString("Chunk Name", chunk_name)
chunk.addPhotos(photos)
doc.chunk = chunk
doc.save()
Metashape.app.messageBox("New chunk added!\n\nChunk Name: " + chunk_name)
addcalib = Metashape.app.getBool("Confirm to import default camera calibration.\n\nDefault Camera: " + cam_name)
if addcalib == True:
readCameraSettings(selected_camera)
useCameraSettings()
doc.save()
else:
diaSelectCamera()
readCameraSettings(selected_camera)
useCameraSettings()
nadaljujem = Metashape.app.getBool("Camera set...\nUsing Camera: " + str(selected_camera) + "\n\nContinue with marker detection and coordinates import?")
if nadaljujem == True:
chunk.detectMarkers(target_type=Metashape.CircularTarget12bit, tolerance=98)
Metashape.app.messageBox("Marker Detection complete!\n\nNext step: Choose file with target coordinates.\nPoint file must have header.\nImport starts at line 7.")
path_ref = Metashape.app.getOpenFileName("Import Target Coordinates", image_folder, "Text file (*.txt)")
chunk.importReference(path_ref, format=Metashape.ReferenceFormatCSV, columns='nxyz', delimiter=',', skip_rows=6, create_markers=True)
chunk.updateTransform()
Metashape.app.messageBox("Target coordinates imported.\n\nNext step: Workflow > Align Photos")
Metashape.app.update()
doc.save()
else:
projectOpenedCheck()
# Create chunk AUTO - automaticaly use predefined options
def newchunk_auto(name_prefix, name_suffix, work_folder):
global projectOpened
if projectOpened == True:
doc = Metashape.app.document
netpath = Metashape.app.document.path
netroot = work_folder
try:
image_folder = Metashape.app.getExistingDirectory("Select data folder", netroot)
except:
print("Add Chunk cancelled...")
else:
photos = find_files(image_folder, [".jpg", ".jpeg", ".png", ".tif", ".tiff"])
chunk = doc.addChunk()
chunk.addPhotos(photos)
chunk_nameraw = os.path.basename(image_folder)
chunk_name = name_prefix + chunk_nameraw + name_suffix
# chunk.label = Metashape.app.getString("Chunk Name", chunk_name)
chunk.label = chunk_name
doc.chunk = chunk
doc.save(netpath)
Metashape.app.update()
# Metashape.app.messageBox("Nalaganje slik...")
# time.sleep(3)
readCameraSettings(selected_camera)
useCameraSettings()
chunk.detectMarkers(target_type=Metashape.CircularTarget12bit, tolerance=98)
# path_ref = Metashape.app.getOpenFileName("Import marker coordinates", image_folder, "Text file (*.txt)")
points_file = image_folder + "/" + chunk_nameraw + ".txt"
chunk.importReference(points_file, format=Metashape.ReferenceFormatCSV, columns='nxyz', delimiter=',', skip_rows=6, create_markers=True)
chunk.updateTransform()
doc.save(netpath)
Metashape.app.update()
else:
projectOpenedCheck()
# Choose default camera routine
def selectCamDefault():
camCfgLoad()
diaSelectCamera()
if selected_camera == None:
Metashape.app.messageBox("No camera selected. Nothing has changed...")
else:
if projectOpened == True:
projCfg.set('PROJECT SETTINGS', 'default_camera', selected_camera)
with open(projCfgFilePath, 'w') as configfile:
projCfg.write(configfile)
projCfg.read(projCfgFilePath)
else:
appCfg.set('APP SETTINGS', 'default_camera', selected_camera)
with open(appCfgFilePath, 'w') as configfile:
appCfg.write(configfile)
appCfg.read(appCfgFilePath)
print("Default camera settings saved.\nDefault Camera: " + selected_camera)
# Create About message dialog
def appAbout():
app_aboutmsg = app_name + "\n\nVersion: " + app_ver + "\n" + app_author + "\n" + app_about + "\n\n" + app_repo + "\n\nReferences:\n" + ref_repo + "\n\n" + ref_scripts + "\n"
message_box = QMessageBox()
message_box.setMinimumSize(600,500)
message_box.setTextFormat(Qt.PlainText)
message_box.setText(app_aboutmsg)
message_box.exec_()
def prazno():
print("Prazna vrstica")
# Routine for calling Edit Settings UI - called when user want's to edit settings
def editSettings():
app = QtWidgets.QApplication.instance()
parent = app.activeWindow()
editDialog = Ui_settingsDialog(parent)
# Routine for calling Edit Settings UI - called when user want's to edit settings
def addCameraDialog(camnew, camname):
app = QtWidgets.QApplication.instance()
parent = app.activeWindow()
if camnew == False:
dia = Ui_DialogAddEditCam(parent, camnew, camname)
else:
dia = Ui_DialogAddEditCam(parent, camnew, camname="")
# Routine for calling Edit Settings UI - called when user want's to edit settings
def diaSelectCamera():
app = QtWidgets.QApplication.instance()
parent = app.activeWindow()
diaChCam = Ui_dialogChooseCamera(parent)
# Routine for calling Edit Settings UI - called when user want's to edit settings
def camerasEditor():
app = QtWidgets.QApplication.instance()
parent = app.activeWindow()
camEditDialog = Ui_dialogCamGui(parent)
# Routine for calling Copy Regions UI
def copy_bbox():
app = QtWidgets.QApplication.instance()
parent = app.activeWindow()
dlg = CopyBoundingBoxDlg(parent)
def diaAddChunkSingle():
app = QtWidgets.QApplication.instance()
parent = app.activeWindow()
dia = Ui_DialogAddChunkQuick(parent)
def diaAddChunkBatch():
projectOpenedCheck()
app = QtWidgets.QApplication.instance()
parent = app.activeWindow()
dia2 = Ui_DialogBatchChunk(parent)
def diaChunkSettings():
app = QtWidgets.QApplication.instance()
parent = app.activeWindow()
dia_cs = Ui_DialogChunkSettings(parent)
icon_app = ":/icons/AutoFTG-appicon.png"
icon_app2 = ":/icons/AUTOFTG-V2.png"
icon0 = ":/icons/icons8-about-50.png"
iconadd = ":/icons/icons8-add-50.png"
icon2 = ":/icons/icons8-add-camera-50.png"
icon3 = ":/icons/icons8-add-list-50.png"
icon4 = ":/icons/icons8-add-new-50.png"
icon5 = ":/icons/icons8-aperture-50.png"
icon6 = ":/icons/icons8-apps-tab-50.png"
icon7 = ":/icons/icons8-bursts-50.png"
icon8 = ":/icons/icons8-camera-50.png"
icon9 = ":/icons/icons8-cameras-50.png"
icon10 = ":/icons/icons8-cancel-50.png"
icon11 = ":/icons/icons8-christmas-star-50.png"
icon12 = ":/icons/icons8-close-50.png"
icon13 = ":/icons/icons8-close-window-50.png"
icon14 = ":/icons/icons8-design-50.png"
icon15 = ":/icons/icons8-drag-and-drop-50.png"
icon16 = ":/icons/icons8-edit-50.png"
icon17 = ":/icons/icons8-full-page-view-50.png"
icon18 = ":/icons/icons8-images-folder-50.png"
icon19 = ":/icons/icons8-ios-application-placeholder-50.png"
icon20 = ":/icons/icons8-my-location-50.png"
icon21 = ":/icons/icons8-opened-folder-50.png"
icon22 = ":/icons/icons8-overscan-settings-50.png"
icon23 = ":/icons/icons8-panorama-50.png"
icon24 = ":/icons/icons8-quadcopter-50.png"
icon25 = ":/icons/icons8-restore-50.png"
icon26 = ":/icons/icons8-save-50.png"
icon27 = ":/icons/icons8-save-as-50.png"
icon28 = ":/icons/icons8-services-50.png"
icon29 = ":/icons/icons8-settings-50.png"
icon30 = ":/icons/icons8-slr-back-side-50.png"
icon31 = ":/icons/icons8-slr-camera-50.png"
icon32 = ":/icons/icons8-tools-50.png"
icon33 = ":/icons/icons8-video-stabilization-50.png"
icon34 = ":/icons/icons8-video-wall-50.png"
icon35 = ":/icons/icons8-vintage-camera-50.png"
icon36 = ":/icons/icons8-wallpaper-50.png"
icon37 = ":/icons/icons8-web-camera-50.png"
icon38 = ":/icons/icons8-map-marker-50.png"
icon40 = ":/icons/icons8-toolbox-50.png"
iconaddc = ":/icons/icons8-plus-50.png"
iconloads = ":/icons/icons8-share-50.png"
iconimg28 = ":/icons/kalota.png"
iconimg29 = ":/icons/kalota_m.png"
iconimg59 = ":/icons/stopnca_o.png"
iconimg60 = ":/icons/stopnca_s.png"
# Add Main Menu to start with
labelmenu= "About Auto FTG"
Metashape.app.addMenuItem(labelmenu, appAbout, icon=icon_app)
labelAddChSingle = "AutoFTG/Add Chunk (Single)"
Metashape.app.addMenuItem(label=labelAddChSingle, func=diaAddChunkSingle, shortcut="Ctrl++", icon=iconadd)
labelAddChBatch = "AutoFTG/Batch Chunk Creator"
Metashape.app.addMenuItem(label=labelAddChBatch, func=diaAddChunkBatch, shortcut="Ctrl+*", icon=icon4)
labelChSet = "AutoFTG/Chunk Definition Settings"
Metashape.app.addMenuItem(label=labelChSet, func=diaChunkSettings, icon=":/icons/icons8-content-50.png")
labelsep1a = "AutoFTG/--------------------"
Metashape.app.addMenuItem(labelsep1a, prazno)
label3a = "AutoFTG/Detect markers && Import coordinates"
Metashape.app.addMenuItem(label3a, marker_targets, icon=icon38)
label4 = "AutoFTG/Copy Region (Bounding Box)"
Metashape.app.addMenuItem(label4, copy_bbox, icon=icon15)
labelsep1 = "AutoFTG/--------------------"
Metashape.app.addMenuItem(labelsep1, prazno)
label2 = "AutoFTG/Change Camera (Chunk)"
Metashape.app.addMenuItem(label2, selectCamChunk, icon=icon8)
label2aaa = "AutoFTG/Set Default Camera (Project)"
Metashape.app.addMenuItem(label2aaa, selectCamDefault, icon=icon35)
label2cccc = "AutoFTG/Cameras Editor"
Metashape.app.addMenuItem(label2cccc, camerasEditor, icon=icon9)
labelsep55 = "AutoFTG/--------------------"
Metashape.app.addMenuItem(labelsep55, prazno)
labelset2 = "AutoFTG/Load Project Settings"
Metashape.app.addMenuItem(labelset2, projectOpenedCheck, icon=icon40)
labelset4 = "AutoFTG/Edit Loaded Settings"
Metashape.app.addMenuItem(labelset4, editSettings, icon=icon32)
labelset2i = "Load Project Settings"
Metashape.app.addMenuItem(labelset2i, projectOpenedCheck, icon=icon40)
labelAddChQui = "Add Chunk (Single)"
Metashape.app.addMenuItem(label=labelAddChQui, func=diaAddChunkSingle, icon=iconadd)
labelAddChBat = "Add Chunk (Multi)"
Metashape.app.addMenuItem(label=labelAddChBat, func=diaAddChunkBatch, icon=icon4)
labelCopyReg = "Copy Region"
Metashape.app.addMenuItem(labelCopyReg, copy_bbox, icon=icon15)
# labelsep3 = "AutoFTG/New Chunk (2TIR)/--------------------"
# Metashape.app.addMenuItem(labelsep3, prazno)
#
# labelNewStIz = "AutoFTG/New Chunk (2TIR)/STOPNICA (IZKOP) Pefix\Suffix"
# Metashape.app.addMenuSeparator(labelNewStIz)
#
# label0c = "AutoFTG/New Chunk (2TIR)/STOPNICA (IZKOP) Pefix\Suffix/< Modify prefix"
# Metashape.app.addMenuItem(label0c, changeNameStIzPre)
#
# label0d = "AutoFTG/New Chunk (2TIR)/STOPNICA (IZKOP) Pefix\Suffix/> Modify suffix"
# Metashape.app.addMenuItem(label0d, changeNameStIzSuf)
#
# labelNewStBb = "AutoFTG/New Chunk (2TIR)/STOPNICA (B.BET.) Pefix\Suffix"
# Metashape.app.addMenuSeparator(labelNewStBb)
#
# label0f = "AutoFTG/New Chunk (2TIR)/STOPNICA (B.BET.) Pefix\Suffix/< Modify prefix"
# Metashape.app.addMenuItem(label0f, changeNameStBbPre)
#
# label0g = "AutoFTG/New Chunk (2TIR)/STOPNICA (B.BET.) Pefix\Suffix/> Modify suffix"
# Metashape.app.addMenuItem(label0g, changeNameStBbSuf)
# changeChunkAppend(setting_name, append_type)
# labelsep2 = "Cameras"
# Metashape.app.addMenuSeparator(labelsep2)
# labelsep5 = "AutoFTG/--------------------"
# Metashape.app.addMenuItem(labelsep5, prazno)
# Initialize AutoFTG
def loadAutoftg():
global projectOpened
camCfgLoad()
chunksCfgLoad()
loadIcoSettings()
projectOpenedCheck()
checkSettingsVer()
print("\n\nAutoFTG initialized...\nApp Version: " + str(app_ver) + "\nSettings Version: " + str(appCfg.get('APP SETTINGS', 'settings_version')))
print(str(app_author))
# Run
loadAutoftg()