iOS AR 高通Vuforia —— 获取摄像头帧图片

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012490014/article/details/80128794

最近有一个获取Vuforia 框架下摄像头的帧图片的需求就研究了一下,其实官方是有相关API的,里面有java和c++两种语言

https://library.vuforia.com/articles/Solution/Working-with-the-Camera#How-To-Access-the-Camera-Image-in-Native

(有一点不好的是,官方给的地址会变,以前的版本和现在的版本地址都不一样)vuforia里面的图片格式有两种,RGB565和RGB888

RGB888

    首先需要在start出现的地方设置图片格式setFrameFormat(startCamera和resumeAR中

        if (!Vuforia::CameraDevice::getInstance().start()) {
            [self NSErrorWithCode:E_STARTING_CAMERA error:error];
            return NO;
        }
        Vuforia::setFrameFormat(Vuforia::RGB888, true);

    然后vuforia_onUpdate函数中添加下面的代码

- (void) Vuforia_onUpdate:(Vuforia::State *) state {
    Vuforia::Image *imageRGB888 = NULL;
    Vuforia::Frame frame = state->getFrame();

    for (int i = 0; i < frame.getNumImages(); ++i) {
        const Vuforia::Image *image = frame.getImage(i);
        if (image->getFormat() == Vuforia::RGB888) {
            imageRGB888 = (Vuforia::Image*)image;

            break;
        }
    }
    if (imageRGB888) {
        int width = imageRGB888->getWidth();
        int height = imageRGB888->getHeight();
        int bitsPerComponent = 8;
        int bitsPerPixel = Vuforia::getBitsPerPixel(Vuforia::RGB888);
        int bytesPerRow = imageRGB888->getBufferWidth() * bitsPerPixel / bitsPerComponent;
        CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
        CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault | kCGImageAlphaNone;
        CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;
        
        CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, imageRGB888->getPixels(), Vuforia::getBufferSize(width, height, Vuforia::RGB888), NULL);
        
        CGImageRef imageRef = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);
        UIImage *result = [UIImage imageWithCGImage:imageRef];//得到UIImage
        
        CGDataProviderRelease(provider);
        CGColorSpaceRelease(colorSpaceRef);
        CGImageRelease(imageRef);

    }
    
  
    if ((self.delegate != nil) && [self.delegate respondsToSelector:@selector(onVuforiaUpdate:)]) {
        [self.delegate onVuforiaUpdate:state];
    }
}


RGB565

首先需要在start出现的地方设置图片格式(startCamera和resumeAR中用到了start

        if (!Vuforia::CameraDevice::getInstance().start()) {
            [self NSErrorWithCode:E_STARTING_CAMERA error:error];
            return NO;
        }
        Vuforia::setFrameFormat(Vuforia::RGB565, true);

然后vuforia_onUpdate函数中添加下面的代码

- (void) Vuforia_onUpdate:(Vuforia::State *) state {
    Vuforia::Image *imageRGB565 = NULL;
    Vuforia::Frame frame = state->getFrame();
    
    for (int i = 0; i < frame.getNumImages(); ++i) {
        const Vuforia::Image *image = frame.getImage(i);
        if (image->getFormat() == Vuforia::RGB565) {
            imageRGB565 = (Vuforia::Image*)image;
            
            break;
        }
    }
    if (imageRGB565) {
    
        
        int width = imageRGB565->getWidth();
        int height = imageRGB565->getHeight();
        const size_t bufferLength = width * height * 2;
        const short* pixels = (const short*) imageRGB565->getPixels();
        NSData *data = [NSData dataWithBytes:pixels length:bufferLength];

        CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
        CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)data);
        NSLog(@"bits per pixel %d",Vuforia::getBitsPerPixel(Vuforia::RGB565));
        // Creating CGImage from cv::Mat
        CGImageRef imageRef = CGImageCreate(width,          //width
                                            height,         //height
                                            5,              //bits per component
                                            Vuforia::getBitsPerPixel(Vuforia::RGB565),             //bits per pixel
                                            width * 2,      //bytesPerRow
                                            colorSpace,     //colorspace
                                            kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder16Little,// bitmap info
                                            provider,               //CGDataProviderRef
                                            NULL,                   //decode
                                            false,                  //should interpolate
                                            kCGRenderingIntentDefault   //intent
                                            );

        // Getting UIImage from CGImage
        UIImage *finalImage = [UIImage imageWithCGImage:imageRef];

        CGImageRelease(imageRef);
        CGDataProviderRelease(provider);
        CGColorSpaceRelease(colorSpace);

    }
    
    if ((self.delegate != nil) && [self.delegate respondsToSelector:@selector(onVuforiaUpdate:)]) {
        [self.delegate onVuforiaUpdate:state];
    }
}

但是需要注意的是用RGB888转换成的UIImage是正常的,而RGB565转成的UIImage是非正常的,因为正常的RGB24是由24位即3个字节来描述一个像素,R、G、B各8位。而实际使用中为了减少图像数据的尺寸,如视频领域,对R、G、B所使用的位数进行的缩减,如RGB565和RGB555。
RGB565 就是R-5bit,G-6bit,B-5bit
RGB555 就是R-5bit,G-5bit,B-5bit

RGB888 就是R-8bit,G-8bit,B-8bit 

使用RGB565,会导致图片数据的缺失,影响精度,在前端显示的时候还是建议用RGB888

猜你喜欢

转载自blog.csdn.net/u012490014/article/details/80128794