4

AVCaptureSessionビデオを録画するために使用してAVAssetWriterInputいます。ビデオをファイルに書き込んでいます。
私の問題は、リンゴの例を使用してビデオの向きにあり、ビデオが正しい向きになるように RosyWriter変換でき ます。AVAssetWriterInput

- (CGFloat)angleOffsetFromPortraitOrientationToOrientation:(AVCaptureVideoOrientation)orientation
{
    CGFloat angle = 0.0;

    switch (orientation) {
        case AVCaptureVideoOrientationPortrait:
            angle = 0.0;
            break;
        case AVCaptureVideoOrientationPortraitUpsideDown:
            angle = M_PI;
            break;
        case AVCaptureVideoOrientationLandscapeRight:
            angle = -M_PI_2;
            break;
        case AVCaptureVideoOrientationLandscapeLeft:
            angle = M_PI_2;
            break;
        default:
            break;
    }

    return angle;
}

- (CGAffineTransform)transformFromCurrentVideoOrientationToOrientation:(AVCaptureVideoOrientation)orientation
{
    CGAffineTransform transform = CGAffineTransformIdentity;

    // Calculate offsets from an arbitrary reference orientation (portrait)
    CGFloat orientationAngleOffset = [self angleOffsetFromPortraitOrientationToOrientation:orientation];
    CGFloat videoOrientationAngleOffset = [self angleOffsetFromPortraitOrientationToOrientation:self.videoOrientation];

    // Find the difference in angle between the passed in orientation and the current video orientation
    CGFloat angleOffset = orientationAngleOffset - videoOrientationAngleOffset;
    transform = CGAffineTransformMakeRotation(angleOffset);

    return transform;
}  

問題はフロント カメラの向きにあります。ユーザーがフロント カメラに変更した後、このコードを使用しても機能しません。

AVCaptureConnection問題の原因は、カムをフロントに変更すると、フロントカムとバックカムの向きが変わることが原因のようです。

そのため、バック カムとフロント カムの初期方向の違いに合わせて調整する必要があるかもしれません。ユーザーがカムを切り替えるたびに接続の向きを
変更したくはありません.Appleが言っているように、パフォーマンスが低下するためです(実際、私がそれを行うと見栄えが悪くなります).AVAssetWriterInput transformを使用できるかどうかわかりません。transform記録中にユーザーがカメラを切り替えられるようにしたいのですが、transform書き込みを開始した後に を変更できません (クラッシュします)...

これを解決する方法はありますか?

4

2 に答える 2

1

フロントカメラからの画像はミラーリングされているため、変換もミラーリングする必要があります。これを行う関数は、次元の 1 つを -1 でスケーリングするだけです。これで遊んでみてください:

transform = CGAffineTransformConcat(CGAffineTransformMakeRotation(angle), CGAffineTransformMakeScale(1.0, -1.0));

可能な順列は(角度のほかに)Xスケール係数で-1あり、または次の順序を入れ替えることに注意してくださいconcat

編集:説明

AVCaptureSession は、デバイスのように回転しない画像データを返します。当然、それは左または右の横向きになると思います。デバイスの持ち方に応じてビデオを正しい向きにする必要がある場合は、何らかの変換を適用する必要があります。ほとんどの場合、回転を適用するだけで十分です。ただし、前面カメラは、ミラーリングされていないフレームをまだ受信している間にミラーをシミュレートするため、特殊なケースです。この結果、あなたのビデオは、適用している回転に応じて、上下左右または他のすべての組み合わせのように見えます。そうですね…」。ここでも、ミラー効果をシミュレートするには、軸の 1 つを -1 でスケーリングする必要があります。

編集:向きの交換(コメントから)

これは単なるアイデアであり、良いアイデアだと思います. アセット変換はまったく使用せず、独自に行ってください。ビデオを希望するサイズのビューを作成し、必要なすべての変換、クリッピング、およびコンテンツ モードを含むイメージ ビュー サブビューを作成します。取得したサンプルから画像を作成し、それらを画像ビューに設定し、ビューからレイヤー スナップショットを取得します。次に、スナップショットをアセット ライターに送信します。

ここであなたが考えているのは「オーバーヘッド」であることはわかっています。まあ、そうは思いません。ビューと画像ビューがアセット ライターと同じように CPU で変換を行うため、内部変換をキャンセルして独自のシステムを使用するだけで済みます。もしあなたがこれを試してみたら、私はあなたの結果について聞きたいです.

レイヤー画像を取得するには:

- (UIImage *)imageFromLayer:(CALayer *)layer {
    UIGraphicsBeginImageContext([layer frame].size);
    [layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return outputImage;
}
于 2013-06-12T10:17:49.553 に答える
0

最も簡単な方法ではありませんが、フレームをインターセプトして独自の変換を実行すれば、確実に機能すると思います。そのために UIView は必要ありません。AVFoundation を使用すると、そのフレームに直接アクセスして操作できます (必要に応じて、ファイルへの書き込み時に独自のバッファーに置き換えることができます)。私が見る唯一の欠点はパフォーマンスです。画像を反転するだけでも、古いデバイスや高解像度では非常に遅くなる場合があります。

これによりパフォーマンスが低下する場合は、ビデオをそのまま保存し、フレームごとに個別の向きの配列を維持できます。ビデオを保存したら、再度開き、フレームごとに変換を実行し、新しいファイルに保存します。私は似たようなことをしましたが、うまくいきます。

ちなみに、AVAssetWriterInputtransformプロパティは iPhone でのみ機能します。たとえば、AVFoundation でビデオを録画し、どこかにアップロードしてブラウザで見ると、向きが正しくありません。したがって、完全な解決策を求めている場合は、自分自身の変革が最適です。

ビデオ/画像処理 (たとえば、この場合は反転/回転) を頻繁に行う場合は、OpenCV ライブラリを検討してください。習得には時間がかかりますが、それだけの価値があります。

于 2013-06-21T03:29:02.490 に答える