将 vector<dlib::point> 转换为 NSArray,以便将其传递给 Swift class

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

我正在使用 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,以便我可以 return 数组并在我的 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。任何帮助将不胜感激!

NSArrays 只能包含 Objective-C 对象,不能包含 C++ 对象。所以你必须先把你的点数转换成NSValues。这样的事情应该有效:

NSMutableArray* facialLandmarksArray = [NSMutableArray arrayWithCapacity: facialLandmarks.size()];

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

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

但是,请注意,这对于大向量来说效果不佳。 SwiftC++ 都能够确保 arrays/vectors 的值存储在 consecutive memory, 桥接 Objective-C 破坏本地.

这里的几个挑战是:

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

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

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

1) performance/memory 足迹有多重要?如果这不是问题,则在将值提供给 Swift 时复制这些值是可以的。当然,这也取决于 C++ 代码是否必须使用 Swift.

更改的值

2) 我们在谈论多少个地标点?如果它是一百点左右,那么复制它们不太可能影响性能。

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

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

5) 可以容忍多少复杂度?您愿意编写大量 C++ 代码吗?您是否喜欢使用 Swift 中的指针类型,例如UnsafeMutablePointer?

这里有一些关于如何做到这一点的想法:

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

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

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

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

如果你提供一些关于你的用例的细节,我可以试着想出一个例子。