DJI IOS开发之三:Step By Step搭建基于DJI Phantom和iOS的计算机视觉及UAV控制开发平台
1 前言
在这之前,世界上有很多研究团队花了大量时间自己造四轴,自己开发硬件,才终于可以研究空中机器人的飞行控制,视觉等方面的问题,了不起在几年前用AR Drone来做。但我们知道AR Drone飞行范围太小,摄像头也很不稳定,因此用AR Drone来做研究有很大的局限性。
现在好了,使用DJI的飞行器,我们轻而易举的拥有了一个非常棒的研究平台,去研究最前沿的问题,或者说最值得去研究的问题,那就是 计算机视觉+机器学习+机器人控制 。把这三个领域结合起来会产生什么令人兴奋的东西呢?
说了一些废话,回到正题。在上一篇文章中,我介绍了如何使用iOS平台来搭建基本的计算机视觉开发环境,在本文中,我将介绍如何搭建基于DJI Phantom和iOS的开发平台。
2 开发环境
Mac OS X 10.10 Yosemite
Xcode 6.1
DJI SDK 1.0.6
OpenCV for iOS 2.4.10
3 搭建步骤
对于基本的建立iOS工程和使用DJI SDK这里就不详细介绍了,
http://blog.csdn.net/songrotek/article/details/44408081
上面这篇Blog介绍了基本的使用DJI SDK的东西。
那么本文主要是说明如何修改DJI SDK的东西使得我们可以直接添加OpenCV的代码对图像进行处理。
链接的库如上所示,主要还是加了很多和图像处理有关的库,有的可能用不着。
将DJI SDK中的ViewPreviewer文件夹直接拉进来。
注意lib和header的search path:
要对应
我主要在VideoPreviewer和MovieGLView两个文件进行更改
Step 1:在VideoPreviewer中添加UIImageView用于显示
@property (strong,nonatomic) UIImageView *imageView;
Step 2:在setView:中初始化这个UIImageView
-(BOOL)setView:(UIView *)view
{
BEGIN_DISPATCH_QUEUE
if(_glView == nil){
_glView = [[MovieGLView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, view.frame.size.width/2, view.frame.size.height/2)];
_status.isGLViewInit = YES;
}
if (self.imageView == nil) {
self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(view.frame.size.width/2, 0.0f, view.frame.size.width/2, view.frame.size.height/2)];
}
dispatch_async(dispatch_get_main_queue(), ^{
[_glView setFrame:CGRectMake(0.0f, 0.0f, view.frame.size.width/2, view.frame.size.height/2)];
[view addSubview:_glView];
[view addSubview:self.imageView];
});
END_DISPATCH_QUEUE
return NO;
}
上面的view的大小显然可以自己更改
Step 3:修改startRun的代码
主要是修改下面这一段代码:
if(_status.isGLViewInit && !_status.isPause && !_status.isBackground)
{
UIImage *image = [_glView render:_renderYUVFrame[_renderFrameIndex]];
if(self.delegate !=nil && [self.delegate respondsToSelector:@selector(processImage:)]){
dispatch_async(dispatch_get_main_queue(), ^{
UIImageToMat(image,matImage);
[self.delegate processImage:matImage];
self.imageView.image = MatToUIImage(matImage);
});
} else {
dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image = image;
});
}
}
我更改了render这个代码,从而将glview转换为UIImage,然后对UIImage进行Mat格式转换,并设置Delegate从而在外部进行处理,然后在转换回来。使用dispatch_async从而在主线程进行操作。
Step 4:修改render代码
// grabbing image from FBO
NSInteger x = 0, y = 0;
NSInteger dataLength = _backingWidth * _backingHeight * 4;
GLubyte *data = (GLubyte*)malloc(dataLength * sizeof(GLubyte));
glPixelStorei(GL_PACK_ALIGNMENT, 4);
glReadPixels(x, y, _backingWidth, _backingHeight, GL_RGBA, GL_UNSIGNED_BYTE, data);
CGDataProviderRef ref = CGDataProviderCreateWithData(NULL, data, dataLength, NULL);
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
CGImageRef iref = CGImageCreate(_backingWidth, _backingHeight, 8, 32, _backingWidth * 4, colorspace, kCGBitmapByteOrder32Big | kCGImageAlphaPremultipliedLast,
ref, NULL, true, kCGRenderingIntentDefault);
UIGraphicsBeginImageContext(CGSizeMake(_backingWidth, _backingHeight));
CGContextRef cgcontext = UIGraphicsGetCurrentContext();
CGContextSetBlendMode(cgcontext, kCGBlendModeCopy);
CGContextDrawImage(cgcontext, CGRectMake(0.0, 0.0, _backingWidth, _backingHeight), iref);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
free(data);
CFRelease(ref);
CGImageRelease(iref);
return image;
在method后部添加了如上的代码实现glview转UIImage。
经过上面的处理,我们在viewController就可以很方便调用了。
Step 5:ViewController的代码
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// Setup Drone
self.drone = [[DJIDrone alloc] initWithType:DJIDrone_Phantom];
self.drone.delegate = self;
self.drone.camera.delegate = self;
// 设置视频流
[[VideoPreviewer instance] start];
[VideoPreviewer instance].delegate = self;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[VideoPreviewer instance] setView:self.view];
[self.drone connectToDrone];
}
-(void) viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self.drone.camera startCameraSystemStateUpdates];
}
-(void) viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[self.drone disconnectToDrone];
[self.drone destroy];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - DJICameraDelegate
// OpenCV的处理都在下面这个Method里面
- (void)processImage:(cv::Mat &)image
{
cvtColor(image, image, CV_BGR2GRAY);
}
- (void)camera:(DJICamera *)camera didReceivedVideoData:(uint8_t *)videoBuffer length:(int)length
{
uint8_t *pBuffer = (uint8_t*)malloc(length);
memcpy(pBuffer, videoBuffer, length);
[[[VideoPreviewer instance] dataQueue] push:pBuffer length:length];
}
大家看到,在ViewController的代码可以非常简单,因为整个处理过程都在ViewPreviewer中实现,在这里,可以说我们只要在processImage:里面贴Opencv的代码就OK了。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。