原文鏈接:
https://developer.apple.com/documentation/realitykit/creating_3d_objects_from_photographs
構(gòu)建虛擬物體以用于你的AR體驗嗦随。
概述
要從一系列的照片中創(chuàng)建一個三維物體窖杀,需要使用PhotogrammetrySession將圖像提交給RealityKit奢赂,注冊以接收狀態(tài)更新荣暮,然后啟動會話。這個過程完成之后會產(chǎn)生一個拍攝對象的三維呈現(xiàn)这揣,你可以在你的應(yīng)用程序中使用,或者導(dǎo)出到其他軟件影斑,如Reality Composer给赞。
關(guān)于為攝影測量捕獲高質(zhì)量的圖像的更多信息,請參閱Capturing Photographs for RealityKit Object Capture矫户。
檢查設(shè)備是否可用
RealityKit對象捕捉只適用于滿足執(zhí)行對象重建的最低要求的Mac電腦--包括至少4GB的內(nèi)存--并且擁有支持光線追蹤的GPU片迅。在使用任何Object Capture APIs之前,請檢查你的代碼所運行的計算機是否符合這些要求皆辽,只有在符合這些要求的情況下才可以進行柑蛇。
import Metal
// Checks to make sure at least one GPU meets the minimum requirements
// for object reconstruction. At least one GPU must be a "high power"
// device, which means it has at least 4 GB of RAM, provides
// barycentric coordinates to the fragment shader, and is running on an
// Apple silicon Mac or an Intel Mac with a discrete GPU.
private func supportsObjectReconstruction() -> Bool {
for device in MTLCopyAllDevices() where
!device.isLowPower &&
device.areBarycentricCoordsSupported &&
device.recommendedMaxWorkingSetSize >= UInt64(4e9) {
return true
}
return false
}
// Returns `true` if at least one GPU has hardware support for ray tracing.
// The GPU that supports ray tracing need not be the same GPU that supports
// object reconstruction.
private func supportsRayTracing() -> Bool {
for device in MTLCopyAllDevices() where device.supportsRaytracing {
return true
}
return false
}
// Returns `true` if the current hardware supports Object Capture.
func supportsObjectCapture() -> Bool {
return supportsObjectReconstruction() && supportsRayTracing()
}
func doObjectCapture() {
guard supportsObjectCapture() else {
print("Object capture not available")
return
}
// ...
}
創(chuàng)建攝影測量法會話
首先創(chuàng)建一個PhotogrammetrySession.Request,其URL指向生成的USDZ文件所需的輸出位置和模型所需的細節(jié)級別驱闷。接下來耻台,使用該請求,以及指向包含你的圖像的目錄的URL空另,來創(chuàng)建PhotogrammetrySession對象盆耽。
let inputFolderUrl = URL(fileURLWithPath: "/tmp/MyInputImages/")
let url = URL(fileURLWithPath: "MyObject.usdz")
var request = PhotogrammetrySession.Request.modelFile(url: url,
detail: .full)
guard let session = try PhotogrammetrySession(input: inputFolderUrl) else {
return }
監(jiān)聽更新并開始創(chuàng)建
RealityKit使用PhotogrammetrySession.Output對象的AsyncSequence來在后臺提供關(guān)于對象創(chuàng)建過程的狀態(tài)更新。為了更新你的應(yīng)用程序的用戶界面或采取其他行動作為這些狀態(tài)更新的結(jié)果痹换,創(chuàng)建一個異步任務(wù)并對輸出使用for-try-await循環(huán)征字。
let waiter = async {
do {
for try await output in session.outputs {
switch output {
case .processingComplete:
// RealityKit has processed all requests.
case .requestError(let request, let error):
// Request encountered an error.
case .requestComplete(let request, let result):
// RealityKit has finished processing a request.
case .requestProgress(let request, let fractionComplete):
// Periodic progress update. Update UI here.
case .inputComplete:
// Ingestion of images is complete and processing begins.
case .invalidSample(let id, let reason):
// RealityKit deemed a sample invalid and didn't use it.
case .skippedSample(let id):
// RealityKit was unable to use a provided sample.
case .automaticDownsampling:
// RealityKit downsampled the input images because of
// resource constraints.
case .processingCancelled
// Processing was canceled.
@unknown default:
// Unrecognized output.
}
}
} catch {
print("Output: ERROR = \(String(describing: error))")
// Handle error.
}
}
一旦你創(chuàng)建了一個會話并注冊接收狀態(tài)更新,就可以通過調(diào)用process(request:)啟動對象創(chuàng)建過程娇豫。RealityKit在后臺處理照片匙姜,并在過程完成或失敗時通知你的應(yīng)用程序。
session.process(requests: [request])
補償具有挑戰(zhàn)性的圖像
RealityKit的默認攝影測量設(shè)置對絕大多數(shù)的輸入圖像都有效冯痢。然而氮昧,如果你的圖像集對比度低或缺乏許多可識別的地標框杜,你可以通過創(chuàng)建一個PhotogrammetrySession.Configuration對象并在創(chuàng)建PhotogrammetrySession時將其傳入初始化器來覆蓋默認值以進行補償。
為了簡化對象創(chuàng)建過程袖肥,你可以使用自定義配置咪辱,通過將相鄰的圖像列在一起,依次向PhotogrammetrySession提供圖像椎组,或者控制對對象遮蔽的支持油狂,遮蔽對象周圍圖像的一部分。
let config = Configuration()
// Use slower, more sensitive landmark detection.
config.featureSensitivity = .high
// Adjacent images are next to each other.
config.sampleOrdering = .sequential
// Object masking is enabled.
config.isObjectMaskingEnabled = true
let session = try PhotogrammetrySession(input: inputFolderUrl,
configuration:config)