xml_image_information.py
Go to the documentation of this file.
00001 # -*- coding: utf-8 -*-
00002 
00003 import xml.dom.minidom
00004 import datetime
00005 
00006 ## @package face_contour_detector.image_information.xml_image_information
00007 #  The only classed defined here is XMLImageInformationDatabase - used to save and read image information databases from xml files.
00008 #  @author Fabian Wenzelmann
00009 
00010 ## @brief Exception that is thrown if an error occured parsing the xml file.
00011 #  @author Fabian Wenzelmann
00012 #  @date 2011-02-20
00013 class XMLValueException(Exception):
00014     def __init__(self, error_msg):
00015         super(XMLValueException, self).__init__(error_msg)
00016 
00017 ## @brief Class to read a database from a xml file and to write a database to a xml file.
00018 #  @author Fabian Wenzelmann
00019 #  @date 2011-02-20
00020 #
00021 #  A image database ist a list of dictionaries. Such a dictionary maps property names to tuples where the first component of the tuple is the value of this property and the second component is the type as string. Allowed types are "int", "float" and "string". For example if the only information for one image is the MaxPixelValue the dictionary has the form \verbatim { "MaxPixelValue" : (200, "int") } \endverbatim which means that the max pixel value in the image is 200 and the result is of type int. A list of such dictionaries is saved in a field called images.<br>
00022 #  There is also a max_size parameter to restrict the size of images that can be stored in a database.
00023 class XMLImageInformationDatabase:
00024     ## The constructor
00025     #  @param self the object pointer
00026     #  @param max_size If max_size is not None it is an integer >= 1. The append() method takes care that there are not more than max_size elements in the list. Also the load() method loads only max_size elements, even if there are more in the xml file. If it's None the database has no limit.
00027     def __init__(self, max_size=None):
00028         self.images = []
00029         self.max_size = max_size
00030     
00031     # field documentation
00032     ## @var images
00033     #  the list containing the images: images is a list of dictionaries.
00034     #  Such a dictionary maps property names to tuples where the first component of the tuple is the value of this property and the second component is the type as string. Allowed types are "int", "float" and "string". For example if the only information for one image is the MaxPixelValue the dictionary has the form \verbatim { "MaxPixelValue" : (200, "int") } \endverbatim which means that the max pixel value in the image is 200 and the result is of type int. A list of such dictionaries is saved in a field called images.
00035     
00036     ## @var max_size
00037     #  the maximum amount of images stores in the images list
00038     
00039     ## Load a xml file and add all entries to the images list.
00040     #  @param self the object pointer
00041     #  @param doc a xml object as received by xml.dom.minidom.parse
00042     #
00043     #  Parses a xml file and adds all images images list. The xml file must follow the XML Schema of imageInformationDatabase as defined in image_information.xsd. This means that the root note is "imageInformationDatabase". This node has subnodes with name "image". A image node has "entry" subnodes where each entry node has two child nodes: "name" (with the name of the property) and "content" (the value of this property). An entry also has an attribute "type" which is "int", "float" or "string".<br>
00044     #  Also max_size value is checked so if there are more than max_size elements in the file you only have max_size elements in the list (following the order of the document).
00045     #  @exception XMLValueError if the root node is not "imageInformationDatabase"
00046     #  @exception XMLValueError if the type attribute of entry is not "int", "float" or "string"
00047     #  @exception Exception An exception may be thrown if there is no attribute "type" in entry or if an entry has no name or no content subnode. We also assume that if entry is if type int the int function of python can translate the content of this entry to an integer (also for float).
00048     def load(self, doc):
00049         text_node_type = xml.dom.minidom.Node.TEXT_NODE
00050         root = doc.documentElement
00051         if root.tagName != "imageInformationDatabase":
00052             raise XMLValueException("Expected imageInformationDatabase as root of document not " + root.tagName)
00053         images = root.getElementsByTagName("image")
00054         for image in images:
00055             if self.max_reached():
00056                 break
00057             image_information = {}
00058             information_entries = image.getElementsByTagName("entry")
00059             for entry in information_entries:
00060                 entry_type = entry.getAttribute("type")
00061                 translate_function = None
00062                 if entry_type == "int":
00063                     translate_function = int
00064                 elif entry_type == "float":
00065                     translate_function = float
00066                 elif entry_type == "string":
00067                     translate_function = lambda x: x
00068                 else:
00069                     raise XMLValueException("Only 'int', 'float' and 'string' are allowed values for entries in image information. Got " + entry_type)
00070                 name_node = entry.getElementsByTagName("name")[0]
00071                 value_node = entry.getElementsByTagName("content")[0]
00072                 name = ""
00073                 value = ""
00074                 for n in name_node.childNodes:
00075                     if n.nodeType == text_node_type:
00076                         name += n.data
00077                 for n in value_node.childNodes:
00078                     if n.nodeType == text_node_type:
00079                         value += n.data
00080                 image_information[name] = translate_function(value.strip()), entry_type
00081             self.images.append(image_information)
00082             
00083     @staticmethod
00084     ## internal method to create an "entry" node
00085     def __information_entry_to_node(doc, type_name, name, content):
00086         root = doc.createElement("entry")
00087         attr = doc.createAttribute("type")
00088         attr.value = type_name
00089         root.setAttributeNode(attr)
00090         
00091         name_node = doc.createElement("name")
00092         name_text_node = doc.createTextNode(name)
00093         name_node.appendChild(name_text_node)
00094         root.appendChild(name_node)
00095         
00096         content_node = doc.createElement("content")
00097         content_text_node = doc.createTextNode(str(content))
00098         content_node.appendChild(content_text_node)
00099         root.appendChild(content_node)
00100         
00101         return root
00102 
00103     @staticmethod
00104     ## internal method to create an "image" node
00105     def __create_image_node(doc, entries):
00106         root = doc.createElement("image")
00107         for entry_name, (value, type_name) in entries.items():
00108             root.appendChild( XMLImageInformationDatabase.__information_entry_to_node(doc, type_name, entry_name, value) )
00109         return root
00110         
00111     @staticmethod
00112     ## internalt method: writes an "entry" node to the writer object (should have a write method)
00113     def __pretty_write_entry(typename, name, content, writer, indent, addindent, newl):
00114         writer.write(indent)
00115         writer.write('<entry type="')
00116         xml.dom.minidom._write_data(writer, typename)
00117         writer.write('">')
00118         writer.write(newl)
00119         
00120         next_indent = indent + addindent
00121         
00122         writer.write(next_indent)
00123         writer.write("<name>")
00124         xml.dom.minidom._write_data(writer, name)
00125         writer.write("</name>")
00126         writer.write(newl)
00127         
00128         writer.write(next_indent)
00129         writer.write("<content>")
00130         xml.dom.minidom._write_data(writer, str(content))
00131         writer.write("</content>")
00132         writer.write(newl)
00133         
00134         writer.write(indent)
00135         writer.write("</entry>")
00136         writer.write(newl)
00137     
00138     @staticmethod
00139     ## internal method to write an "image" node to writer (should have a write method)
00140     def __pretty_write_image(entries, writer, indent, addindent, newl):
00141         writer.write(indent)
00142         writer.write("<image>")
00143         writer.write(newl)
00144         for entry_name, (value, type_name) in entries.items():
00145             XMLImageInformationDatabase.__pretty_write_entry(type_name, entry_name, value, writer, indent + addindent, addindent, newl)
00146         writer.write(indent)
00147         writer.write("</image>")
00148         writer.write(newl)
00149     
00150     ## Write the database to the writer object.
00151     #  @param self the object pointer
00152     #  @param writer a object that has e "write" functions (file object interface)
00153     #  @param addindent a string that is the incremental idention for subnodes
00154     #  @param newl a string that is used as newline (after most nodes)
00155     #
00156     #  Writes a xml file that satisfies the imageInformationDatabase type as defined in image_information.xsd
00157     def write_pretty_xml(self, writer, addindent="\t", newl="\n"):
00158         writer.write('<?xml version="1.0" encoding="UTF-8"?>')
00159         writer.write(newl)
00160         writer.write(newl)
00161         writer.write("<!-- automatically generated on ")
00162         writer.write(str(datetime.date.today()))
00163         writer.write(" -->")
00164         writer.write(newl)
00165         writer.write("<!-- This file contains information about images used for the PR2 Drawing Faces module. Just technically stuff - no personal data! -->")
00166         writer.write(newl)
00167         writer.write(newl)
00168         
00169         writer.write("<imageInformationDatabase>")
00170         writer.write(newl)
00171         for image in self.images:
00172             XMLImageInformationDatabase.__pretty_write_image(image, writer, addindent, addindent, newl)
00173             writer.write(newl)
00174         writer.write("</imageInformationDatabase>")
00175     
00176     ## Write a xml file to path
00177     #  @param self the object pointer
00178     #  @param path file path to the xml file
00179     #
00180     #  @see write_pretty_xml()
00181     def write_file(self, path):
00182         with open(path, "w") as f:
00183             self.write_pretty_xml(f)
00184     
00185     ## Load the database from an xml file.
00186     #  @param path path of the xml file
00187     #  @exception Exception if file does not exists
00188     #
00189     #  Just calls load() method with xml.dom.minidom.parse(path)
00190     def load_file(self, path):
00191         self.load( xml.dom.minidom.parse(path) )
00192     
00193     ## Return true if max_size is reached for this database
00194     #  @param self the object pointer
00195     def max_reached(self):
00196         if self.max_size is None:
00197             return False
00198         return len(self.images) >= self.max_size
00199     
00200     ## Append a new entry to the database
00201     #  @param self the object pointer
00202     #  @param entry The new entry to add (a dictionary as defined in preface)
00203     #
00204     #  Adds a new element to the list. If max_size is reached the new entry will displace the oldest entry in the list. Which is assumed to be the first entry in the list.
00205     def append(self, entry):
00206         if self.max_reached():
00207             self.images[0] = entry
00208         else:
00209             self.images.append(entry)
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends


face_contour_detector
Author(s): Fabian Wenzelmann and Julian Schmid
autogenerated on Wed Dec 26 2012 16:18:17