Android基于OpenCV实现相机实时图像检测

计算机软件开发 2024-10-3 06:18:29 27 0 来自 中国
一.Android摄像头预览

Android OpenCV开辟过程中,我们有3种可选方式去实现Android摄像头预览功能:

  • 利用Android体系Camera API
  • 利用CameraX(JetPack组件)
  • 利用OpenCV SDK辅助类(JavaCameraView、JavaCamera2View等)
利用Android OpenCV SDK实现相机预览

1.分析权限
  <uses-permission android:name="android.permission.CAMERA" />  <uses-feature        android:name="android.hardware.camera"        android:required="false" />    <uses-feature        android:name="android.hardware.camera.autofocus"        android:required="false" />    <uses-feature        android:name="android.hardware.camera.front"        android:required="false" />    <uses-feature        android:name="android.hardware.camera.front.autofocus"        android:required="false" />2.布局添加JavaCameraView或者JavaCamera2View至布局
<?xml version="1.0" encoding="utf-8"?><androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    tools:context=".MainActivity">    <org.opencv.android.JavaCamera2View        android:id="@+id/camera_view"        app:layout_constraintTop_toTopOf="parent"        app:layout_constraintLeft_toLeftOf="parent"        android:layout_width="match_parent"        android:layout_height="match_parent">    </org.opencv.android.JavaCamera2View>    <ImageView        android:id="@+id/image_view"        android:layout_width="match_parent"        android:layout_height="match_parent">    </ImageView></androidx.constraintlayout.widget.ConstraintLayout>3.Activity继续CameraActivity,实现CameraBridgeViewBase.CvCameraViewListener或者CameraBridgeViewBase.CvCameraViewListener2接口,两个接口的差异重要会集在onCameraFrame回调。
  @Override    public void onCameraViewStarted(int width, int height) {    }    @Override    public void onCameraViewStopped() {    }    @Override    public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {        // 获取相机中的图像        Mat rgba = inputFrame.rgba();        Core.rotate(rgba, rgba, Core.ROTATE_90_CLOCKWISE);        Bitmap bitmap = Bitmap.createBitmap(rgba.cols(), rgba.rows(), Bitmap.Config.ARGB_8888);        Utils.matToBitmap(rgba, bitmap);        Bitmap location = location(bitmap);        if (location==null){            return null;        }        runOnUiThread(() -> image_view.setImageBitmap(location));        return null;    }4.复写方法getCameraViewList
@Override    protected List<? extends CameraBridgeViewBase> getCameraViewList() {        return Arrays.asList(mCVCamera);    }二.物体检测

1.在onCameraFrame回调中拿到图像后做一次滤镜去除干扰再举行边沿检测,这时间边沿大概并不是连通的以是我们再对图像做一次膨胀利用。最后举行轮廓检测将检测到的轮廓绘制到原图上。
  private Bitmap location(Bitmap bmp) {        Mat originMat=new Mat();        Utils.bitmapToMat(bmp,originMat);        Mat resultG = new Mat();        Mat result = new Mat();        Imgproc.GaussianBlur(originMat, resultG, new Size(3.0, 3.0), 0);        Imgproc.Canny(resultG, result, 100.0, 220.0, 3);        // 膨胀,毗连边沿        Imgproc.dilate(result, result, new Mat(), new Point(-1,-1), 4, 1, new Scalar(1));//        Bitmap Bmp = Bitmap.createBitmap(result.cols(), result.rows(), Bitmap.Config.ARGB_8888);//        Utils.matToBitmap(result,Bmp);        List<MatOfPoint> contours  = new ArrayList<>();        Mat hierarchy = new Mat();        Imgproc.findContours(result, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);        //有了轮廓之后,为了方便我们先将轮廓给画出来,这里的resultMat实在就是srcMat,为了区分用了Mat resultMat = srcMat.clone();,        // 下面代码的意思是,把contours轮廓列表中的所有轮廓(-1体现所有轮廓)在,resultMat上画用玄色(new Scalar(0, 0, 0))粗细为10的线条画出来。        if (contours.isEmpty()){            return null;        }        Mat resultMat = resultG.clone();        double arcLength=0;        int index=0;        for (int i = 0; i < contours.size(); i++) {            MatOfPoint2f source = new MatOfPoint2f();            source.fromList(contours.get(i).toList());            if (Imgproc.arcLength(source, true)>arcLength){                arcLength=Imgproc.arcLength(source, true);                index=i;            }        }        MatOfPoint matOfPoint = contours.get(index);        MatOfPoint2f tempMat=new MatOfPoint2f();        Imgproc.approxPolyDP(new MatOfPoint2f(matOfPoint.toArray()), tempMat, Imgproc.arcLength(new MatOfPoint2f(matOfPoint.toArray()), true)*0.04, true);        Point[] points = tempMat.toArray();        if (points.length!=4){            return null;        }        List<MatOfPoint> matOfPoints  = new ArrayList<>();        matOfPoints.add(new MatOfPoint(tempMat.toArray()));        Imgproc.drawContours(resultMat, matOfPoints, -1, new Scalar(0, 0, 255), 4);        Bitmap resultBmp = Bitmap.createBitmap(resultMat.cols(), resultMat.rows(), Bitmap.Config.ARGB_8888);        Utils.matToBitmap(resultMat,resultBmp);        return resultBmp;    }三.结果

没办法传视频。https://github.com/jzqCode/OpenCvDemo

您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-10-18 16:50, Processed in 0.121163 second(s), 32 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表