版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u012490014/article/details/80128794
最近有一个获取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