C#+OpenCV实战(四)_特定钢板缺陷检测

/// <summary>
/// 板材瑕疵检测(凹凸坑、划痕、颜料瑕疵)
/// </summary>
/// <param name="mat">图片</param>
/// <param name="resultMat">结果图片</param>
/// <param name="minArcLength">最小有效斑弧长;默认为5</param>
/// <param name="thickness">标注线条的宽度;默认为1</param>
/// <returns>斑点信息</returns>
public static Point[][] BoardSpot(Mat mat, out Mat resultMat, double minArcLength = 3, int thickness = 2)
{
    List<Point[]> points = new List<Point[]>();
    resultMat = new Mat();
    mat.CopyTo(resultMat);

    // 滤波 - 高斯滤波
    Mat mat1 = new Mat();
    Cv2.BilateralFilter(mat, mat1, 0, 20, 5);

    // 二值化
    Cv2.CvtColor(mat1, mat1, ColorConversionCodes.BGR2GRAY);
    Cv2.Threshold(mat1, mat1, 100, 255, ThresholdTypes.BinaryInv);
    //Cv2.ImShow("11",mat1);

    //发现轮廓
    /*
     * 找轮廓(输入图像,out 轮廓集合,out 级别,轮廓检索模式,近似法,偏移量)
     * 输入图像:单通道图像矩阵,可以是灰度图,但更常用的是二值图像,一般是经过Canny、拉普拉斯等边缘检测算子处理过的二值图像;
     * 轮廓集合:contours 
     * 历史轮廓:hierarchy:0:后一个轮廓,1:前一个轮廓,2:父轮廓,3:内嵌轮廓
     * 轮廓检索模式:轮廓的检索模式
     *         取值一:CV_RETR_EXTERNAL 只检测最外围轮廓,包含在外围轮廓内的内围轮廓被忽略
     *         取值二:CV_RETR_LIST     检测所有的轮廓,包括内围、外围轮廓,但是检测到的轮廓不建立等级关系,彼此之间独立,没有等级关系,这就意味着这个检索模式下不存在父轮廓或内嵌轮廓,所以hierarchy向量内所有元素的第3、第4个分量都会被置为-1,具体下文会讲到
     *         取值三:CV_RETR_CCOMP    检测所有的轮廓,但所有轮廓只建立两个等级关系,外围为顶层,若外围内的内围轮廓还包含了其他的轮廓信息,则内围内的所有轮廓均归属于顶层
     *         取值四:CV_RETR_TREE     检测所有轮廓,所有轮廓建立一个等级树结构。外层轮廓包含内层轮廓,内层轮廓还可以继续包含内嵌轮廓。
     * 近似方法:轮廓的近似方法
     *         取值一:CV_CHAIN_APPROX_NONE   保存物体边界上所有连续的轮廓点到contours向量内
     *         取值二:CV_CHAIN_APPROX_SIMPLE 仅保存轮廓的拐点信息,把所有轮廓拐点处的点保存入contours向量内,拐点与拐点之间直线段上的信息点不予保留
     *         取值三和四:CV_CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法
     * 偏移量:Point偏移量,所有的轮廓信息相对于原始图像对应点的偏移量,相当于在每一个检测出的轮廓点上加上该偏移量,且Point可以是负值。不填为默认不偏移Point()
    */
    Cv2.FindContours(mat1, out Point[][] contours, out HierarchyIndex[] hierarchy,
        RetrievalModes.External, ContourApproximationModes.ApproxNone);

    //绘制指定轮廓 
    for (int i = 0; i < contours.Length; i++)
    {
        double size = Cv2.ArcLength(contours[i], true);  // 弧长
        if (size > minArcLength)
        {
            Cv2.DrawContours(resultMat, contours, i, Scalar.Red, thickness);
            points.Add(contours[i]);
        }
    }
    return points.ToArray();
}
posted @ 2024-07-11 11:50  ꧁执笔小白꧂  阅读(189)  评论(0编辑  收藏  举报