该数据预处理工作主要是基于图片数据集&坐标文本信息数据集来对图片进行切割和文本信息的匹配。
实现过程中参考的博客:
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]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分割。