您的位置:首页 > 理论基础

DJI IOS开发之三:Step By Step搭建基于DJI Phantom和iOS的计算机视觉及UAV控制开发平台

2015-05-14 17:02 453 查看

1 前言

在这之前,世界上有很多研究团队花了大量时间自己造四轴,自己开发硬件,才终于可以研究空中机器人的飞行控制,视觉等方面的问题,了不起在几年前用AR Drone来做。但我们知道AR Drone飞行范围太小,摄像头也很不稳定,因此用AR Drone来做研究有很大的局限性。现在好了,使用DJI的飞行器,我们轻而易举的拥有了一个非常棒的研究平台,去研究最前沿的问题,或者说最值得去研究的问题,那就是 计算机视觉+机器学习+机器人控制 。把这三个领域结合起来会产生什么令人兴奋的东西呢?说了一些废话,回到正题。在上一篇文章中,我介绍了如何使用iOS平台来搭建基本的计算机视觉开发环境,在本文中,我将介绍如何搭建基于DJI Phantom和iOS的开发平台。

2 开发环境

Mac OS X 10.10 YosemiteXcode 6.1DJI SDK 1.0.6OpenCV 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了。
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐