【问题标题】:glReadPixel() return black imageglReadPixel() 返回黑色图像
【发布时间】:2014-04-11 12:58:38
【问题描述】:

我将 AVCaptureSession 用于实时 cameraview 提要,然后我在相机覆盖视图上渲染一些图像。我没有使用任何 EAGLView,只是使用带有 previewlayer 的 AVCaptureSession 覆盖了一些图像。我想截取实时摄像头图像和叠加图像。因此,我搜索了一些最终使用 glReadPixel() 获得的链接,但是当我实现此代码时,它返回黑色图像。刚刚添加了OpenGLES.framework库并导入。

- (void)viewDidLoad
 {
 [super viewDidLoad];

 [self setCaptureSession:[[AVCaptureSession alloc] init]];


 [self  addVideoInputFrontCamera:NO]; // set to YES for Front Camera, No for Back camera

 [self  addStillImageOutput];

 [self setPreviewLayer:[[AVCaptureVideoPreviewLayer alloc] initWithSession:[self captureSession]] ];



 [[self previewLayer] setVideoGravity:AVLayerVideoGravityResizeAspectFill];



 CGRect layerRect = [[[self view] layer] bounds];


 [[self previewLayer]setBounds:layerRect];
 [[self  previewLayer] setPosition:CGPointMake(CGRectGetMidX(layerRect),CGRectGetMidY(layerRect))];
 [[[self view] layer] addSublayer:[self  previewLayer]];


 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(saveImageToPhotoAlbum) name:kImageCapturedSuccessfully object:nil];


 [[self captureSession] startRunning];


 UIImageView *dot =[[UIImageView alloc] initWithFrame:CGRectMake(50,50,200,200)];
 dot.image=[UIImage imageNamed:@"draw.png"];
 [self.view addSubview:dot];

 }

使用 glReadPixel() 捕获带有覆盖内容的实时摄像机源:

 - (UIImage*) glToUIImage

 {
 CGFloat scale = [[UIScreen mainScreen] scale];
 // CGRect s = CGRectMake(0, 0, 320.0f * scale, 480.0f * scale);

 CGRect  s = CGRectMake(0, 0, 768.0f * scale, 1024.0f * scale);

 uint8_t *buffer = (uint8_t *) malloc(s.size.width * s.size.height * 4);



 glReadPixels(0, 0, s.size.width, s.size.height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);

 CGDataProviderRef ref = CGDataProviderCreateWithData(NULL, buffer, s.size.width * s.size.height * 4, NULL);


 CGImageRef iref = CGImageCreate(s.size.width, s.size.height, 8, 32, s.size.width * 4, CGColorSpaceCreateDeviceRGB(), kCGBitmapByteOrderDefault, ref, NULL, true, kCGRenderingIntentDefault);


 size_t width = CGImageGetWidth(iref);
 size_t height = CGImageGetHeight(iref);
 size_t length = width * height * 4;
 uint32_t *pixels = (uint32_t *)malloc(length);



 CGContextRef context1 = CGBitmapContextCreate(pixels, width, height, 8, width * 4,
 CGImageGetColorSpace(iref), kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Big);


 CGAffineTransform transform = CGAffineTransformIdentity;
 transform = CGAffineTransformMakeTranslation(0.0f, height);
 transform = CGAffineTransformScale(transform, 1.0, -1.0);
 CGContextConcatCTM(context1, transform);
 CGContextDrawImage(context1, CGRectMake(0.0f, 0.0f, width, height), iref);
 CGImageRef outputRef = CGBitmapContextCreateImage(context1);


 outputImage = [UIImage imageWithCGImage: outputRef];


 CGDataProviderRelease(ref);
 CGImageRelease(iref);
 CGContextRelease(context1);
 CGImageRelease(outputRef);
 free(pixels);
 free(buffer);




 UIImageWriteToSavedPhotosAlbum(outputImage, nil, nil, nil);

 NSLog(@"Screenshot size: %d, %d", (int)[outputImage size].width, (int)[outputImage size].height);

 return outputImage;

 }


 -(void)screenshot:(id)sender{

 [self glToUIImage];


 }

但它返回黑色图像。

【问题讨论】:

  • 从您的帖子中不清楚您是要截屏还是要从相机捕获原始图像。 glReadPixel 仅返回 openGL 渲染缓冲区,因为您似乎没有使用 openGL,因此您不会得到任何返回。对于屏幕截图,您可以关注此线程,尤其是最后一个帖子stackoverflow.com/questions/2200736/…
  • 我不想截屏。我需要原始图像(实时摄像头)和像图像这样的叠加内容。请参阅附加的增强现实图像,我需要捕获实时摄像头和覆盖内容。
  • 这里是对 Apple Docs 的参考,它解释了如何从 Camera Capture 创建图像。 developer.apple.com/library/ios/qa/qa1702/_index.html#//…。 Apple 开发人员“RosyWriter”示例应用程序给出了一个示例或检索图像缓冲区并对每个像素应用色调,然后通过 openGL 显示修改后的像素缓冲区。 Apple 的公园示例展示了如何在相机源上叠加位置。您可以采用多种方法,尽管使用 AR SDK 可能更简单。如果您需要更多信息/帮助,请告诉我。
  • 我没有为我的应用使用任何 AR SDK。我只是使用叠加图像和捕获。我从这里提到musicalgeometry.com/?p=1681。但是,如果我移动叠加图像并拍摄快照,它将不会通过实时提要获得叠加图像的当前像素。它总是给出 [overlay drawInRect:CGRectMake(30 * xScaleFactor, 100 * yScaleFactor, overlaySize.width * xScaleFactor, overlaySize.height * yScaleFactor)];如何解决这个问题?这就是问题

标签: ios objective-c opengl-es avcapturesession glreadpixels


【解决方案1】:

glReadPixels() 不适用于 AV Foundation 预览层。没有 OpenGL ES 上下文可以从中捕获像素,即使有,您也需要在将场景呈现给显示器之前从中捕获。

如果您要从摄像机捕获覆盖在实时视频上的图像,我的GPUImage 框架可以为您处理。您需要做的就是设置一个 GPUImageVideoCamera、一个用于覆盖的 GPUImagePicture 实例以及某种混合过滤器。然后,您可以将输出提供给 GPUImageView 进行显示,并能够在任何时候从混合滤镜中捕获静止图像。框架为您处理所有这些繁重的工作。

【讨论】:

    猜你喜欢
    • 2014-04-27
    • 1970-01-01
    • 2011-08-08
    • 1970-01-01
    • 2015-09-12
    • 2019-06-21
    • 1970-01-01
    • 1970-01-01
    • 2015-06-20
    相关资源
    最近更新 更多