一.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
|