将 vector<dlib::p oint> 转换为 NSArray,以便将其传递给 Swift 类

Convert a vector<dlib::point> to an NSArray so it can be passed to a Swift class

本文关键字:Swift 转换 dlib lt vector oint gt NSArray      更新时间:2023-10-16

我正在使用 dlib 的面部特征点检测器,并希望将面部特征点坐标存储在可在 Swift 中使用的数组中。

目前,我已经将地标坐标存储在一个向量中:

std::vector<dlib::point> facialLandmarks;

for (unsigned long k = 0; k < shape.num_parts(); k++) {
dlib::point p = shape.part(k);
facialLandmarks.push_back(p);
}

我现在想编写一个函数,将向量转换为 NSArray,以便我可以返回数组并在我的 Swift 代码中使用它。

当我尝试如下操作时:

NSArray* facialLandmarksArray = &facialLandmarks[0];

我收到一个错误:

Cannot initialize a variable of type 'NSArray *__strong' with an rvalue of type 'std::__1::__vector_base<dlib::vector<long, 2>, std::__1::allocator<dlib::vector<long, 2> > >::value_type *' (aka 'dlib::vector<long, 2> *')

我对Objective-C或C++知之甚少,但需要将其用于Dlib。任何帮助将不胜感激!

NSArray

只能包含Objective-C对象,不能包含C++对象。因此,您必须先将积分转换为NSValue。这样的事情应该有效:

NSMutableArray* facialLandmarksArray = [NSMutableArray arrayWithCapacity: facialLandmarks.size()];
for (auto const& pt: facialLandmarks) {
[facialLandmarksArray addObject: [NSValue valueWithCGPoint:CGPointMake(pt.x, pt.y)]];
}

并确保将其编译为Objective-C++(文件结尾*.mm(。

但是,请注意,这对于大型矢量不能很好地缩放。SwiftC++都能够确保这些数组/向量的值存储在连续内存中,通过Objective-C桥接会破坏这个局部性。

这里的一些挑战是:

1( 我们希望尽量减少对地标点的复制,因为此类复制会影响软件性能和内存占用。

2( 我们如何在 Swift 代码中使用 C++vector的成员,在本例中为dlib::point类型的实例?

应对这些挑战取决于用例。 需要考虑的一些问题:

1( 性能/内存占用有多重要? 如果这不是问题,那么在将值提供给 Swift 时复制这些值是可以的。 当然,这也取决于C++代码是否必须使用 Swift 更改的值。

2(我们在谈论多少个里程碑点? 如果是一百分左右,那么复制它们不太可能是性能打击。

3( Swift 代码是只使用C++库返回的地标点的值,还是修改这些值并期望C++代码"看到"这些更改?

4( 通常,Swift 代码会访问每个地标点多少次? 如果每个点被多次访问,那么最好将所有点复制到可以在 Swift 中使用的结构中,而不是在每次访问时创建副本,而不是在每次 Swift 访问时都复制坐标。

5(可以容忍多少复杂性? 你愿意写很多C++代码吗? 您是否习惯在 Swift 中使用指针类型,例如UnsafeMutablePointer

以下是有关如何执行此操作的一些想法:

1( 在 Objective-C++ 中构造一个可以在 Swift 中使用的集合,并将地标点坐标值复制到该结构中。 @Tobi的回答就是一个例子。

2( 与上面的 (1( 类似,但 Swift 可访问的集合包含指向坐标值的指针。

3( 编写一个 Objective-C++ 类,其接口可从 Swift 访问,并且所有特定于C++的代码都隐藏在实现中。 该接口可以允许 Swift 代码读取(如果需要,还可以写入(特定地标点的特定坐标。

4( (3( 的变体,其中 Swift 代码访问指向坐标值的指针。 在 Swift 端使用这些坐标值时需要小心,以避免复制坐标值。

如果您提供有关用例的一些细节,我可以尝试举一个例子。