窗口按s保存
API_draw.py
# -*- coding: utf-8 -*-
import copy
import cv2
import numpy as np
WIN_NAME = 'draw_rect'
from API_XML import *
class Rect(object):
def __init__(self):
self.tl = (0, 0)
self.br = (0, 0)
def regularize(self):
"""
make sure tl = TopLeft point, br = BottomRight point
"""
pt1 = (min(self.tl[0], self.br[0]), min(self.tl[1], self.br[1]))
pt2 = (max(self.tl[0], self.br[0]), max(self.tl[1], self.br[1]))
self.tl = pt1
self.br = pt2
class DrawRects(object):
def __init__(self, image, color, thickness=1):
self.original_image = image
self.image_for_show = image.copy()
self.color = color
self.thickness = thickness
self.rects = []
self.current_rect = Rect()
self.left_button_down = False
@staticmethod
def __clip(value, low, high):
"""
clip value between low and high
Parameters
----------
value: a number
value to be clipped
low: a number
low limit
high: a number
high limit
Returns
-------
output: a number
clipped value
"""
output = max(value, low)
output = min(output, high)
return output
def shrink_point(self, x, y):
"""
shrink point (x, y) to inside image_for_show
Parameters
----------
x, y: int, int
coordinate of a point
Returns
-------
x_shrink, y_shrink: int, int
shrinked coordinate
"""
height, width = self.image_for_show.shape[0:2]
x_shrink = self.__clip(x, 0, width)
y_shrink = self.__clip(y, 0, height)
return (x_shrink, y_shrink)
def append(self):
"""
add a rect to rects list
"""
self.rects.append(copy.deepcopy(self.current_rect))
def pop(self):
"""
pop a rect from rects list
"""
rect = Rect()
if self.rects:
rect = self.rects.pop()
return rect
def reset_image(self):
"""
reset image_for_show using original image
"""
self.image_for_show = self.original_image.copy()
def draw(self):
"""
draw rects on image_for_show
"""
for rect in self.rects:
cv2.rectangle(self.image_for_show, rect.tl, rect.br,
color=self.color, thickness=self.thickness)
def draw_current_rect(self):
"""
draw current rect on image_for_show
"""
cv2.rectangle(self.image_for_show,
self.current_rect.tl, self.current_rect.br,
color=self.color, thickness=self.thickness)
def onmouse_draw_rect(event, x, y, flags, draw_rects):
if event == cv2.EVENT_LBUTTONDOWN:
# pick first point of rect
print('pt1: x = %d, y = %d' % (x, y))
draw_rects.left_button_down = True
draw_rects.current_rect.tl = (x, y)
if draw_rects.left_button_down and event == cv2.EVENT_MOUSEMOVE:
# pick second point of rect and draw current rect
draw_rects.current_rect.br = draw_rects.shrink_point(x, y)
draw_rects.reset_image()
draw_rects.draw()
draw_rects.draw_current_rect()
if event == cv2.EVENT_LBUTTONUP:
# finish drawing current rect and append it to rects list
draw_rects.left_button_down = False
draw_rects.current_rect.br = draw_rects.shrink_point(x, y)
print('pt2: x = %d, y = %d' % (draw_rects.current_rect.br[0],
draw_rects.current_rect.br[1]))
draw_rects.current_rect.regularize()
draw_rects.append()
if (not draw_rects.left_button_down) and event == cv2.EVENT_RBUTTONDOWN:
# pop the last rect in rects list
draw_rects.pop()
draw_rects.reset_image()
draw_rects.draw()
if __name__ == '__main__':
#image = np.zeros((256, 256, 3), np.uint8)
image=cv2.imread("test1.jpg")
draw_rects = DrawRects(image, (0, 255, 0), 2)
cv2.namedWindow(WIN_NAME, 0)
cv2.setMouseCallback(WIN_NAME, onmouse_draw_rect, draw_rects)
while True:
cv2.imshow(WIN_NAME, draw_rects.image_for_show)
key = cv2.waitKey(30)
if key == ord('q') or key == ord('Q') : # ESC
break
elif key == ord('s') or key == ord('S') :
print("===========\n")
i=1
#1创建
# 1.创建DOM树对象
dom=minidom.Document()
API_Creat_Xml_Node1(dom,"root")
for rect in draw_rects.rects:
print("x1",rect.tl[0],"y1",rect.tl[1], "x2",rect.br[0],"y2",rect.br[1])
# 2.1创建次节点
root2_node=API_Creat_Xml_Node2(dom,"zuowei",str(i))
API_Creat_Xml_Node3(dom,root2_node,"xmin",str(rect.tl[0]))
API_Creat_Xml_Node3(dom,root2_node,"ymin",str(rect.tl[1]))
API_Creat_Xml_Node3(dom,root2_node,"xmax",str(rect.br[0]))
API_Creat_Xml_Node3(dom,root2_node,"ymax",str(rect.br[1]))
i=i+1
try:
with open(path_xml,'w',encoding='UTF-8') as fh:
# 4.writexml()第一个参数是目标文件对象,第二个参数是根节点的缩进格式,第三个参数是其他子节点的缩进格式,
# 第四个参数制定了换行格式,第五个参数制定了xml内容的编码。
dom.writexml(fh,indent='',addindent='\t',newl='\n',encoding='UTF-8')
print('写入xml OK!')
except Exception as err:
print('错误信息:{0}'.format(err))
#2读取
#USE_2_1ReadXMLNode(path_xml,"zuowei","xmin")
#访问所有的座位节点
USE_2_2ReadXMLNode(path_xml,"zuowei",["xmin","ymin","xmax","ymax"])
cv2.destroyAllWindows()
API_XML.py
#导入minidom
from xml.dom import minidom
path_xml='config.xml'
# 1.创建DOM树对象
dom=minidom.Document()
def API_Creat_Xml_Node1(dom,root1_Name):
# 1.创建DOM树对象
#dom=minidom.Document()
# 2.创建根节点。每次都要用DOM对象来创建任何节点。
root_node=dom.createElement(root1_Name)
# 3.用DOM对象添加根节点
dom.appendChild(root_node)
# 设置该节点的属性
root_node.setAttribute('info','主节点')
def API_Creat_Xml_Node2(dom,root2_Name,msg):
# 获取根节点
root_node=dom.documentElement
# 节点名称
print(root_node.nodeName)
# 用DOM对象创建元素子节点
root2_node=dom.createElement(root2_Name)
# 用父节点对象添加元素子节点
root_node.appendChild(root2_node)
# 设置该节点的属性
root2_node.setAttribute('info',msg)
return root2_node
def API_Creat_Xml_Node3(dom,root2_node,root3_Name,msg):
root3_node=dom.createElement(root3_Name)
root2_node.appendChild(root3_node)
# 也用DOM创建文本节点,把文本节点(文字内容)看成子节点
name_text=dom.createTextNode(msg)
# 用添加了文本的节点对象(看成文本节点的父节点)添加文本节点
root3_node.appendChild(name_text)
'''
函数功能:创建数据
函数输入:path_xml 文件名字
函数输出:
<?xml version="1.0" encoding="UTF-8"?>
<root info="主节点">
<car info="car1">
<xmin>1</xmin>
<ymin>2</ymin>
<xmax>3</xmax>
<ymax>4</ymax>
</car>
<car info="car2">
<xmin>5</xmin>
<ymin>6</ymin>
<xmax>7</xmax>
<ymax>8</ymax>
</car>
</root>
'''
def USE_1Creat_Xml(path_xml):
# 1.创建DOM树对象
dom=minidom.Document()
API_Creat_Xml_Node1(dom,"root")
# 2.1创建次节点
root2_node=API_Creat_Xml_Node2(dom,"car","car1")
API_Creat_Xml_Node3(dom,root2_node,"xmin","1")
API_Creat_Xml_Node3(dom,root2_node,"ymin","2")
API_Creat_Xml_Node3(dom,root2_node,"xmax","3")
API_Creat_Xml_Node3(dom,root2_node,"ymax","4")
# 2.2创建次节点
root2_node=API_Creat_Xml_Node2(dom,"car","car2")
API_Creat_Xml_Node3(dom,root2_node,"xmin","5")
API_Creat_Xml_Node3(dom,root2_node,"ymin","6")
API_Creat_Xml_Node3(dom,root2_node,"xmax","7")
API_Creat_Xml_Node3(dom,root2_node,"ymax","8")
# 每一个结点对象(包括dom对象本身)都有输出XML内容的方法,如:toxml()--字符串, toprettyxml()--美化树形格式。
try:
with open(path_xml,'w',encoding='UTF-8') as fh:
# 4.writexml()第一个参数是目标文件对象,第二个参数是根节点的缩进格式,第三个参数是其他子节点的缩进格式,
# 第四个参数制定了换行格式,第五个参数制定了xml内容的编码。
dom.writexml(fh,indent='',addindent='\t',newl='\n',encoding='UTF-8')
print('写入xml OK!')
except Exception as err:
print('错误信息:{0}'.format(err))
'''
函数功能:读取数据
函数输入:
path_xml 文件名字
root1_Name 2次节点 car
root2_Name 3次节点 xmin
函数输出:
<?xml version="1.0" encoding="UTF-8"?>
<root info="主节点">
<car info="car1">
<xmin>1</xmin>
<ymin>2</ymin>
<xmax>3</xmax>
<ymax>4</ymax>
</car>
<car info="car2">
<xmin>5</xmin>
<ymin>6</ymin>
<xmax>7</xmax>
<ymax>8</ymax>
</car>
</root>
'''
def USE_2_1ReadXMLNode(path_xml,root1_Name,root2_Name):
#打开文件
with open(path_xml,'r',encoding='utf8') as fh:
# 1 获取根节点
# parse()获取DOM对象
dom=minidom.parse(fh)
# 获取根节点
root=dom.documentElement
# 节点名称
print(root.nodeName)
#2 获取2次节点 root1_Name 是一个列表
change_1Node_all = root.getElementsByTagName(root1_Name) # 所有的 car节点
#循环访问每个次节点
for change_1Node_i in change_1Node_all:
#3 获取2次节点 root1_Name 下面的3次节点 root2_Name 是一个列表
change_2Node = change_1Node_i.getElementsByTagName(root2_Name)[0] #肯恶搞有很多个root2_Name xmin
change_old= change_2Node.childNodes[0].data
print(change_old)
'''
函数功能:访问所有 root1_Name下面的 指定属性root2_NameList
函数输入:
节点root1_Name car
指定属性root2_NameList ["xmin","ymin","xmax","ymax"]
函数输出:
root
节点名字 ['xmin', 'ymin', 'xmax', 'ymax']
相同节点 0 ['33', '42', '106', '90']
相同节点 0 ['80', '139', '167', '195']
相同节点 0 ['150', '87', '217', '141']
'''
def USE_2_2ReadXMLNode(path_xml,root1_Name,root2_NameList):
#打开文件
with open(path_xml,'r',encoding='utf8') as fh:
# 1 获取根节点
# parse()获取DOM对象
dom=minidom.parse(fh)
# 获取根节点
root=dom.documentElement
# 节点名称
print(root.nodeName)
#2 获取2次节点 root1_Name 是一个列表
change_1Node_all = root.getElementsByTagName(root1_Name) # 所有的 car节点
print('节点名字',root1_Name)
print('节点属性',root2_NameList)
i=0
#循环访问每个次节点
for change_1Node_i in change_1Node_all:
data_msg=[]
for root2_Name_i in root2_NameList:
#3 获取2次节点 root1_Name 下面的3次节点 root2_Name 是一个列表
change_2Node = change_1Node_i.getElementsByTagName(root2_Name_i)[0] #肯恶搞有很多个root2_Name xmin
date= change_2Node.childNodes[0].data
#print(root2_Name_i,date)
data_msg.append(date)
print(root1_Name,'节点',i,data_msg)
i=i+1
'''
#1创建
USE_1Creat_Xml(path_xml)
#2读取
USE_2_1ReadXMLNode(path_xml,"car","xmin")
#2-1读取
USE_2_2ReadXMLNode(path_xml,"car",["xmin","ymin","xmax","ymax"])
'''
'''
#1创建
# 1.创建DOM树对象
dom=minidom.Document()
API_Creat_Xml_Node1(dom,"root")
#2循环添加节点
for rect in rects:
print("x1",rect.tl[0],"y1",rect.tl[1], "x2",rect.br[0],"y2",rect.br[1])
# 2.1创建次节点
root2_node=API_Creat_Xml_Node2(dom,"zuowei",str(i))
API_Creat_Xml_Node3(dom,root2_node,"xmin",str(rect.tl[0]))
API_Creat_Xml_Node3(dom,root2_node,"ymin",str(rect.tl[1]))
API_Creat_Xml_Node3(dom,root2_node,"xmax",str(rect.br[0]))
API_Creat_Xml_Node3(dom,root2_node,"ymax",str(rect.br[1]))
i=i+1
try:
with open(path_xml,'w',encoding='UTF-8') as fh:
# 4.writexml()第一个参数是目标文件对象,第二个参数是根节点的缩进格式,第三个参数是其他子节点的缩进格式,
# 第四个参数制定了换行格式,第五个参数制定了xml内容的编码。
dom.writexml(fh,indent='',addindent='\t',newl='\n',encoding='UTF-8')
print('写入xml OK!')
except Exception as err:
print('错误信息:{0}'.format(err))
#2读取
#USE_2_1ReadXMLNode(path_xml,"zuowei","xmin")
#访问所有的座位节点
USE_2_2ReadXMLNode(path_xml,"zuowei",["xmin","ymin","xmax","ymax"])
'''