一:方法原理

图像形态学操作的时候,可以通过自定义的结构元素实现结构元素对输入图像一些对象敏感,另一些不敏感。这样就会是敏感的对象改变而不敏感的对象保留输出。通过使用两个最基本的形态学操作:膨胀和腐蚀。使用不同的结构元素实现对输入图像的操作,得到不同的结果。
**膨胀:**输出的像素值是结构元素覆盖下输入图像的最大像素值。
**腐蚀:**输出的像素值是结构元素覆盖下输入图像的最小像素值。

二:示意图

二值图像和灰度图像上的膨胀操作:

Dilation on a binary image
在这里插入图片描述
Dilation on a grayscale image

在这里插入图片描述
二值图像和灰度图像上的腐蚀操作:

Erosion on a binary image

在这里插入图片描述
Erosion on a grayscale image
在这里插入图片描述

三:结构元素

  • 上述的结构元素可以是任意的形状的结构元素。
  • 常见的结构元素有,矩形 、圆、直线、菱形等等。

四:提取步骤

  1. 输入色彩图像
  2. 转为灰度图像
  3. 转为二值图像
  4. 定义结构元素
  5. 开操作 (膨胀 + 腐蚀)提取水平或垂直线

六:代码

提取线条:

 static void Main(string[] args)
        {
            string imagePath = @"C:\Users\whx\Desktop\opcvImage\X1.jpg";
            GetLine(imagePath);
        }
            /// <summary>
            /// 提取线条
            /// </summary>
        private static void GetLine(string path)
        {
            using (Mat src = new Mat(path, ImreadModes.AnyColor | ImreadModes.AnyDepth))
            {
                //转为灰度图像
                Mat dst = new Mat();
                Cv2.CvtColor(src, dst, ColorConversionCodes.BGR2GRAY);

                //转为二值图像
                /*
                 * API AdaptiveThreshold:
                 * 参数:1:输入的灰度图像  '~' 符号是背景色取反
                 *      2:输出的二值化图像
                 *      3:二值化的最大值
                 *      4:自适应的方法(枚举类型,目前只有两个算法)
                 *      5:阀值类型(枚举类型,这里选择二进制)
                 *      6: 块大小
                 *      7: 常量 (可以是正数 0 负数)
                 */
                Mat binImage = new Mat();
                Cv2.AdaptiveThreshold(~dst, binImage, 255, AdaptiveThresholdTypes.MeanC, ThresholdTypes.Binary, 15, -2);

                int xSize = dst.Cols / 16; //宽
                int ySize = dst.Rows / 16; //高

                //定义结构元素 new Size(xSize, 1) 相当于横着的一条线:水平结构体 new Size(1, ySize) 相当于竖着的一条线:垂直结构体
                InputArray kernelX = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(xSize, 1),new Point(-1,-1));
                InputArray kernelY = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(1, ySize), new Point(-1, -1));

                Mat result = new Mat();
                腐蚀
                //Cv2.Erode(binImage, result, kernelY);
                膨胀
                //Cv2.Dilate(result, result, kernelY);

                //开操作代替 腐蚀和膨胀
                Cv2.MorphologyEx(binImage, result, MorphTypes.Open, kernelY);
                Cv2.Blur(result, result, new Size(3, 3), new Point(-1, -1)); //使用归一化框过滤器平滑图像
                Cv2.BitwiseNot(result, result); //背景变成白色(背景值取反)


                using(new Window("result", WindowMode.Normal, result))
                using(new Window("binImage", WindowMode.Normal, binImage))
                using(new Window("dst", WindowMode.Normal, dst))
                using (new Window("SRC", WindowMode.Normal, src))
                {
                    Cv2.WaitKey(0);
                }
            }
        }

在这里插入图片描述
上面的代码,定义了一个相当于垂直直线的结构体。通过开操作,(先腐蚀后膨胀):
垂直结构体在图像上卷积操作,经过横线时和结构图不重合,先腐蚀,取(二值图像)的最小像素值=0,测像素就被擦除掉了。当经过竖线时和结构重合,像素值都是一样的(1),腐蚀操作后还是1,像素就被保留下来了。再经过膨胀取最大值 1。
下面换称 X 轴的结构体:

Cv2.MorphologyEx(binImage, result, MorphTypes.Open, kernelX);

在这里插入图片描述

提取文字:

 /// <summary>
        /// 实际应用,得到文字
        /// </summary>
        private static void GetTxt(string path)
        {
            using (Mat src = new Mat(path, ImreadModes.AnyColor | ImreadModes.AnyDepth))
            using (Mat dst = new Mat())
            using (Mat binImage = new Mat())
            using (Mat result = new Mat())
            {
                Cv2.CvtColor(src, dst, ColorConversionCodes.BGR2GRAY);
                //对数组应用自适应阈值。包含二值图像等多种操作
                Cv2.AdaptiveThreshold(~dst, binImage, 255, AdaptiveThresholdTypes.MeanC, ThresholdTypes.Binary, 15, -2);
                InputArray kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 3), new Point(-1, -1));
                Cv2.MorphologyEx(binImage, result, MorphTypes.Open, kernel, new Point(-1, -1));
                Cv2.BitwiseNot(result, result);
                using (new Window("Result", WindowMode.Normal, result))
                using (new Window("SRC", WindowMode.Normal, src))
                {
                    Cv2.WaitKey(0);
                }
            }
        }

在这里插入图片描述
想要获取指定的内容,还需要合适的结构体元素,上图使用 (3 X 3)大小的结构体。如果换成(5 X 5)大小文字将要抹去掉。

7:API

Cv2.AdaptiveThreshold(): 对数组应用自适应阈值。

参数描述
InputArray srcSource 8-bit single-channel image. 输入的灰度图像
OutputArray dstDestination image of the same size and the same type as src .与src大小和类型相同的目标映像。
double maxValueNon-zero value assigned to the pixels for which the condition is satisfied 二值化的最大值
AdaptiveThresholdTypes adaptiveMethod要使用的自适应阈值算法有adaptive_threshold _mean_c或adaptive_threshold _gaussian_c (枚举类型,目前只有两个算法)
ThresholdTypes thresholdType阈值类型必须是阈值二进制或阈值binary_inv。
int blockSize用于计算像素阈值的像素邻域的大小:3,5,7,依此类推。块大小
double c常量 (可以是正数 0 负数)从平均值或加权平均值中减去的常数

两种阈值公式:第五个参数
在这里插入图片描述
阈 值 T = s u m ( b l o c k s i z e X b l o c k s i z e 的 平 均 像 素 ) − 常 量 C 阈值 T=sum(blocksize X blocksize的平均像素) - 常量 C T=sum(blocksizeXblocksize)C

Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐