gpt4 book ai didi

ios - 如何在 Swift 中对 simd_float4x4 元素数组进行编码(将 simd_float4x4 转换为数据)?

转载 作者:行者123 更新时间:2023-12-05 09:08:15 29 4
gpt4 key购买 nike

我正在构建一个从 iPhone TrueDepth 相机捕获面部跟踪数据的应用。

我需要将此数据写入文件,以便将其用作另一个应用程序的基础。

在应用程序中,数据被保存到四个单独的数组中,一个包含 ARFaceGeometry 对象,另外三个具有变换坐标作为 simd_float4x4 矩阵。

我正在使用 archivedData(withRootObject: requiringSecureCoding:) 将数组转换为 Data 对象,然后对它们调用 write(to:) 以创建文件。

包含 ARFaceGeometry 数据的文件被正确写入和读回。但是三个 simd_float4x4 数组并没有被写入,尽管这样做的代码是相同的。连同我的打印日志,给出的错误是“无法识别的选择器发送到实例”。

属性:

var faceGeometryCapture = [ARFaceGeometry]()
var faceTransformCapture = [simd_float4x4]()
var leftEyeTransformCapture = [simd_float4x4]()
var rightEyeTransformCapture = [simd_float4x4]()

var faceGeometryCaptureFilePath: URL!
var faceTransformCaptureFilePath: URL!
var leftEyeTransformCaptureFilePath: URL!
var rightEyeTransformCaptureFilePath: URL!

建立文件URL的代码:

let fileManager = FileManager.default
let dirPaths = fileManager.urls(for: .documentDirectory,
in: .userDomainMask)

faceGeometryCaptureFilePath = dirPaths[0].appendingPathComponent("face-geometries.txt")
faceTransformCaptureFilePath = dirPaths[0].appendingPathComponent("face-transforms.txt")
leftEyeTransformCaptureFilePath = dirPaths[0].appendingPathComponent("left-eye-transforms.txt")
rightEyeTransformCaptureFilePath = dirPaths[0].appendingPathComponent("right-eye-transforms.txt")

将数据写入文件的代码:

do {
let data = try NSKeyedArchiver.archivedData(withRootObject: faceGeometryCapture, requiringSecureCoding: false)
try data.write(to: faceGeometryCaptureFilePath)
} catch { print("Error writing face geometries to file") }
do {
let data = try NSKeyedArchiver.archivedData(withRootObject: faceTransformCapture, requiringSecureCoding: false)
try data.write(to: faceTransformCaptureFilePath)
} catch { print("Error writing face transforms to file") }
do {
let data = try NSKeyedArchiver.archivedData(withRootObject: leftEyeTransformCapture, requiringSecureCoding: false)
try data.write(to: leftEyeTransformCaptureFilePath)
} catch { print("Error writing left eye transforms to file") }
do {
let data = try NSKeyedArchiver.archivedData(withRootObject: rightEyeTransformCapture, requiringSecureCoding: false)
try data.write(to: rightEyeTransformCaptureFilePath)
} catch { print("Error writing right eye transforms to file") }

我猜是 simd_float4x4 结构导致了这个问题,因为这是工作和不工作之间的唯一区别。谁能确认并提出解决方案?

提前致谢。

最佳答案

正如评论中已经提到的,结构不符合 NSCoding 但您可以使 simd_float4x4 符合 Codable 并保留其数据:

extension simd_float4x4: Codable {
public init(from decoder: Decoder) throws {
var container = try decoder.unkeyedContainer()
try self.init(container.decode([SIMD4<Float>].self))
}
public func encode(to encoder: Encoder) throws {
var container = encoder.unkeyedContainer()
try container.encode([columns.0,columns.1, columns.2, columns.3])
}
}

Playground 测试:

do {
let vector = simd_float4x4(2.7) // simd_float4x4([[2.7, 0.0, 0.0, 0.0], [0.0, 2.7, 0.0, 0.0], [0.0, 0.0, 2.7, 0.0], [0.0, 0.0, 0.0, 2.7]])
let data = try JSONEncoder().encode(vector) // 111 bytes
let json = String(data: data, encoding: .utf8)
print(json ?? "") // [[[2.7000000476837158,0,0,0],[0,2.7000000476837158,0,0],[0,0,2.7000000476837158,0],[0,0,0,2.7000000476837158]]]\n"
let decoded = try JSONDecoder().decode(simd_float4x4.self, from: data)
print(decoded) // "simd_float4x4([[2.7, 0.0, 0.0, 0.0], [0.0, 2.7, 0.0, 0.0], [0.0, 0.0, 2.7, 0.0], [0.0, 0.0, 0.0, 2.7]])\n"
decoded == vector // true
} catch {
print(error)
}

编辑/更新:

另一种选择是保存其原始字节。它将仅使用 64 个字节:

extension simd_float4x4: ContiguousBytes {
public func withUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R {
try Swift.withUnsafeBytes(of: self) { try body($0) }
}
}

extension ContiguousBytes {
init<T: ContiguousBytes>(_ bytes: T) {
self = bytes.withUnsafeBytes { $0.load(as: Self.self) }
}
var bytes: [UInt8] { withUnsafeBytes { .init($0) } }
var data: Data { withUnsafeBytes { .init($0) } }
func object<T>() -> T { withUnsafeBytes { $0.load(as: T.self) } }
func objects<T>() -> [T] { withUnsafeBytes { .init($0.bindMemory(to: T.self)) } }
var simdFloat4x4: simd_float4x4 { object() }
var simdFloat4x4Collection: [simd_float4x4] { objects() }
}

extension Array where Element: ContiguousBytes {
var bytes: [UInt8] { withUnsafeBytes { .init($0) } }
var data: Data { withUnsafeBytes { .init($0) } }
}

let vector1 = simd_float4x4(.init(2, 1, 1, 1), .init(1, 2, 1, 1), .init(1, 1, 2, 1), .init(1, 1, 1, 2))
let vector2 = simd_float4x4(.init(3, 1, 1, 1), .init(1, 3, 1, 1), .init(1, 1, 3, 1), .init(1, 1, 1, 3))
let data = [vector1,vector2].data // 128 bytes
let loaded = data.simdFloat4x4Collection
print(loaded) // "[simd_float4x4([[2.0, 1.0, 1.0, 1.0], [1.0, 2.0, 1.0, 1.0], [1.0, 1.0, 2.0, 1.0], [1.0, 1.0, 1.0, 2.0]]), simd_float4x4([[3.0, 1.0, 1.0, 1.0], [1.0, 3.0, 1.0, 1.0], [1.0, 1.0, 3.0, 1.0], [1.0, 1.0, 1.0, 3.0]])]\n"
loaded[0] == vector1 // true
loaded[1] == vector2 // true

关于ios - 如何在 Swift 中对 simd_float4x4 元素数组进行编码(将 simd_float4x4 转换为数据)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63661474/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com