예제 #1
0
 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)
예제 #2
0
    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)
예제 #3
0
    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)
예제 #4
0
 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])
예제 #5
0
    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)
예제 #6
0
    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_)
예제 #7
0
    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)
예제 #8
0
    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']))
예제 #9
0
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
        })
예제 #10
0
    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))
예제 #11
0
    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_))
예제 #12
0
    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_])
예제 #13
0
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()
예제 #14
0
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)
예제 #16
0
 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)
예제 #17
0
    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)