形态学处理
形态学处理之前需要将图像进行二值化处理, 然后我们需要设定一个卷积核, 最后将像素上每个点都完成卷积计算.
形态学很多高级处理的基础, 有很多作用: 消除毛刺、填充空隙、检测边缘,检查拐角(使用十字形卷积核)
腐蚀 Erode
腐蚀作用和膨胀相反, 用来腐蚀减小白色区域, 常用来消除一些白色毛刺等细小区域, 也会腐蚀掉边缘部分.
卷积计算方法: 卷积核为一个全1的小矩阵, 计算过程为, 图像一个像素和卷积核对齐后, 如果卷积覆盖区域中图像有含0的像素, 则该像素取值为0, 即白色, 如果全部都为1, 则该像素值为1.
代码示例:
public void erodeTest()
{
string file = @"D:\my_workspace\opencv\images\毛刺.jpg";
var img = Cv2.ImRead(file, ImreadModes.Grayscale);
var elements = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(3, 3));
var newImg1 = img.Clone();
newImg1 = newImg1.Erode(elements, null, iterations: 1);
Cv2.ImShow("img", img);
Cv2.ImShow("腐蚀1次", newImg1);
Cv2.WaitKey();
Cv2.DestroyAllWindows();
}
效果:
膨胀 Dilate
膨胀用来扩张白色区域, 减少黑色区域, 常用来消除区域中的黑色空隙, 也会扩大白色边缘部分.
卷积计算方法: 卷积核为一个全1的小矩阵, 计算过程为, 图像一个像素和卷积核对齐后, 如果卷积覆盖区域中图像有含1的像素, 则该像素取值为1, 即白色, 如果全部都为0, 则该像素值为0.
/// <summary>
/// 膨胀测试
/// 结论: 3次递归, 仍有少量空隙, 这时可增加递归次数, 或者增大卷积核size
/// </summary>
public void dilateTest()
{
string file = @"D:\my_workspace\opencv\images\孔隙.jpg";
var img = Cv2.ImRead(file, ImreadModes.Grayscale);
var elements = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(3, 3));
var newImg3 = img.Clone();
newImg3 = newImg3.Dilate(elements, null, iterations: 3); //3次递归, 仍有少量空隙, 这时可增加递归次数, 或者增大卷积核size
var newImg6 = img.Clone();
newImg6 = newImg6.Dilate(elements, null, iterations: 6); //6次递归, 空隙清除干净
Cv2.ImShow("img", img);
Cv2.ImShow("膨胀3次", newImg3);
Cv2.ImShow("膨胀6次", newImg6);
Cv2.WaitKey();
Cv2.DestroyAllWindows();
}
效果:
经过膨胀后, 空隙被消除了, 但可以看到矩形也变大了.
开运算
开运算是先腐蚀后膨胀, 闭运算是先膨胀后腐蚀, 腐蚀和膨胀其实并不是逆运算, 所以开闭运算最终效果是不一样的.
我们使用开运算的主要目的是利用腐蚀的正向效果, 即消除毛刺和虚假联通部分, 同时使用膨胀来抵消腐蚀的副作用.
代码示例:
/// <summary>
/// 开运算, 先腐蚀后膨胀
/// </summary>
public void openTest()
{
string file = @"D:\my_workspace\opencv\images\毛刺.jpg";
var img = Cv2.ImRead(file, ImreadModes.Grayscale);
var elements = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(3, 3));
var newImg1 = img.Clone();
Cv2.MorphologyEx(newImg1, newImg1, MorphTypes.Open, elements, anchor: null, iterations: 1);
Cv2.ImShow("img", img);
Cv2.ImShow("开运算", newImg1);
Cv2.WaitKey();
Cv2.DestroyAllWindows();
}
效果:
闭运算
闭运算是先膨胀后腐蚀, 开运算是先腐蚀后膨胀, 腐蚀和膨胀其实并不是逆运算, 所以开闭运算最终效果是不一样的.
我们使用闭运算的主要目的是利用膨胀的正向效果, 同时使用腐蚀来抵消膨胀的副作用.
代码:
/// <summary>
/// 闭运算, 先膨胀后腐蚀
/// </summary>
public void closeTest()
{
string file = @"D:\my_workspace\opencv\images\孔隙.jpg";
var img = Cv2.ImRead(file, ImreadModes.Grayscale);
var elements = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(3, 3));
var newImg1 = img.Clone();
Cv2.MorphologyEx(newImg1, newImg1, MorphTypes.Close, elements, anchor: null, iterations: 4);
Cv2.ImShow("img", img);
Cv2.ImShow("闭运算", newImg1);
Cv2.WaitKey();
Cv2.DestroyAllWindows();
}
效果:
梯度 Gradient
梯度相当于膨胀后的图像减去腐蚀后的图像, 可以用来刻画出轮廓部分.
代码示例:
/// <summary>
/// 梯度: 膨胀-腐蚀
/// </summary>
public void gradientTest()
{
string file = @"D:\my_workspace\opencv\images\circle.png";
var img = Cv2.ImRead(file, ImreadModes.Grayscale);
var newImg3 = img.Clone();
var elements3 = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(3, 3));
Cv2.MorphologyEx(newImg3, newImg3, MorphTypes.Gradient, elements3, anchor: null, iterations: 1);
var newImg5 = img.Clone();
var elements5 = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(5, 5));
Cv2.MorphologyEx(newImg5, newImg5, MorphTypes.Gradient, elements5, anchor: null, iterations: 1);
Cv2.ImShow("img", img);
Cv2.ImShow("梯度3", newImg3);
Cv2.ImShow("梯度5", newImg5);
Cv2.WaitKey();
Cv2.DestroyAllWindows();
}
效果:
礼帽和顶帽 Top Hat
礼帽也叫做顶帽 Top Hat: 原始图像-开运算, 能将一些细小的毛刺凸显出来
黑帽 Black Hat: 闭操作-原始图像, 能将一些黑色的空隙凸显出来.
代码示例:
/// <summary>
/// 礼帽(顶帽), 原始图像-开操作
/// </summary>
public void topHatTest()
{
string file = @"D:\my_workspace\opencv\images\毛刺.jpg";
var img = Cv2.ImRead(file, ImreadModes.Grayscale);
var elements = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(3, 3));
var newImg1 = img.Clone();
Cv2.MorphologyEx(newImg1, newImg1, MorphTypes.TopHat, elements, anchor: null, iterations: 1);
Cv2.ImShow("img", img);
Cv2.ImShow("礼帽(顶帽)", newImg1);
Cv2.WaitKey();
Cv2.DestroyAllWindows();
}
效果:
黑帽 Black Hat
黑帽 Black Hat: 闭操作-原始图像, 能将一些黑色的空隙凸显出来.
礼帽也叫做顶帽 Top Hat: 原始图像-开运算, 能将一些细小的毛刺凸显出来
代码示例:
/// <summary>
/// 黑帽运算, 闭操作-原始图像
/// </summary>
public void blackHatTest()
{
string file = @"D:\my_workspace\opencv\images\孔隙.jpg";
var img = Cv2.ImRead(file, ImreadModes.Grayscale);
var elements = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(3, 3));
var newImg1 = img.Clone();
Cv2.MorphologyEx(newImg1, newImg1, MorphTypes.BlackHat, elements, anchor: null, iterations: 4);
Cv2.ImShow("img", img);
Cv2.ImShow("黑帽运算", newImg1);
Cv2.WaitKey();
Cv2.DestroyAllWindows();
}
效果演示:
参考
https://zhuanlan.zhihu.com/p/273475106