您的位置:首页 > 运维架构

OpenCV 文字区域的提取

2017-10-27 10:03 609 查看


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()


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: ",rect)

# box是四个点的坐标
box = cv2.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


完整代码:

# coding:utf8

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. 查找轮廓
binary,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: ",rect)

# box是四个点的坐标
box = cv2.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__':
# 读取文件
img = cv2.imread('/Users/yuki/Downloads/timg3.jpg')
detect(img)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: