Python代码库OpenCV之14 按照先列后行切割

Python代码库OpenCV之13 古书一页切成两页

前置项目

首先将pdf切割成图片,

  • Python代码库之PDF转换为图片poppler
    将图片切割为2页
  • Python代码库OpenCV之13 古书一页切成两页

测试图片

1.png

代码

import cv2
import numpy as np
import cv2
from matplotlib import pyplot as plt
import os
import pandas as pd
import shutil

img_filename='./image/1.png'
out_path='./chunqiu_out_split'
filename=0

# 二值化
def thresh_binary(img):
    blur = cv2.GaussianBlur(img, (9, 9), 0)
    # OTSU's binaryzation
    ret3, th3 = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
    kernel = np.ones((2, 2), np.uint8)
    opening = cv2.morphologyEx(th3, cv2.MORPH_OPEN, kernel)
    return opening
    
# 统计每一行的黑点数
def hist_col(img):
    list=[]
    row, col = img.shape
    for i in range(col):
        list.append((img[:, i] < 200).sum())
    return list

def cut_col(img, hist_list):
    minlist = []
    images = []
    row, col = img.shape
    np_list = np.array(hist_list)
    avg = col/64
    i = 0
    # print np_list
    while i < col-1:
        if i >= col-10:
            if np_list[i] < 40 and np_list[i] <= np_list[i+1: col].min():
                minlist.append(i)
                break
            if i == col-1:
                minlist.append(i)
                break
        else:
            i=int(i)
            if np_list[i] < 40 and np_list[i] < np_list[i+1: i+10].min():
                minlist.append(i)
                i += avg
        i += 1
    print (minlist)
    for j in range(len(minlist)-1):
        print (j)
        images.append(img[0:row, minlist[j]:minlist[j+1]])
    return images
# 直方图绘制
def hist_show(one_list):
    data=one_list
    # 将列表转换成pandas的Series格式(因为里边有自带的函数可以统计元素出现的个数, for统计列表中元素出现的次数,效率过慢,不适用于大数据量)
    data_pd = pd.Series(data)
    l_unique_data = list(data_pd.value_counts().index)  # 该数据中的唯一值
    l_num = list(data_pd.value_counts())  # 唯一值出现的次数
    plt.bar(l_unique_data, l_num, width=0.1)
    plt.show()

# sum the black pixel numbers in each rows
def hist_row(img):
    list=[]
    row, col = img.shape
    for i in range(row):
        list.append((img[i, :] < 200).sum())
    return cut_row(img, list)

# find each segmentation rows
def cut_row(img, row_list):
    minlist = []
    single_images_with_rect = []
    row, col = img.shape
    np_list = np.array(row_list)
    avg = row/32
    i = 0
    while i <= row-1:
        i=int(i)
        if i >= row-10 and np_list[i] == 0:
            minlist.append(i)
            break
        elif np_list[i] == 0 and (np_list[i+1: i+10] < 200).sum() >= 5:
            minlist.append(i)
            i += avg
        i += 1
    print (minlist)
    for j in range(len(minlist)-1):
        single_img = img[minlist[j]:minlist[j+1], 0:col]
        single_img_with_rect = single_cut(single_img)
        if single_img_with_rect is not None:
            single_images_with_rect.append(single_img_with_rect)
    return single_images_with_rect

# find the single word's contours and take off the redundant margin
def single_cut(img):
    global filename
    blur = cv2.GaussianBlur(img, (9, 9), 0)
    ret3, th3 = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
    contours, hierarchy = cv2.findContours(th3, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    up, left = img.shape
    down, right = 0, 0
    for i in range(len(contours)):
        cnt = contours[i]
        x, y, w, h = cv2.boundingRect(cnt)
        if w < 6 and h < 6:
            continue
        if x < up:
            up = x
        if y < left:
            left = y
        if x+w > down:
            down = x+w
        if y+h > right:
            right = y+h
    if down-up >= 40 and right-left >= 40:
        word = img[left:right, up:down]
        cv2.imwrite(out_path+'/'+str(filename)+'.png', word)
        cv2.rectangle(img,(up, left), (down, right), (0, 255, 0), 2)
        filename += 1
        return img
    else:
        return None


# 准备工作,文件
##

## 创建文件夹
if os.path.exists(out_path): 
    shutil.rmtree(out_path, ignore_errors=True)
os.mkdir(out_path)

#第一步,灰度
img = cv2.imread(img_filename,cv2.IMREAD_GRAYSCALE)
#第二步 二值化(膨胀blur,腐蚀)
opening=thresh_binary(img)

#反转

r,c=0,0
for rows in opening:
    c=0
    
    for citem in rows:
        #print('r',r,'c',c)
        if citem == 255:opening[r,c]=0
        else: opening[r,c]=255
        c=c+1
    r=r+1

#第三步,直方图
hist_list = hist_col(opening)
#第四步,切割图片
images = cut_col(opening, hist_list)
# create two plt
fig, axes = plt.subplots(1, len(images), sharex=True, sharey=True)
fig2, axes2 = plt.subplots(len(images), 12, sharex=True, sharey=True)

#第五步,
# split the pieces into single words by rows
for i in range(len(images)):
    axes[i].imshow(images[i], 'gray')
    single_images_with_rect = hist_row(images[i])
    for j in range(len(single_images_with_rect)):
        axes2[i, j].imshow(single_images_with_rect[j], 'gray')
fig.savefig(out_path+'/cut_col.png')
fig2.savefig(out_path+'/single.png')
plt.clf()

#cv2.imshow('gray',img)
#cv2.waitKey()


#cv2.imshow('opening1',opening)
#cv2.waitKey(0)

更多精彩代码请关注我的专栏

  • selenium & python 源码大全
  • reportlab教程和源码大全
  • python源码大全

你可能感兴趣的:(Python代码库OpenCV之14 按照先列后行切割)