使用python与opencv解析xml文件 裁剪目标图像 关键点与遇到的问题
零、任务描述:
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
四、正负样本输出:
在裁剪的过程中判断图像是否正常
常见错误1
错误提示:TypeError: src is not a numpy array, neither a scalar
原因分析:使用image.open打开图像后,进行resize操作之后,不能直接使用cv2.imwrite保存图像。
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()函数判断图像是否正常。
参考链接:
PIL及matplotlib:OSError: cannot identify image file錯誤及解決方式
Python:批量按xml标注将目标crop剪切图片并按类保存到相应文件夹
python利用文件夹下xml格式标签文件批量裁剪出图片中的目标(文件夹、图片名称、目标框数量无限制,逐行注释)