2

私は、iPhoneカメラから見た光の状態に関する統計を表示するアプリケーションを作成しています。私は毎秒画像を撮り、それに対して計算を実行します。

画像をキャプチャするには、次の方法を使用しています。

-(void) captureNow
{
    AVCaptureConnection *videoConnection = nil;
    for (AVCaptureConnection *connection in captureManager.stillImageOutput.connections)
    {
        for (AVCaptureInputPort *port in [connection inputPorts])
        {
            if ([[port mediaType] isEqual:AVMediaTypeVideo] )
            {
                videoConnection = connection;
                break;
            }
        }
        if (videoConnection) { break; }
    }

    [captureManager.stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error)
     {   
         NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer];
         latestImage = [[UIImage alloc] initWithData:imageData];
     }];
}

ただし、このcaptureStillImageAsynhronously....方法では「シャッター」音が電話で再生されます。これは、常に画像をキャプチャするため、私のアプリケーションには適していません。

この効果音を無効にすることはできません。代わりに、電話のビデオ入力からフレームをキャプチャしたいと思います。

AVCaptureDeviceInput *newVideoInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self backFacingCamera] error:nil];

うまくいけば、これらをUIImageオブジェクトに変換します。

どうすればこれを達成できますか?AVFoundationのものがどのように機能しているかについてはあまりわかりません。サンプルコードをダウンロードして、目的に合わせて変更しました。

4

1 に答える 1

5

これには静止カメラを使用しないでください。代わりに、デバイスのビデオ カメラから取得し、AVCaptureVideoDataOutputSampleBufferDelegate であることに応答して取得したピクセル バッファー内に含まれるデータを処理します。

次のようなコードを使用して、ビデオ接続をセットアップできます。

// Grab the back-facing camera
AVCaptureDevice *backFacingCamera = nil;
NSArray *devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
for (AVCaptureDevice *device in devices) 
{
    if ([device position] == AVCaptureDevicePositionBack) 
    {
        backFacingCamera = device;
    }
}

// Create the capture session
captureSession = [[AVCaptureSession alloc] init];

// Add the video input  
NSError *error = nil;
videoInput = [[[AVCaptureDeviceInput alloc] initWithDevice:backFacingCamera error:&error] autorelease];
if ([captureSession canAddInput:videoInput]) 
{
    [captureSession addInput:videoInput];
}

// Add the video frame output   
videoOutput = [[AVCaptureVideoDataOutput alloc] init];
[videoOutput setAlwaysDiscardsLateVideoFrames:YES];
[videoOutput setVideoSettings:[NSDictionary dictionaryWithObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey:(id)kCVPixelBufferPixelFormatTypeKey]];

[videoOutput setSampleBufferDelegate:self queue:dispatch_get_main_queue()];

if ([captureSession canAddOutput:videoOutput])
{
    [captureSession addOutput:videoOutput];
}
else
{
    NSLog(@"Couldn't add video output");
}

// Start capturing
[captureSession setSessionPreset:AVCaptureSessionPreset640x480];
if (![captureSession isRunning])
{
    [captureSession startRunning];
};

次に、次のようなデリゲート メソッドでこれらのフレームを処理する必要があります。

- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection
{
    CVImageBufferRef cameraFrame = CMSampleBufferGetImageBuffer(sampleBuffer);
    CVPixelBufferLockBaseAddress(cameraFrame, 0);
    int bufferHeight = CVPixelBufferGetHeight(cameraFrame);
    int bufferWidth = CVPixelBufferGetWidth(cameraFrame);

        // Process pixel buffer bytes here

    CVPixelBufferUnlockBaseAddress(cameraFrame, 0);
}

BGRA 画像の生のピクセル バイトは、 から始まる配列内に含まれますCVPixelBufferGetBaseAddress(cameraFrame)。それらを繰り返し処理して、目的の値を取得できます。

ただし、CPU 上のイメージ全体に対して実行される操作は、少し遅くなることがわかります。ここで必要なように、平均的な色操作を支援するために Accelerate を使用できます。私はvDSP_meanv()過去に、輝度値を配列に入れて平均化するために使用しました。そのような場合は、ここでプルダウンした BGRA 値の代わりに、カメラから YUV 平面データを取得するのが最善の方法かもしれません。

OpenGL ES を使用してビデオを処理するためのオープン ソース フレームワークも作成しましたが、ここでのような画像分析に必要なような画像全体の縮小操作はまだありません。私のヒストグラムジェネレーターは、おそらくあなたがやろうとしていることに最も近いものです。

于 2012-05-14T21:43:03.403 に答える