在Android上玩转Opencv 系列:20.基础知识 利用霍夫变换检测直线和圆

Android 版 OpenCV 直线识别和圆识别

在 Android 上使用 OpenCV 进行直线识别 (Line Detection)和圆识别(Circle Detection)主要依赖 Hough 变换(Hough Transform),这是一种强大的几何检测方法,可用于检测边缘检测后的直线和圆形目标。

1. 直线识别(Hough 直线变换)

1.1 直线检测原理

Hough 直线检测主要用于在图像中寻找直线,其原理基于极坐标表示直线方程

其中:

通过遍历所有可能的 组合,将投票数最高的参数对确定为直线。

1.2 直线识别步骤

  1. 读取图像并转换为灰度图

  2. 使用 Canny 算法提取边缘

  3. 使用 HoughLines 或 HoughLinesP 进行直线检测

  4. 绘制检测出的直线

1.3 直线检测代码(标准 Hough 变换)

ini 复制代码
import org.opencv.android.Utils;
import org.opencv.core.*;
import org.opencv.imgproc.Imgproc;
import android.graphics.Bitmap;
import java.util.*;

public class LineDetection {
    public static Bitmap detectLines(Bitmap inputBitmap) {
        // 将 Bitmap 转换为 Mat
        Mat srcMat = new Mat();
        Utils.bitmapToMat(inputBitmap, srcMat);

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

        // 使用 Canny 进行边缘检测
        Mat edges = new Mat();
        Imgproc.Canny(grayMat, edges, 50, 150);

        // 进行 Hough 直线检测
        Mat lines = new Mat();
        Imgproc.HoughLines(edges, lines, 1, Math.PI / 180, 100);

        // 在原图上绘制检测到的直线
        for (int i = 0; i < lines.rows(); i++) {
            double[] data = lines.get(i, 0);
            double rho = data[0];
            double theta = data[1];
            double a = Math.cos(theta);
            double b = Math.sin(theta);
            double x0 = a * rho;
            double y0 = b * rho;
            Point pt1 = new Point(x0 + 1000 * (-b), y0 + 1000 * (a));
            Point pt2 = new Point(x0 - 1000 * (-b), y0 - 1000 * (a));
            Imgproc.line(srcMat, pt1, pt2, new Scalar(0, 255, 0), 2);
        }

        // 转换回 Bitmap
        Bitmap outputBitmap = Bitmap.createBitmap(srcMat.cols(), srcMat.rows(), Bitmap.Config.ARGB_8888);
        Utils.matToBitmap(srcMat, outputBitmap);

        return outputBitmap;
    }
}

1.4 直线检测代码(概率 Hough 变换)

HoughLinesP() 是 HoughLines() 的优化版本,适用于断续线条的检测。

ini 复制代码
public static Bitmap detectProbabilisticLines(Bitmap inputBitmap) {
    // 转换 Bitmap 为 Mat
    Mat srcMat = new Mat();
    Utils.bitmapToMat(inputBitmap, srcMat);

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

    // Canny 边缘检测
    Mat edges = new Mat();
    Imgproc.Canny(grayMat, edges, 50, 150);

    // 进行概率 Hough 直线检测
    Mat lines = new Mat();
    Imgproc.HoughLinesP(edges, lines, 1, Math.PI / 180, 50, 50, 10);

    // 绘制检测到的直线
    for (int i = 0; i < lines.rows(); i++) {
        double[] points = lines.get(i, 0);
        Point pt1 = new Point(points[0], points[1]);
        Point pt2 = new Point(points[2], points[3]);
        Imgproc.line(srcMat, pt1, pt2, new Scalar(255, 0, 0), 2);
    }

    // 转换回 Bitmap
    Bitmap outputBitmap = Bitmap.createBitmap(srcMat.cols(), srcMat.rows(), Bitmap.Config.ARGB_8888);
    Utils.matToBitmap(srcMat, outputBitmap);

    return outputBitmap;
}

2. 圆识别(Hough 圆变换)

2.1 圆检测原理

Hough 圆检测利用标准方程:

通过遍历不同的 (a, b, r) 值,找出可能的圆形边缘。

2.2 圆识别步骤

  1. 读取图像并转换为灰度图

  2. 使用 GaussianBlur 平滑图像

  3. 使用 HoughCircles 进行圆检测

  4. 绘制检测出的圆

2.3 圆检测代码

ini 复制代码
import org.opencv.android.Utils;
import org.opencv.core.*;
import org.opencv.imgproc.Imgproc;
import android.graphics.Bitmap;
import java.util.*;

public class CircleDetection {
    public static Bitmap detectCircles(Bitmap inputBitmap) {
        // 转换 Bitmap 为 Mat
        Mat srcMat = new Mat();
        Utils.bitmapToMat(inputBitmap, srcMat);

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

        // 进行高斯模糊,减少噪声
        Imgproc.GaussianBlur(grayMat, grayMat, new Size(9, 9), 2, 2);

        // 进行 Hough 圆检测
        Mat circles = new Mat();
        Imgproc.HoughCircles(grayMat, circles, Imgproc.HOUGH_GRADIENT, 1, 30, 100, 30, 10, 100);

        // 在原图上绘制检测到的圆
        for (int i = 0; i < circles.cols(); i++) {
            double[] data = circles.get(0, i);
            Point center = new Point(data[0], data[1]);
            int radius = (int) data[2];
            Imgproc.circle(srcMat, center, radius, new Scalar(0, 255, 0), 2);
            Imgproc.circle(srcMat, center, 2, new Scalar(0, 0, 255), 3);
        }

        // 转换回 Bitmap
        Bitmap outputBitmap = Bitmap.createBitmap(srcMat.cols(), srcMat.rows(), Bitmap.Config.ARGB_8888);
        Utils.matToBitmap(srcMat, outputBitmap);

        return outputBitmap;
    }
}

3. 直线 vs 圆检测

Hough 直线检测 Hough 圆检测
适用场景 道路检测、边缘检测 车轮检测、标志识别
输入参数 需要边缘检测 需要模糊处理
计算复杂度

总结

HoughLines() 适用于规则直线(如道路边界)。

HoughLinesP() 适用于断续线(如车道线)。

HoughCircles() 适用于圆形检测(如硬币、车轮)。

• 预处理(如 CannyGaussianBlur)能提高检测精度。

相关推荐
qq_5260991316 小时前
图像采集卡:藏在机器“眼睛”背后的枢纽,撑起视觉智能化半边天
数码相机·opencv·计算机视觉
我是无敌小恐龙1 天前
Java SE 零基础入门Day01 超详细笔记(开发前言+环境搭建+基础语法)
java·开发语言·人工智能·opencv·spring·机器学习
是梦终空1 天前
计算机毕业设计271—基于python+深度学习+YOLOV7的车牌识别系统(源代码+数据库+3万字论文)
python·深度学习·opencv·yolo·毕业设计·pyqt5·车牌识别系统
爱凤的小光1 天前
OpenCV4机器学习算法原理与代码---个人学习篇
opencv·机器学习
JMchen1232 天前
集成第三方 C/C++ 库到 Android NDK 项目:OpenCV 与 FFmpeg 实战指南
opencv·ffmpeg·音视频开发·cmake·jni·ndk·abi 兼容性
明月醉窗台2 天前
Python-opencv批量处理文件夹中图像操作
开发语言·python·opencv
纤纡.2 天前
轻松实现多语言文字识别与实时检测:PaddleOCR 实战指南
人工智能·深度学习·opencv·paddlepaddle
格林威3 天前
工业相机“心跳”监测脚本(C# 版) 支持海康 / Basler / 堡盟工业相机
开发语言·人工智能·数码相机·opencv·计算机视觉·c#·视觉检测
编码小哥3 天前
OpenCV图像增强实战:对比度调整与Gamma校正
人工智能·opencv·计算机视觉
ComputerInBook4 天前
OpenCV图像处理——图像缩放函数 resize
图像处理·opencv·计算机视觉