ICPR MTWI 2018挑战赛 网络图像的文本识别之数据预处理

该数据预处理工作主要是基于图片数据集&坐标文本信息数据集来对图片进行切割和文本信息的匹配。

实现过程中参考的博客:

 opencv图片旋转矩形分割 https://blog.csdn.net/u013948010/article/details/78605043 

基于anaconda的编辑器spyder,python3.6,图像处理的库使用了Opencv,由于anaconda自带有的集成环境以及Anaconda Navigator可以让总是被折磨于环境和库的配置的菜鸟得以苟活。综上所述就是配置Opencv时候直接在Navigator里面搜索并install就OK了(如下图)。


数据的处理主要分为以下三步:

一.读出txt文件中的目标图片的坐标以及文本信息;

二.根据所得到的坐标进行图片截取并旋正;

三.保存目标图片以及其对应的文本信息。

首先呢先吧工作路径改到目标文件,为了方便用.glob来获取所有的图片名字(因为数据集的文件名悠长而鬼畜)

os.chdir('d:\\[update]ICPR_text_train_part1_20180316\\image_1000')#修改默认路径
retval =os.getcwd()#获取当前路径
SetofimageName =glob.glob('*.jpg') #获取当前路径下所有jpg格式文件名到list中

关于文件路径的写法,是一个玄学问题,反正多试几次总会碰到正确的写法的,反正我的python3.6路径全部使用 \\ 是可以的。程序的完整代码如下

import cv2
from math import *
import math
import numpy as np
import os
import glob

'''旋转图像并剪裁'''
def rotate(
        img,                    # 图片
        pt1, pt2, pt3, pt4,     # 四点坐标
        NewimageName            # 输出图片路径
):
    withRect = math.sqrt((pt4[0] - pt1[0]) ** 2 + (pt4[1] - pt1[1]) ** 2)      # 矩形框的宽度
#    heightRect = math.sqrt((pt1[0] - pt2[0]) ** 2 + (pt1[1] - pt2[1]) **2)
    if(withRect!=0):
        angle = acos((pt4[0] - pt1[0]) / withRect) * (180 / math.pi)               # 矩形框旋转角度
    
        if pt4[1]<pt1[1]:
            angle=-angle
        
        height = img.shape[0]  # 原始图像高度
        width = img.shape[1]   # 原始图像宽度
        rotateMat = cv2.getRotationMatrix2D((width / 2, height / 2), angle, 1)     # 按angle角度旋转图像
        heightNew = int(width * fabs(sin(radians(angle))) + height * fabs(cos(radians(angle))))
        widthNew = int(height * fabs(sin(radians(angle))) + width * fabs(cos(radians(angle))))
    
        rotateMat[0, 2] += (widthNew - width) / 2
        rotateMat[1, 2] += (heightNew - height) / 2
        imgRotation = cv2.warpAffine(img, rotateMat, (widthNew, heightNew), borderValue=(255, 255, 255))
    
        # 旋转后图像的四点坐标
        [[pt1[0]], [pt1[1]]] = np.dot(rotateMat, np.array([[pt1[0]], [pt1[1]], [1]]))
        [[pt3[0]], [pt3[1]]] = np.dot(rotateMat, np.array([[pt3[0]], [pt3[1]], [1]]))
        [[pt2[0]], [pt2[1]]] = np.dot(rotateMat, np.array([[pt2[0]], [pt2[1]], [1]]))
        [[pt4[0]], [pt4[1]]] = np.dot(rotateMat, np.array([[pt4[0]], [pt4[1]], [1]]))
    
        # 处理反转的情况
        if pt2[1]>pt4[1]:
            pt2[1],pt4[1]=pt4[1],pt2[1]
        if pt1[0]>pt3[0]:
            pt1[0],pt3[0]=pt3[0],pt1[0]
    
        imgOut = imgRotation[int(pt2[1]):int(pt4[1]), int(pt1[0]):int(pt3[0])]
        cv2.imwrite(NewimageName, imgOut)  # 保存得到的旋转后的矩形框
        return imgRotation                 # rotated image

#  读取四点坐标
def ReadTxt(directory,last):
    global Newpathofimage, Newpathoftxt, allpic, nowimage, nowtxt, nowline, invalidimg
    SetofimageName = glob.glob('*.jpg')                     #获取当前路径下所有jpg格式文件名到list中
    Numofimage = len(SetofimageName) 
    for j in range(Numofimage):
        print('处理图片:'+str(j))
        imageTxt = directory + SetofimageName[j][:-4] + last     # txt路径
        imageName =SetofimageName[j]
        nowimage = imageName
        nowtxt = imageTxt
        nowline = 0
        imgSrc = cv2.imread(imageName)
        if(imgSrc is None):
            invalidimg.append(nowimage)
        else:
            F = open(imageTxt,'rb')								#以二进制模式打开目标txt文件
            lines = F.readlines()								#逐行读入内容
            length=len(lines)
            s = 0                                               #计算图片编号,对应文本描述
            for i in range(length):
                lines[i] = str(lines[i], encoding = "utf-8")    #从bytes转为str格式
                des = lines[i].split(',')[-1:]
                nowline = i
                if ((des != ['###\n']) and (des != ['###'])):
                    s = s + 1
                    allpic+=1
                    #保存新图片/txt格式为"原名字+编号+.jpg/.txt"
                    NewimageName = Newpathofimage + imageName[:-3] + str(s) + '.jpg'
                    NewtxtName = Newpathoftxt + imageName[:-3] + str(s) + '.txt'
                    #写入新TXT文件
                    if (s == length):
                        des = str(des)[2:-2]
                    else:
                        des = str(des)[2:-4]
                    file = open(NewtxtName,'w')				#打开or创建一个新的txt文件
                    file.write(des)        					#写入内容信息  
                    file.close()  
                    # str转float
                    pt1 = list(map(float,lines[i].split(',')[:2]))
                    pt2 = list(map(float,lines[i].split(',')[2:4]))
                    pt3 = list(map(float,lines[i].split(',')[4:6]))
                    pt4 = list(map(float,lines[i].split(',')[6:8]))
                    # float转int 
                    pt1=list(map(int,pt1))
                    pt2=list(map(int,pt2))        
                    pt4=list(map(int,pt4))
                    pt3=list(map(int,pt3))
                    rotate(imgSrc,pt1,pt2,pt3,pt4,NewimageName)                
    
if __name__=="__main__":
    Newpathofimage = 'd:\\competition\\[update] ICPR_text_train_part1_20180316\\newimage\\'
    Newpathoftxt = 'd:\\competition\\[update] ICPR_text_train_part1_20180316\\newtxt\\'
    allpic = 0
    nowimage = ''
    nowtxt = ''
    nowline = 0
    invalidimg=[]
    os.chdir('d:\\competition\\[update] ICPR_text_train_part1_20180316\\image_1000')#修改默认路径
    retval = os.getcwd()#获取当前路径
    directory = 'd:\\competition\\[update] ICPR_text_train_part1_20180316\\txt_1000\\'#TXT文件路径
    last = '.txt'
    ReadTxt(directory,last)

关于TXT读取部分,F = open(imageTxt,'rb'),imageTxt为文件路径,’’为打开的模式,由于该数据集中既有数字又有中文等等符号,所以用’r’模式是无法打开的(会报错),只能先用二进制模式打开,自己再转str就可以了。Txt文本格式如下:


新txt文件写入直接使用如下代码就可以了:

file = open(NewtxtName,'w')				#打开or创建一个新的txt文件,NewTXTName为新文件的全路径
file.write(des)        					#写入内容信息  
file.close()  

关于目标图像的截取以及保存呢其实是直接参考一篇博客的,测试了下可以就修修改改直接用了,原理也不是很难就不赘述。注意一点就是虽然数据集提供的是两位小数的坐标,但考虑到实际就将坐标转为整数(像素数不可能小于1噻),所以需要加上if(withRect!=0)的判断条件。

总结

数据预处理过程中学会了:文件的打开,读取,写入;图片的截取,旋转,保存;文件路径的改变;批量读取文件名的方法;split分割。




猜你喜欢

转载自blog.csdn.net/guijieling/article/details/80009823