diff options
Diffstat (limited to 'offsetProject/src/imageStore.h')
| -rw-r--r-- | offsetProject/src/imageStore.h | 198 |
1 files changed, 110 insertions, 88 deletions
diff --git a/offsetProject/src/imageStore.h b/offsetProject/src/imageStore.h index 5f30163..8d1b584 100644 --- a/offsetProject/src/imageStore.h +++ b/offsetProject/src/imageStore.h @@ -7,6 +7,10 @@ #include "ofMain.h" #include "ofxJSONElement.h" +#include "ofxOpenCv.h" +//#include <opencv/include/opencv2/flann/flann.hpp> + +using namespace cvflann; long ofToLong(const string& intString); @@ -19,15 +23,39 @@ class imageStore : public ofThread{ std::string instagram_url; ofxJSONElement response; std::map<std::string,ofImage> images; + vector<ofImage*> imageptrs; deque<std::string> to_update; + //Matrix<float> dataset; doesn't need to be retained? + + //need to be able to add arbitrary data and keep it? + //see pucilar behaviour if we delete the data after indexing it + //we see some puzzling performance anomalies if we add data + //maybe rebuild the index rather than use index.addPoints() + //this way the data can be kept contiguously + //or maybe just get a pointer to vector data with an offset + vector<float> data; + //to begin, get a single point per image + + //retain a pointer to the flann indexer + Index<L2<float> >* index; + + //Index<L2<float> > index(dataset, cv::flann::KDTreeIndexParams(4)); + imageStore(){ instagram_url = "https://api.instagram.com/v1/tags/tycleeson/media/recent?client_id=c1d74d701fdf4ddd9f8d30ee9e8f944b"; interval=5.00f; ofImage img; img.allocate(MAX_TILE_SIZE,MAX_TILE_SIZE,OF_IMAGE_COLOR); + img.clear(); + img.setUseTexture(true); + img.update(); images["000000"]=img; colours["000000"]=ofColor(0,0,0); + + } + ~imageStore(){ + delete index; } void set_interval(float _interval){ @@ -49,85 +77,66 @@ class imageStore : public ofThread{ //how to make the search algorithm faster and better //http://www.semanticmetadata.net/lire/ - /* - 1. The box nature of the image matching isn't appealing - 2. The way that the images flip quickly isn't appealing - - can we improve this by changing the screen gradually in some way? - - search tree/ octree - - each node associates an image, start with a black image - - a node owns a volume of RGB space - - new image: determine which octant it lands in - subdivide the octant in R, G or B and give half to each image - - Q: does this lead to the possibility that images end up in the wrong place? - - with the naive algorithm, we measure distance between the colours in RGB space - - it becomes a long process because the number of calculations increases exponentially - - space partitioning: we observe that the image will often be nearest to an image in the same box - although it may not be if they are at the edges - - so at each level, each node of the tree contains a list of images - - we traverse the tree and try to find the lowest level box with a match - if the lowest level box with a match has more than 1 we compute distance? - - a difference algorithm - minimise the error - this involves comparing every pixel though - - gpu? - - put every quarter of every image into an image tree - - every image has an entry on levels 1-8 - start at level 8 (most detailed) - check the leaf node ie 10110101 01101001 00110101 - if there are 1 or more images here choose one - if none go to the next level... - - ie 1011010 0110100 0011010 - if there are more than 1 images here find the nearest - if there is 1 choose it - if there are none go to the next level - - */ - - std::map<std::string,ofColor> colours; ofImage& get_image(const ofColor& col){ //float shortest_dist=999999.0f; int sd=1000; ofImage& im=images.begin()->second; - std::string s=images.begin()->first; - for (map<string,ofImage>::iterator it=images.begin();it!=images.end();++it){ - ofColor& c=colours[it->first]; - int rd=c.v[0]-col.v[0]; - int gd=c.v[1]-col.v[1]; - int bd=c.v[2]-col.v[2]; - //float dist=pow((float)((rd*rd)+(gd*gd)+(bd*bd)),0.5); - int dist=abs(rd)+abs(gd)+abs(bd); - if (dist<sd){ - sd=dist; - im=it->second; - s=it->first; - } - } + if( lock() ){ + std::string s=images.begin()->first; + for (map<string,ofImage>::iterator it=images.begin();it!=images.end();++it){ + ofColor& c=colours[it->first]; + int rd=c.v[0]-col.v[0]; + int gd=c.v[1]-col.v[1]; + int bd=c.v[2]-col.v[2]; + //float dist=pow((float)((rd*rd)+(gd*gd)+(bd*bd)),0.5); + int dist=abs(rd)+abs(gd)+abs(bd); + if (dist<sd){ + sd=dist; + im=it->second; + s=it->first; + } + } + unlock(); + } //cerr<<"got image "<<s<<endl; return im; } + + ofImage& get_image(float r,float g,float b){ + ofImage& im=images.begin()->second; + if( lock() ){ + float* test=new float[3]; + test[0]=r; + test[1]=g; + test[2]=b; + Matrix<float> query(test,1,3); + Matrix<int> indices(new int[1], query.rows, 1); + Matrix<float> dists(new float[1], query.rows, 1); + index->knnSearch(query, indices, dists, 1,SearchParams(4)); + im=*imageptrs[*indices[0]]; + //int i=rand()%imageptrs.size(); + //im=images[imageptrs[i]]; + //cerr<<"returning image "<<i<<endl; + unlock(); + } + return im; + } + ofColor get_colour(const ofImage& _img){ ofImage img=_img; img.resize(1,1); return ofColor(img.getPixels()[0],img.getPixels()[1],img.getPixels()[2]); } + void add_data(const ofImage& _img){ + ofImage img=_img; + img.resize(1,1); + data.push_back(img.getPixels()[0]); + data.push_back(img.getPixels()[1]); + data.push_back(img.getPixels()[2]); + } + //-------------------------- void threadedFunction(){ @@ -135,32 +144,42 @@ class imageStore : public ofThread{ ofDirectory image_path(ofToString(IMAGE_STORE_SIZE)+"/"); cerr<<"image path: "<<image_path.getAbsolutePath()<<endl; - if (image_path.exists()){ - image_path.listDir(); - cerr<<"image path found, "<<image_path.size()<<" images"<<endl; - for (int i=0;i<image_path.size();i++){ - ofImage img; - img.setUseTexture(false); - img.loadImage(ofToString(IMAGE_STORE_SIZE)+"/"+image_path.getFiles()[i].getFileName()); - img.resize(MAX_TILE_SIZE,MAX_TILE_SIZE); - if( lock() ){ - colours[image_path.getFiles()[i].getBaseName()]=get_colour(img); + if( lock() ){ //lock the thread while preparing the initial images + if (image_path.exists()){ + image_path.listDir(); + cerr<<"image path found, "<<image_path.size()<<" images"<<endl; + for (int i=0;i<image_path.size();i++){ + ofImage img; + img.setUseTexture(false); + img.loadImage(ofToString(IMAGE_STORE_SIZE)+"/"+image_path.getFiles()[i].getFileName()); + img.resize(MAX_TILE_SIZE,MAX_TILE_SIZE); + + //colours[image_path.getFiles()[i].getBaseName()]=get_colour(img); + add_data(img); images[image_path.getFiles()[i].getBaseName()]=img; - cerr<<image_path.getFiles()[i].getBaseName()<<": "<<colours[image_path.getFiles()[i].getBaseName()]<<endl; + imageptrs.push_back(&images[image_path.getFiles()[i].getBaseName()]); + //cerr<<image_path.getFiles()[i].getBaseName()<<": "<<colours[image_path.getFiles()[i].getBaseName()]<<endl; to_update.push_back(image_path.getFiles()[i].getBaseName()); - unlock(); + } } + else { + cerr<<"creating image path"<<endl; + image_path.create(); } - } - else { - cerr<<"creating image path"<<endl; - image_path.create(); + + //build the flann index + Matrix<float> dataset(&data[0],data.size()/3,3); + index= new Index<L2<float> >(dataset, KDTreeIndexParams(4)); + index->buildIndex(); + + unlock(); } cout << "Api: " << instagram_url<<endl; while( isThreadRunning() != 0 ){ + /* cout<<"."<<std::flush; if (!response.open(instagram_url)) { @@ -192,6 +211,7 @@ class imageStore : public ofThread{ } } } + */ ofSleepMillis(interval * 1000); } } @@ -214,13 +234,15 @@ class imageStore : public ofThread{ to_update.pop_front(); - //int drawcount=0; - //for (map<string,ofImage>::iterator i=images.begin();i!=images.end();++i){ - // if(i->second.isUsingTexture()){ - // drawcount++; - // } - //} - //cout<<"loaded "<<im<<" "<<ofToLong(im)%(long)(ofGetWidth()-images[im].getWidth()+1)<<","<<ofToLong(im)%(long)(ofGetHeight()-images[im].getHeight()+1)<<endl; + /* + int drawcount=0; + for (map<string,ofImage>::iterator i=images.begin();i!=images.end();++i){ + if(i->second.isUsingTexture()){ + drawcount++; + } + } + cout<<"loaded "<<im<<" "<<ofToLong(im)%(long)(ofGetWidth()-images[im].getWidth()+1)<<","<<ofToLong(im)%(long)(ofGetHeight()-images[im].getHeight()+1)<<endl; + */ } unlock(); } |
