前言
这是一次学习记录,第一次使用skimage库做cv项目,其中在学校做的项目都是基于opencv的,但好像由于opencv是C++编写,导致python调用起来效率会低很多,skimage是python编写,使用可能更适合python的cv项目吧。
Canny算子
如何寻找图像中物体的边缘,那就是图像中明暗区域变化显著的部分,对于灰度图来说,就是灰度值梯度变化剧烈的部分。
Canny主要有四个步骤
- 高斯滤波
- 梯度计算
- 非极大值阈值
- 双阈值滞后边界跟踪
灰度化
一般对图像处理首先都需要进行灰度处理,即现在大多有色图像都是RGB三通道,二灰度图像只有一个通道,有色图像可通过下面公式进行转换为灰度
G
r
a
y
=
0.299
R
+
0.587
G
+
0.114
B
Gray=0.299R+0.587G+0.114B
Gray=0.299R+0.587G+0.114B
也可用skimage中的color库中的rgb2gray()方法
这次项目因为数据集本身就是灰度图像所以不用转化。
高斯滤波
高斯滤波其实就是将图像模糊化,为的是排除背景中虚假的边缘对主要识别对象边缘的影响。常用的滤波器有3╳3和5╳5的,中间为(0,0)周围都是刚好与原点相反,为的是把图像信息“抹匀”。其中有一个重要参数标准差σ,代表数据的离散程度。σ越小,模板的中心系数越大,周围的系数越小,这样对图像的平滑效果就不是很明显;σ越大,模板的各个系数相差就不是很大,比较类似均值模板,对图像的平滑效果比较明显。
梯度计算
canny中的梯度计算一般采用sobel算子进行梯度幅值和梯度方向的计算,它有水平和垂直两个模板,分别可以计算出水平和垂直方向上的梯度,再通过平方和开根的计算得到梯度大小,通过反三角函数计算得到梯度的方向。
非极大值抑制
双阈值之后边界跟踪
这里有两个阈值low_threshold和high_threshold,由于图中边缘有强边缘和弱边缘,因此采用双阈值,把低于low_threshold阈值的点抑制,高于high_threshold阈值的点保留,在low_threshold和high_threshold之间的判断该点周围是否有高于high_threshold阈值的点,若有则保留,没有则抑制。
寻边缘点
找边缘点除了可以直接用canny后的图像也可采用霍夫变换求得边缘直线
霍夫直线变换
霍夫直线变换是极坐标系向霍夫空间的映射,霍夫空间中的横坐标为该点在笛卡尔坐标系下的斜率,纵坐标为笛卡尔坐标系中与y轴的交点,但由于笛卡尔坐标系无法表示铅直方向上的线,使用采用极坐标系与霍夫空间的映射。极坐标系中的一条直线代表霍夫空间中的一个点,极坐标系中的一个点代表霍夫空间中的一条曲线。
这里我运用的是概率霍夫直线变换,两个原理都一样,就是概率霍夫变换要比普通的速度高。
画出图像中边缘所在直线
Pandas Series
做数据处理时要对点的频率区间进行筛选,使用这里用了Pands中的cut().value_counts()方法,该方法可传入两个列表,返回一个series对象,该对象是类似于字典类型,也是由键值对组成。通过对其中的值进行排序,就可得到点频率最高的区间段。
均值化
这里我是直接取得区间点集的平均值,但准确率不是很高,有的图片还是有一定的偏移量,也可采用其他方法,后续还会尝试。
画线
最后直接将均值化后的x坐标和y坐标调用matplatlib中的画线方法直接画出贯穿全图是水平和竖直直线。
效果还是非常明显的识别出了内圈的边缘并标记出。但若是电池正负级片高度差小到一定程度时,会因为太近而检测不到内部的直线,
总结
我觉得有以下原因:
1.原图较为模糊;
2.canny参数选取不当,未识别出内侧轮廓,应当反复尝试;
3.不能采用平均值寻找直线,过于粗糙,可以尝试直线拟合方式或者有限元分析;
4.点的预处理不够到位,可以试试去除掉干扰点。
最后
明天就是端午节啦,是入职以来第一个节日,祝大家端午安康!
2023.06.21