OpenCV4Android中如何运用手机摄像头获取Canny边缘

发布时间:2021-12-15 18:07:16 作者:柒染
来源:亿速云 阅读:259

OpenCV4Android中如何运用手机摄像头获取Canny边缘,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。

在图像中获取主要影响的边缘用处比较广泛,这样就用到了Canny边缘的效果

Canny边缘的提取流程

  1. 高斯模糊

  2. 梯度计算

  3. 非最大信息压制

  4. 高低阈值链接

  5. 显示

还是用我们的Demo

不过这次我们加上新的东西,因为正好学习了OpenCV里面调用手机里的摄像头功能获取图片信息,花了整整一天算是入了个门吧.

首先在原来的MainActivity里面增加一个按钮

OpenCV4Android中如何运用手机摄像头获取Canny边缘

OpenCV4Android中如何运用手机摄像头获取Canny边缘

对应增加的事件

OpenCV4Android中如何运用手机摄像头获取Canny边缘

照相机页面

OpenCV4Android中如何运用手机摄像头获取Canny边缘

首先我们增加了一个opencvcarema.xml页面和一个OpenCVCarema的activity

opencvcarema.xml

这里面可以直接增加org.opencv.android.JavaCameraView,然后又在下方增加了一个按钮

OpenCV4Android中如何运用手机摄像头获取Canny边缘

OpenCV4Android中如何运用手机摄像头获取Canny边缘

OpenCvCarema

这个class我们需要继承Activity并且引用了

CameraBridgeViewBase.CvCameraViewListener2

里面几个的方法

按钮获取当前图像提取边缘

OpenCV4Android中如何运用手机摄像头获取Canny边缘

里面就是根据获取的图像创建一个bitbmp的图像,然后把获取的图像mRgbaF先用高斯模糊后,再转成灰度图,然后再运用Canny边缘提取出新的Mat,再将提取完的转回为bmp图像,因为我们需要返回数据,所以返回时把bmp图像转为byte[]发送回去,原来我们的MainActivity里的onActivityResult里面增加了返回照相机数据

OpenCV4Android中如何运用手机摄像头获取Canny边缘

照相机获取图像时加入了横竖屏的判断

在OpenCV调用照相机时,默认的都是横屏,所以我们竖屏手机打开时会是个90的旋转样子,非常不友好,经常查找资料和多次测试,我自己修改了onCameraFrame这个函数

OpenCV4Android中如何运用手机摄像头获取Canny边缘

标红的这块是就是判断当前手机屏幕是横屏和竖屏,通过宽度和高度进行对比,宽度大于高度时就是横屏,小于时就是竖屏.

如果是竖屏我们就执行以下步骤:

下面的我们的视频效果,最后有OpenCVCarema.java整个类的代码

下面的整个OpenCvCarema.java的类

package dem.vaccae.opencvdemo;

import android.app.Activity;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Camera;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.support.annotation.Nullable;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;

import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.OpenCVLoader;
import org.opencv.android.Utils;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;

import java.io.ByteArrayOutputStream;

/**
 * Created by Administrator on 2018-01-01.
 */

public class OpenCvCarema extends Activity implements CameraBridgeViewBase.CvCameraViewListener2 {

    private static final String TAG = "OpenCvCameraActivity";

    static {
        OpenCVLoader.initDebug();
    }


    private Mat mRgba;
    private Mat mRgbaF;
    private Mat mFlipRgba;

    private Camera mCamera;

    private CameraBridgeViewBase mOpenCvCameraView;

    private Button btnCanny;

    //是否按下按键
    private boolean isbtn = false;
    private Bitmap bmp;


    public OpenCvCarema() {
        Log.i(TAG, "Instantiated new " + this.getClass());
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        Log.i(TAG, "called onCreate");
        super.onCreate(savedInstanceState);

        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);

        setContentView(R.layout.opencvcarema);


        mOpenCvCameraView = findViewById(R.id.opencvcaremaview);
        mOpenCvCameraView.enableView();
        mOpenCvCameraView.setCvCameraViewListener(this);
        //后置摄像头
        mOpenCvCameraView.setCameraIndex(CameraBridgeViewBase.CAMERA_ID_BACK);

        btnCanny = findViewById(R.id.btnCanny);
        btnCanny.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                isbtn = true;
                bmp = Bitmap.createBitmap(mRgbaF.width(), mRgbaF.height(), Bitmap.Config.ARGB_8888);

                //先进行高斯模糊
                Imgproc.GaussianBlur(mRgbaF, mRgbaF, new Size(3, 3), 0, 0, Imgproc.BORDER_DEFAULT);
                //先改为灰度图像
                Imgproc.cvtColor(mRgbaF, mRgbaF, Imgproc.COLOR_BGRA2GRAY);
                //t代表低阈值,高阈值一般是低阈值的2倍,所以threshold用t*2或t*3即可,
                //apertureSize这里输入3,就是代表3*3的眼膜
                //L2gradient这个是对精度要求,如果是true精度会高,但是会慢,所以一般来说我们都用false就可以了
                Imgproc.Canny(mRgbaF, mFlipRgba, 112, 112 * 2, 3, false);

                Utils.matToBitmap(mFlipRgba, bmp);

                //将图片压缩成byte[]传递回去
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                bmp.compress(Bitmap.CompressFormat.PNG, 100, baos);
                byte[] bitmapByte = baos.toByteArray();

                Intent rtnintent = new Intent();
                rtnintent.putExtra("bitmap", bitmapByte);
                OpenCvCarema.this.setResult(Activity.RESULT_OK, rtnintent);
                finish();
            }
        });
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mOpenCvCameraView != null)
            mOpenCvCameraView.disableView();
    }

    @Override
    protected void onResume() {
        super.onResume();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mOpenCvCameraView.disableView();
    }

    @Override
    public void onCameraViewStarted(int width, int height) {
        mRgba = new Mat();
        mRgbaF = new Mat();
        mFlipRgba = new Mat();
    }

    @Override
    public void onCameraViewStopped() {
        mFlipRgba.release();
        mRgbaF.release();
    }

    @Override
    public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
        if (!isbtn) {
            //注意
            mRgba = inputFrame.rgba();

            //获取屏幕宽和高用于判断是横屏还是竖屏
            DisplayMetrics dm = getResources().getDisplayMetrics();
            if (dm.widthPixels < dm.heightPixels) {
                //转置函数,可以水平的图像变为垂直
                Core.transpose(mRgba, mFlipRgba);
                //将转置后的图像缩放为mRgbaF的大小
                Imgproc.resize(mFlipRgba, mRgbaF, mRgba.size(), 0.0D, 0.0D, 0);
                //flipCode>0将mRgbaF水平翻转(沿Y轴翻转)得到mRgba
                Core.flip(mRgbaF, mRgbaF, 1);
            } else {
                mRgbaF = mRgba;
            }
        }
        return mRgbaF;
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        return true;
    }
}

看完上述内容,你们掌握OpenCV4Android中如何运用手机摄像头获取Canny边缘的方法了吗?如果还想学到更多技能或想了解更多相关内容,欢迎关注亿速云行业资讯频道,感谢各位的阅读!

推荐阅读:
  1. OpenCV中如何使用Sobel、Laplacian、Canny进行边缘检测
  2. 如何实现python Canny边缘检测算法

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

canny android opencv

上一篇:OpenCV如何实现腐蚀

下一篇:linux如何修改path环境变量

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》