iOS AR 高通Vuforia —— 獲取攝像頭幀圖片
阿新 • • 發佈:2018-11-28
最近有一個獲取Vuforia 框架下攝像頭的幀圖片的需求就研究了一下,其實官方是有相關API的,裡面有java和c++兩種語言
(有一點不好的是,官方給的地址會變,以前的版本和現在的版本地址都不一樣)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