3

私はMonoTouchでリアルタイムのビデオ画像処理を行おうとしています。AVCaptureSessionを使用して、AVCaptureVideoPreviewLayerで動作するカメラからフレームを取得しています。

また、デリゲートクラスでコールバックメソッド「DidOutputSampleBuffer」を正常に取得しました。ただし、結果のCMSampleBufferからUIImageを作成しようとしたすべての方法が失敗します。

キャプチャセッションを設定するコードは次のとおりです。

captureSession = new AVCaptureSession ();
            captureSession.BeginConfiguration ();
            videoCamera = AVCaptureDevice.DefaultDeviceWithMediaType (AVMediaType.Video);

            if (videoCamera != null)
            {
                captureSession.SessionPreset = AVCaptureSession.Preset1280x720;

                videoInput = AVCaptureDeviceInput.FromDevice (videoCamera);

                if (videoInput != null)
                    captureSession.AddInput (videoInput);

                //DispatchQueue queue = new DispatchQueue ("videoFrameQueue");

                videoCapDelegate = new videoOutputDelegate (this);

                DispatchQueue queue = new DispatchQueue("videoFrameQueue");
                videoOutput = new AVCaptureVideoDataOutput ();

                videoOutput.SetSampleBufferDelegateAndQueue (videoCapDelegate, queue);
                videoOutput.AlwaysDiscardsLateVideoFrames = true;
                videoOutput.VideoSettings.PixelFormat = CVPixelFormatType.CV24RGB;

                captureSession.AddOutput (videoOutput);

                videoOutput.ConnectionFromMediaType(AVMediaType.Video).VideoOrientation = AVCaptureVideoOrientation.Portrait;

                previewLayer = AVCaptureVideoPreviewLayer.FromSession (captureSession);
                previewLayer.Frame = UIScreen.MainScreen.Bounds;
                previewLayer.AffineTransform = CGAffineTransform.MakeRotation (Convert.DegToRad (-90));
                //this.View.Layer.AddSublayer (previewLayer);

                captureSession.CommitConfiguration ();
                captureSession.StartRunning ();
            }

次のように、サンプルバッファの画像バッファからキャストされたCVPixelBufferからCGBitmapContextを作成してみました。

public override void DidOutputSampleBuffer (AVCaptureOutput captureOutput, MonoTouch.CoreMedia.CMSampleBuffer sampleBuffer, AVCaptureConnection connection)
    {

        CVPixelBuffer pixelBuffer = sampleBuffer.GetImageBuffer () as CVPixelBuffer;
        CVReturn flag = pixelBuffer.Lock (0);
        if(flag == CVReturn.Success)
        {
            CGBitmapContext context = new CGBitmapContext
                    (
                        pixelBuffer.BaseAddress,
                        pixelBuffer.Width,
                        pixelBuffer.Height,
                        8,
                        pixelBuffer.BytesPerRow, 
                        CGColorSpace.CreateDeviceRGB (), 
                        CGImageAlphaInfo.PremultipliedFirst
                        );

            UIImage image = new UIImage(context.ToImage());

            ProcessImage (image);

            pixelBuffer.Unlock(0);

        }else
            Debug.Print(flag.ToString()

        sampleBuffer.Dispose();
    }

これにより、次のエラーが発生します

<Error>: CGBitmapContextCreate: invalid data bytes/row: should be at least 2880 for 8 integer bits/component, 3 components, kCGImageAlphaPremultipliedFirst.

パラメータを微調整しても、ネイティブObjective-cで無効なHandle例外またはsegfaultが発生します。

また、CVImageBufferを使用してCIImageを作成し、そこからUIImageを次のように作成してみました。

public override void DidOutputSampleBuffer (AVCaptureOutput captureOutput, MonoTouch.CoreMedia.CMSampleBuffer sampleBuffer, AVCaptureConnection connection)
    {

        CIImage cImage = new CIImage(sampleBuffer.GetImageBuffer ());
        UIImage image = new UIImage(cImage);
        ProcessImage (image);

        sampleBuffer.Dispose();
    }

これにより、CIImageの初期化時に例外が発生します。

NSInvalidArgumentException Reason: -[CIImage initWithCVImageBuffer:]: unrecognized selector sent to instance 0xc821d0

これは正直なところ、MonoTouchのある種のバグのように感じますが、何かが足りない場合や、奇妙な方法でこれを実行しようとしている場合は、別の解決策を教えてください。

ありがとう

4

1 に答える 1

3

このエラーメッセージはそれを説明しています:

<Error>: CGBitmapContextCreate: invalid data bytes/row: should be at least 2880 for 8 integer bits/component, 3 components, kCGImageAlphaPremultipliedFirst.

幅が720ピクセルで行あたり1084バイトで、ピクセルあたり1.5バイトを少し超えています。これはRGB24(ピクセルあたり3バイト)ではなく、平面形式です。

AVCaptureVideoDataOutput.AvailableVideoCVPixelFormatTypes使用可能なピクセル形式をチェックして、操作しやすいサポートされている形式があるかどうかを確認することをお勧めします。

于 2012-11-28T21:43:59.547 に答える