Android OpenCV SDK使用图像对比

下载SDK mode导入

implementation project(path: ':opencvsdk')

 

//opencvsdk 的gradle

// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.

//
// Notes about integration OpenCV into existed Android Studio application project are below (application 'app' module should exist).
//
// This file is located in <OpenCV-android-sdk>/sdk directory (near 'etc', 'java', 'native' subdirectories)
//
// Add module into Android Studio application project:
//
// - Android Studio way:
//   (will copy almost all OpenCV Android SDK into your project, ~200Mb)
//
//   Import module: Menu -> "File" -> "New" -> "Module" -> "Import Gradle project":
//   Source directory: select this "sdk" directory
//   Module name: ":opencv"
//
// - or attach library module from OpenCV Android SDK
//   (without copying into application project directory, allow to share the same module between projects)
//
//   Edit "settings.gradle" and add these lines:
//
//   def opencvsdk='<path_to_opencv_android_sdk_rootdir>'
//   // You can put declaration above into gradle.properties file instead (including file in HOME directory),
//   // but without 'def' and apostrophe symbols ('): opencvsdk=<path_to_opencv_android_sdk_rootdir>
//   include ':opencv'
//   project(':opencv').projectDir = new File(opencvsdk + '/sdk')
//
//
//
// Add dependency into application module:
//
// - Android Studio way:
//   "Open Module Settings" (F4) -> "Dependencies" tab
//
// - or add "project(':opencv')" dependency into app/build.gradle:
//
//   dependencies {
//       implementation fileTree(dir: 'libs', include: ['*.jar'])
//       ...
//       implementation project(':opencv')
//   }
//
//
//
// Load OpenCV native library before using:
//
// - avoid using of "OpenCVLoader.initAsync()" approach - it is deprecated
//   It may load library with different version (from OpenCV Android Manager, which is installed separatelly on device)
//
// - use "System.loadLibrary("opencv_java4")" or "OpenCVLoader.initDebug()"
//   TODO: Add accurate API to load OpenCV native library
//
//
//
// Native C++ support (necessary to use OpenCV in native code of application only):
//
// - Use find_package() in app/CMakeLists.txt:
//
//   find_package(OpenCV 3.4 REQUIRED java)
//   ...
//   target_link_libraries(native-lib ${OpenCV_LIBRARIES})
//
// - Add "OpenCV_DIR" and enable C++ exceptions/RTTI support via app/build.gradle
//   Documentation about CMake options: https://developer.android.com/ndk/guides/cmake.html
//
//   defaultConfig {
//       ...
//       externalNativeBuild {
//           cmake {
//               cppFlags "-std=c++11 -frtti -fexceptions"
//               arguments "-DOpenCV_DIR=" + opencvsdk + "/sdk/native/jni" // , "-DANDROID_ARM_NEON=TRUE"
//           }
//       }
//   }
//
// - (optional) Limit/filter ABIs to build ('android' scope of 'app/build.gradle'):
//   Useful information: https://developer.android.com/studio/build/gradle-tips.html (Configure separate APKs per ABI)
//
//   splits {
//       abi {
//           enable true
//           universalApk false
//           reset()
//           include 'armeabi-v7a' // , 'x86', 'x86_64', 'arm64-v8a'
//       }
//   }
//

apply plugin: 'com.android.library'

def openCVersionName = "4.3.0"
def openCVersionCode = ((4 * 100 + 3) * 100 + 0) * 10 + 0

println "OpenCV: " +openCVersionName + " " + project.buildscript.sourceFile

android {
    compileSdkVersion 26

    defaultConfig {
        minSdkVersion 21
        targetSdkVersion 26

        versionCode openCVersionCode
        versionName openCVersionName

        externalNativeBuild {
            cmake {
                arguments "-DANDROID_STL=c++_shared"
                targets "opencv_jni_shared"
            }
        }
    }

    buildTypes {
        debug {
            packagingOptions {
                doNotStrip '**/*.so'  // controlled by OpenCV CMake scripts
            }
        }
        release {
            packagingOptions {
                doNotStrip '**/*.so'  // controlled by OpenCV CMake scripts
            }
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_6
        targetCompatibility JavaVersion.VERSION_1_6
    }

    sourceSets {
        main {
            jniLibs.srcDirs = ['native/libs']
            java.srcDirs = ['java/src']
            aidl.srcDirs = ['java/src']
            res.srcDirs = ['java/res']
            manifest.srcFile 'java/AndroidManifest.xml'
        }
    }

    externalNativeBuild {
        cmake {
            path (project.projectDir.toString() + '/libcxx_helper/CMakeLists.txt')
        }
    }
}

dependencies {
}

 

 

 

//使用

//判断是否加载成功
if (!OpenCVLoader.initDebug()) {
    Log.d("TAG", "Internal OpenCV library not found. Using OpenCV Manager for initialization");
    // OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, null);
} else {
    Log.d("TAG", "OpenCV library found inside package. Using it!");

}
使用openvc比较图片,可以使用相机拍照

public class HistUtils {

    /**
     * 比较来个矩阵的相似度
     *
     * @param mBitmap1
     * @param mBitmap2
     * @return
     */
    public static double comPareHist(Bitmap mBitmap1, Bitmap mBitmap2) {

        mBitmap2 = imageScale(mBitmap1,mBitmap2);

        Mat mat1 = new Mat();
        Mat mat2 = new Mat();
        Utils.bitmapToMat(mBitmap1, mat1);
        Utils.bitmapToMat(mBitmap2, mat2);
        return comPareHist(mat1, mat2);
    }

    /**
     * 调整图片大小
     *
     * @return
     */
    public static Bitmap imageScale(Bitmap bitmap1,Bitmap bitmap2) {

        int dst_w = bitmap1.getWidth();
        int dst_h = bitmap1.getHeight();
        int src_w = bitmap2.getWidth();
        int src_h = bitmap2.getHeight();
        float scale_w = ((float) dst_w) / src_w;
        float scale_h = ((float) dst_h) / src_h;
        Matrix matrix = new Matrix();
        matrix.postScale(scale_w, scale_h);
        Bitmap dstbmp = Bitmap.createBitmap(bitmap2, 0, 0, src_w, src_h, matrix,
                true);
        return dstbmp;
    }



    public static Mat yuv420(Image image) {
        // yuv420图片有三个通道,按顺序下来分别对应YUV
        // 转换需要把三个通道的数据按顺序合并在一个数组里,
        // 即全部Y,随后全部U,再随后全部是V,
        // 再由此数组生成Yuv420的Mat,
        // 之后可以利用opencv将其转为其他格式
        Image.Plane[] plans = image.getPlanes();
        ByteBuffer y = plans[0].getBuffer();
        ByteBuffer u = plans[1].getBuffer();
        ByteBuffer v = plans[2].getBuffer();
        // 此处需要把postition移到0才能读取
        y.position(0);
        u.position(0);
        v.position(0);
        int yl = y.remaining();
        // yuv420即4个Y对应1个U和一个V,即4:1:1的关系,长度刚好是Y的1.5倍
        ByteBuffer data = ByteBuffer.allocateDirect(yl * 3 / 2);
        // y通道直接全部插入
        data.put(y);
        copy(data, u, yl);
        copy(data, v, yl);
        // 生成Yuv420格式的Mat
        int rows = image.getHeight();
        int cols = image.getWidth();
        return new Mat(rows * 3 / 2, cols, CvType.CV_8UC1, data);
    }

    // 复制uv通道数据
    private static void copy(ByteBuffer data, ByteBuffer uv, int yl) {
        int l = uv.remaining();
        int quarter = yl / 4;
        int half = yl / 2;
        if (l == quarter) {
            // 魅族M8,长度刚好是y的四分之一,直接写入。
            data.put(uv);
        } else if (quarter < l && l <= half) {
            // 华为荣耀,实际读取到的长度是y的(1 / 2 - 1)
            for (int i = 0; i < l; i++) {
                byte b = uv.get();
                if (i % 2 == 0) {
                    data.put(b);
                }
            }
        } else if (l > half) {
            // 未发现此种情况,先预留着
            for (int i = 0; i < l; i++) {
                byte b = uv.get();
                if (i % 4 == 0) {
                    data.put(b);
                }
            }
        }
    }


    /**
     * 比较来个矩阵的相似度
     *
     * @param mat1
     * @param mat2
     * @return
     */
    public static double comPareHist(Mat mat1, Mat mat2) {
        Mat srcMat = new Mat();
        Mat desMat = new Mat();


        Imgproc.cvtColor(mat1, srcMat, Imgproc.COLOR_BGR2GRAY);
        Imgproc.cvtColor(mat2, desMat, Imgproc.COLOR_BGR2GRAY);
        srcMat.convertTo(srcMat, CvType.CV_32F);
        desMat.convertTo(desMat, CvType.CV_32F);
        double target = Imgproc.compareHist(srcMat, desMat,
                Imgproc.CV_COMP_CORREL);
        return target;
    }



}

 

 

使用相机拍照部分代码


    private Bitmap bmp1, bmp2;
    private TextView textView;
    private Camera mCamera = null;

        mSurfaceView = findViewById(R.id.surface_view);
        SurfaceHolder mSurfaceHolder = mSurfaceView.getHolder();
        mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        mSurfaceHolder.addCallback(new NewSurfaceHolder());



    class NewSurfaceHolder implements SurfaceHolder.Callback {

        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            L.e("surfaceCreated");
            try {
                if (mCamera != null) {
                    mCamera.stopPreview();
                    mCamera.release();
                    mCamera = null;
                }

                int numberOfCameras = Camera.getNumberOfCameras();
                if (numberOfCameras > 0) {
                    mCamera = Camera.open(0);
                    mCameraIsOpening = true;
                    mCamera.setPreviewDisplay(holder);
//                    mCamera.startPreview();
                }


            } catch (Exception e) {
                e.printStackTrace();
                writeLog(e.toString());

                // T.showShort(context, e.toString());

            }
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
            L.e("surfaceChanged");
            new Handler().postDelayed(
                    () -> {
                        if (mCamera != null) {
                            Camera.Parameters parameters = mCamera.getParameters(); // 获取各项参数
                            parameters.setPictureFormat(PixelFormat.JPEG); // 设置图片格式
                            parameters.setJpegQuality(40); // 设置照片质量
                            // 以下不设置在某些机型上报错

                            List<Camera.Size> sizeList = parameters.getSupportedPreviewSizes();

                            writeLog("支持的宽高:"+new Gson().toJson(sizeList));
                            int w0 = sizeList.get(0).width;
                            int h0 = sizeList.get(0).height;
                            for(int i =0; i < sizeList.size();i++){
                                if(w0>sizeList.get(i).width){
                                    if(sizeList.get(i).width>=640){
                                        w0 = sizeList.get(i).width;
                                        h0 = sizeList.get(i).height;
                                    }

                                }
                            }
                            parameters.setPreviewSize(w0, h0);
                            writeLog("预览宽高  :"+w0 + "  *  " + h0);



                            List<Camera.Size> picSizeList = parameters.getSupportedPictureSizes();

                            writeLog("支持的图片宽高:"+new Gson().toJson(picSizeList));
                            int picW0 = picSizeList.get(0).width;
                            int picH0 = picSizeList.get(0).height;
                            for(int i =0; i < picSizeList.size();i++){
                                if(picW0>picSizeList.get(i).width){
                                    if(picSizeList.get(i).width>=640){
                                        picW0 = picSizeList.get(i).width;
                                        picH0 = picSizeList.get(i).height;
                                    }

                                }
                            }
                            parameters.setPictureSize(picW0, picH0);
                            writeLog("预览图片宽高  :"+picW0 + "  *  " + picH0);


                            mCamera.setParameters(parameters);
                            mCamera.startPreview();
                            mCameraIsOpening = false;
                        }
                    }
                    , 5000);


        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
            L.e("surfaceDestroyed");
            if (mCamera != null) {
                mCamera.stopPreview();
                mCamera.release();
                mCamera = null;
            }

        }
    }

















//拍照


    private void getPicture() {
        if (mCamera != null && !mCameraIsOpening) {

            try {
                mCamera.takePicture(null, null, (data, camera) -> {
                    Bitmap source = BitmapFactory.decodeByteArray(data, 0, data.length);
                    if (bmp1 == null) {
                        bmp1 = source;
                    } else {
                        bmp2 = source;
                        hist();
                    }
                    //  mCamera.startPreview();
                });

            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

    @SuppressLint({"DefaultLocale", "SetTextI18n"})
    private void hist() {
        L.e("hist");
        new Thread(() -> {

            if (bmp1 != null & bmp2 != null) {
                final double target = HistUtils.comPareHist(bmp1, bmp2);
                L.e(target + "");
                //975 980  990
                if (target < Datas.threshold) {
                
                }
                activity.runOnUiThread(() -> {
                    textView.setText(String.format("%.6f", target) + "\n");
                    cameraPicIndex++;
                    if (cameraPicIndex > 3) {
                        bmp1 = bmp2;
                        cameraPicIndex = 0;
                    }

                });
            }

        }).start();
    }


 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值