コード例 #1
0
FBL_Begin_Namespace


/**********************************************************************************************/
#if FBL_MAC


/**********************************************************************************************/
// NOTE:  fullPath to item that EXISTS on disk. Otherwise file not found error.
//
#if FBL_SUPPORT_FSSPEC
//
OSErr Path2Spec_FSRef( const char *inPath, FSSpec *spec)
{
	// parse path on parent folder and file name. 
	const char* pFileName = ExtractNameFromFullPath(inPath);
	const char* pDelim = pFileName - 1;

//	String folder_path( inPath, vuint32(pDelim - inPath) );

	vuint32 len;
	if( pDelim >= inPath )
		len = vuint32(pDelim - inPath);
	else
		len = strlen( inPath );
	
	MemPtr<char> folder_path( inPath, len + 1 );
	folder_path[len] = 0;
	
	char* pFolderPath = folder_path.begin();
	
	// convert the POSIX path to an FSRef of parent folder 
	FSRef ref;
	OSStatus result = FSPathMakeRef( (vuint8*) pFolderPath, &ref, NULL);
	
	if( result != 0 )
		return (OSErr) result;

	// and then convert the FSRef to an FSSpec 
	FSSpec parent;
	result = FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, &parent, NULL);
	if( result != 0 )
		return (OSErr) result;

	// now we have parent folder FSSpec, get its ID. 
	vint32 theDirID;
	bool isDirectory;
	GetDirectoryID( parent.vRefNum, parent.parID, parent.name, &theDirID, &isDirectory );
	
	// and now we make File spec:
	Str255 pasFileName;
	FBL::c2pstrcpy( pFileName, pasFileName );
	result = FSMakeFSSpec( parent.vRefNum, theDirID, pasFileName, spec );
	
	return (OSErr) result;
}
コード例 #2
0
    /** Runs the precision/recall test.
     * May log errors and even end the application in case of severe error.
     * @param params The program options.
     */
    void eval_precision_recall( const program_options& params) {

        LOG(info) << "Loading class membership mappings...";
        Vec1UInt membership_mappings;
        Vec1str cluster_files;
    
        exit_if_false( from_file( params.membership_mappings_file, membership_mappings), RETURN_CODE::IO_ERROR);
        exit_if_false( from_file( params.cluster_file_paths_file,  cluster_files),       RETURN_CODE::IO_ERROR);

        const uint n_features = static_cast<uint>(membership_mappings.size());
        const uint n_clusters = static_cast<uint>(cluster_files.size());

        LOG(info) << "# features: " << n_features;
        LOG(info) << "# clusters: " << n_clusters;


        LOG( info) << "calculating precision / recall ...";

        // find best class for each cluster
        vector<cluster_info_t> class_mapping;

        for( uint i=0; i<n_clusters; ++i) {

            Vec1str current_cluster_image_paths;
            Vec1str current_cluster_real_image_classes;
            std::map<string, uint> class_votes;
            from_file( cluster_files[i], current_cluster_image_paths);
        

            for( auto it=current_cluster_image_paths.begin(); it!=current_cluster_image_paths.end(); ++it) {
            
                const string class_name = bfs::path(*it).parent_path().filename().string();

                current_cluster_real_image_classes.push_back( class_name); 

                const auto map_it = class_votes.find( class_name);
                if( map_it == class_votes.end())
                    class_votes[class_name] = 1;
                else
                    map_it->second += 1;
            }
            
            const auto max_it = std::max_element( class_votes.begin(), 
                                                  class_votes.end(), 
                                                  []( const std::pair<string, int>& p, const std::pair<string, int>& q) { 
                                                      return p.second < q.second; 
                                                  });
            
            if( max_it == class_votes.end()) {
                // ***cluster empty *** (yes, that can happen!)
                continue;
            }

            const string assigned_class( max_it->first);

            const uint n_retrieved_images( static_cast<uint>(current_cluster_image_paths.size()));
            uint false_positives(0);
            uint true_positives(0);
            uint false_negatives(0);

            // find true positives, false positives
            for( auto it=current_cluster_real_image_classes.begin(); it!=current_cluster_real_image_classes.end(); ++it) {
                const string& real_class = *it;
                if( assigned_class.compare( real_class) == 0) {
                    ++true_positives;
                } else {
                    ++false_positives;
                }
            }
            // false negatives
            std::stringstream folder_name;
            folder_name << params.image_db_directory << '/' << assigned_class;
            bfs::path folder_path( folder_name.str());
            assert( bfs::exists( folder_path) && "the directory must exist.");

        
            uint n_relevant_images(0);
            for( bfs::directory_iterator it(folder_path); it!=bfs::directory_iterator(); ++it) {
                bfs::path p(*it);
                p.make_preferred();
                
                if( !p.has_extension() || !is_image_filetype_supported( p.extension().string()))
                    continue;

                ++n_relevant_images;
            
                Vec1str::iterator pos = std::find( current_cluster_image_paths.begin(), current_cluster_image_paths.end(), p.string());
                if( pos == current_cluster_image_paths.end())
                    ++false_negatives;
            }
            assert( true_positives + false_negatives == n_relevant_images && "number of relevant images must be identical to the number of true positivies and false positives");

            // *** found true positivies, false positives, false negatives for cluster i ***
            // calc precision/recall for each class
            const real precision = static_cast<real>(true_positives) / n_retrieved_images;
            const real recall    = static_cast<real>(true_positives) / n_relevant_images;

            class_mapping.push_back( cluster_info_t( assigned_class, true_positives, false_positives, false_negatives, precision, recall));
        }

        real avg_true_positives(0);
        real avg_false_positives(0);
        real avg_false_negatives(0);
        real avg_precision(0);
        real avg_recall(0);

        LOG( info) << "<class name> <true positives> <false positives> <false negatives> <precision> <recall>";
        for( uint i=0; i<class_mapping.size(); ++i) {
            const cluster_info_t& ci = class_mapping[i];
            const string& cluster_name   = std::get<0>(ci);
            const uint true_positives    = std::get<1>(ci);
            const uint false_positives   = std::get<2>(ci);
            const uint false_negatives   = std::get<3>(ci);
            const real precision         = std::get<4>(ci);
            const real recall            = std::get<5>(ci);

            avg_true_positives  += true_positives;
            avg_false_positives += false_positives;
            avg_false_negatives += false_negatives;
            avg_precision       += precision;
            avg_recall          += recall;

            LOG(info) << cluster_name << " " << true_positives << " " << false_positives << " " << false_negatives << " " << precision << " " << recall;
        }

        avg_true_positives  /= class_mapping.size();
        avg_false_positives /= class_mapping.size();
        avg_false_negatives /= class_mapping.size();
        avg_precision       /= class_mapping.size();
        avg_recall          /= class_mapping.size();

        LOG(info) << "Average: <true positives> <false positives> <false negatives> <precision> <recall>";
        LOG(info) << avg_true_positives << " " << avg_false_positives << " " << avg_false_negatives << " " << avg_precision << " " << avg_recall;


        LOG(info) << "Writing stats to file \"" << params.precision_recall_file << "\"...";
        to_file( params.precision_recall_file, class_mapping);

    }