使用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

四、正负样本输出:

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

def is_valid_image(path):
  '''
  检查文件是否损坏
  '''
  try:
    bValid = True
    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:
      try:
        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-图像区域标注及抠图

posted @ 2021-03-01 11:44  yk要努力  阅读(1126)  评论(0编辑  收藏  举报