目录
一、图像连通域
1、连通域概念介绍
连通域是指图像中具有相同像素值且位置相邻的像素组成的区域。在图像处理中,连通域分析是指在图像中寻找出彼此互相独立的连通域并将其标记出来。连通域分析常用于目标检测、图像分割、特征提取等领域。
2、邻域类型介绍
在OpenCV中,邻域类型主要有两种:4-邻域和8-邻域。
- 4-邻域:像素点只与其上、下、左、右四个相邻像素相连通。
- 8-邻域:像素点除了与其上、下、左、右四个相邻像素相连通外,还与其对角线上的四个相邻像素相连通。
3、两遍扫描法
两遍扫描法是一种常用的连通域标记算法,它的基本思想是通过两次遍历图像,给每个连通域分配一个唯一的标签。
- 第一遍扫描:从左到右,从上到下遍历图像,为每个非零像素赋予一个唯一的标签。如果当前像素的上方或左侧邻域像素已经被赋予标签,则取两者中的最小值作为当前像素的标签;否则,赋予当前像素一个新的标签。
- 第二遍扫描:再次从左到右,从上到下遍历图像,使用并查集(Union-Find)数据结构将属于同一连通域的不同标签合并,实现同一个连通域中的所有像素点的标签一致。
4、种子填充法
种子填充法是一种基于区域生长的连通域标记算法。它的基本思想是从一个种子像素开始,根据邻域关系不断扩充种子像素所在的连通域,直到达到预设的停止条件。
- 初始化:将所有非零像素放入一个集合中,选择一个种子像素。
- 生长过程:检查种子像素的邻域像素,如果邻域像素具有相同的像素值且未被访问过,则将其加入连通域,并标记为已访问。重复此过程,直到连通域无法再扩充。
- 重复:从集合中随机选择一个新的种子像素,重复上述生长过程,直到集合中没有像素为止。
5、实例讲解
下面是一个使用OpenCV进行连通域分析的实例代码:
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main() {
// 读取图像
Mat src = imread("path_to_image.jpg", IMREAD_GRAYSCALE);
if (src.empty()) {
cout << "Could not open or find the image!" << endl;
return -1;
}
// 二值化处理
Mat binary;
threshold(src, binary, 127, 255, THRESH_BINARY);
// 连通域分析
Mat labels, stats, centroids;
int num_labels = connectedComponents(binary, labels, 8, CV_32S);
// 输出连通域数量
cout << "Number of connected components: " << num_labels << endl;
// 标记连通域(为了可视化,将标签转换为彩色图像)
Mat result;
result.create(binary.size(), CV_8UC3);
result = Scalar(0, 0, 0); // 初始化为黑色
// 为每个连通域分配随机颜色
std::map<int, Vec3b> colors;
for (int i = 1; i < num_labels; i++) {
colors[i] = Vec3b(rand() % 256, rand() % 256, rand() % 256);
}
// 填充连通域颜色
for (int y = 0; y < binary.rows; y++) {
for (int x = 0; x < binary.cols; x++) {
int label = labels.at<int>(y, x);
if (label > 0) {
result.at<Vec3b>(y, x) = colors[label];
}
}
}
// 显示结果
imshow("Connected Components", result);
waitKey(0);
return 0;
}
二、图像距离变换
1、概念
图像距离变换用于计算二值图像中每个像素到最近前景像素(通常为白色区域)或背景像素(黑色区域)的距离,生成灰度图像(距离图),其中像素灰度值表示距离值。例如,在分割后的二值图像中,距离变换可量化每个像素到边缘的空间分布。
2、原理
- 输入:二值图像(单通道,8位无符号整数,CV_8U),前景像素值为非零(如255),背景为0。
- 输出:灰度图像(单通道,32位浮点数,CV_32F),每个像素值表示到最近背景像素的距离。
- 核心逻辑:通过遍历图像,计算每个像素到最近背景像素的距离,并更新距离图。距离度量方式(如欧式距离、街区距离)影响计算结果。
3、作用
- 形态学分割:通过阈值处理距离图,可分离粘连物体(如细胞分割)。
- 骨架提取:结合形态学操作(如腐蚀、膨胀),可提取目标的中心线。
- 边缘检测:计算像素到边缘的距离,辅助非极大值抑制和阈值分割。
- 目标检测后处理:优化检测框或分割掩码的边界。
- 模板匹配:计算图像与模板的像素级距离,提升匹配精度。
4、分类
根据距离度量方式,距离变换分为以下三类:
| 类型 | 别名 | 定义 | 特点 |
|---|---|---|---|
| 欧式距离 | L2距离 | D(p,q)=(x1−x2)²+(y1−y2)² | 物理意义明确,计算复杂度高(含浮点运算), 适合物体中心定位。 |
| 街区距离 | L1距离、D4 | $D(p,q) =|x1-x2|+|y1-y2| | 旋转敏感性差,计算速度快,适合网格化场景。 |
| 棋盘距离 | D8距离 | $D(p,q) = max(|x1-x2|,|y1-y2|) | 对角线敏感,速算速度快,适合形态学操作。 |
5、计算方法
在Android OpenCV中,使用Imgproc.distanceTransform()函数实现距离变换,其参数如下:
public static void distanceTransform(
Mat src, // 输入二值图像(CV_8U)
Mat dst, // 输出距离图(CV_32F)
int distanceType, // 距离类型(DIST_L1、DIST_L2、DIST_C)
int maskSize, // 掩码大小(DIST_MASK_3、DIST_MASK_5、DIST_MASK_PRECISE)
int dstType // 输出类型(通常为CV_32F)
)
参数说明
- distanceType:选择距离度量方式(L1/L2/棋盘距离)。
- maskSize:控制计算精度。若
distanceType为DIST_L1或DIST_C,maskSize强制为3(3×3模板与5×5结果相同)。 - dstType:输出图像类型,通常为
CV_32F(浮点数)。
6、实例
以下代码演示如何对二值图像进行距离变换,并标记几何中心:
import org.opencv.android.Utils;
import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.widget.ImageView;
import androidx.appcompat.app.AppCompatActivity;
public class DistanceTransformActivity extends AppCompatActivity {
private Mat mBinary = new Mat(); // 二值图像
private Mat mDistance = new Mat(); // 距离图
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 1. 加载并二值化图像
Mat src = Imgcodecs.imread("input.jpg", Imgcodecs.IMREAD_GRAYSCALE);
Imgproc.threshold(src, mBinary, 127, 255, Imgproc.THRESH_BINARY_INV);
// 2. 计算距离变换(欧式距离)
Imgproc.distanceTransform(mBinary, mDistance, Imgproc.DIST_L2, 3, CV_32F);
// 3. 找到距离最大值(几何中心)
Core.MinMaxLocResult result = Core.minMaxLoc(mDistance);
Point center = result.maxLoc;
double maxDistance = result.maxVal;
// 4. 在原图标记中心
Mat resultImg = src.clone();
Imgproc.circle(resultImg, center, 5, new Scalar(0, 0, 255), -1);
// 5. 显示结果
ImageView ivResult = findViewById(R.id.iv_result);
Bitmap bitmap = Bitmap.createBitmap(resultImg.cols(), resultImg.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(resultImg, bitmap);
ivResult.setImageBitmap(bitmap);
}
}
代码解析
- 二值化:将输入图像转换为二值图像(前景为255,背景为0)。
- 距离变换:使用
Imgproc.distanceTransform()计算欧式距离图。 - 几何中心定位:通过
Core.minMaxLoc()找到距离最大值点(即几何中心)。 - 结果可视化:在原图标记几何中心并显示。
7、应用场景扩展
- 粘连物体分割:对距离图进行阈值处理,分离重叠区域。
- 指纹识别:提取指纹骨架,匹配特征点。
- 医学图像分析:测量细胞或器官的几何参数(如直径、面积)。
三、图像形态学
1、概念
图像形态学(Mathematical Morphology)是数字图像处理中基于形状的数学分析方法,通过结构元素(Kernel)与图像的相互作用提取形状特征。其核心思想是利用局部结构信息对图像进行非线性变换,广泛应用于二值图像处理(如目标检测、分割)和灰度图像处理(如边缘增强、去噪)。
2、原理
形态学操作基于结构元素(如矩形、十字形、椭圆形)在图像上滑动,通过比较结构元素与覆盖区域的像素值决定中心像素的输出值。
- 腐蚀(Erosion):结构元素覆盖区域内所有像素均为前景(白色)时,中心像素保留为前景;否则置为背景(黑色)。
- 膨胀(Dilation):结构元素覆盖区域内至少有一个像素为前景时,中心像素设置为前景。
- 开运算(Opening):先腐蚀后膨胀,消除小物体并平滑轮廓。
- 闭运算(Closing):先膨胀后腐蚀,填充小孔洞并连接邻近物体。
- 形态学梯度(Gradient):膨胀图与腐蚀图之差,突出边缘。
- 顶帽(Top Hat):原图与开运算结果之差,提取比邻近点亮的斑块。
- 黑帽(Black Hat):闭运算结果与原图之差,提取比邻近点暗的斑块。
3、作用
- 去噪:消除小噪声点(腐蚀)或填充小孔洞(膨胀)。
- 分离物体:断开粘连目标(腐蚀)或连接断裂部分(膨胀)。
- 边缘检测:通过形态学梯度或黑帽/顶帽运算提取轮廓。
- 形状分析:提取骨架、凸包等形状特征。
- 预处理:为后续分割、识别等任务提供更清晰的图像。
4、分类
| 操作类型 | 数学表达式 | 应用场景 |
|---|---|---|
| 腐蚀(Erosion) | dst=min(x′,y′)∈kernelsrc(x+x′,y+y′) | 去噪、分离物体 |
| 膨胀(Dilation) | dst=max(x′,y′)∈kernelsrc(x+x′,y+y′) | 填充孔洞、连接物体 |
| 开运算(Opening) | dst=dilate(erode(src)) | 去噪、平滑轮廓 |
| 闭运算(Closing) | dst=erode(dilate(src)) | 填充孔洞、连接断裂部分 |
| 形态学梯度(Gradient) | dst=dilate(src)−erode(src) | 边缘检测 |
| 顶帽(Top Hat) | dst=src−open(src) | 提取亮斑块 |
| 黑帽(Black Hat) | dst=close(src)−src | 提取暗斑块 |
| 击中击不中(Hit or Miss) | Intersection(erode(src),erode(src1)) | 粗化* |
5、计算方法
OpenCV通过Imgproc.morphologyEx()函数实现形态学操作,核心参数如下:
Imgproc.morphologyEx(
Mat src, // 输入图像(二值或灰度)
Mat dst, // 输出图像
int op, // 操作类型(如MORPH_ERODE、MORPH_DILATE等)
Mat kernel, // 结构元素(通过getStructuringElement生成)
Point anchor, // 锚点(默认中心)
int iterations,// 迭代次数(默认1)
int borderType,// 边界处理方式(默认BORDER_CONSTANT)
Scalar borderValue // 边界填充值
);
生成结构元素:
Mat kernel = Imgproc.getStructuringElement(
Imgproc.MORPH_RECT, // 形状(MORPH_RECT、MORPH_CROSS、MORPH_ELLIPSE)
new Size(3, 3) // 大小
);
6、图例
原图

腐蚀(去噪)

膨胀(填充空洞)

开运算(平滑轮廓)

闭运算(连接断裂部分)

morphology(突出边缘)

顶帽(亮斑提取)

黑帽(暗斑提取)

四、图像腐蚀
1、概念
图像腐蚀是形态学操作中的基础算法,通过结构元素(核)对图像进行局部最小值计算,消除边界点并使目标区域收缩。在OpenCV中,腐蚀操作常用于去除噪声、分离物体、提取骨架等场景,尤其适用于二值图像(黑白图像)的处理。
2、原理
(1)结构元素(核):
腐蚀操作的核心是结构元素,其形状和大小决定了腐蚀效果。OpenCV提供三种常见结构元素:
- 矩形(MORPH_RECT):适用于水平/垂直边缘处理。
- 十字形(MORPH_CROSS):对中心像素敏感,适合交叉点检测。
- 椭圆形(MORPH_ELLIPSE):各向同性,适合平滑边缘处理。
(2)操作过程:
结构元素在图像上滑动,覆盖区域的像素值与结构元素进行逻辑“与”操作。若所有覆盖像素均为高亮(白色),则中心像素保持原值;否则置为背景(黑色)。数学表达式为:
其中,src为输入图像,dst为输出图像,kernel为结构元素。
3、作用
- 消除小物体:去除图像中孤立的噪声点或微小目标。
- 分离粘连物体:通过腐蚀使相邻物体断开连接。
- 边界收缩:细化物体轮廓,提取骨架信息。
- 预处理:为后续分割、识别等任务提供更清晰的图像。
4、分类
根据结构元素和迭代次数,腐蚀操作可分为:
- 单次腐蚀:结构元素滑动一次,适用于轻度收缩。
- 多次腐蚀:通过
iterations参数控制迭代次数,增强腐蚀效果。 - 不同结构元素腐蚀:根据需求选择矩形、十字形或椭圆形核,适应不同场景。
5、计算方法
OpenCV中腐蚀操作通过Imgproc.erode()函数实现,其参数如下:
Imgproc.erode(
Mat src, // 输入图像(二值图像)
Mat dst, // 输出图像
Mat kernel, // 结构元素
Point anchor, // 锚点位置(默认中心)
int iterations, // 迭代次数(默认1)
int borderType, // 边界处理方式(默认BORDER_CONSTANT)
Scalar borderValue // 边界填充值
);
关键步骤:
(1)生成结构元素:使用Imgproc.getStructuringElement()创建核。
Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(3, 3));
(2)执行腐蚀:调用erode()函数处理图像。
Imgproc.erode(srcImage, dstImage, kernel);
6、实例
以下是一个完整的Android OpenCV图像腐蚀示例:
import org.opencv.android.Utils;
import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import android.graphics.Bitmap;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("opencv_java4"); // 加载OpenCV库
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 1. 读取图像(假设已转换为Mat格式)
Mat srcImage = Imgcodecs.imread("input.jpg", Imgcodecs.IMREAD_GRAYSCALE);
// 2. 二值化处理(腐蚀通常作用于二值图像)
Mat binaryImage = new Mat();
Imgproc.threshold(srcImage, binaryImage, 127, 255, Imgproc.THRESH_BINARY);
// 3. 生成结构元素(3x3矩形核)
Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(3, 3));
// 4. 执行腐蚀操作
Mat dstImage = new Mat();
Imgproc.erode(binaryImage, dstImage, kernel);
// 5. 显示结果(需将Mat转换为Bitmap)
Bitmap resultBitmap = Bitmap.createBitmap(dstImage.cols(), dstImage.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(dstImage, resultBitmap);
// 在ImageView中显示resultBitmap(代码略)
}
}
效果说明:
- 输入图像:包含噪声的二值图像。
- 输出图像:噪声被去除,物体边界收缩,粘连部分分离。
7、参数优化建议
(1)结构元素大小:
- 核越大,腐蚀效果越强,但可能丢失细节。
- 示例:分离粘连文字时,可尝试
Size(5,5)或Size(7,7)。
(2)迭代次数:
- 默认
iterations=1,若需更强腐蚀,可增加至2或3次。
(3)结构元素形状:
- 矩形核适合水平/垂直边缘,十字形核适合交叉点,椭圆形核适合平滑处理
五、图像膨胀
1、概念
图像膨胀(Dilation)是形态学图像处理中的基本操作之一,通过将结构元素(核)在图像上滑动,将覆盖区域内的最大像素值赋给中心像素,实现图像中亮区域的扩张。在二值图像中,膨胀使白色区域(前景)向外扩展,填补空洞或连接断裂部分;在灰度图像中,则增强高亮区域的亮度。
2、原理
(1)结构元素(Kernel)
定义膨胀操作的形状和大小,常见形状包括矩形(MORPH_RECT)、椭圆形(MORPH_ELLIPSE)、十字形(MORPH_CROSS)等。结构元素通常为奇数尺寸(如3×3、5×5),中心点为锚点。
(2)操作过程
-
遍历图像每个像素,将结构元素中心与当前像素对齐。
-
检查结构元素覆盖区域内的像素值,取最大值作为中心像素的新值。
-
数学表达式:
其中,`src`为输入图像,`dst`为输出图像。
3、作用
(1)填补空洞
消除物体内部的小孔(如二值图像中噪声导致的断裂)。
(2)连接断裂部分
合并相邻的物体(如文字分割中断裂的笔画)。
(3)增强边缘
突出物体轮廓,便于边缘检测或特征提取。
(4)预处理
为后续操作(如开运算、闭运算)提供基础,改善图像质量。
4、分类
(1)按结构元素形状
- 矩形膨胀:适用于均匀扩张,如填充矩形区域。
- 椭圆形膨胀:平滑边缘,减少方向性偏差。
- 十字形膨胀:沿水平和垂直方向扩展,适合连接线性结构。
(2)按迭代次数
- 单次膨胀:轻微扩展,适用于细小空洞填补。
- 多次膨胀:通过
iterations参数控制,增强效果(如连接远距离断裂)。
5、计算方法
(1)核心函数
Android OpenCV中通过Imgproc.dilate()实现膨胀:
Imgproc.dilate(
Mat src, // 输入图像(灰度或二值)
Mat dst, // 输出图像
Mat kernel, // 结构元素
Point anchor, // 锚点(默认中心)
int iterations,// 迭代次数(默认1)
int borderType,// 边界处理模式(默认BORDER_CONSTANT)
Scalar borderValue // 边界填充值
);
(2)结构元素生成
使用Imgproc.getStructuringElement()创建核:
Mat kernel = Imgproc.getStructuringElement(
Imgproc.MORPH_RECT, // 形状
new Size(3, 3) // 尺寸
);
6、实例
场景:连接二值图像中断裂的数字字符。
步骤:
(1)读取图像并二值化
Mat src = Imgcodecs.imread("input.png", Imgcodecs.IMREAD_GRAYSCALE);
Mat binary = new Mat();
Imgproc.threshold(src, binary, 127, 255, Imgproc.THRESH_BINARY);
(2)定义结构元素并膨胀
Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(3, 3));
Mat dilated = new Mat();
Imgproc.dilate(binary, dilated, kernel, new Point(-1, -1), 2); // 迭代2次
(3)显示结果
Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(3, 3));
Mat dilated = new Mat();
Imgproc.dilate(binary, dilated, kernel, new Point(-1, -1), 2); // 迭代2次
效果对比:
- 原始图像:数字“8”中间断裂。
- 膨胀后:断裂部分被连接,数字完整。
7、关键点总结
- 结构元素选择:根据目标形状选择核类型(如连接线性结构用十字形)。
- 迭代次数:控制膨胀强度,避免过度扩张导致物体粘连。
- 应用场景:常与腐蚀(Erosion)结合使用,实现开运算(先腐蚀后膨胀)或闭运算(先膨胀后腐蚀)。
通过合理使用膨胀操作,可显著提升图像中物体的完整性和可分析性,为后续处理(如目标检测、OCR)奠定基础。
六、霍夫变换
1.什么是Hough变换
霍夫变换是图像处理中的一种特征提取技术,通过投票算法检测识别具有特定几何形状的物体。我们这篇文章,主要对直线进行检测。

我们看见直角坐标系中有两个点A B,他们构成了一条直线y=kx=b。知道了斜率k和截距b就可以确定一条直线。
我们可以将这个坐标系看成一个笛卡尔空间。往深处思考一下,其实x就是我们的输入,k和b就是参数,y就是输出。就是当我们知道一个x,就一定知道直线上对应的点。
接下来,我们就要将笛卡尔空间转化为霍夫空间。其实就是需要将直角坐标系上的点转化为极坐标上的点。
那现在有了点,我们需要处理直线了。

已知直线 y=kx+b上一点P的坐标为(x,y),设
点 P到原点距离为(gamma)
点 P到原点连线和 x 轴夹角为(phi)
原点到直线的距离为(rho)
原点到直线的垂线和 x轴夹角为(theta)
可得
当我们知道和
就可以确定这一条直线了,由于我们有点P的坐标,通过坐标就知道了
和
的数值。我们将左边的式子变化为右边的式子。此时我们将右式转换为下式。
此时,我们给定和
时,知道x就可以求出y。与之前的y=kx+b相同,都是两个参数确定一条直线。
也就是说在极坐标下,一个点代表一条直线。
2.Hough变换原理
在一张图中,只有边缘才可能是直线,因此,在进行Hough变换之前,需要进行边缘检测。

从这幅图我们可以很清晰看出,在经过边缘检测后,图中所有的边缘都检测出来了,但是很明显并不是所有的边缘都是我们需要的,因此需要对需要的边缘进行提取。 其实最好的思路就是,有多少的像素点可以贡献给这条直线。
ok,知道思路后,我们先对一个像素点分析,图中一个像素点可以有无数条直线过这一点。

这些直线可以可以在极坐标坐标系中进行表示出来。
那在图中我们想得到的直线上不同的两个点,都可以在极坐标上用不同的曲线表示出。

我们发现直角坐标上的点转化到极坐标中,可以发现转化到极坐标中的曲线相交在某一个点。
结合之前说到的”有多少的像素点可以贡献给这条直线“,所以我们就可以根据极坐标上相交多的一个点来确定这些曲线在直角坐标系中其实是在一条直线上。
那此时,可能有很多的边缘其实也相交的很多,但是这些并不是我需要的,此时就需要对其阈值进行设置。
3. Hough变换整体流程
①直线检测(边缘检测图像,阈值)阈值其实就是直线上像素点的数量
②建立一个极坐标空间
③遍历边缘图像中的每一个边缘点(通过边缘图像坐标转到极坐标)
④便利极坐标中的
⑤根据求出,在矩阵上计数
⑥返回技术超过阈值的和,就得到直线的函数了



七、霍夫直线检测
1、概念
霍夫直线检测(Hough Line Transform)是一种基于霍夫变换的图像特征提取算法,用于检测图像中的直线。其核心思想是将图像空间中的边缘点映射到参数空间(霍夫空间),通过统计参数空间中的峰值点来反推图像中的直线方程。OpenCV 提供了两种主要实现:
- 标准霍夫变换(HoughLines):返回直线的极坐标参数(ρ, θ)。
- 概率霍夫变换(HoughLinesP):返回线段的端点坐标(x₁, y₁, x₂, y₂),更适合检测有限长度的线段。
2、原理
(1)坐标空间变换
将图像空间(直角坐标系)中的点 (x,y) 映射到霍夫空间(极坐标系)中的曲线,方程为:
ρ=xcosθ+ysinθ
其中,ρ 是直线到原点的距离,θ 是直线与 x 轴的夹角。
(2)投票机制
- 每个边缘点在霍夫空间中生成一条正弦曲线。
- 多条曲线的交点对应图像空间中的一条直线。
- 通过累加器数组统计交点数量,峰值点即为检测到的直线。
3、作用
(1)直线检测
识别图像中的直线,如文档边缘、道路标线、建筑轮廓等。
(2)几何形状分析
辅助计算直线的角度、长度、位置等参数。
(3)预处理优化
结合边缘检测(如 Canny),提升后续目标检测或分割的准确性。
4、分类
| 类型 | 输出形式 | 适用场景 |
|---|---|---|
| 标准霍夫变换(HoughLines) | 极坐标参数 (ρ,θ) | 检测无限长直线 |
| 概率霍夫变换(HoughLinesP) | 线段端点 (x1,y1,x2,y2) | 检测有限长线段(推荐使用) |
5、计算方法
(1)关键参数
- rho(ρ):距离分辨率(像素单位),通常设为 1。
- theta(θ):角度分辨率(弧度),通常设为 π/180(1°)。
- threshold:累加器阈值,值越高检测到的直线越显著。
- minLineLength:线段最小长度(仅 HoughLinesP)。
- maxLineGap:线段最大间隔(仅 HoughLinesP),用于合并断裂线段。
(2)核心函数
// 标准霍夫变换(返回极坐标参数)
Imgproc.HoughLines(
Mat image, // 输入图像(二值图)
Mat lines, // 输出直线参数(Vec2f)
double rho, // 距离分辨率
double theta, // 角度分辨率
int threshold // 累加器阈值
);
// 概率霍夫变换(返回线段端点)
Imgproc.HoughLinesP(
Mat image, // 输入图像(二值图)
Mat lines, // 输出线段端点(Vec4i)
double rho, // 距离分辨率
double theta, // 角度分辨率
int threshold, // 累加器阈值
double minLineLength, // 线段最小长度
double maxLineGap // 线段最大间隔
);
6、实例
场景:检测图像中的线段并绘制结果。
步骤:
(1)读取图像并转为灰度图
Mat src = Imgcodecs.imread("input.jpg");
Mat gray = new Mat();
Imgproc.cvtColor(src, gray, Imgproc.COLOR_BGR2GRAY);
(2)边缘检测(Canny)
Mat edges = new Mat();
Imgproc.Canny(gray, edges, 50, 150);
(3)概率霍夫变换检测线段
Mat lines = new Mat();
Imgproc.HoughLinesP(
edges, lines, 1, Math.PI / 180, 50, 50, 10
);
(4)绘制检测到的线段
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(src, pt1, pt2, new Scalar(0, 0, 255), 2);
}
(5)显示结果
HighGui.imshow("Source", src);
HighGui.waitKey(0);
效果对比:
- 原始图像:包含多条线段(如桌角、书本边缘)。
- 检测结果:线段被红色标记,断裂部分被合并。
7、关键点总结
(1)预处理重要性:霍夫变换对噪声敏感,需先用 Canny 提取边缘。
(2)参数调优:
- 降低
threshold可检测更多短线段,但可能引入噪声。 - 调整
minLineLength和maxLineGap可优化线段连接效果。
(3)性能优化:概率霍夫变换(HoughLinesP)比标准霍夫变换更快,适合实时应用。
八、霍夫圆检测
1、概念
霍夫圆检测(Hough Circle Transform)是一种基于霍夫变换的图像处理技术,用于从图像中检测圆形对象。它将图像空间中的圆映射到三维参数空间(圆心坐标 x,y 和半径 r),通过统计参数空间中的峰值点来反推图像中的圆。OpenCV 提供了 Imgproc.HoughCircles() 函数实现该功能,支持标准霍夫变换和霍夫梯度法(默认)。
2、原理
(1)参数空间转换
圆的方程为 (x−a)2+(y−b)2=r2,其中 (a,b) 为圆心,r 为半径。在霍夫空间中,每个圆对应一个三维点 (a,b,r),而图像中的每个边缘点对应一个三维锥面。通过寻找锥面的交点,即可确定圆的参数。
(2)霍夫梯度法(优化实现)
OpenCV 默认使用霍夫梯度法,步骤如下:
- 边缘检测:使用 Canny 算法提取边缘。
- 梯度计算:通过 Sobel 算子计算边缘点的梯度方向(切线方向)。
- 圆心投票:沿梯度方向搜索可能的圆心,并在累加器中投票。
- 峰值检测:统计累加器中的局部最大值,筛选出最可能的圆心。
- 半径确定:根据圆心到边缘点的距离确定半径。
3、作用
- 目标识别:检测图像中的圆形物体(如硬币、交通标志、工业零件)。
- 缺陷检测:识别圆形结构的缺陷(如孔洞、裂纹)。
- 医学成像:辅助分析细胞、血管等圆形结构。
- 机器人导航:识别环境中的圆形标记(如地标、路径指示)。
4、分类
| 类型 | 特点 |
|---|---|
| 标准霍夫变换 | 直接在三维参数空间中搜索,计算量大,适合简单场景。 |
| 霍夫梯度法 | 通过梯度信息优化搜索,计算效率高,抗噪声能力强,适合复杂场景(OpenCV 默认)。 |
5、计算方法
OpenCV 中通过 Imgproc.HoughCircles() 实现,函数原型如下:
Imgproc.HoughCircles(
Mat image, // 输入图像(8位单通道灰度图)
Mat circles, // 输出圆参数(Vec3f 数组,包含 x, y, radius)
int method, // 检测方法(HOUGH_GRADIENT)
double dp, // 累加器分辨率与图像分辨率的比值(默认 1)
double minDist, // 检测到的圆心之间的最小距离(避免重复检测)
double param1, // Canny 边缘检测的高阈值(默认 100)
double param2, // 圆心累加器阈值(值越小,检测到的圆越多,默认 100)
int minRadius, // 圆的最小半径(默认 0)
int maxRadius // 圆的最大半径(默认 0)
);
6、实例
场景:检测图像中的硬币并标记圆心和半径。
步骤:
(1)读取图像并转为灰度图
Mat src = Imgcodecs.imread("coins.jpg");
Mat gray = new Mat();
Imgproc.cvtColor(src, gray, Imgproc.COLOR_BGR2GRAY);
(2)高斯模糊降噪
Mat blurred = new Mat();
Imgproc.GaussianBlur(gray, blurred, new Size(9, 9), 2);
(3)霍夫圆检测
Mat circles = new Mat();
Imgproc.HoughCircles(
blurred, circles, Imgproc.HOUGH_GRADIENT,
1, // dp
50, // minDist
100, // param1(Canny 高阈值)
30, // param2(圆心累加器阈值)
20, // minRadius
100 // maxRadius
);
(4)绘制检测结果
for (int i = 0; i < circles.cols(); i++) {
double[] circle = circles.get(0, i);
Point center = new Point(Math.round(circle[0]), Math.round(circle[1]));
int radius = (int) Math.round(circle[2]);
// 绘制圆心
Imgproc.circle(src, center, 3, new Scalar(0, 0, 255), -1);
// 绘制圆轮廓
Imgproc.circle(src, center, radius, new Scalar(0, 0, 255), 2);
}
(5)显示结果
HighGui.imshow("Detected Circles", src);
HighGui.waitKey(0);
效果对比:
- 原始图像:包含多个不同半径的硬币。
- 检测结果:硬币被红色色圆心和轮廓标记,边缘模糊或重叠的硬币可能被忽略。

7、关键点总结
(1)预处理重要性:高斯模糊可显著减少噪声干扰,提升检测精度。
(2)参数调优:
param1(Canny 阈值):值过高会漏检边缘,过低会引入噪声。param2(圆心阈值):值过高会漏检圆,过低会检测到虚假圆。minDist:根据硬币间距调整,避免重复检测。
(3)性能优化:
- 限制
minRadius和maxRadius可减少计算量。 - 对大图像可先下采样(
Imgproc.resize())再检测。
8.圆检测技术在各领域的应用实例
圆检测技术作为一种图像处理的重要工具,广泛应用于工业、医学、交通及安防监控等多个领域。它不仅提高了效率,而且在许多情况下,提供了更准确和更可靠的结果。在本章节中,我们将深入了解圆检测技术在不同领域中的实际应用,以及如何通过Hough变换检测圆形原理来解决现实世界的问题。
8.1 工业领域的应用
在工业领域中,圆检测技术可以用于自动化检测和质量控制,对于提高生产效率和保证产品质量具有重要意义。
8.1.1 工业零件的检测和分类
工业零件的形状和尺寸往往是判断其是否合格的重要标准。利用圆检测技术,可以快速地识别零件轮廓中的圆形部分,从而判断零件是否达到设计要求。例如,在轴承的自动检测系统中,可以使用圆检测算法来识别轴承内外圈是否完整、是否存在缺口或变形。
关键技术实现:
在实现过程中,首先需要对零件图像进行预处理,包括灰度化、边缘检测等步骤,以突出圆的边缘信息。然后,通过Hough变换检测圆形,得到圆心位置和半径信息。通过比较检测到的圆与标准零件模板中的圆形特征,可以自动判定零件是否合格。
8.1.2 工业自动化中的应用案例
在自动化的生产线中,圆检测技术可以用于跟踪和定位零件,以实现精确的装配和组装。例如,在电子制造行业,电路板上的孔洞位置对于元件的正确装配至关重要。
应用案例分析:
在电路板制造中,可以使用高分辨率摄像头拍摄电路板图像,随后进行必要的图像预处理。通过应用Hough变换来检测电路板上的孔洞位置,系统可以实时调整机械臂的移动路径,确保电子元件能够准确无误地装配到指定位置。
8.2 医学领域的应用
医学图像处理是现代医疗技术的重要组成部分,圆检测技术在其中扮演着重要角色。
8.2.1 医学图像中的结构识别
在医学影像分析中,许多生物组织结构呈现为圆形或近似圆形。例如,在眼科检查中,眼底的血管和视网膜的视盘都需要进行精确的圆形识别和分析。
技术应用场景:
利用圆检测技术对眼底图像中的圆形结构进行识别,不仅可以帮助医生检测到视网膜疾病,还可以用于监测患者病情的变化。此外,它同样适用于肿瘤的定位、测量和生长速率的计算。
8.2.2 病理图像分析中的应用
在病理图像分析中,细胞结构、细胞核等圆形特征的识别对于诊断某些疾病如肿瘤是非常重要的。
技术实施细节:
病理图像通常需要进行预处理来增强细胞结构的对比度,之后应用圆检测算法来识别和分析细胞核。通过比较细胞核的大小、形状和分布情况,可以辅助病理学家进行疾病的早期诊断和分类。
8.3 交通领域的应用
圆检测技术在交通领域的应用也十分广泛,尤其在车辆检测、交通标志的识别等方面。
8.3.1 车辆识别与跟踪
在智能交通系统中,车辆检测是重要的功能之一。圆检测技术可以帮助识别和跟踪车辆的轮廓,从而为交通流量统计和异常行为分析提供数据支持。
技术关键点:
车辆的轮廓往往包含多个圆形特征,如车轮和后视镜。通过利用Hough变换,可以快速定位这些圆形特征,并根据其位置和大小进行车辆跟踪。
8.3.2 交通标志的检测与识别
交通标志是确保道路交通安全的重要设施。利用圆检测技术,可以快速识别交通标志中的圆形标志,例如停车标志、限速标志等。
技术运用:
通过对交通场景图像进行预处理后,圆检测算法可以用来识别并提取标志中的圆形元素。然后,通过比较这些元素与已知的交通标志模板,可以实现对交通标志的准确识别。
8.4 安防监控的应用
在安防监控领域,圆检测技术同样有其独特的作用,尤其是在异常行为检测和人流量统计分析方面。
8.4.1 安防视频中的异常行为检测
在监控视频中,通过对场景中圆形物体的检测和分析,可以帮助识别和警告异常行为,如遗留物检测、物体移除等。
技术操作步骤:
利用视频监控图像进行实时处理,对图像中移动的圆形物体进行跟踪。一旦发现圆形物体的位置变化异常,系统可以发出报警。例如,如果在机场等敏感区域发现未被人员携带的行李,系统可以通过圆检测技术分析行李的轮廓特征并发出警报。
8.4.2 人流量统计与分析
对于商场、体育馆等公共场所来说,了解和分析人流量对于运营管理和安全规划至关重要。
技术实现方法:
通过在摄像头前部署圆检测技术,可以统计经过某一区域的人数。这通常通过跟踪人体轮廓中的圆形特征(如头部)来实现。通过累计检测到的圆形数量,即可估算出特定时间段内的客流量。
8.4.3 圆检测技术的未来展望
随着计算机视觉和机器学习技术的快速发展,圆检测技术在未来将变得更加智能化和高效。结合深度学习方法,圆检测不仅能够更准确地识别圆形对象,还可以学习不同场景下的特定圆形特征,从而适应更为复杂的应用环境。例如,深度学习可以用于改善圆检测的准确率和抗噪声能力,甚至在多目标跟踪和复杂背景中进行圆形检测。展望未来,圆检测技术将广泛地应用于更广泛的领域,推动着相关行业技术的革新和发展。
九、直线拟合
1、概念
直线拟合是一种数学技术,用于从一组离散数据点中找到最能代表整体趋势的直线。在图像处理中,它通过最小化数据点到拟合直线的垂直距离(或加权距离)来估计直线参数(方向向量和直线上的一点)。与霍夫直线检测不同,直线拟合假设数据点已近似分布在一条直线上,但可能受噪声或离群点影响,需通过算法优化拟合结果。
2、原理
(1)最小二乘法
核心思想是最小化所有数据点到直线的垂直距离平方和。对于直线方程 y=kx+b,通过求解线性方程组得到最优参数 k 和 b。OpenCV 的 cv::fitLine 函数默认使用基于最小二乘的加权方法,支持多种距离度量(如 L2 范数)。
(2)加权最小二乘法
针对离群点问题,OpenCV 通过赋予不同数据点不同权重来减少异常值影响。权重计算方式包括:
- L2 距离(
DIST_L2):标准欧氏距离,对离群点敏感。 - Huber 距离(
DIST_HUBER):对小误差使用二次损失,大误差使用线性损失,平衡鲁棒性和效率。 - Fair 距离(
DIST_FAIR)、Welsch 距离(DIST_WELSCH)等:通过非线性函数抑制离群点权重。
(3)参数输出
cv::fitLine 返回一个 Vec4f(2D)或 Vec6f(3D)向量:
- 前半部分(
line[0],line[1]):直线的方向向量(单位向量)。 - 后半部分(
line[2],line[3]):直线上的一点坐标。
3、作用
(1)图像几何校正
通过拟合文档边缘的直线,计算透视变换矩阵,校正倾斜图像(如扫描文档、车牌识别)。
(2)特征提取
在道路检测中识别车道线,或在工业检测中分析零件边缘的直线特征。
(3)运动分析
拟合运动轨迹的直线,分析物体运动方向(如视频中的车辆轨迹)。
(4)噪声数据优化
在含噪声的边缘检测结果中,拟合出更平滑的直线,提升后续处理精度。
4、分类
| 方法 | 特点 |
|---|---|
| 标准最小二乘法 | 计算简单,但对离群点敏感,适合干净数据。 |
| 加权最小二乘法 | 通过权重分配抑制离群点,支持多种距离度量(如 Huber、Fair),适合复杂场景。 |
| RANSAC 拟合 | 随机采样数据点估计模型,适合含大量离群点的数据(需结合 OpenCV 其他函数实现)。 |
5、计算方法
OpenCV 提供 cv::fitLine 函数实现直线拟合:
// 函数原型(Java)
Imgproc.fitLine(
Mat points, // 输入点集(N×2 或 N×3 的 Mat)
Mat line, // 输出直线参数(Vec4f 或 Vec6f)
int distType, // 距离类型(如 Imgproc.DIST_L2)
double param, // 距离参数(如 Huber 的阈值 c)
double reps, // 径向精度(建议 0.01)
double aeps // 角度精度(建议 0.01)
);
参数说明:
distType:选择距离度量方式(如DIST_L2、DIST_HUBER)。param:仅对某些距离类型有效(如 Huber 的阈值c=1.345)。reps和aeps:控制拟合精度的阈值,值越小精度越高。
6、实例
场景:拟合图像中检测到的边缘点,绘制拟合直线并标记端点。
步骤:
(1)读取图像并预处理
Mat src = Imgcodecs.imread("edges.jpg");
Mat gray = new Mat();
Imgproc.cvtColor(src, gray, Imgproc.COLOR_BGR2GRAY);
(2)边缘检测(Canny)
Mat edges = new Mat();
Imgproc.Canny(gray, edges, 50, 150);
(3)提取边缘点坐标
List<Point> points = new ArrayList<>();
for (int y = 0; y < edges.rows(); y++) {
for (int x = 0; x < edges.cols(); x++) {
if (edges.get(y, x)[0] > 0) {
points.add(new Point(x, y));
}
}
}
// 转换为 Mat 格式
Mat pointsMat = Converters.vector_Point2f_to_Mat(points);
(4)直线拟合
Mat line = new Mat(4, 1, CvType.CV_64FC1);
Imgproc.fitLine(
pointsMat, line, Imgproc.DIST_L2, 0, 0.01, 0.01
);
// 解析参数
double vx = line.get(0, 0)[0]; // 方向向量 x
double vy = line.get(1, 0)[0]; // 方向向量 y
double x0 = line.get(2, 0)[0]; // 直线上一点 x
double y0 = line.get(3, 0)[0]; // 直线上一点 y
(5)计算端点并绘制
// 计算图像边界上的端点
double k = vy / vx;
Point pt1 = new Point(0, y0 - k * x0);
Point pt2 = new Point(src.cols(), y0 + k * (src.cols() - x0));
// 绘制拟合直线
Imgproc.line(src, pt1, pt2, new Scalar(0, 255, 0), 2);
// 显示结果
HighGui.imshow("Fitted Line", src);
HighGui.waitKey(0);
效果:
- 原始图像中的离散边缘点被拟合为一条绿色直线,端点自动延伸至图像边界。
- 若数据中含离群点,改用
DIST_HUBER可显著提升鲁棒性。
7、关键点总结
(1)预处理重要性:边缘检测质量直接影响拟合结果,建议先降噪(如高斯模糊)。
(2)距离类型选择:
- 干净数据:
DIST_L2(最快)。 - 含离群点:
DIST_HUBER或DIST_FAIR(鲁棒性更强)。
(3)参数调优:reps 和 aeps 需根据图像分辨率调整,通常设为 0.01。
(4)性能优化:对大规模点集,可先使用 cv::approxPolyDP 简化轮廓,再拟合。
8.应用场景
直线拟合在计算机视觉中有广泛的应用:
(1)车道线检测
从道路图像中检测和拟合车道线
用于自动驾驶和辅助驾驶系统
(2)文档校正
检测文档边缘并校正透视变形
用于扫描和OCR应用
(3)工业检测
检测产品的直线边缘
测量物体的方向和位置
(4)机器人导航
从传感器数据中提取环境的结构信息
用于路径规划和导航
(5)建筑测量
从图像中提取建筑物的直线特征
用于建筑测量和建模
感谢观看

1524

被折叠的 条评论
为什么被折叠?



