3
« Last post by JyunPingJhan on December 05, 2024, 05:56:46 PM »
Hi Alexey
Here is code for local processing, it works fine.
import Metashape
import math
# 計算兩點之間的平面距離
def calculate_distance(point1, point2):
"""計算兩個點之間的平面距離 (忽略 Z 軸)。"""
return (point1.x - point2.x) ** 2 + (point1.y - point2.y) ** 2
# 根據平面坐標 (E, N) 自訂建立 pairs
def custom_pairs(chunk):
"""根據相機標籤與距離條件建立自訂 pairs 列表。"""
cameras = [camera for camera in chunk.cameras if camera.reference.location is not None] # 確保參考位置存在
pairs = []
for i, cam1 in enumerate(cameras):
loc1 = cam1.reference.location
for j, cam2 in enumerate(cameras):
if i >= j: # 避免重複計算和自配對
continue
# 獲取相機參考位置
loc2 = cam2.reference.location
distance = calculate_distance(loc1, loc2)
# 配對規則
if cam1.label.endswith("PL") and distance <= 25:
pairs.append((cam1.key, cam2.key))
elif cam1.label.endswith("PR") and distance <= 25:
pairs.append((cam1.key, cam2.key))
elif cam1.label.endswith("SL"):
if cam2.label.endswith("PL") and distance <= 25:
pairs.append((cam1.key, cam2.key))
elif cam2.label.endswith("PR") and distance <= 25:
pairs.append((cam1.key, cam2.key))
elif cam2.label.endswith("SL") and distance <= 225:
pairs.append((cam1.key, cam2.key))
elif cam2.label.endswith("SR") and distance <= 225:
pairs.append((cam1.key, cam2.key))
elif cam1.label.endswith("SR"):
if cam2.label.endswith("PL") and distance <= 25:
pairs.append((cam1.key, cam2.key))
elif cam2.label.endswith("PR") and distance <= 25:
pairs.append((cam1.key, cam2.key))
elif cam2.label.endswith("SL") and distance <= 225:
pairs.append((cam1.key, cam2.key))
elif cam2.label.endswith("SR") and distance <= 225:
pairs.append((cam1.key, cam2.key))
return pairs
# 主程式
doc = Metashape.app.document
chunk = doc.chunk
# 呼叫自訂配對函數
pairs = custom_pairs(chunk)
print(len(pairs))
print(pairs[0])
chunk.matchPhotos(pairs=pairs, keypoint_limit=5000, tiepoint_limit=5000, generic_preselection=False, reference_preselection=False)
# 執行相機對齊
chunk.alignCameras()
And the following is code for network processing.
import Metashape
import tkinter as tk
from tkinter import messagebox
import subprocess
import math
# 計算兩點之間的平面距離
def calculate_distance(point1, point2):
"""計算兩個點之間的平面距離 (忽略 Z 軸)。"""
return (point1.x - point2.x) ** 2 + (point1.y - point2.y) ** 2
# 根據平面坐標 (E, N) 自訂建立 pairs
def custom_pairs(chunk):
"""根據相機標籤與距離條件建立自訂 pairs 列表。"""
cameras = [camera for camera in chunk.cameras if camera.reference.location is not None] # 確保參考位置存在
pairs = []
for i, cam1 in enumerate(cameras):
loc1 = cam1.reference.location
for j, cam2 in enumerate(cameras):
if i >= j: # 避免重複計算和自配對
continue
# 獲取相機參考位置
loc2 = cam2.reference.location
distance = calculate_distance(loc1, loc2)
# 配對規則
if "PL" in cam1.label and distance <= 25:
pairs.append((cam1.key, cam2.key))
elif "PR" in cam1.label and distance <= 25:
pairs.append((cam1.key, cam2.key))
elif "SL" in cam1.label:
if "PL" in cam2.label and distance <= 25:
pairs.append((cam1.key, cam2.key))
elif "PR" in cam2.label and distance <= 25:
pairs.append((cam1.key, cam2.key))
elif "SL" in cam2.label and distance <= 225:
pairs.append((cam1.key, cam2.key))
elif "SR" in cam2.label and distance <= 225:
pairs.append((cam1.key, cam2.key))
elif "SR" in cam1.label:
if "PL" in cam2.label and distance <= 25:
pairs.append((cam1.key, cam2.key))
elif "PR" in cam2.label and distance <= 25:
pairs.append((cam1.key, cam2.key))
elif "SL" in cam2.label and distance <= 225:
pairs.append((cam1.key, cam2.key))
elif "SR" in cam2.label and distance <= 225:
pairs.append((cam1.key, cam2.key))
return pairs
def align_batch():
root = tk.Tk()
root.withdraw()
response = messagebox.askquestion("確認", "確認執行Batch Align")
if response == 'no':
return
doc = Metashape.app.document
doc.save()
if not doc.chunks:
Metashape.app.messageBox("No chunks in the project!")
return
# 創建 NetworkClient 來與伺服器通信
network_client = Metashape.NetworkClient()
server_ip = "140.118.119.121" # 用實際伺服器的 IP 替換
network_client.connect(server_ip)
# 任務列表
tasks = []
enabled_chunks = []
# 遍歷所有啟用的 chunk,為每個 chunk 創建 MatchPhotos 任務
for chunk in doc.chunks:
if chunk.enabled:
enabled_chunks.append(chunk)
pairs = custom_pairs(chunk) # 呼叫自訂配對函數
#print(pairs[5])
# 創建 MatchPhotos 任務
match_photos_task = Metashape.Tasks.MatchPhotos()
match_photos_task.pairs = pairs
match_photos_task.keypoint_limit = 5000
match_photos_task.tiepoint_limit = 5000
match_photos_task.downscale = 1
match_photos_task.generic_preselection = False
match_photos_task.reference_preselection = True
match_photos_task.filter_mask = True
match_photos_task.mask_tiepoints = False
match_photos_task.filter_stationary_points = False
match_photos_task.guided_matching = False
match_photos_task.reset_matches = True
# 轉換為 NetworkTask 並加入任務列表
network_task = match_photos_task.toNetworkTask(chunk)
tasks.append(network_task)
## 創建 AlignCameras 任務,並將其加入任務列表
align_cameras_task = Metashape.Tasks.AlignCameras()
align_cameras_task.reset_alignment = True # 可以設置其他 AlignCameras 參數
align_cameras_task.adaptive_fitting = False
network_task_align = align_cameras_task.toNetworkTask(enabled_chunks)
tasks.append(network_task_align)
## 使用 createBatch 提交所有任務
project_path = doc.path # 取得當前專案的路徑
batch_id = network_client.createBatch(project_path, tasks) # 提交批次處理
# 開始執行批次處理
network_client.setBatchPaused(batch_id, False)
Metashape.app.quit()
metashape_executable = r"C:\Program Files\Agisoft\Metashape Pro\metashape.exe" # 請根據實際路徑修改
subprocess.Popen([metashape_executable, project_path])
Metashape.app.addMenuItem("PRIDE/B. Batch Align", align_batch)