OpenCV入门笔记(七) 文字区域的提取

前面我们已经学了一些OpenCV中基本的图片处理的知识,可以拿来做一些小应用。比如怎样从一张图片中,把文字圈出来。这一步骤对OCR(Optical Character Recognition)非常有用,因为一般的OCR引擎只是拿来识别文字,并没有对图片做预处理,因此精度可能会收到图片质量影响。

当然,我们这里只是粗略的查找文字区域,并没有进一步地处理图片。而且对背景复杂,或者文字旋转角度过于倾斜的情况也无法自适应,因此只能给大家做参考。若要实用到项目中,还有很多工作要做。


效果图

比如我们有下面的一篇文章的截图,想把其中的文字区域全部找出来。

这里写图片描述


当然这里的截图只有文字和白花花的背景,效果会非常好。绿色的的矩形框的是我们根据检测到的文字区域,手动画出来的。

这里写图片描述


原理

那么我们是怎么做到检测到区域的呢?

首先,我们会注意到,文字区域和其他的图片背景很不一样。我们用膨胀处理图片,让文字变成一块块大区域,然后识别整块的轮廓,用矩形去框住这个轮廓。

这个程序分三个子函数,detect(检测),preprocess(图片预处理),findTextRegion(查找和筛选文字区域)。即main函数调用detect函数去实际完成文字区域检测。detect函数又分成preprocess和findTextRegion两个步骤来做。

见下面的序列图,可能会清晰点。

Created with Raphaël 2.1.0 main main detect detect preprocess preprocess findTextRegion findTextRegion 检测文本区域 返回检测到的文本矩形 Sobel,二值化, 膨胀和腐蚀 Morphology方法预处理图片 返回预处理后的图片 轮廓检测,去掉 面积小的,过长的 查找和筛选文字区域 返回区域box的坐标


1. Detect

先来看main函数和Detect函数

def detect(img):
    # 1.  转化成灰度图
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
 
    # 2. 形态学变换的预处理,得到可以查找矩形的图片
    dilation = preprocess(gray)
 
    # 3. 查找和筛选文字区域
    region = findTextRegion(dilation)
 
    # 4. 用绿线画出这些找到的轮廓
    for box in region:
        cv2.drawContours(img, [box], 0, (0, 255, 0), 2)
 
    cv2.namedWindow("img", cv2.WINDOW_NORMAL)
    cv2.imshow("img", img)
 
    # 带轮廓的图片
    cv2.imwrite("contours.png", img)
 
    cv2.waitKey(0)
    cv2.destroyAllWindows()
 
 
if __name__ == '__main__':
    # 读取文件
    imagePath = sys.argv[1]
    img = cv2.imread(imagePath)
    detect(img)

 

2. Preprocess

利用数学形态学(Morphology)进行预处理。

这个过程很重要,是文字区域检测效果好坏的核心代码,尤其是一下几个参数:

  • 膨胀的核函数大小,这里用了 30 x 9,可以调节
  • 腐蚀的核函数大小,这里用了 24 x 6,可以调节
def preprocess(gray):

# 1. Sobel算子,x方向求梯度

sobel = cv2.Sobel(gray, cv2.CV_8U, 1, 0, ksize = 3)

# 2. 二值化

ret, binary = cv2.threshold(sobel, 0, 255, cv2.THRESH_OTSU+cv2.THRESH_BINARY)


# 3. 膨胀和腐蚀操作的核函数

element1 = cv2.getStructuringElement(cv2.MORPH_RECT, (30, 9))

element2 = cv2.getStructuringElement(cv2.MORPH_RECT, (24, 6))


# 4. 膨胀一次,让轮廓突出

dilation = cv2.dilate(binary, element2, iterations = 1)


# 5. 腐蚀一次,去掉细节,如表格线等。注意这里去掉的是竖直的线

erosion = cv2.erode(dilation, element1, iterations = 1)


# 6. 再次膨胀,让轮廓明显一些

dilation2 = cv2.dilate(erosion, element2, iterations = 3)


# 7. 存储中间图片

cv2.imwrite("binary.png", binary)

cv2.imwrite("dilation.png", dilation)

cv2.imwrite("erosion.png", erosion)

cv2.imwrite("dilation2.png", dilation2)


return dilation2

 

3. findTextRegion

def findTextRegion(img):
    region = []
 
    # 1. 查找轮廓
    contours, hierarchy = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
 
    # 2. 筛选那些面积小的
    for i in range(len(contours)):
        cnt = contours[i]
        # 计算该轮廓的面积
        area = cv2.contourArea(cnt) 
 
        # 面积小的都筛选掉
        if(area < 1000):
            continue
 
        # 轮廓近似,作用很小
        epsilon = 0.001 * cv2.arcLength(cnt, True)
        approx = cv2.approxPolyDP(cnt, epsilon, True)
 
        # 找到最小的矩形,该矩形可能有方向
        rect = cv2.minAreaRect(cnt)
        print "rect is: "
        print rect
 
        # box是四个点的坐标
        box = cv2.cv.BoxPoints(rect)
        box = np.int0(box)
 
        # 计算高和宽
        height = abs(box[0][1] - box[2][1])
        width = abs(box[0][0] - box[2][0])
 
        # 筛选那些太细的矩形,留下扁的
        if(height > width * 1.2):
            continue
 
        region.append(box)
 
    return region

 

完整代码

加上头文件,把几个函数合并以后,贴在这里。注意开头要写明用utf8编码,不然中文注释可能不会被系统识别。而且Python没有花括号来控制流程,所以对看不见的Tab缩进很敏感,写代码的时候要规范。

直接在终端里敲下面的命令,既可以运行

python textDetection.py ./pic/1.png

代码:textDetection.py

# coding:utf8


import sys


import cv2

import numpy as np


def preprocess(gray):

# 1. Sobel算子,x方向求梯度

sobel = cv2.Sobel(gray, cv2.CV_8U, 1, 0, ksize = 3)

# 2. 二值化

ret, binary = cv2.threshold(sobel, 0, 255, cv2.THRESH_OTSU+cv2.THRESH_BINARY)


# 3. 膨胀和腐蚀操作的核函数

element1 = cv2.getStructuringElement(cv2.MORPH_RECT, (30, 9))

element2 = cv2.getStructuringElement(cv2.MORPH_RECT, (24, 6))


# 4. 膨胀一次,让轮廓突出

dilation = cv2.dilate(binary, element2, iterations = 1)


# 5. 腐蚀一次,去掉细节,如表格线等。注意这里去掉的是竖直的线

erosion = cv2.erode(dilation, element1, iterations = 1)


# 6. 再次膨胀,让轮廓明显一些

dilation2 = cv2.dilate(erosion, element2, iterations = 3)


# 7. 存储中间图片

cv2.imwrite("binary.png", binary)

cv2.imwrite("dilation.png", dilation)

cv2.imwrite("erosion.png", erosion)

cv2.imwrite("dilation2.png", dilation2)


return dilation2



def findTextRegion(img):

region = []


# 1. 查找轮廓

contours, hierarchy = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)


# 2. 筛选那些面积小的

for i in range(len(contours)):

cnt = contours[i]

# 计算该轮廓的面积

area = cv2.contourArea(cnt)


# 面积小的都筛选掉

if(area < 1000):

continue


# 轮廓近似,作用很小

epsilon = 0.001 * cv2.arcLength(cnt, True)

approx = cv2.approxPolyDP(cnt, epsilon, True)


# 找到最小的矩形,该矩形可能有方向

rect = cv2.minAreaRect(cnt)

print "rect is: "

print rect


# box是四个点的坐标

box = cv2.cv.BoxPoints(rect)

box = np.int0(box)


# 计算高和宽

height = abs(box[0][1] - box[2][1])

width = abs(box[0][0] - box[2][0])


# 筛选那些太细的矩形,留下扁的

if(height > width * 1.2):

continue


region.append(box)


return region



def detect(img):

# 1. 转化成灰度图

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)


# 2. 形态学变换的预处理,得到可以查找矩形的图片

dilation = preprocess(gray)


# 3. 查找和筛选文字区域

region = findTextRegion(dilation)


# 4. 用绿线画出这些找到的轮廓

for box in region:

cv2.drawContours(img, [box], 0, (0, 255, 0), 2)


cv2.namedWindow("img", cv2.WINDOW_NORMAL)

cv2.imshow("img", img)


# 带轮廓的图片

cv2.imwrite("contours.png", img)


cv2.waitKey(0)

cv2.destroyAllWindows()



if __name__ == '__main__':

# 读取文件

imagePath = sys.argv[1]

img = cv2.imread(imagePath)

detect(img)

 

  • 1
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
WPF是Windows Presentation Foundation的缩写,是一种用于创建客户端应用程序的开发框架。而OpenCvSharp4是一个基于OpenCV的C#封装库,用于实现计算机视觉相关的功能。 在WPF中使用OpenCvSharp4实现文字提取的过程如下: 首先,需要在项目中引入OpenCvSharp4的库文件,并在代码中添加对该库的引用。 然后,可以使用OpenCvSharp4中的图像处理函数对图像进行预处理,例如灰度化、二值化等。这些处理可以通过调用相应的函数来实现,如cv.CvtColor()、cv.Threshold()等函数。 接下来,可以使用OpenCvSharp4中的文字提取功能对图像进行处理。可以选择使用OCR(Optical Character Recognition,光学字符识别)算法,通过训练模型来识别文字OpenCvSharp4库中提供了OCR相关的函数,例如cv.TextOcr()等。 在调用文字提取函数时,需要将预处理后的图像作为函数的输入,并指定相关参数。然后,函数会返回识别出的文字或文本区域的信息。 最后,可以将识别出的文字信息在WPF应用程序的界面上进行展示或保存到文件中,以便用户查看。 需要注意的是,文字提取是一项复杂的任务,其结果可能受到多种因素的影响,如图像质量、文字大小、字体等。因此,在实际使用中,可能需要对文字提取功能进行调试和优化,以获得更好的识别效果。 综上所述,通过使用WPF和OpenCvSharp4,我们可以实现文字提取的功能,将图像中的文字信息提取出来,并展示给用户或进行后续处理。这对于一些需要文字识别的应用场景,如自动化办公、图像搜索等,具有重要的实际意义。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值