如何使用DJI SDK(Swift)在每个航点处理拍摄的图像?
解决DJI航点任务中获取拍照图片并执行自定义逻辑的方案
我来给你梳理下在DJI Mobile SDK里实现这个需求的具体步骤,亲测可行:
一、监听航点到达事件,触发自定义方法
DJI的航点任务(DJIWaypointMission)提供了代理回调,可以精准捕获无人机到达每个航点的时机,这时候你就能调用自己的非DJIWaypointAction方法了。
首先要设置航点任务的代理:
// 假设你已经初始化了waypointMission对象 waypointMission.delegate = self;
然后实现代理方法waypointMission:didReachWaypointAtIndex:,这个方法会在无人机到达指定索引的航点时触发:
- (void)waypointMission:(DJIWaypointMission *)mission didReachWaypointAtIndex:(NSInteger)index { // 这里就是你执行自定义逻辑的地方 NSLog(@"到达第%ld个航点,开始执行自定义操作", index); [self fetchLatestImageFromSDCard]; // 调用你自己的获取图片方法 }
二、从无人机SD卡获取照片并转为UIImage
要获取SD卡中的照片,核心是用DJIMediaManager来操作媒体文件:
- 先获取飞行器的MediaManager实例:
DJIAircraft *aircraft = (DJIAircraft *)[DJISDKManager product]; if (!aircraft || !aircraft.mediaManager) { NSLog(@"无法获取MediaManager,请检查飞行器连接状态"); return; } DJIMediaManager *mediaManager = aircraft.mediaManager;
- 获取SD卡中的媒体列表,筛选出最新的拍照文件:
[mediaManager fetchMediaListWithCompletion:^(NSArray<DJIMedia *> * _Nullable mediaList, NSError * _Nullable error) { if (error) { NSLog(@"获取媒体列表失败:%@", error.localizedDescription); return; } // 筛选出照片(排除视频、缩略图等),并按创建时间倒序排列,取最新的一张 NSArray<DJIMedia *> *photoMediaList = [mediaList filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(DJIMedia *media, NSDictionary *bindings) { return media.mediaType == DJIMediaTypePhoto; }]]; // 按创建时间排序 NSArray<DJIMedia *> *sortedPhotos = [photoMediaList sortedArrayUsingComparator:^NSComparisonResult(DJIMedia *obj1, DJIMedia *obj2) { return [obj2.createDate compare:obj1.createDate]; }]; if (sortedPhotos.count > 0) { DJIMedia *latestPhoto = sortedPhotos.firstObject; [self downloadMedia:latestPhoto]; } else { NSLog(@"SD卡中没有照片"); } }];
- 下载选中的媒体文件并转为UIImage:
- (void)downloadMedia:(DJIMedia *)media { DJIAircraft *aircraft = (DJIAircraft *)[DJISDKManager product]; if (!aircraft || !aircraft.mediaManager) return; // 下载原尺寸图片 [aircraft.mediaManager downloadMedia:media withDestinationPath:[self getLocalSavePath] progress:^(NSInteger bytesWritten, NSInteger totalBytesWritten, NSInteger totalBytesExpectedToWrite) { // 可以在这里更新下载进度 NSLog(@"下载进度:%.2f%%", (float)totalBytesWritten / totalBytesExpectedToWrite * 100); } completion:^(NSURL * _Nullable filePath, NSError * _Nullable error) { if (error) { NSLog(@"下载失败:%@", error.localizedDescription); return; } // 转成UIImage,注意要在主线程更新UI dispatch_async(dispatch_get_main_queue(), ^{ UIImage *image = [UIImage imageWithContentsOfFile:filePath.path]; if (image) { // 这里拿到了UIImage,你可以进行后续处理(比如显示、上传等) NSLog(@"成功获取到图片,尺寸:%.fx%.f", image.size.width, image.size.height); [self processCapturedImage:image]; // 调用你的图片处理方法 } else { NSLog(@"图片转码失败"); } }); }]; } // 生成本地保存路径的辅助方法 - (NSString *)getLocalSavePath { NSString *documentsDir = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject; return [documentsDir stringByAppendingPathComponent:@"DJIPhoto.jpg"]; }
三、注意事项
- 确保App已经获取了文件读写权限和相册访问权限(如果需要保存到相册的话);
- 操作MediaManager时,要保证无人机和App处于稳定的连接状态;
- 下载媒体文件是异步操作,记得处理回调中的错误情况;
- 如果需要对应每个航点的照片,可以在航点到达时记录时间戳,后续筛选媒体文件时匹配时间范围,避免获取到其他航点的照片。
内容的提问来源于stack exchange,提问作者Vhan




