为什么AVCaptureSession输出错误的方向?

Pet*_*ter 48 iphone avcapturesession avcapturedevice

因此,我按照Apple的说明使用AVCaptureSession以下方法捕获视频会话:http://developer.apple.com/iphone/library/qa/qa2010/qa1702.html.我面临的一个问题是,即使相机/ iPhone设备的方向是垂直的(并且AVCaptureVideoPreviewLayer显示垂直相机流),输出图像似乎处于横向模式.我检查了imageFromSampleBuffer:示例代码中imageBuffer的宽度和高度,分别得到640px和480px.有谁知道为什么会这样?

谢谢!

Jon*_*etz 41

看看标题AVCaptureSession.h.枚举的定义称为AVCaptureVideoOrientation定义各种视频方向.在AVCaptureConnection对象上有一个名为videoOrientation的属性,它是一个AVCaptureVideoOrientation.您应该可以将其设置为更改视频的方向.你可能想要AVCaptureVideoOrientationLandscapeRightAVCaptureVideoOrientationLandscapeLeft.

您可以通过查看会话的输出来查找会话的AVCaptureConnections.输出具有连接属性,该属性是该输出的连接数组.

  • @cheesus videoOrientation位于AVCaptureConnection上,而不是AVCaptureSession (11认同)
  • @rptwsthi你可以在将输出添加到会话之后设置`captureSession.addOutput(videoOutput)let connection = videoOutput.connectionWithMediaType(AVFoundation.AVMediaTypeVideo)connection.videoOrientation = .Portrait captureSession.startRunning()` (11认同)
  • 在'AVCaptureSession*'类型的对象上找不到`属性'videoOrientation' (8认同)

Raw*_*ean 21

我对其进行了简单的单行修改以imageFromSampleBuffer纠正方向问题(请参阅"我修改过..."下的代码中的注释).希望它对某人有所帮助,因为我花了太多时间在这上面.

// Create a UIImage from sample buffer data
- (UIImage *) imageFromSampleBuffer:(CMSampleBufferRef) sampleBuffer  {
    // Get a CMSampleBuffer's Core Video image buffer for the media data
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
    // Lock the base address of the pixel buffer
    CVPixelBufferLockBaseAddress(imageBuffer, 0); 

    // Get the number of bytes per row for the pixel buffer
    void *baseAddress = CVPixelBufferGetBaseAddress(imageBuffer); 

    // Get the number of bytes per row for the pixel buffer
    size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer); 
    // Get the pixel buffer width and height
    size_t width = CVPixelBufferGetWidth(imageBuffer); 
    size_t height = CVPixelBufferGetHeight(imageBuffer); 

    // Create a device-dependent RGB color space
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 

    // Create a bitmap graphics context with the sample buffer data
    CGContextRef context1 = CGBitmapContextCreate(baseAddress, width, height, 8, 
                                                 bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);

    // Create a Quartz image from the pixel data in the bitmap graphics context
    CGImageRef quartzImage = CGBitmapContextCreateImage(context1); 
    // Unlock the pixel buffer
    CVPixelBufferUnlockBaseAddress(imageBuffer,0);

    // Free up the context and color space
    CGContextRelease(context1); 
    CGColorSpaceRelease(colorSpace);

    // Create an image object from the Quartz image
    //I modified this line: [UIImage imageWithCGImage:quartzImage]; to the following to correct the orientation:
    UIImage *image =  [UIImage imageWithCGImage:quartzImage scale:1.0 orientation:UIImageOrientationRight]; 

    // Release the Quartz image
    CGImageRelease(quartzImage);

    return (image);
}
Run Code Online (Sandbox Code Playgroud)


Nic*_*ner 19

你们都很困难.

在DidOutputSampleBuffer中,只需在抓取图像之前更改方向.它是单声道的,但你有

    public class OutputRecorder : AVCaptureVideoDataOutputSampleBufferDelegate {    
        public override void DidOutputSampleBuffer (AVCaptureOutput captureOutput, CMSampleBuffer sampleBuffer, AVCaptureConnection connection)
        {
            try {
                connection.videoOrientation = AVCaptureVideoOrientation.LandscapeLeft;
Run Code Online (Sandbox Code Playgroud)

在objC中,这是这种方法

- ( void ) captureOutput: ( AVCaptureOutput * ) captureOutput
   didOutputSampleBuffer: ( CMSampleBufferRef ) sampleBuffer
      fromConnection: ( AVCaptureConnection * ) connection
Run Code Online (Sandbox Code Playgroud)


Rub*_*con 15

这是一个正确的序列:

AVCaptureVideoDataOutput *videoCaptureOutput = [[AVCaptureVideoDataOutput alloc] init];

if([self.captureSession canAddOutput:self.videoCaptureOutput]){
    [self.captureSession addOutput:self.videoCaptureOutput];
}else{
    NSLog(@"cantAddOutput");
}

// set portrait orientation
AVCaptureConnection *conn = [self.videoCaptureOutput connectionWithMediaType:AVMediaTypeVideo];
[conn setVideoOrientation:AVCaptureVideoOrientationPortrait];
Run Code Online (Sandbox Code Playgroud)

  • 这对我有用.如此代码所示,在更改这些属性之前将输出添加到捕获会话非常重要.带有videoMirrored = true的AVCaptureVideoOrientationLandscapeRight给了我与使用带前置摄像头的标准相机应用程序相同的效果. (2认同)

ja'*_*ja' 11

例如:

AVCaptureConnection *captureConnection = <a capture connection>;
if ([captureConnection isVideoOrientationSupported]) {
    captureConnection.videoOrientation = AVCaptureVideoOrientationPortrait;
}
Run Code Online (Sandbox Code Playgroud)

默认似乎是AVCaptureVideoOrientationLandscapeRight.

另请参阅QA1744:使用AV Foundation设置视频的方向.


Mar*_*uch 7

对于那些需要使用CIImage并且缓冲区方向错误的人来说,我使用了这种修正.

就这么简单.BTW数字3,1,6,8来自这里https://developer.apple.com/reference/imageio/kcgimagepropertyorientation

并且不要问我为什么3,1,6,8是正确的组合.我用暴力法找到它.如果你知道为什么要在评论中解释请...

- (void)captureOutput:(AVCaptureOutput *)captureOutput
    didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
           fromConnection:(AVCaptureConnection *)connection
{

    // common way to get CIImage

    CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);

    CFDictionaryRef attachments = CMCopyDictionaryOfAttachments(kCFAllocatorDefault, sampleBuffer, kCMAttachmentMode_ShouldPropagate);

    CIImage *ciImage = [[CIImage alloc] initWithCVPixelBuffer:pixelBuffer
                                                      options:(__bridge NSDictionary *)attachments];

    if (attachments) {
       CFRelease(attachments);
    }

    // fixing the orientation of the CIImage

    UIInterfaceOrientation curOrientation = [[UIApplication sharedApplication] statusBarOrientation];

    if (curOrientation == UIInterfaceOrientationLandscapeLeft){
        ciImage = [ciImage imageByApplyingOrientation:3];
    } else if (curOrientation == UIInterfaceOrientationLandscapeRight){
        ciImage = [ciImage imageByApplyingOrientation:1];
    } else if (curOrientation == UIInterfaceOrientationPortrait){
        ciImage = [ciImage imageByApplyingOrientation:6];
    } else if (curOrientation == UIInterfaceOrientationPortraitUpsideDown){
        ciImage = [ciImage imageByApplyingOrientation:8];
    }



    // ....

}
Run Code Online (Sandbox Code Playgroud)


mik*_*eho 5

如果AVCaptureVideoPreviewLayer方向正确,您可以在捕获图像之前简单地设置方向.

AVCaptureStillImageOutput *stillImageOutput;
AVCaptureVideoPreviewLayer *previewLayer;
NSData *capturedImageData;

AVCaptureConnection *videoConnection = [stillImageOutput connectionWithMediaType:AVMediaTypeVideo];
if ([videoConnection isVideoOrientationSupported]) {
    [videoConnection setVideoOrientation:previewLayer.connection.videoOrientation];
}
[stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler:^(CMSampleBufferRef imageSampleBuffer, NSError *error) {
    CFDictionaryRef exifAttachments =
            CMGetAttachment(imageSampleBuffer, kCGImagePropertyExifDictionary, NULL);
    if (exifAttachments) {
        // Do something with the attachments.
    }
    // TODO need to manually add GPS data to the image captured
    capturedImageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];
    UIImage *image = [UIImage imageWithData:capturedImageData];
}];
Run Code Online (Sandbox Code Playgroud)

此外,重要的是要注意UIImageOrientation并且AVCaptureVideoOrientation不同.UIImageOrientationUp指的是横向模式,音量控制向下朝向地面(如果您考虑将音量控制用作快门按钮,则不会启动).

因此,AVCaptureVideoOrientationPortrait实际上,电源按钮指向天空()的纵向方向UIImageOrientationLeft.