零、任务描述:

xml文件中只有点坐标和其中可以结对的点坐标。要求将结对点坐标形成的区域裁剪出来并进行分类组成正样本,然后对所有点坐标两两结对,剔除可以两两结对的组合,然后进行裁图行程负样本。

本文将对过程中的关键点进行梳理,并对常见错误的解决方案进行说明。

xml格式如下:

-<point>
<name>0</name>
<x1>404</x1>
<y1>70</y1>
</point>
-<port>
<name>port</name>
<pose>Unspecified</pose>
-<portbox>
<x1>404</x1>
<y1>70</y1>
<x2>395</x2>
<y2>185</y2>
<portType>0</portType>
<portAngle>90</portAngle>
</portbox>
</port>

一、环境准备:

我这里使用的是vscode开启anaconda虚拟环境,关键库如下:

python、opencv-python、opencv-contrib-python、PIL、numpy等

下面是我导入语的库:

import sys,os
import numpy as np
from matplotlib import pyplot as plt
import xml.etree.ElementTree as ET
from math import *   #实现弧度变换
import cv2
import math
import PIL
from PIL import Image
import os.path
import glob

二、读取xml文件:

关键代码如下:

for img_file in os.listdir(img_path):    #遍历图片文件夹
    if img_file[-4:] in ['.png', '.jpg']:    #判断文件是否为图片格式
        if os.path.exists(xml_name):  #判断与图片同名的标签是否存在,因为图片不一定每张都打标
            root = ET.parse(xml_name).getroot() #利用ET读取xml文件

三:定义旋转矩阵:

在裁剪的过程中,需要对图像旋转:

def rotateImage(image, angle):
  image_center = tuple(np.array([(int(x0)+int(x1))/2,(int(y0)+int(y1))/2]))
  rot_mat = cv2.getRotationMatrix2D(image_center,angle,1.0)
  result = cv2.warpAffine(image, rot_mat, image.shape[1::-1],flags=cv2.INTER_LINEAR)
  return result

四、正负样本输出:

在裁剪的过程中判断图像是否正常

fileObj = open(path, 'rb') # 以二进制形式打开
buf = fileObj.read()
if not buf.startswith(b'\xff\xd8'): # 是否以\xff\xd8开头
bValid = False
elif buf[6:10] in (b'JFIF', b'Exif'): # “JFIF”的ASCII码
if not buf.rstrip(b'\0\r\n').endswith(b'\xff\xd9'): # 是否以\xff\xd9结尾
bValid = False
else:
Image.open(fileObj).verify()
except Exception as e:
bValid = False
print(e)
except Exception as e:
return False
return bValid

常见错误1

错误提示:TypeError: src is not a numpy array, neither a scalar

原因分析:使用image.open打开图像后,进行resize操作之后,不能直接使用cv2.imwrite保存图像。

解决方式:在cv2.imwrite之前,使用np.asarray进行数据转换。例如
obj_img2 = np.asarray(obj_img1)

常见错误2

错误现象:裁剪后的图像颜色不一致,偏蓝。

原因分析:因为OpenCV是以BGR模式读入图片,如果想要正常显示图片,则需要改成RGB格式。

解决方式:格式转换

obj_img2=cv2.cvtColor(obj_img2,cv2.COLOR_BGR2RGB)

常见错误3

错误报错:OSError: cannot identify image file

原因分析:图像格式出错。

解决方式:使用自定义的函数 is_valid_image()函数判断图像是否正常。

参考链接:

Python XML 解析

PIL及matplotlib:OSError: cannot identify image file錯誤及解決方式

利用Python获取VOC中的xml标注文件中的目标框

Python:批量按xml标注将目标crop剪切图片并按类保存到相应文件夹

python利用文件夹下xml格式标签文件批量裁剪出图片中的目标(文件夹、图片名称、目标框数量无限制,逐行注释)

解析大量xml文件坐标位置,裁剪图片

Python读取xml文件后,裁剪标注图片,并扩容数据

解决使用anaconda VSCODE无法import cv2问题

Python - 深度学习系列3-图像区域标注及抠图