Opencv for Android(一) OpenCV概述及简单案例

1,247 阅读3分钟

Mat

Mat的概念

在Android中对图像是用bitmap格式来进行处理,而OpenCV中则是采用Mat格式,所以我们在程序中需要将bitmap转换成Mat格式以便使用OpenCV。Mat类用于表示一个多维的单通道或者多通道数组,能够用来保存实数或复数的向量,矩阵,灰度或者彩色图形,立体元素,张量以及直方图。简而言之,Mat就是表示图像的矩阵。

加载图片

Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.lbxx);

Bitmap和Mat的转换

Bitmap转Mat

Utils.matToBitmap(srcMat, dstMat);

Mat转Bitmap

Utils.bitmapToMat(srcMat,dstMat);

常见Mat位运算运算

修饰语与类型方法描述
static voidand (Mat src1, Mat src2, Mat dst)计算两个数组或一个数组和一个标量的每个元素的和
static voidbitwise_not (Mat src, Mat dst)反转数组的每一位
static voidbitwise_or (Mat src1, Mat src2, Mat dst)计算两个数组或一个数组和一个标量的逐元素逐位析取
static voidbitwise_xor (Mat src1, Mat src2, Mat dst)在两个数组或一个数组和一个标量上按位计算每个元素的“互斥或”操作

常见Mat算数运算

修饰语与类型方法描述
static voidadd (Mat src1, Mat src2, Mat dst)计算两个数组或一个数组和一个标量的每个元素的和
static voidsubtract (Mat src1, Mat src2, Mat dst)计算两个数组或数组与标量之间每个元素的差值
static voidmultiply (Mat src1, Mat src2, Mat dst)计算两个数组按元素缩放的乘积
static voiddivide (Mat src1, Mat src2, Mat dst)对两个数组或一个标量执行每个元素的除法

案例

这里以and()方法为例,即计算两个Mat的和,然后将结果显示出来

由于Android基本语法不是本文重点,所以界面的编写不做阐述,简单来说上面两个为源图像,下面的为结果图像,按钮AND会将计算他们两个每个元素的合,然后将结果显示到下面的图像。

加载源图像

        try {
            srcMat1 = Utils.loadResource(this, R.drawable.lbxx);
            srcMat2 = Utils.loadResource(this, R.drawable.lbxx2);
        } catch (IOException e) {
            e.printStackTrace();
        }

AND按钮的监听事件

        btnAnd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Core.bitwise_and(srcMat1, srcMat2, dstMat);
                resultBitmap = Bitmap.createBitmap(dstMat.width(), dstMat.height(), Bitmap.Config.ARGB_8888);
                Utils.matToBitmap(dstMat, resultBitmap);
                imageViewDst.setImageBitmap(resultBitmap);
            }
        });

按下后结果如下图所示

完整代码

MainActivity.java

package com.example.opencvdemo;

import androidx.appcompat.app.AppCompatActivity;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

import org.opencv.android.OpenCVLoader;
import org.opencv.android.Utils;
import org.opencv.core.Core;
import org.opencv.core.Mat;

import java.io.IOException;

public class MainActivity extends AppCompatActivity {

    private String TAG = "MainActivity";

    private Button btnAnd, btnNot, btnOr, btnXor, btnAdd, btnSub, btnMul, btnDiv;
    private ImageView imageViewSrc1, imageViewSrc2, imageViewDst;
    private Mat srcMat1, srcMat2, dstMat;
    private Bitmap resultBitmap;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        OpenCVInit();

        btnAnd = findViewById(R.id.btn_and);
        btnNot = findViewById(R.id.btn_not);
        btnOr = findViewById(R.id.btn_or);
        btnXor = findViewById(R.id.btn_xor);
        btnAdd = findViewById(R.id.btn_add);
        btnSub = findViewById(R.id.btn_sub);
        btnMul = findViewById(R.id.btn_mul);
        btnDiv = findViewById(R.id.btn_div);


        srcMat1 = new Mat();
        srcMat2 = new Mat();
        dstMat = new Mat();

        imageViewSrc1 = findViewById(R.id.iv_src1);
        imageViewSrc2 = findViewById(R.id.iv_src2);
        imageViewDst = findViewById(R.id.iv_dst);



        try {
            srcMat1 = Utils.loadResource(this, R.drawable.lbxx);
            srcMat2 = Utils.loadResource(this, R.drawable.lbxx2);
        } catch (IOException e) {
            e.printStackTrace();
        }

        btnAnd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Core.bitwise_and(srcMat1, srcMat2, dstMat);
                resultBitmap = Bitmap.createBitmap(dstMat.width(), dstMat.height(), Bitmap.Config.ARGB_8888);
                Utils.matToBitmap(dstMat, resultBitmap);
                imageViewDst.setImageBitmap(resultBitmap);
            }
        });

        btnNot.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Core.bitwise_not(srcMat1, dstMat);
                resultBitmap = Bitmap.createBitmap(srcMat1.width(), srcMat1.height(), Bitmap.Config.ARGB_8888);
                Utils.matToBitmap(dstMat, resultBitmap);
                imageViewDst.setImageBitmap(resultBitmap);
            }
        });

        btnOr.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Core.bitwise_or(srcMat1, srcMat2, dstMat);
                resultBitmap = Bitmap.createBitmap(srcMat1.width(), srcMat1.height(), Bitmap.Config.ARGB_8888);
                Utils.matToBitmap(dstMat, resultBitmap);
                imageViewDst.setImageBitmap(resultBitmap);
            }
        });

        btnXor.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Core.bitwise_xor(srcMat1, srcMat2, dstMat);
                resultBitmap = Bitmap.createBitmap(srcMat1.width(), srcMat1.height(), Bitmap.Config.ARGB_8888);
                Utils.matToBitmap(dstMat, resultBitmap);
                imageViewDst.setImageBitmap(resultBitmap);
            }
        });

        btnAdd.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Core.add(srcMat1, srcMat2, dstMat);
                resultBitmap = Bitmap.createBitmap(srcMat1.width(), srcMat1.height(), Bitmap.Config.ARGB_8888);
                Utils.matToBitmap(dstMat, resultBitmap);
                imageViewDst.setImageBitmap(resultBitmap);
            }
        });

        btnSub.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Core.subtract(srcMat1, srcMat2, dstMat);
                resultBitmap = Bitmap.createBitmap(srcMat1.width(), srcMat1.height(), Bitmap.Config.ARGB_8888);
                Utils.matToBitmap(dstMat, resultBitmap);
                imageViewDst.setImageBitmap(resultBitmap);
            }
        });

        btnMul.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Core.multiply(srcMat1, srcMat2, dstMat);
                resultBitmap = Bitmap.createBitmap(srcMat1.width(), srcMat1.height(), Bitmap.Config.ARGB_8888);
                Utils.matToBitmap(dstMat, resultBitmap);
                imageViewDst.setImageBitmap(resultBitmap);
            }
        });

        btnDiv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Core.divide(srcMat1, srcMat2, dstMat);
                resultBitmap = Bitmap.createBitmap(srcMat1.width(), srcMat1.height(), Bitmap.Config.ARGB_8888);
                Utils.matToBitmap(dstMat, resultBitmap);
                imageViewDst.setImageBitmap(resultBitmap);
            }
        });
    }


    private void OpenCVInit() {
        boolean success = OpenCVLoader.initDebug();
        if (success) {
            Log.d(TAG, "OpenCV Lode success");
        } else {
            Log.d(TAG, "OpenCV Lode failed ");
        }
    }

    @Override
    protected void onDestroy() {
        srcMat1.release();
        srcMat2.release();
        dstMat.release();
        super.onDestroy();
    }
}

activity_main.xml

<?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">

    <ImageView
        android:id="@+id/iv_src1"
        android:layout_width="125dp"
        android:layout_height="125dp"
        app:layout_constraintBottom_toTopOf="@+id/btn_not"
        app:layout_constraintEnd_toStartOf="@id/iv_src2"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@drawable/lbxx" />

    <ImageView
        android:id="@+id/iv_src2"
        android:layout_width="125dp"
        android:layout_height="125dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@id/iv_src1"
        app:layout_constraintTop_toTopOf="@+id/iv_src1"
        app:srcCompat="@drawable/lbxx2" />

    <Button
        android:id="@+id/btn_and"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="and"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@id/btn_not"
        app:layout_constraintHorizontal_bias="0.5"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.363" />

    <Button
        android:id="@+id/btn_not"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="not"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@id/btn_or"
        app:layout_constraintStart_toEndOf="@id/btn_and"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.363" />

    <Button
        android:id="@+id/btn_or"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="or"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@id/btn_xor"
        app:layout_constraintStart_toEndOf="@id/btn_not"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.363" />

    <Button
        android:id="@+id/btn_xor"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="xor"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@id/btn_or"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.363" />

    <Button
        android:id="@+id/btn_add"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="add"
        app:layout_constraintStart_toStartOf="@+id/btn_and"
        app:layout_constraintTop_toBottomOf="@+id/btn_and" />

    <Button
        android:id="@+id/btn_sub"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="sub"
        app:layout_constraintStart_toStartOf="@+id/btn_not"
        app:layout_constraintTop_toTopOf="@+id/btn_add" />

    <Button
        android:id="@+id/btn_mul"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="mul"
        app:layout_constraintStart_toStartOf="@+id/btn_or"
        app:layout_constraintTop_toTopOf="@+id/btn_sub" />

    <Button
        android:id="@+id/btn_div"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="div"
        app:layout_constraintStart_toStartOf="@+id/btn_xor"
        app:layout_constraintTop_toTopOf="@+id/btn_mul" />

    <ImageView
        android:id="@+id/iv_dst"
        android:layout_width="206dp"
        android:layout_height="206dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.497"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/btn_sub"
        app:srcCompat="@drawable/lbxx" />
</androidx.constraintlayout.widget.ConstraintLayout>

图像素材