40

OpenCV 2.4.3.2 を使用してカメラ アプリを作成し、opencv 処理を実行しようとしています。ランドスケープだけでなく、複数の UI 方向を使用できるようにしたいと考えています。

問題は、向きを縦に変更すると画像が横向きになることです。

画像処理を行う前に入力画像を回転させることができることを理解しています(したがって、向きを横向きのままにしておく)。これは問題なく機能しますが、UIの残りの部分が間違った向きになるという問題は解決しません.

また、このコードを使用してカメラを 90 度回転させようとしましたが、うまくいかないようです。

mCamera.setDisplayOrientation(90);

効果がないか、プレビューが真っ暗になることがあります

OpenCVでこれを成功させた人はいますか? 私のクラスは JavaCameraView から拡張されています。 縦向きの画像と横向きのプレビュー

編集

CameraBridgeViewBase.java クラスに表示されるように、OpenCV 内で画像を回転させたという改善を行いました。

配信してフレームを描画する方法:

if (canvas != null) {
            canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR);
            //canvas.drawBitmap(mCacheBitmap, (canvas.getWidth() - mCacheBitmap.getWidth()) / 2, (canvas.getHeight() - mCacheBitmap.getHeight()) / 2, null);
            //Change to support portrait view
            Matrix matrix = new Matrix();
            matrix.preTranslate((canvas.getWidth() - mCacheBitmap.getWidth()) / 2,(canvas.getHeight() - mCacheBitmap.getHeight()) / 2);

            if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT)
                matrix.postRotate(90f,(canvas.getWidth()) / 2,(canvas.getHeight()) / 2);
            canvas.drawBitmap(mCacheBitmap, matrix, new Paint());

...基本的に、これは入力画像を次のように回転させるだけです

入力画像を 90 度回転

これはより良いですが、私は明らかにこれを全画面表示にしたいと考えています。

4

19 に答える 19

10

実際には、幅または高さを親 (フルスクリーン) に一致させることができます。

if (canvas != null) {
        Bitmap bitmap = Bitmap.createScaledBitmap(mCacheBitmap, canvas.getHeight(), canvas.getWidth(), true);
        canvas.rotate(90,0,0);
        float scale = canvas.getWidth() / (float)bitmap.getHeight();
        float scale2 = canvas.getHeight() / (float)bitmap.getWidth();
        if(scale2 > scale){
            scale = scale2;
        }
        if (scale != 0) {
            canvas.scale(scale, scale,0,0);
        }
        canvas.drawBitmap(bitmap, 0, -bitmap.getHeight(), null);

...

また、プレビューサイズを画面より大きくすることもできます。スケールを変更するだけです。

于 2015-02-28T07:54:20.960 に答える
2

他の回答と同様に、deliverAndDrawFrameの個人的なバージョンを作成しました (コードの開始位置と終了位置をコメントで通知しました):

protected void deliverAndDrawFrame(CvCameraViewFrame frame) {
    Mat modified;

    if (mListener != null) {
        modified = mListener.onCameraFrame(frame);
    } else {
        modified = frame.rgba();
    }

    boolean bmpValid = true;
    if (modified != null) {
        try {
            Utils.matToBitmap(modified, mCacheBitmap);
        } catch(Exception e) {
            Log.e(TAG, "Mat type: " + modified);
            Log.e(TAG, "Bitmap type: " + mCacheBitmap.getWidth() + "*" + mCacheBitmap.getHeight());
            Log.e(TAG, "Utils.matToBitmap() throws an exception: " + e.getMessage());
            bmpValid = false;
        }
    }

    if (bmpValid && mCacheBitmap != null) {
        Canvas canvas = getHolder().lockCanvas();
        if (canvas != null) {
            canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR);
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "mStretch value: " + mScale);
            }

            // Start of the fix
            Matrix matrix = new Matrix();
            matrix.preTranslate( ( canvas.getWidth() - mCacheBitmap.getWidth() ) / 2f, ( canvas.getHeight() - mCacheBitmap.getHeight() ) / 2f );
            matrix.postRotate( 90f, ( canvas.getWidth()) / 2f, canvas.getHeight() / 2f );
            float scale = (float) canvas.getWidth() / (float) mCacheBitmap.getHeight();
            matrix.postScale(scale, scale, canvas.getWidth() / 2f , canvas.getHeight() / 2f );
            canvas.drawBitmap( mCacheBitmap, matrix, null );

            // Back to original OpenCV code
            if (mFpsMeter != null) {
                mFpsMeter.measure();
                mFpsMeter.draw(canvas, 20, 30);
            }

            getHolder().unlockCanvasAndPost(canvas);
        }
    }

}

ご覧のとおり、プレビューはポートレート モードになりました。

縦向きプレビュー

于 2019-07-24T10:49:30.487 に答える
1

新しい OpenCVCameraBridgeViewBase.javaクラスはレベルが高すぎて、カメラ プレビューのレイアウトを十分に制御できないようです。古い OpenCV サンプルのいくつかに基づいており、純粋な Android コードを使用している私のサンプル コードを見てください。で渡されたバイト配列を使用するにはonPreviewFrameput()Mat に変換し、YUV から RGB に変換します。

mYuv = new Mat(previewHeight + previewHeight/2, previewWidth, CvType.CV_8UC1);
mYuv.put(0, 0, mBuffer);
Imgproc.cvtColor(mYuv, mRgba, Imgproc.COLOR_YUV420sp2RGBA, 4);

古い OpenCV4Android のサンプルはインターネット上で見つけることができるかもしれませんが、それらは数バージョン前に公開されています。ただし、リンクされたサンプル コードと上記のスニペットだけで十分に作業を開始できます。

于 2013-08-08T03:03:30.970 に答える
1

いくつかのことを考慮する必要があります。

  • onPreviewFrame() は、常に生のカメラ データをアセンブルされたローテーションで配信します。
  • getSupportedPreviewSizes() は、対応するアスペクト比を提供します
  • アルゴリズムは、オブジェクトを正しく検出するために縦向きのフレームを分析する必要があります。
  • 結果のフレームを格納するために (Java 側で) 作成されたビットマップにも、正しい縦横比が必要です。

したがって、高速で高解像度のソリューションのために、JavaCameraView.java と JNI 部分を変更しました。JavaCameraView.java で:

...

      if (sizes != null) {
         /* Select the size that fits surface considering maximum size allowed */
         Size frameSize;
         if(width > height)
         {
            frameSize = calculateCameraFrameSize(sizes, new JavaCameraSizeAccessor(), width, height);
         }else{
            frameSize = calculateCameraFrameSize(sizes, new JavaCameraSizeAccessor(), height, width);
         }
...

         mCamera.setParameters(params);
         params = mCamera.getParameters();

         int bufFrameWidth, bufFrameHeight;
         bufFrameWidth = params.getPreviewSize().width;
         bufFrameHeight = params.getPreviewSize().height;

         if(width > height) {
             mFrameWidth = params.getPreviewSize().width;
             mFrameHeight = params.getPreviewSize().height;
         }else{
             mFrameWidth = params.getPreviewSize().height;
             mFrameHeight = params.getPreviewSize().width;
         }
...

         mFrameChain = new Mat[2];
         mFrameChain[0] = new Mat(bufFrameHeight + (bufFrameHeight/2), bufFrameWidth, CvType.CV_8UC1);
         mFrameChain[1] = new Mat(bufFrameHeight + (bufFrameHeight/2), bufFrameWidth, CvType.CV_8UC1);

         AllocateCache();

         mCameraFrame = new JavaCameraFrame[2];
         mCameraFrame[0] = new JavaCameraFrame(mFrameChain[0], bufFrameWidth, bufFrameHeight);
         mCameraFrame[1] = new JavaCameraFrame(mFrameChain[1], bufFrameWidth, bufFrameHeight);

これらの変更により、ポートレートに使用できる最高の結果を使用していることを確認しました (calculateCameraFrameSize で高さ/幅を切り替えます)。onPreviewFrame() からの入力としてランドスケープを引き続き処理しますが、ビットマップを作成してポートレート (AllocateCache) で描画します。

最後に、アルゴリズムが「立っている」オブジェクトを検出し、それをビットマップの保存とレンダリングのために返せるようにするために、アルゴリズムにポートレート フレームを指定する必要があります。したがって、アクティビティに次の変更を加えます。

public Mat rot90(Mat matImage, int rotflag){
    //1=CW, 2=CCW, 3=180
    Mat rotated = new Mat();
    if (rotflag == 1){
        rotated = matImage.t();
        flip(rotated, rotated, 1); //transpose+flip(1)=CW
    } else if (rotflag == 2) {
        rotated = matImage.t();
        flip(rotated, rotated,0); //transpose+flip(0)=CCW
    } else if (rotflag ==3){
        flip(matImage, rotated,-1);    //flip(-1)=180
    } else if (rotflag != 0){ //if not 0,1,2,3:
       Log.e(TAG, "Unknown rotation flag("+rotflag+")");
    }
    return rotated;
}

public Mat onCameraFrame(CvCameraViewFrame inputFrame) {

    mRgba = rot90(inputFrame.rgba(), 1);
    mGray = rot90(inputFrame.gray(), 1);
...
于 2016-04-14T12:44:37.787 に答える
1

openCV 2.4.9 を使用している場合は、次のことを試してください。1) コード内の opencv チュートリアル混合処理の内容をコピーします。2) 不一致エラー (アクティビティ名とおそらくレイアウト参照) を修正します。3) 追加してマニフェストを変更しますandroid:screenOrientation ="landscape" 。4) 未成年者のエラーを修正し、!!!! を実行します。bbaamm (これで正常に動作するはずです)

注: この方法では、電話が縦向きの場合、ステータス バーが右側に表示されます。カメラ プロジェクトを開発しているため、プレビューからステータス バーを削除することをお勧めします。

それが役に立てば幸い !!!

于 2015-02-19T05:42:56.047 に答える
0

私は CameraBridgeViewBase を縦向きにしていますが、OpenCV 内の JavaCameraView.java を変更する必要がありました :( アイデアは次のとおりです。

setDisplayOrientation(mCamera, 90);
mCamera.setPreviewDisplay(getHolder());

および setDisplayOrientation メソッド

protected void setDisplayOrientation(Camera camera, int angle){
    Method downPolymorphic;
    try
    {
        downPolymorphic = camera.getClass().getMethod("setDisplayOrientation", new Class[] { int.class });
        if (downPolymorphic != null)
            downPolymorphic.invoke(camera, new Object[] { angle });
    }
    catch (Exception e1)
    {
    }
}
于 2015-05-21T12:09:26.357 に答える
-3

このページJavaCameraView.javaで概説されているようにコードを変更します

修正するのは本当に簡単です。

Log.d(TAG, "startPreview");

mCamera.startPreview();

Log.d(TAG, "startPreview");

setDisplayOrientation(mCamera, 90);

mCamera.setPreviewDisplay(getHolder());

mCamera.startPreview();
于 2019-11-26T13:54:01.870 に答える