從metashape導出深度圖,從深度圖恢復密集點云

從metashape導出深度圖,從深度圖恢復密集點云

1.從metashape導出深度圖

參考:https://blog.csdn.net/WHU_StudentZhong/article/details/123107072?spm=1001.2014.3001.5502

2.從深度圖建立密集點云

首先從metashape導出blockExchange格式的xml文件,里面記錄了相機的內外參等信息
file->export->export camera
下面就開始上代碼

import numpy as np
import xml.etree.ElementTree as ET
import os
import cv2def write_point_cloud(ply_filename, points):formatted_points = []for point in points:formatted_points.append("%f %f %f %d %d %d 0\n" % (point[0], point[1], point[2], point[3], point[4], point[5]))out_file = open(ply_filename, "w")out_file.write('''plyformat ascii 1.0element vertex %dproperty float xproperty float yproperty float zproperty uchar blueproperty uchar greenproperty uchar redproperty uchar alphaend_header%s''' % (len(points), "".join(formatted_points)))out_file.close()def depth_image_to_point_cloud(rgb, depth, scale, K, pose):u = range(0, rgb.shape[1])v = range(0, rgb.shape[0])u, v = np.meshgrid(u, v)u = u.astype(float)v = v.astype(float)Z = depth.astype(float) / scaleX = (u - K[0, 2]) * Z / K[0, 0]Y = (v - K[1, 2]) * Z / K[1, 1]X = np.ravel(X)Y = np.ravel(Y)Z = np.ravel(Z)valid = (Z > 0) & (Z < 300)# 計算 valid 中有效元素的數量valid_count = np.count_nonzero(valid)# 打印結果print("有效元素的數量:", valid_count)X = X[valid]Y = Y[valid]Z = Z[valid]position = np.vstack((X, Y, Z, np.ones(len(X))))position = np.dot(pose, position)R = np.ravel(rgb[:, :, 0])[valid]G = np.ravel(rgb[:, :, 1])[valid]B = np.ravel(rgb[:, :, 2])[valid]points = np.transpose(np.vstack((position[0:3, :], R, G, B))).tolist()return pointsdef getDepth(position,depth, scale, K, pose):inverse_pose = np.linalg.inv(pose)position_camera=np.dot(inverse_pose, position)Z = position_camera[2]*scaleu=round(position_camera[0]*K[0, 0]/Z+K[0, 2])v=round(position_camera[1]*K[1, 1]/Z+K[1, 2])z=depth[v][u]return Z# image_files: XXXXXX.jpg (RGB, 24-bit, jpg)
# depth_files: XXXXXX.tif (32-bit, tif)
# poses: camera-to-world, 4×4 matrix in homogeneous coordinates
def build_point_cloud(K,dist_coeffs, scale, view_ply_in_world_coordinate,images,dataPath):images_path = os.path.join(dataPath, 'undistort')depth_path = os.path.join(dataPath, 'depth')for id, image in images.items():# 獲取文件所在的文件夾路徑image_name=os.path.join(images_path,image['imgName'])depth_name=os.path.join(depth_path,image['imgName'])depth_name=os.path.splitext(depth_name)[0]depth_name = depth_name + '.tif'rgb = cv2.imread(image_name)depth = cv2.imread(depth_name, cv2.IMREAD_UNCHANGED)height, width = depth.shape[:2]# # 創建深度圖畸變映射# mapx, mapy = cv2.initUndistortRectifyMap(K, dist_coeffs, None, None, (width,height), cv2.CV_32FC1)# # 應用映射# depth = cv2.remap(depth, mapx, mapy, interpolation=cv2.INTER_NEAREST)rgb_resized=cv2.resize(rgb,(width, height))# # 創建rgb畸變映射# mapx, mapy = cv2.initUndistortRectifyMap(K, dist_coeffs, None, None, (width,height), cv2.CV_32FC1)# rgb_resized = cv2.remap(rgb_resized, mapx, mapy, interpolation=cv2.INTER_NEAREST)depth_values = depth.astype(np.float32)#顯示深度值范圍print('最小深度值:', np.min(depth_values))print('最大深度值:', np.max(depth_values))if view_ply_in_world_coordinate:current_points_3D = depth_image_to_point_cloud(rgb_resized, depth, scale=scale, K=K, pose=image['trans_M'])else:current_points_3D = depth_image_to_point_cloud(rgb_resized, depth, scale=scale, K=K, pose=image['trans_M'])save_ply_name = os.path.basename(os.path.splitext(image_name)[0]) + ".ply"#save_ply_path = os.path.join(dataPath, "point_clouds_frompoint")save_ply_path = os.path.join(dataPath, "point_clouds_any")if not os.path.exists(save_ply_path):  # 判斷是否存在文件夾如果不存在則創建為文件夾os.mkdir(save_ply_path)write_point_cloud(os.path.join(save_ply_path, save_ply_name), current_points_3D)def compute_K_matrix(focal_length, principal_point_x, principal_point_y):"""計算內參數矩陣 K參數:focal_length:焦距principal_point_x: 主點在 x 方向上的像素坐標principal_point_y: 主點在 y 方向上的像素坐標skew: 像素間的 skew factor,默認為 0返回值:K 矩陣"""K = np.array([[focal_length, 0, principal_point_x],[0, focal_length, principal_point_y],[0, 0, 1]])return Kdef loadAllfrom_xml(path):# 解析 XML 文件doc = ET.parse(path)root = doc.getroot()# 初始化相機和圖像列表cameras = {}images = {}# 查找相機元素photogroups = root.find(".//Photogroups")if photogroups is None:print("error: invalid scene file")return False# 解析相機信息for photogroup in photogroups.findall("Photogroup"):camera_model_type = photogroup.find("CameraModelType")if camera_model_type is None or camera_model_type.text != "Perspective":continueimage_dimensions = photogroup.find("ImageDimensions")if image_dimensions is None:continuewidth = int(image_dimensions.find("Width").text)height = int(image_dimensions.find("Height").text)resolution_scale = max(width, height)focal_length_pixels = photogroup.find("FocalLengthPixels")if focal_length_pixels is not None:f = float(focal_length_pixels.text)else:focal_length = float(photogroup.find("FocalLength").text)sensor_size = float(photogroup.find("SensorSize").text)f = focal_length * resolution_scale / sensor_sizeprincipal_point = photogroup.find("PrincipalPoint")if principal_point is not None:cx = float(principal_point.find("x").text) cy = float(principal_point.find("y").text)pxl_size = 1# 解析畸變參數distortion = photogroup.find("Distortion")k1 = k2 = k3 = p1 = p2 = 0if distortion is not None:k1_elem = distortion.find("K1")if k1_elem is not None:k1 = float(k1_elem.text)k2_elem = distortion.find("K2")if k2_elem is not None:k2 = float(k2_elem.text)k3_elem = distortion.find("K3")if k3_elem is not None:k3 = float(k3_elem.text)p1_elem = distortion.find("P1")if p1_elem is not None:p1 = float(p1_elem.text)p2_elem = distortion.find("P2")if p2_elem is not None:p2 = float(p2_elem.text)  camera = {'width': width, 'height': height, 'f': f, 'cx': cx, 'cy': cy, 'pxlSize': pxl_size,'k1': k1, 'k2': k2, 'k3': k3, 'p1': p2, 'p2': p1}cameras[1] = camera# 解析圖像信息for photo in photogroup.findall("Photo"):img_id = int(photo.find("Id").text)image_path = photo.find("ImagePath").textfound = image_path.rfind("/")img_name = image_path[found + 1:]photo_pose = photo.find("Pose")if photo_pose is None:continuerotation = photo_pose.find("Rotation")if rotation is None:continuerotation_matrix = np.array([[float(rotation.find("M_00").text), float(rotation.find("M_01").text),float(rotation.find("M_02").text)],[float(rotation.find("M_10").text),float(rotation.find("M_11").text), float(rotation.find("M_12").text)],[float(rotation.find("M_20").text), float(rotation.find("M_21").text),float(rotation.find("M_22").text)]])center = photo_pose.find("Center")if center is None:continueXs = float(center.find("x").text)Ys = float(center.find("y").text)Zs = float(center.find("z").text)position= np.array([Xs,Ys,Zs])trans=create_transformation_matrix(rotation_matrix,position)img = {'iid': img_id,'image_path':image_path, 'imgName': img_name,'R':rotation_matrix,'Xs': Xs, 'Ys': Ys, 'Zs': Zs,'trans_M':trans}images[img_id] = imgreturn images, camerasdef create_transformation_matrix(rotation_matrix, translation_vector):# 創建一個 4x4 的單位矩陣transformation_matrix = np.eye(4)transformation_matrix[:3, :3] = rotation_matrix.T#將rotation求逆transformation_matrix[:3, 3] = translation_vectorreturn transformation_matriximages, cameras = loadAllfrom_xml('pos_undistort.xml')
K=compute_K_matrix(cameras[1]['f'],cameras[1]['cx'],cameras[1]['cy'])
dist_coeffs = np.array([cameras[1]['k1'],cameras[1]['k2'], cameras[1]['p1'], cameras[1]['p2'], cameras[1]['k3']])view_ply_in_world_coordinate = True
K=K*0.5
K[2][2]=1build_point_cloud(K,dist_coeffs*0.5,1,view_ply_in_world_coordinate,images,'G:\\graduate2024\\experiment\\test')

需要注意的是,如果深度圖的width height和rgb影像存在一個比例關系scale,則K也需要進行相應的尺度變換,例如,我使用的深度圖長寬是rgb影像的一半,那么我的K乘以了一個0.5
另外由于我的影像已經事先去除了畸變,其畸變系數為0,因此此代碼沒有提供去除影像畸變的部分,需自行添加

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/715173.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/715173.shtml
英文地址,請注明出處:http://en.pswp.cn/news/715173.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

OpenHarmony、HarmonyOS打開編輯 PDF 等操作的三方組件使用教程

項目場景: 隨著數字化時代的發展,PDF 文檔成為廣泛應用于各行業的重要文件格式。為了提高OpenHarmony/HarmonyOS生態系統的功能性和用戶體驗,我們需要一款支持打開、編輯PDF文件的應用程序。 使用戶能夠輕松打開、瀏覽和編輯PDF文件。該應用將充分利用OpenHarmony/HarmonyO…

【NTN 衛星通信】衛星和無人機配合的應用場景

1 場景概述 衛星接入網是一種有潛力的技術&#xff0c;可以為地面覆蓋差地區的用戶提供無處不在的網絡服務。然而&#xff0c;衛星覆蓋范圍對于位于考古或采礦地點內部/被茂密森林覆蓋的村莊/山谷/靠近山丘或大型建筑物的用戶可能很稀疏。因此&#xff0c;涉及衛星接入和無人駕…

HarmonyOS Full SDK的安裝

OpenHarmony的應用開發工具HUAWEI DevEco Studio現在隨著OpenHarmony版本發布而發布,只能在版本發布說明中下載,例如最新版本的OpenHarmony 4.0 Release。對應的需要下載DevEco Studio 4.0 Release,如下圖。 圖片 下載Full SDK主要有兩種方式,一種是通過DevEco Studio下載…

教你用Fiddler捕獲HTTPS請求

安裝Fiddler 這里不特別說明了&#xff0c;網上搜索一大把&#xff0c;根據安裝引導一步步安裝即可。&#xff08;這里采用的是fiddler v4.6&#xff09; 配置Fiddler 1、打開fiddler配置Tools –>Telerik Fiddler Options。 2、打開HTTPS配置項&#xff0c;勾選“Captur…

【程序員養生延壽系列-萬人關注的養生指南 4 】

1.早起一杯溫水&#xff0c;疏通腸胃&#xff0c;補充水分。 2.早十點和下午三點左右活動活動身體&#xff08;運動or健身&#xff09;&#xff0c;放松緊張疲憊的身體&#xff0c;幫助消化&#xff0c;給身體透個氣。 3.每天散步&#xff0c;好處多多&#xff08;減肥健身&a…

ctf_show筆記篇(web入門---爆破)

爆破 21&#xff1a;直接bp抓包跑字典&#xff0c;需base64加密 22&#xff1a;可用工具跑也可用瀏覽器找還可以用網上做好的域名查找去找 23&#xff1a;此題需跑腳本已經附上自寫腳本 最后跑出來六個答案一個一個嘗試得到答案為3j import hashlibm "0123456789qwert…

C++_AVL樹

目錄 1、AVL的概念 2、平衡因子的調整概念 3、AVL樹的插入 3.1 調整平衡因子代碼實現 3.2 右旋操作 3.2 左旋操作 3.3 雙旋-先右旋再左旋 3.4 雙旋-先左旋再右旋 3.5 旋轉操作的小結 4、AVL的驗證與實現 結語 前言&#xff1a; 在C中&#xff0c;AVL樹是在二叉搜索…

2024中國眼博會,山東省眼科醫學技術交流大會

以展帶會&#xff0c;以會促展&#xff0c;展與會有機結合&#xff0c;立足山東打造具全國影響力的眼康產業發展盛會&#xff1b; ——隨著時代的高速發展&#xff0c;科技的進步&#xff0c;現代生活節奏的加快&#xff0c;青少年近視問題日益嚴重&#xff0c;對兒童青少年的…

舊的Spring Security OAuth已停止維護,全面擁抱新解決方案Spring SAS

Spring Authorization Server 替換 Shiro 指引 背景 Spring 團隊正式宣布 Spring Security OAuth 停止維護&#xff0c;該項目將不會再進行任何的迭代 目前 Spring 生態中的 OAuth2 授權服務器是 Spring Authorization Server 已經可以正式生產使用作為 SpringBoot 3.0 的最新…

如何使用naive 做一個模態框的方式

1.我的問題使用了一個table 表格&#xff0c;在表格中設置倆個按鈕 最后做出來的效果 <template><div><h1>測試文件</h1><!-- 表格 --><n-data-table :columns"columns" :data"data" :pagination"pagination" …

Linux內核隊列queue.h

文章目錄 一、簡介二、SLIST單向無尾鏈表2.1 介紹2.2 操作2.3 例子 三、STAILQ單向有尾鏈表四、LIST雙向無尾鏈表五、TAILQ雙向有尾鏈表六、CIRCLEQ循環鏈表七、queue源碼參考 一、簡介 queue.h是一個非常經典的文件&#xff0c;定義了一系列宏的操作&#xff0c;它定義了一系…

筆記72:關于IMU(慣性測量單元)傳感器的作用【不涉及公式推導】

一、IMU傳感器是什么&#xff1a; 慣性測量單元IMU&#xff08;Inertial Measurement Unit&#xff09;是一種使用【加速度計】和【陀螺儀】來測量【物體三軸姿態角&#xff08;空間姿態&#xff09;】的裝置&#xff1b;IMU在坐標系的每個坐標軸上&#xff0c;均安裝有1個陀螺…

90-子集2(回溯算法)

題目 給你一個整數數組 nums &#xff0c;其中可能包含重復元素&#xff0c;請你返回該數組所有可能的子集&#xff08;冪集&#xff09;。 解集 不能 包含重復的子集。返回的解集中&#xff0c;子集可以按 任意順序 排列。 示例 1&#xff1a; 輸入&#xff1a;nums [1,2,2] …

深入理解CSS常見選擇器

標題&#xff1a;深入理解CSS常見選擇器 在CSS中&#xff0c;選擇器是一種強大的工具&#xff0c;用于定位和樣式化HTML文檔中的元素。通過選擇器的靈活運用&#xff0c;我們能夠精準地選擇需要操作的元素&#xff0c;從而實現豐富多彩的頁面布局和設計。本文將重點介紹常見的…

Vue2:用node+express部署Vue項目

一、編譯項目 命令 npm run build執行命令后&#xff0c;我們會在項目文件夾中看到如下生成的文件 二、部署Vue項目 接上一篇&#xff0c;nodeexpress編寫輕量級服務 1、在demo中創建static文件夾 2、將dist目錄中的文件放入static中 3、修改server.js文件 關鍵配置&…

全量知識系統問題及SmartChat給出的答復 之13 解析器+DDD+文法型

Q32. DDD的領域概念和知識系統中設計的解析器之間的關系。 那下面&#xff0c;我們回到前面的問題上來。 前面說到了三種語法解析器&#xff0c;分別是 形式語言的&#xff08;機器或計算機語言&#xff09;、人工語言的和自然語言的。再前面&#xff0c;我們聊到了DDD設計思…

基于java的學生派遣信息管理系統設計開題報告

歡迎添加微信互相交流學習哦&#xff01; 項目源碼&#xff1a;biye2: 畢業設計源碼 一、項目名稱 Java基于學生派遣信息管理系統設計 二、項目背景 隨著科技的發展&#xff0c;互聯網在我國的應用越來越廣泛&#xff0c;尤其是在教育領域。為了能更好地管理學生派遣信息&am…

DayDreamInGIS 之 ArcGIS Pro二次開發 圖層屬性中換行符等特殊字符替換

具體參考ArcMap中類似的問題&#xff0c;本帖開發一個ArcGISPro版的工具 1.基礎庫部分 插件開發&#xff0c;經常需要處理圖層與界面的交互。基礎庫把常用的交互部分做了封裝&#xff0c;方便之后的重復使用。 &#xff08;1&#xff09;下述類定義了數據存儲結構&#xff0…

DFA還原白盒AES密鑰

本期內容是關于某app模擬登錄的,涉及的知識點比較多,有unidbg補環境及輔助還原算法,ida中的md5以及白盒aes,fart脫殼,frida反調試 本章所有樣本及資料均上傳到了123云盤 llb資料官方版下載丨最新版下載丨綠色版下載丨APP下載-123云盤 目錄 首先抓包 fart脫殼 加密位置定位…

0048__Unix傳奇

Unix傳奇 &#xff08;上篇&#xff09;_unix傳奇(上篇)-CSDN博客 Unix傳奇 &#xff08;下篇&#xff09;-CSDN博客 Unix現狀與未來——CSDN對我的采訪_nuix郵件系統行業地位-CSDN博客