def test_trainer_ae(self): """Test the `test-ann` subcommands.""" filter_ = self.config.classification.filter.as_dict() with db.session_scope(META_FILE) as (session, metadata): tester = TestAnn(self.config) tester.test(self.ann_file, self.train_file) tester.export_results(self.test_result, filter_, 0.001)
def test_trainer_ba(self): """Test the `data-batch` subcommands.""" with db.session_scope(META_FILE) as (session, metadata): cache = PhenotypeCache() cache.make(IMAGE_DIR, TEMP_DIR, self.config, update=False) train_data = BatchMakeTrainData(self.config, TEMP_DIR) train_data.batch_export(self.train_dir)
def test_trainer_aa(self): """Test the `meta` subcommands.""" sys.stdout.write("Initializing database...\n") db.make_meta_db(META_FILE) with db.session_scope(META_FILE) as (session, metadata): mkmeta = db.MakeMeta(self.config, IMAGE_DIR) mkmeta.make(session, metadata)
def test_get_photos_with_taxa(self): """Test the get_photos_with_taxa() method.""" with db.session_scope(META_FILE) as (session, metadata): q = db.get_photos_with_taxa(session, metadata) ret = q.all() self.assertEqual(len(ret), len(self.expected_taxa)) for photo, genus, section, species in ret: class_ = [genus, section, species] self.assertEqual(class_, self.expected_taxa[photo.md5sum])
def test_trainer_bc(self): """Test the `test-ann-batch` subcommands.""" with db.session_scope(META_FILE) as (session, metadata): tester = TestAnn(self.config) tester.test_with_hierarchy(self.train_dir, self.ann_dir, 0.001) correct, total = tester.export_hierarchy_results(self.test_result_batch) print "Correctly classified: {0}/{1} ({2:.2%})\n".\ format(correct, total, float(correct)/total)
def test_trainer_ab(self): """Test the `data` subcommands.""" filter_ = self.config.classification.filter.as_dict() with db.session_scope(META_FILE) as (session, metadata): cache = PhenotypeCache() cache.make(IMAGE_DIR, TEMP_DIR, self.config, update=False) train_data = MakeTrainData(self.config, TEMP_DIR) train_data.export(self.train_file, filter_)
def setUpClass(cls): """Create a new metadata file if it does not exist. This is executed before any test is started. """ config = open_config(CONF_FILE) if not os.path.isfile(META_FILE): sys.stdout.write("Initializing database...\n") db.make_meta_db(META_FILE) with db.session_scope(META_FILE) as (session, metadata): mkmeta = db.MakeMeta(config, IMAGE_DIR) mkmeta.make(session, metadata)
def test_get_classes_from_filter(self): """Test the get_classes_from_filter() method.""" filter_genera = {'class': 'genus'} filter_sections = {'class': 'section'} filter_mexi_section = { 'class': 'section', 'where': { 'genus': 'Mexipedium' } } filter_trigo = { 'class': 'species', 'where': { 'genus': 'Cypripedium', 'section': 'Trigonopedia' } } with db.session_scope(META_FILE) as (session, metadata): classes = db.get_classes_from_filter(session, metadata, filter_genera) self.assertEqual( classes, set([ 'Cypripedium', 'Mexipedium', 'Paphiopedilum', 'Selenipedium', 'Phragmipedium' ])) classes = db.get_classes_from_filter(session, metadata, filter_sections) self.assertEqual( classes, set([ 'Obtusipetala', 'Arietinum', 'Trigonopedia', 'Brachypetalum', 'Micropetalum', None ])) classes = db.get_classes_from_filter(session, metadata, filter_mexi_section) self.assertEqual(classes, set([None])) classes = db.get_classes_from_filter(session, metadata, filter_trigo) self.assertEqual(classes, set(['sichuanense', 'fargesii']))
def validate(config, k, autoskip=False): """Start validation routines.""" with db.session_scope(META_FILE) as (session, metadata): cache = PhenotypeCache() cache.make(IMAGE_DIR, TEMP_DIR, config, update=False) validator = Validator(config, TEMP_DIR, TEMP_DIR) scores = validator.k_fold_xval_stratified(k, autoskip) print for path in sorted(scores.keys()): values = np.array(scores[path]) print "Accuracy[{path}]: {mean:.2%} (+/- {sd:.2%})".format(**{ 'path': path, 'mean': values.mean(), 'sd': values.std() * 2 })
def test_get_taxon_hierarchy(self): """Test the get_taxon_hierarchy() method.""" with db.session_scope(META_FILE) as (session, metadata): expected = { u'Paphiopedilum': { u'Brachypetalum': [u'godefroyae', u'wenshanense'] }, u'Selenipedium': { None: [u'palmifolium'] }, u'Mexipedium': { None: [u'xerophyticum'] }, u'Cypripedium': { u'Trigonopedia': [u'fargesii', u'sichuanense'], u'Obtusipetala': [u'flavum'], u'Arietinum': [u'plectrochilum'] }, u'Phragmipedium': { u'Micropetalum': [u'besseae'] } } hier = db.get_taxon_hierarchy(session, metadata) self.assertEqual(str(hier), str(expected)) # Setting `photo_count_min` to 4 should only return the species with # at least 4 photos. conf.photo_count_min = 4 expected = { u'Paphiopedilum': { u'Brachypetalum': [u'godefroyae'] }, u'Cypripedium': { u'Obtusipetala': [u'flavum'] }, u'Phragmipedium': { u'Micropetalum': [u'besseae'] } } hier = db.get_taxon_hierarchy(session, metadata) self.assertEqual(str(hier), str(expected))
def test_trainer_ad(self): """Test the `classify` subcommands.""" filter_ = self.config.classification.filter.as_dict() image = os.path.join(IMAGE_DIR, "Cypripedium/Arietinum/plectrochilum/14990382409.jpg") with db.session_scope(META_FILE) as (session, metadata): classes = db.get_classes_from_filter(session, metadata, filter_) if not classes: raise ValueError("No classes found for filter `%s`" % filter_) codewords = get_codewords(classes) classifier = ImageClassifier(self.config) codeword = classifier.classify_image(image, self.ann_file, self.config) classification = get_classification(codewords, codeword, 0.001) class_ = [class_ for mse,class_ in classification] print "Image is classified as {0}".format(", ".join(class_))
def test_get_taxa_photo_count(self): """Test the get_taxa_photo_count() method.""" expected = { 'Cypripedium_Obtusipetala_flavum': 4, 'Cypripedium_Arietinum_plectrochilum': 3, 'Cypripedium_Trigonopedia_sichuanense': 3, 'Cypripedium_Trigonopedia_fargesii': 3, 'Mexipedium_None_xerophyticum': 3, 'Paphiopedilum_Brachypetalum_wenshanense': 3, 'Paphiopedilum_Brachypetalum_godefroyae': 4, 'Selenipedium_None_palmifolium': 3, 'Phragmipedium_Micropetalum_besseae': 4 } with db.session_scope(META_FILE) as (session, metadata): q = db.get_taxa_photo_count(session, metadata) ret = q.all() self.assertEqual(len(ret), len(expected)) for genus, section, species, count in ret: class_ = '_'.join([genus, str(section), species]) self.assertEqual(count, expected[class_])
def save_bow(args, bow, nclusters, imglist): """ The function takes the result of an argument parser, a dictionary with image 'words' (Bag-Of-Words = bow), a number of clusters and a list with image filenames. A header is created and saved to a .tsv file. A connection to the database is made. For every image in the imagelist, a photo_id is taken out of the filename. A title for the image is taken from the database. The photo_id, title and all values in the bow of this image are written to the .tsv file. """ print("Saving bag-of-words...") if not args.bow.endswith(".tsv"): args.bow += ".tsv" outputfile = open(args.bow, "w") header = make_header(nclusters) outputfile.write(header) # Connect to database. with db.session_scope(args.meta_file) as (session, metadata): Base = automap_base(metadata=metadata) Base.prepare() configure_mappers() Photo = Base.classes.photos for filename in imglist: photo_id = filename.split(".")[0] title = photo_id for pic in session.query(Photo).filter(Photo.id == photo_id): title = photo_id if pic.title is None else pic.title valuelist = [photo_id, title] words = bow[filename.rstrip()] for item in words: valuelist.append(str(item)) row = "\t".join(valuelist) row += "\n" outputfile.write(row) outputfile.close()
def main(): # Create argument parser. parser = argparse.ArgumentParser( description="Image histogram maker.\nImages are devided in " "horizontal and vertical bins. The mean blue, green and red " "intensities are calculated for each bin and this data is " "stored in a tab separated file.") parser.add_argument("imdir", metavar="PATH", help="Base directory where the images are stored.") parser.add_argument( "outputfile", metavar="OUTFILE", help="Output filename. An existing file with the same name will be " "overwritten.") parser.add_argument("meta_file", metavar="METAFILE", help="File name of the metadata file (e.g. meta.db).") parser.add_argument("--verbose", "-v", action="store_const", const=True, help="Explain what is being done.") parser.add_argument( "--bins", metavar="N", default=50, type=int, help="Number of bins the image is devided in horizontally and " "vertically. Defaults to 50 if omitted.") parser.add_argument( "--roi_pix", metavar="x,y,w,h", help="Region Of Interest, expressed as X,Y,Width,Height in pixel " "units. If both roi-pix and roi-frac are given with valid " "values, only roi-frac will be used.") parser.add_argument( "--roi_frac", metavar="x1,x2,y1,y2", help="Region Of Interest, expressed as X1,X2,Y1,Y2 in fractions of " "total image size. X1 and Y1 start in left upper corner, X2 goes " "to the right, Y2 goes to the bottom. If both roi-pix and " "roi-frac are given with valid values, only roi-frac will be " "used.") # Parse arguments. args = parser.parse_args() # Make the image directory path absolute. args.imdir = os.path.realpath(args.imdir) # Check if the image directory exists. if not os.path.exists(args.imdir): raise IOError("The given path does not exist.") # Check if metadata file exists. if not os.path.isfile(args.meta_file): raise IOError("The given metadata file does not exist.") # Check if (a valid) roi argument is given. what_roi = check_roi(args) # Create a new outputfile. create_output_file(args) # Connect to database. with db.session_scope(args.meta_file) as (session, metadata): make_histogram(args, what_roi, session, metadata)
def test_trainer_bb(self): """Test the `ann-batch` subcommands.""" with db.session_scope(META_FILE) as (session, metadata): ann_maker = BatchMakeAnn(self.config) ann_maker.batch_train(self.train_dir, self.ann_dir)
def test_get_filtered_photos_with_taxon(self): """Test the get_filtered_photos_with_taxon() method.""" filter_mexi_species = { 'class': 'species', 'where': { 'genus': 'Mexipedium', 'section': None } } filter_mexi_section = { 'class': 'section', 'where': { 'genus': 'Mexipedium' } } filter_trigo = { 'class': 'species', 'where': { 'genus': 'Cypripedium', 'section': 'Trigonopedia' } } filter_cypr = {'class': 'section', 'where': {'genus': 'Cypripedium'}} filter_cypr_none = { 'class': 'species', 'where': { 'genus': 'Cypripedium', 'section': None } } filter_genera = {'class': 'genus'} with db.session_scope(META_FILE) as (session, metadata): q = db.get_filtered_photos_with_taxon(session, metadata, filter_mexi_species).all() self.assertEqual(len(q), 3) for photo, class_ in q: self.assertEqual(class_, self.expected_taxa[photo.md5sum][2]) q = db.get_filtered_photos_with_taxon(session, metadata, filter_mexi_section).all() self.assertEqual(len(q), 3) for photo, class_ in q: self.assertEqual(class_, self.expected_taxa[photo.md5sum][1]) q = db.get_filtered_photos_with_taxon(session, metadata, filter_trigo).all() self.assertEqual(len(q), 6) taxa = set([taxon for photo, taxon in q]) self.assertEqual(taxa, set(['fargesii', 'sichuanense'])) q = db.get_filtered_photos_with_taxon(session, metadata, filter_cypr).all() self.assertEqual(len(q), 13) taxa = set([taxon for photo, taxon in q]) self.assertEqual( taxa, set(['Arietinum', 'Obtusipetala', 'Trigonopedia'])) q = db.get_filtered_photos_with_taxon(session, metadata, filter_cypr_none).all() self.assertEqual(len(q), 0) q = db.get_filtered_photos_with_taxon(session, metadata, filter_genera).all() self.assertEqual(len(q), len(self.expected_taxa)) taxa = set([taxon for photo, taxon in q]) self.assertEqual( taxa, set([ 'Cypripedium', 'Mexipedium', 'Paphiopedilum', 'Selenipedium', 'Phragmipedium' ]))
def main(): # Create argument parser. parser = argparse.ArgumentParser( description="Image histogram maker.\nImages are devided in " "horizontal and vertical bins. The mean blue, green and red " "intensities are calculated for each bin and this data is " "stored in a tab separated file.") parser.add_argument( "imdir", metavar="PATH", help="Base directory where the images are stored.") parser.add_argument( "outputfile", metavar="OUTFILE", help="Output filename. An existing file with the same name will be " "overwritten.") parser.add_argument( "meta_file", metavar="METAFILE", help="File name of the metadata file (e.g. meta.db).") parser.add_argument( "--verbose", "-v", action="store_const", const=True, help="Explain what is being done.") parser.add_argument( "--bins", metavar="N", default=50, type=int, help="Number of bins the image is devided in horizontally and " "vertically. Defaults to 50 if omitted.") parser.add_argument( "--roi_pix", metavar="x,y,w,h", help="Region Of Interest, expressed as X,Y,Width,Height in pixel " "units. If both roi-pix and roi-frac are given with valid " "values, only roi-frac will be used.") parser.add_argument( "--roi_frac", metavar="x1,x2,y1,y2", help="Region Of Interest, expressed as X1,X2,Y1,Y2 in fractions of " "total image size. X1 and Y1 start in left upper corner, X2 goes " "to the right, Y2 goes to the bottom. If both roi-pix and " "roi-frac are given with valid values, only roi-frac will be " "used." ) # Parse arguments. args = parser.parse_args() # Make the image directory path absolute. args.imdir = os.path.realpath(args.imdir) # Check if the image directory exists. if not os.path.exists(args.imdir): raise IOError("The given path does not exist.") # Check if metadata file exists. if not os.path.isfile(args.meta_file): raise IOError("The given metadata file does not exist.") # Check if (a valid) roi argument is given. what_roi = check_roi(args) # Create a new outputfile. create_output_file(args) # Connect to database. with db.session_scope(args.meta_file) as (session, metadata): make_histogram(args, what_roi, session, metadata)