一:方法原理

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

二:示意图

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

Dilation on a binary image

java使用opencv识别文字区域 opencvsharp 文字识别_二值图像


Dilation on a grayscale image

java使用opencv识别文字区域 opencvsharp 文字识别_灰度图像_02


二值图像和灰度图像上的腐蚀操作:

Erosion on a binary image

java使用opencv识别文字区域 opencvsharp 文字识别_灰度图像_03


Erosion on a grayscale image

java使用opencv识别文字区域 opencvsharp 文字识别_java使用opencv识别文字区域_04

三:结构元素

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

四:提取步骤

  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);
                }
            }
        }

java使用opencv识别文字区域 opencvsharp 文字识别_自适应_05


上面的代码,定义了一个相当于垂直直线的结构体。通过开操作,(先腐蚀后膨胀):

垂直结构体在图像上卷积操作,经过横线时和结构图不重合,先腐蚀,取(二值图像)的最小像素值=0,测像素就被擦除掉了。当经过竖线时和结构重合,像素值都是一样的(1),腐蚀操作后还是1,像素就被保留下来了。再经过膨胀取最大值 1。

下面换称 X 轴的结构体:

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

java使用opencv识别文字区域 opencvsharp 文字识别_图像处理_06

提取文字:

/// <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);
                }
            }
        }

java使用opencv识别文字区域 opencvsharp 文字识别_二值图像_07


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

7:API

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

参数

描述

InputArray src

Source 8-bit single-channel image. 输入的灰度图像

OutputArray dst

Destination image of the same size and the same type as src .与src大小和类型相同的目标映像。

double maxValue

Non-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 负数)从平均值或加权平均值中减去的常数

两种阈值公式:第五个参数

java使用opencv识别文字区域 opencvsharp 文字识别_灰度图像_08


java使用opencv识别文字区域 opencvsharp 文字识别_图像处理_09