opencv:去除表格线

C++版:

void preProcessToEraseLine(cv::Mat input, cv::Mat& output)
{
	cv::Mat gray, binary, inv_img, horizonal_img, vertical_img, h_kernel, v_kernel, mask_img, no_border_img;
	cv::cvtColor(input, gray, cv::COLOR_BGR2GRAY);
	cv::threshold(gray, binary, 200, 255, 0);
	inv_img = 255 - binary;
	horizonal_img = inv_img;
	vertical_img = inv_img;

	cv::Mat h_img_erode, h_img_dilate;
	h_kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(100, 1));
	cv::erode(horizonal_img, h_img_erode, h_kernel);
	cv::dilate(h_img_erode, h_img_dilate, h_kernel);

	cv::Mat v_img_erode, v_img_dilate;
	v_kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(1, 100));
	cv::erode(vertical_img, v_img_erode, v_kernel);
	cv::dilate(v_img_erode, v_img_dilate, v_kernel);

	mask_img = h_img_dilate + v_img_dilate;
	cv::bitwise_or(binary, mask_img, no_border_img);
	cv::cvtColor(no_border_img, output, cv::COLOR_GRAY2RGB);
	cv::imshow("no_border", output);
	cv::waitKey(0);
	cv::destroyAllWindows();
}

python版:

# coding:utf8
import numpy as np
import cv2
import sys
import os
import matplotlib.pyplot as plt
from PIL import Image

#Method 1:
# 读取文件
imagePath = os.getcwd()+"\\mytest.jpg"
img = cv2.imread(imagePath)

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray, 200, 255, 0)
#assuming, b_w is the binary image
inv = 255 - binary
horizontal_img = inv
vertical_img = inv

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (100,1))
horizontal_img = cv2.erode(horizontal_img, kernel, iterations=1)
horizontal_img = cv2.dilate(horizontal_img, kernel, iterations=1)


kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (1,100))
vertical_img = cv2.erode(vertical_img, kernel, iterations=1)
vertical_img = cv2.dilate(vertical_img, kernel, iterations=1)

mask_img = horizontal_img + vertical_img
# no_border = np.bitwise_or(binary, mask_img)
no_border = cv2.bitwise_or(binary, mask_img)
cv2.imshow("no_border", no_border)


'''
#Method 2:
imagePath = os.getcwd()+"\\mytest.jpg"
img = cv2.imread(imagePath)

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray, 127, 255, 0)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray, 127, 255, 0)
contours,hierarchy = cv2.findContours(binary,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
#绘制独立轮廓,如第四个轮廓
imag = cv2.drawContours(img,contours,-1,(0,255,0),3)
#但是大多数时候,下面方法更有用
#imag = cv2.drawContours(img,contours,3,(0,0,255),3)
cv2.imshow("contour", imag)
'''

#Method 3:
'''imagePath = os.getcwd()+"\\mytest.jpg"
img = cv2.imread(imagePath)

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 此步骤形态学变换的预处理,得到可以查找矩形的图片
# 参数:输入矩阵、输出矩阵数据类型、设置1、0时差分方向为水平方向的核卷积,设置0、1为垂直方向,ksize:核的尺寸
sobel = cv2.Sobel(gray, cv2.CV_8U, 0, 1, ksize = 3)
# 二值化
ret, binary = cv2.threshold(sobel, 0, 255, cv2.THRESH_OTSU+cv2.THRESH_BINARY)
plt.imshow(binary,'gray')
plt.show()

# 设置膨胀和腐蚀操作的核函数
element1 = cv2.getStructuringElement(cv2.MORPH_RECT, (30, 9))
element2 = cv2.getStructuringElement(cv2.MORPH_RECT, (24, 6))

# 膨胀一次,让轮廓突出
dilation = cv2.dilate(binary, element2, iterations = 1)

# 腐蚀一次,去掉细节,如表格线等。注意这里去掉的是竖直的线
erosion = cv2.erode(dilation, element1, iterations = 1)

# aim = cv2.morphologyEx(binary, cv2.MORPH_CLOSE,element1, 1 )   #此函数可实现闭运算和开运算
# 以上膨胀+腐蚀称为闭运算,具有填充白色区域细小黑色空洞、连接近邻物体的作用

# 再次膨胀,让轮廓明显一些
dilation2 = cv2.dilate(erosion, element2, iterations = 3)


# 显示一次闭运算后的效果
plt.imshow(erosion,'gray')
plt.show()

# 显示连续膨胀3次后的效果
plt.imshow(dilation2,'gray')
plt.show()

#  查找和筛选文字区域
region = []
#  查找轮廓
contours, hierarchy = cv2.findContours(dilation2, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 利用以上函数可以得到多个轮廓区域,存在一个列表中。
#  筛选那些面积小的
for i in range(len(contours)):
    # 遍历所有轮廓
    # cnt是一个点集
    cnt = contours[i]

    # 计算该轮廓的面积
    area = cv2.contourArea(cnt)

    # 面积小的都筛选掉、这个1000可以按照效果自行设置
    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.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.3):
        continue

    region.append(box)

# 用绿线画出这些找到的轮廓
for box in region:
    cv2.drawContours(img, [box], 0, (0, 255, 0), 2)


plt.imshow(img,'brg')
plt.show()

# 弹窗显示
cv2.namedWindow("img", cv2.WINDOW_NORMAL)
cv2.imshow("img", img)
'''
    # 带轮廓的图片
cv2.waitKey(0)
cv2.destroyAllWindows()

 

 

Guess you like

Origin blog.csdn.net/lxiao428/article/details/103526209