Я использую детектор ориентира лица 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
s может содержать только 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).
Тем не менее, обратите внимание, что это не подходит для больших векторов. стриж а также C ++ оба способны убедиться, что значения таких массивов / векторов хранятся в последовательная память, преодоление Objective-C разрушает эту местность.
Пара проблем здесь:
1) Мы хотим минимизировать копирование ориентиров, поскольку такое копирование повлияет на производительность программного обеспечения и объем памяти.
2) Как мы используем C ++ vector
члены, экземпляры типа dlib::point
в этом случае в коде Swift?
Решение этих проблем зависит от варианта использования. Некоторые вопросы для рассмотрения:
1) Насколько важна производительность / объем памяти? Если это не проблема, можно скопировать значения, сделав их доступными для Swift. Конечно, это также зависит от того, должен ли код C ++ использовать значения, измененные Swift.
2) О каких ориентирах мы говорим? Если это сто очков или около того, то копирование их вряд ли будет ударом по производительности.
3) Будет ли код Swift просто использовать значения ориентиров, возвращаемых библиотекой C ++, или он собирается изменить эти значения и ожидать, что код C ++ «увидит» эти изменения?
4) Сколько раз, как правило, код Swift будет получать доступ к каждой из ориентиров? Если к каждой точке обращаются несколько раз, то лучше скопировать все точки один раз в структуру, которую можно использовать в Swift, не создавая копию при каждом доступе, вместо того, чтобы делать копию координаты каждый раз, когда Swift обращается к ней.
5) Сколько сложности можно терпеть? Готовы ли вы написать много кода на C ++? Вам удобно работать с типами указателей в Swift, например? UnsafeMutablePointer
?
И вот несколько идей о том, как это сделать:
1) Создайте в Objective-C ++ коллекцию, которую можно использовать в Swift, и скопируйте значения координат точки ориентира в эту структуру. Ответ @ Тоби является примером.
2) Аналогично (1) выше, но доступная Swift коллекция содержит указатели для координатных значений.
3) Напишите класс Objective-C ++, интерфейс которого доступен из Swift, и весь специфичный для C ++ код скрыт в реализации. Интерфейс может позволить коду Swift считывать (и записывать, если необходимо) конкретные координаты конкретных ориентиров.
4) Разновидность (3), где код Swift обращается к указателям на значения координат. При их использовании на стороне Swift необходимо соблюдать осторожность, чтобы избежать копирования значений координат.
Если вы предоставите некоторые подробности о вашем случае использования, я могу попытаться привести пример.