在Android上玩转Opencv 系列:14.基础知识 计算图像的矩

250 阅读3分钟

Android 版本 OpenCV 计算图像的矩(Moments)

在 Android OpenCV 中,可以使用 Imgproc.moments() 方法计算图像的几何矩、中心矩和 Hu 不变矩(Hu Moments) 。这些矩可用于 计算质心(Centroid)图像形状分析目标检测 以及 模式识别

1. OpenCV 矩(Moments)的作用

几何矩(Geometric Moments) :计算图像的基本属性,如面积、质心、方向等。

中心矩(Central Moments) :消除图像的平移影响,使得计算结果不依赖于目标在图像中的位置。

归一化矩(Normalized Moments) :进一步消除尺度影响,使得矩与目标大小无关。

Hu 不变矩(Hu Moments) :在旋转、缩放和平移变换下保持不变,用于形状匹配和目标识别。

2. 在 OpenCV Android 中计算图像的矩

(1) 依赖配置

在 build.gradle 中添加 OpenCV 依赖:

implementation 'org.opencv:opencv-android:4.5.1'

(2) 计算几何矩、中心矩和 Hu 不变矩

下面的代码示例展示了如何在 Android OpenCV 中计算图像的矩,并提取 质心、面积、方向和 Hu 矩

完整代码

import android.graphics.Bitmap;
import android.os.Bundle;
import android.widget.ImageView;
import androidx.appcompat.app.AppCompatActivity;
import org.opencv.android.OpenCVLoader;
import org.opencv.android.Utils;
import org.opencv.core.Mat;
import org.opencv.core.Moments;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;

public class MomentsActivity extends AppCompatActivity {

    static {
        OpenCVLoader.initDebug(); // 初始化 OpenCV
    }

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

        // 加载图像
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.sample_image);
        Mat imgMat = new Mat();
        Utils.bitmapToMat(bitmap, imgMat);

        // 转换为灰度图
        Mat grayMat = new Mat();
        Imgproc.cvtColor(imgMat, grayMat, Imgproc.COLOR_BGR2GRAY);

        // 进行二值化处理
        Mat binaryMat = new Mat();
        Imgproc.threshold(grayMat, binaryMat, 128, 255, Imgproc.THRESH_BINARY);

        // 计算图像的矩
        Moments moments = Imgproc.moments(binaryMat, true);

        // 计算质心
        double cx = moments.get_m10() / moments.get_m00();
        double cy = moments.get_m01() / moments.get_m00();
        System.out.println("质心坐标: (" + cx + ", " + cy + ")");

        // 在图像上绘制质心
        Imgproc.circle(imgMat, new Point(cx, cy), 5, new Scalar(0, 0, 255), -1);

        // 计算 Hu 不变矩
        double[] huMoments = new double[7];
        Imgproc.HuMoments(moments, huMoments);

        // 打印 Hu 矩
        System.out.println("Hu 不变矩:");
        for (int i = 0; i < huMoments.length; i++) {
            System.out.println("I" + (i + 1) + ": " + huMoments[i]);
        }

        // 将结果转换回 Bitmap 并显示
        Bitmap resultBitmap = Bitmap.createBitmap(imgMat.cols(), imgMat.rows(), Bitmap.Config.ARGB_8888);
        Utils.matToBitmap(imgMat, resultBitmap);
        ImageView imageView = findViewById(R.id.imageView);
        imageView.setImageBitmap(resultBitmap);
    }
}

3. 代码解析

(1) 图像预处理

转换为灰度图

Imgproc.cvtColor(imgMat, grayMat, Imgproc.COLOR_BGR2GRAY);

由于计算矩通常对二值图进行,因此首先将图像转换为灰度图。

二值化处理

Imgproc.threshold(grayMat, binaryMat, 128, 255, Imgproc.THRESH_BINARY);

通过 threshold() 方法进行二值化处理,使目标区域清晰可见。

(2) 计算几何矩

Moments moments = Imgproc.moments(binaryMat, true);

• moments.get_m00():计算图像的面积(即目标区域的像素数)。

• moments.get_m10() 和 moments.get_m01():用于计算质心(Centroid)

质心计算公式

double cx = moments.get_m10() / moments.get_m00();
double cy = moments.get_m01() / moments.get_m00();
System.out.println("质心坐标: (" + cx + ", " + cy + ")");

质心的计算对于形状分析、物体跟踪和图像处理非常重要。

绘制质心点

Imgproc.circle(imgMat, new Point(cx, cy), 5, new Scalar(0, 0, 255), -1);

在图像上绘制一个红色的质心点,直观显示中心位置。

(3) 计算 Hu 不变矩

double[] huMoments = new double[7];
Imgproc.HuMoments(moments, huMoments);

Hu 矩的特点

• 具有 平移、缩放、旋转不变性,适用于形状匹配。

• 可以用于 模式识别,如 手写字符识别、目标分类 等。

打印 Hu 矩

for (int i = 0; i < huMoments.length; i++) {
    System.out.println("I" + (i + 1) + ": " + huMoments[i]);
}

4. 示例运行结果

如果输入的是一个白色物体的二值图像(黑色背景),输出示例如下:

质心坐标: (150.4, 180.7)
Hu 不变矩:
I1: 0.002314
I2: 5.6782e-06
I3: 3.0921e-11
I4: 1.3451e-12
I5: 2.7835e-19
I6: 5.4218e-16
I7: 3.1097e-20

同时,在 ImageView 中显示带有红色质心点的图像。

5. 总结

几何矩 可用于计算面积、质心、形状方向等信息。

中心矩 可消除平移影响,适用于位置无关的形状分析

Hu 不变矩 具有平移、旋转、缩放不变性,广泛用于模式识别目标匹配

Android OpenCV 提供了 Imgproc.moments() 计算矩,并可直接计算 Hu 矩,非常适用于图像处理任务。

通过这个方法,我们可以在 Android OpenCV 中高效计算图像的矩,并应用到目标检测、形状匹配和图像分析等领域。🚀