meterviewer.datasets.read.config 源代码

# read dataset from file system.
import typing as t
import xml.etree.ElementTree as ET
from dataclasses import dataclass
from pathlib import Path as P

from meterviewer import func as F
from meterviewer import types as T

from .types import typeOfrect


[文档] @dataclass class RectO(object): """矩形对象类,用于存储和处理矩形框的坐标信息 属性: xmin (str): 矩形左边界x坐标 ymin (str): 矩形上边界y坐标 xmax (str): 矩形右边界x坐标 ymax (str): 矩形下边界y坐标 """ xmin: str = "" ymin: str = "" xmax: str = "" ymax: str = "" def check(self): # assert rect.xmin != "" and rect.ymin != "" and rect.xmax != "" and rect.ymax != "", rect assert ( self.xmin != "" and self.ymin != "" and self.xmax != "" and self.ymax != "" ), self def to_dict(self) -> T.Rect: return T.Rect.model_validate( { "xmin": self.xmin, "ymin": self.ymin, "xmax": self.xmax, "ymax": self.ymax, } ) def __str__(self): return f"RectO({self.xmin}, {self.ymin}, {self.xmax}, {self.ymax})" def __repr__(self): return self.__str__()
[文档] def read_rect_from_node(root: t.Iterable) -> t.Tuple[str, T.Rect]: """从XML节点中读取矩形框信息 Args: root (Iterable): XML根节点 Returns: Tuple[str, T.Rect]: 返回值和矩形框字典的元组 """ val, rect_dict = "", RectO() for child in root: # find object if not child.tag == "object": continue for subchild in child: if subchild.tag == "name": val = str(subchild.text) # print(subchild.tag, subchild.text) if subchild.tag == "bndbox": for sub in subchild: setattr(rect_dict, sub.tag, sub.text) return val, rect_dict.to_dict()
[文档] def read_xml(filename: P): """读取 xml 文件,获取 root 节点""" assert filename.exists(), f"{filename}文件不存在" tree = ET.parse(filename) return tree.getroot()
[文档] def read_xml_to_get( filename: P, read_func: t.Callable[[t.Any], t.Any] = read_rect_from_node, ): """读取并解析XML文件 Args: filename (P): XML文件路径 read_func (Callable): 用于处理XML根节点的回调函数 Returns: Any: 回调函数的返回结果 """ assert filename.exists(), f"{filename}文件不存在" return read_func(read_xml(filename))
[文档] def read_single_digit_rect(filename) -> t.List[RectO]: """读取单个数字的矩形框信息 Args: filename: XML文件路径 Returns: List[RectO]: 包含6个数字位置的矩形框列表 """ def func(root: t.Iterable) -> t.List[RectO]: def find_no(node) -> t.Tuple[int, RectO]: no = -1 rect = RectO() for subchild in node: if subchild.tag == "no": no = int(subchild.text.strip()) else: rect = set_rect(rect, subchild) rect.check() assert no != -1, "cannot find no number" return no, rect def set_rect(rect: RectO, sub) -> RectO: assert hasattr(rect, sub.tag), (sub.tag, sub.text) setattr(rect, sub.tag, sub.text) assert getattr(rect, sub.tag) != "" return rect def num_check(): seta = {0, 1, 2, 3, 4, 5} setb = set() def is_valid(): return seta == setb, (seta, setb) def set_num(no): setb.add(no) return set_num, is_valid digit_rect = [RectO() for _ in range(6)] set_num, is_valid = num_check() is_loop, set_loop = F.looped() for child in root: if child.tag == "digit": no, rect = find_no(child) _ = set_loop(), set_num(no) digit_rect[no] = rect assert is_loop(), "node has no child" cond, _ = is_valid() assert cond # return digit_rect, root, find_no, find_rect return digit_rect return read_xml_to_get(filename, func)
[文档] def get_single_digit_values(filename: P) -> t.Tuple[str, T.Rect]: """获取单个数字的值和位置信息 Args: filename (P): XML文件路径 Returns: Tuple[str, T.Rect]: 返回值和矩形框信息的元组 """ val, _ = read_xml_to_get(filename, read_rect_from_node) block_pos = read_xml_to_get(filename, read_single_digit_rect) return val, block_pos
[文档] def read_rect_from_file(xml_path: P, type_: t.Literal["single", "block"]): """从文件中读取矩形框信息 Args: xml_path (P): XML文件路径 type_ (typeOfrect): 矩形框类型,可以是'single'或'block' Returns: Any: 根据类型返回相应的矩形框信息 """ assert xml_path.suffix == ".xml" function_map: t.Mapping[typeOfrect, t.Callable[[P], t.Any]] = { "single": read_single_digit_rect, "block": get_rectangle, } func = function_map[type_] return func(xml_path)
[文档] def get_rectangle(filename: P) -> T.Rect: """获取矩形框信息 Args: filename (P): XML文件路径 Returns: T.Rect: 矩形框字典 """ _, rect = read_xml_to_get(filename, read_rect_from_node) return rect
[文档] def get_xml_config_path( img_path: P, types: t.Literal["value", "block", "single"] = "value" ) -> P: """根据图片路径获取对应的XML配置文件路径 Args: img_path (P): 图片文件路径 types (Literal): 配置类型,可以是'value'、'block'或'single' Returns: P: XML配置文件路径 """ dataset_path = img_path.parent def value_path(): config_p = P(dataset_path) / "baocun" assert img_path.suffix in (".jpg", ".jpeg") filename = img_path.stem + ".xml" return config_p / filename def block_path(): return P(dataset_path) / "config" / "block.xml" def single_path(): return P(dataset_path) / "config" / "res.xml" funcs: t.Mapping[str, t.Callable] = { "value": value_path, "block": block_path, "single": single_path, } return funcs[types]()
[文档] def get_xml_config(img_path: P) -> t.Tuple[str, T.Rect]: """获取XML配置信息 Args: img_path (P): 图片文件路径 Returns: Tuple[str, T.Rect]: 返回值和矩形框信息的元组 """ return read_xml_to_get( filename=get_xml_config_path(img_path), read_func=read_rect_from_node, )