0

AVCaptureSessionPresetPhoto解像度のAVFoundationでピクセルアライメントを機能させることができないようです。ピクセルの配置は、AVCaptureSessionPreset1280x720(AVCaptureSessionPreset1280x720_Picture)のような低解像度で正常に機能します。AVCaptureSessionPreset1280x720_pictureAVCaptureSessionPresetPhoto_picture

具体的には、これらの行のコメントを解除すると、次のようになります。if([captureSession canSetSessionPreset:AVCaptureSessionPresetPhoto]){[captureSession setSessionPreset:AVCaptureSessionPresetPhoto];
} else {NSLog(@ "解像度をAVCaptureSessionPresetPhotoに設定できません"); 下の2番目の画像に示すように、位置合わせされていない画像が表示されます。コメント/提案は大歓迎です。

これが、1)キャプチャセッション、2)デリゲートコールバック、3)1つのスチーム画像を保存してピクセルの位置合わせを確認するためのコードです。
1.キャプチャセッションの設定

    - (void)InitCaptureSession {
captureSession = [[AVCaptureSession alloc] init];
if ([captureSession canSetSessionPreset:AVCaptureSessionPreset1280x720]) {
    [captureSession setSessionPreset:AVCaptureSessionPreset1280x720];        
} else {
    NSLog(@"Unable to set resolution to AVCaptureSessionPreset1280x720");
}

//    if ([captureSession canSetSessionPreset:AVCaptureSessionPresetPhoto]) {
//        [captureSession setSessionPreset:AVCaptureSessionPresetPhoto];        
//    } else {
//        NSLog(@"Unable to set resolution to AVCaptureSessionPresetPhoto");
//    }

captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
videoInput = [AVCaptureDeviceInput deviceInputWithDevice:captureDevice error:nil];

AVCaptureVideoDataOutput *captureOutput = [[AVCaptureVideoDataOutput alloc] init];
captureOutput.alwaysDiscardsLateVideoFrames = YES; 

dispatch_queue_t queue;
queue = dispatch_queue_create("cameraQueue", NULL);
[captureOutput setSampleBufferDelegate:self queue:queue];
dispatch_release(queue);
NSString* key = (NSString*)kCVPixelBufferPixelFormatTypeKey; 
    NSNumber* value = [NSNumber     numberWithUnsignedInt:kCVPixelFormatType_420YpCbCr8BiPlanarFullRange];
NSDictionary* videoSettings = [NSDictionary dictionaryWithObject:value forKey:key];     
[captureOutput setVideoSettings:videoSettings]; 

[captureSession addInput:videoInput];
[captureSession addOutput:captureOutput];
    [captureOutput release];

    previewLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.captureSession];
[previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];

    CALayer *rootLayer = [previewView layer];// self.view.layer; //

[rootLayer setMasksToBounds:YES];
[previewLayer setFrame:[rootLayer bounds]];
[rootLayer addSublayer:previewLayer];
[captureSession startRunning];  
}


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

NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
static int processedImage = 0;
processedImage++;
if (processedImage==100) {
    [self SaveImage:sampleBuffer]; 
}

[pool drain];
} 

// Create a UIImage CMSampleBufferRef and save for verifying pixel alignment
- (void) SaveImage:(CMSampleBufferRef) sampleBuffer 
{
CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); 
CVPixelBufferLockBaseAddress(imageBuffer, 0); 
CvSize imageSize;
imageSize.width = CVPixelBufferGetWidth(imageBuffer); ;
imageSize.height = CVPixelBufferGetHeight(imageBuffer); 
IplImage *image = cvCreateImage(imageSize, IPL_DEPTH_8U, 1);     
void *y_channel = CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0); 
char *tempPointer = image->imageData;
memcpy(tempPointer, y_channel, image->imageSize);
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray();
NSData *data = [NSData dataWithBytes:image->imageData length:image->imageSize];
CGDataProviderRef provider = CGDataProviderCreateWithCFData((CFDataRef)data);
CGImageRef imageRef = CGImageCreate(image->width, image->height,
                                    8, 8, image->width,
                                    colorSpace, kCGImageAlphaNone|kCGBitmapByteOrderDefault,
                                    provider, NULL, false, kCGRenderingIntentDefault);
UIImage *Saveimage = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
CGDataProviderRelease(provider);
CGColorSpaceRelease(colorSpace);
UIImageWriteToSavedPhotosAlbum(Saveimage, nil, nil, nil);
CVPixelBufferUnlockBaseAddress(imageBuffer,0);
}
4

1 に答える 1

3

SaveImageでは、の5番目の引数はCGImageCreateisであり、メモリアライメントの場合、行あたりのバイト数が異なる可能性があるため、bytesPerRow渡さないでください。image->widthこれは、AVCaptureSessionPresetPhotowhere width = 852(iPhone 4カメラ付き)の場合ですが、1番目の平面(Y)の1行あたりのバイト数は864、16バイト整列されているためです。

1/次のように行あたりのバイト数を取得する必要があります。

size_t bpr = CVPixelBufferGetBytesPerRowOfPlane(imageBuffer, 0);

2 /次に、ピクセルを次の場所にコピーするときに、1行あたりのバイト数を考慮するように注意してくださいIplImage

char *y_channel = (char *) CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0);

// row by row copy
for (int i = 0; i < image->height; i++)
  memcpy(tempPointer + i*image->widthStep, y_channel + i*bpr, image->width);

アラインメント()を考慮して[NSData dataWithBytes:image->imageData length:image->imageSize];いるので、そのままにしておくことができます。image->imageSizeimageSize = height*widthStep

3 /最後に、IplImage幅ステップをCGImageCreate5番目のパラメーターとして渡します。

CGImageCreate(image->width, image->height, 8, 8, image->widthStep, ...);
于 2012-10-04T10:08:16.883 に答える