Пример #1
0
void ofApp::scan_dir_imgs(ofDirectory dir){
    ofDirectory new_dir;
    int size = dir.listDir();
    for (int i = 0; i < size; i++){
        if (dir.getFile(i).isDirectory()){
            new_dir = ofDirectory(dir.getFile(i).getAbsolutePath());
            new_dir.listDir();
            new_dir.sort();
            scan_dir_imgs(new_dir);
        } else if (std::find(std::begin(allowed_ext),
                             std::end(allowed_ext),
                             dir.getFile(i).getExtension()) != std::end(allowed_ext)) {
            imageFiles.push_back(dir.getFile(i));
        }
    }
}
Пример #2
0
//--------------------------------------------------------------
void ofApp::setup(){
    
    // SETUP
    // imageDir, imageSavePath = location of images, path to save the final grid image
    // nx, ny = size of the grid (make sure there are at least nx*ny images in imageDir!)
    // w, h = size of the image thumbnails
    // perplexity, theta (for t-SNE, see 'example' for explanation of these)
    
    // -------------- SET FILE I/O ---------------
    
    string imageDir = "../../../../../../../../../Volumes/BenSnell/torsos-7k/photos-jpg"; // source directory
    
    string folderName = "torsos_7k_all"; // destination directory

    // -------------------------------------------
    
    nx = 87;
    ny = 87;
    w = 340;
    h = 510;
    perplexity = 75;
    theta = 0.001;

    
    /////////////////////////////////////////////////////////////////////
    // CCV activations -> t-SNE embedding -> grid assignments
    
    // get images recursively from directory
    ofLog() << "Gathering images...";
    ofDirectory dir = ofDirectory(imageDir);
    scan_dir_imgs(dir);
    if (imageFiles.size() < nx * ny) {
        ofLog(OF_LOG_ERROR, "There are less images in the directory than the grid size requested (nx*ny="+ofToString((nx*ny))+"). Exiting to save you trouble...");
//        ofExit(); // not enough images to fill the grid, so quitting
    }
    
    // load all the images
//    for(int i=0; i<nx*ny; i++) {
//        if (i % 20 == 0)    ofLog() << " - loading image "<<i<<" / "<<nx*ny<<" ("<<dir.size()<<" in dir)";
//        images.push_back(ofImage());
//        images.back().load(imageFiles[i]);
////        images.back().resize(w, h); // ADDED -- DOES THIS WORK?
//    }
    for(int i=0; i<imageFiles.size(); i++) {
        if (i % 20 == 0)    ofLog() << " - loading image "<<i<<" / "<<imageFiles.size()<<" ("<<dir.size()<<" in dir)";
        images.push_back(ofImage());
        images.back().load(imageFiles[i]);
        //        images.back().resize(w, h); // ADDED -- DOES THIS WORK?
    }
    

    // resize images to w x h
    for (int i=0; i<images.size(); i++) {
        if (images[i].getWidth() > images[i].getHeight()) {
            images[i].crop((images[i].getWidth()-images[i].getHeight()) * 0.5, 0, images[i].getHeight(), images[i].getHeight());
        }
        else if (images[i].getHeight() > images[i].getWidth()) {
            images[i].crop(0, (images[i].getHeight()-images[i].getWidth()) * 0.5, images[i].getWidth(), images[i].getWidth());
        }
        images[i].resize(w, h);
    }
    
    // setup ofxCcv
    ccv.setup("image-net-2012.sqlite3");
    
    // encode all of the images with ofxCcv
    ofLog() << "Encoding images...";
    for (int i=0; i<images.size(); i++) {
        if (i % 20 == 0) ofLog() << " - encoding image "<<i<<" / "<<images.size();
        vector<float> encoding = ccv.encode(images[i], ccv.numLayers()-1);
        encodings.push_back(encoding);
    }
    
    // run t-SNE and load image points to imagePoints
    ofLog() << "Run t-SNE on images";
    tsneVecs = tsne.run(encodings, 2, perplexity, theta, true);
    // tsneVecs contains {x, y} for each image in images
    
    // save tsne
    ofFile tsneFile;
    tsneFile.open(folderName + "/" + "tsne_only_metadata.csv", ofFile::WriteOnly);
    tsneFile << "image_name,tsne_x,tsne_y";
    for (int i = 0; i < images.size(); i++) {
        tsneFile << "\n";
        tsneFile << imageFiles[i].getFileName() << ",";
        tsneFile << ofToString(tsneVecs[i][0]) << ",";
        tsneFile << ofToString(tsneVecs[i][1]);
    }
    tsneFile.close();
    
    ofExit(); // TEMP!!!
    
    // solve assignment grid
    vector<ofVec2f> tsnePoints; // convert vector<double> to ofVec2f
    for (auto t : tsneVecs) tsnePoints.push_back(ofVec2f(t[0], t[1]));
    vector<ofVec2f> gridPoints = makeGrid(nx, ny);
    solvedGrid = solver.match(tsnePoints, gridPoints, false);
    
    // export data to csv containing names and positions of images
    bool bExport = true;
    if (bExport) {
        int nImages = images.size(); //nx * ny;
        ofFile file;
        file.open(folderName + "/" + "tsne_metadata.csv", ofFile::WriteOnly);
        file << "image_name,grid_row,grid_column,grid_x_norm,grid_y_norm,tsne_x,tsne_y";
        for (int i = 0; i < nImages; i++) {
            file << "\n";
            file << imageFiles[i].getFileName() << ",";
            file << ofToString(solvedGrid[i].x * (nx-1)) << ",";
            file << ofToString(solvedGrid[i].y * (ny-1)) << ",";
            file << ofToString(solvedGrid[i].x) << ",";
            file << ofToString(solvedGrid[i].y) << ",";
            file << ofToString(tsneVecs[i][0]) << ",";
            file << ofToString(tsneVecs[i][1]);
        }
        file.close();
    }
    
    // save image grid
    bool bSaveGrid = true;
    if (bSaveGrid) {
        string imageGridName = "tsne_grid.png";
        ofFbo fbo;
        fbo.allocate(nx * w, ny * h);
        fbo.begin();
        ofClear(0, 0);
        ofBackground(0);
        for (int i=0; i<solvedGrid.size(); i++) {
            float x = (fbo.getWidth() - w) * solvedGrid[i].x;
            float y = (fbo.getHeight() - h) * solvedGrid[i].y;
            images[i].draw(x, y, w, h);
        }
        fbo.end();
        ofImage img;
        fbo.readToPixels(img);
        img.save(folderName + "/" + imageGridName);
    }
    
    // save image clusters
    bool bSaveClusters = true;
    float imgScale = 0.5;
    if (bSaveClusters) {
        string imageClustersName = "tsne_clusters.png";
        ofFbo fbo;
        fbo.allocate(nx * w, ny * h);
        fbo.begin();
        ofClear(0, 0);
        ofBackground(255);
        for (int i=0; i<tsneVecs.size(); i++) {
            float x = (fbo.getWidth() - w) * tsneVecs[i][0];
            float y = (fbo.getHeight() - h) * tsneVecs[i][1];
            ofSetColor(255, 180);
            images[i].draw(x, y, w * imgScale, h * imgScale);
            ofSetColor(0);
            ofDrawBitmapString(imageFiles[i].getFileName(), x, y + h * imgScale);
        }
        fbo.end();
        ofImage img;
        fbo.readToPixels(img);
        img.save(folderName + "/" + imageClustersName);
    }
    
    // setup gui
    gui.setup();
    gui.add(scale.set("scale", 1.0, 0.0, 1.0));
}
Пример #3
0
//--------------------------------------------------------------
void ofApp::setup(){
    
    // SETUP
    // imageDir, imageSavePath = location of images, path to save the final grid image
    // nx, ny = size of the grid (make sure there are at least nx*ny images in imageDir!)
    // w, h = downsample (or scale up) for source images prior to encoding!
    // displayW, displayH = resolution of the individual thumbnails for your output image - be careful about going over your maximum texture size on graphics card - 5000x5000 may work, but 10000x10000 may not
    // perplexity, theta (for t-SNE, see 'example' for explanation of these)
    string imageDir = "/Users/gene/Media/ImageSets/animals";
    string imageSavePath = "tsne_grid_animals.png";
    nx = 48;
    ny = 36;
    w = 256; //do not go lower than 256 - it will work, but results won't be as good
    h = 256;
    displayW = 100;
    displayH = 100;
    perplexity = 50; // corresponds to "number of neighbors", somewhere in the range 10-100 is good
    theta = 0.5; // lower is more "accurate" but takes longer, don't need to change this

    
    /////////////////////////////////////////////////////////////////////
    // CCV activations -> t-SNE embedding -> grid assignments
    
    // get images recursively from directory
    ofLog() << "Gathering images...";
    ofDirectory dir = ofDirectory(imageDir);
    scan_dir_imgs(dir);
    if (imageFiles.size() < nx * ny) {
        ofLog(OF_LOG_ERROR, "There are less images in the directory than the grid size requested (nx*ny="+ofToString((nx*ny))+"). Exiting to save you trouble...");
        ofExit(); // not enough images to fill the grid, so quitting
    }
    
    // load all the images
    for(int i=0; i<nx*ny; i++) {
        if (i % 20 == 0)    ofLog() << " - loading image "<<i<<" / "<<nx*ny<<" ("<<dir.size()<<" in dir)";
        images.push_back(ofImage());
        images.back().load(imageFiles[i]);
    }

    // resize images to w x h
    for (int i=0; i<images.size(); i++) {
        if (images[i].getWidth() > images[i].getHeight()) {
            images[i].crop((images[i].getWidth()-images[i].getHeight()) * 0.5, 0, images[i].getHeight(), images[i].getHeight());
        }
        else if (images[i].getHeight() > images[i].getWidth()) {
            images[i].crop(0, (images[i].getHeight()-images[i].getWidth()) * 0.5, images[i].getWidth(), images[i].getWidth());
        }
        images[i].resize(w, h);
    }
    
    // setup ofxCcv
    ccv.setup("image-net-2012.sqlite3");
    
    // encode all of the images with ofxCcv
    ofLog() << "Encoding images...";
    for (int i=0; i<images.size(); i++) {
        if (i % 20 == 0) ofLog() << " - encoding image "<<i<<" / "<<images.size();
        vector<float> encoding = ccv.encode(images[i], ccv.numLayers()-1);
        encodings.push_back(encoding);
    }
    
    // run t-SNE and load image points to imagePoints
    ofLog() << "Run t-SNE on images";
    tsneVecs = tsne.run(encodings, 2, perplexity, theta, true);
    
    // solve assignment grid
    vector<ofVec2f> tsnePoints; // convert vector<double> to ofVec2f
    for (auto t : tsneVecs) tsnePoints.push_back(ofVec2f(t[0], t[1]));
    vector<ofVec2f> gridPoints = makeGrid(nx, ny);
    solvedGrid = solver.match(tsnePoints, gridPoints, false);
    
    // save
    ofFbo fbo;
    fbo.allocate(nx * displayW, ny * displayH);
    fbo.begin();
    ofClear(0, 0);
    ofBackground(0);
    for (int i=0; i<solvedGrid.size(); i++) {
        float x = (fbo.getWidth() - displayW) * solvedGrid[i].x;
        float y = (fbo.getHeight() - displayH) * solvedGrid[i].y;
        images[i].draw(x, y, displayW, displayH);
    }
    fbo.end();
    ofImage img;
    fbo.readToPixels(img);
    img.save(imageSavePath);
    
    // setup gui
    gui.setup();
    gui.add(scale.set("scale", 1.0, 0.0, 1.0));
}