int straightDistance(Node n1, Node n2){ int diff=0; for(int i=1;i<9;i++){ diff += euclidian(n1,n2,i); } return diff; }
int starightDistanceOver(Node n1, Node n2){ int diff=0; for(int i=1;i<9;i++){ diff += pow(euclidian(n1,n2,i),2); } return diff; }
void simple_test() { CovMat<3> eye; eye << 1, 0, 0, 0, 1, 0, 0, 0, 1; FeatVec<3> zero; zero << 0, 0, 0; Kernel<3> euclidian(mh_dist<3>, zero, eye); FeatVec<3> pt; pt << 0, 1, 1; double sq_root_two = euclidian(pt); std::cout << sq_root_two << " " << std::sqrt(2.0) << std::endl; }
PointContainer knn(const PointContainer& container, const Point& data, int k) { std::map<float, Point> point_map; for(PointContainer::const_iterator it = container.begin(); it != container.end(); ++it) { point_map[euclidian(data, *it)] = *it; } PointContainer result; std::map<float, Point>::const_iterator it = point_map.begin(); for(int i = 0; i < k; ++i) { result.push_back(it->second); ++it; } return result; }
int gcd(int a, int b) { if (b > a) { int tmp = a; a = b; b = tmp; } int q, gcd, r = b; //a = b*q + r; while (r) { gcd = r; euclidian(a,b,&q,&r); a = b; b = r; } return gcd; }
/** Posterize an image from the trained SOM otput. * * This function fill a vector containing the RGB values of each pixels of an * image with the output of a trained SOM. The original image pixels RGB values * are needed to compute the euclidian distance from its colors to the trained * SIOM output colors. * Basicaly you can see this function job as a smart color selector. For each * pixel of the original image the function compute the "nearest" color among * the reduced set of olors of the SOM output. * * @param[out] postPixels The 2D array wich will contains the posterized pixels. * @param[in] origPixels The original image pixels. * @param[in] train The trained SOM output vector (its map). * @param[in] nbPixels The number of pixels of th image (height * width). * @param[in] nbNeurons The posterization level defined by its number of * neurons. */ void som_posterize(float **postPixels, float **origPixels, float *train[], unsigned int nbPixels, int nbNeurons){ unsigned int i; float dists[nbNeurons]; float choosen, o0, o1, o2; for(i = 0; i < nbPixels; i++){ euclidian(dists, nbNeurons, train[0], train[1], train[2], origPixels[i]); choosen = arr_min_idx(dists, nbNeurons); o0 = train[0][(int)choosen]; o1 = train[1][(int)choosen]; o2 = train[2][(int)choosen]; postPixels[i][0] = (int)(o0 * 255.); postPixels[i][1] = (int)(o1 * 255.); postPixels[i][2] = (int)(o2 * 255.); } }
/** Train the unsupervised SOM network. * * The network is initialized with random (non-graduate) values. It is then * trained with the image pixels (RGB). Once the network is done training the * centroids of the resulting clusters is returned. * * @note The length of the clusters depends on the parameter 'n'. The greatest * n, the more colors in the clusters, the less posterized the image. * * @param[out] res The resulting R, G and B clusters centroids. * @param[in] imgPixels The original image pixels. * @param[in] nbPixels The number of pixels of th image (height * width). * @param[in] nbNeurons The posterization leveldefined by its number of * neurons. * @param[in] noEpoch Number of training passes (a too small number of epochs * won't be enough for the network to correctly know the image but a too high * value will force the network to modify the wieghts so much that the image * can actually looks "ugly"). * @param[in] thresh The threshold value. The SOM delta parameter and the * training rate are dicreasing from one epoch to the next. The treshold value * set a stop condifition in case the value has fallen under this minimum * value. * * @return SOM_OK if everything goes right or SOM_NO_MEMORY if a memory * allocation (malloc) fail. */ int som_train(float **res, float **imgPixels, unsigned int nbPixels, int nbNeurons, int noEpoch, float thresh){ int mapWidth = // Map width. This can be calculated from its (int)sqrt(nbNeurons); // number of neurons as the map is square. int mapHeight = // Map height. This can be calculated from its (int)sqrt(nbNeurons); // number of neurons as the map is square. float delta = INT_MAX; // Start with an almost impossible value int it = 0; // Count the network iterations unsigned int pick; // The choosen input pixel float rad; // Neighbooring radius (keep dicreasing) float eta; // Learning rate (keep dicreasing) float pickRGB[3] = {0}; // Contains the choosen input RGB vector size_t choosen; // Best Matching Unit (BMU) int choosen_x; // BMU abscissa int choosen_y; // BMU ordinate float *neigh = // Neighbooring mask malloc(sizeof(float) * nbNeurons); if(neigh == NULL){ return SOM_NO_MEMORY; } memset(neigh, 0, nbNeurons); float *WR = // RED part of the network weight vectors malloc(sizeof(float) * nbNeurons); if(WR == NULL){ return SOM_NO_MEMORY; } memset(WR, 0, nbNeurons); float *WG = // GREEN part of the network weight vectors malloc(sizeof(float) * nbNeurons); if(WG == NULL){ return SOM_NO_MEMORY; } memset(WG, 0, nbNeurons); float *WB = // BLUE part of the network weight vectors malloc(sizeof(float) * nbNeurons); if(WB == NULL){ return SOM_NO_MEMORY; } memset(WB, 0, nbNeurons); float *deltaR = // New RED part of the network weight vectors malloc(sizeof(float) * nbNeurons); if(deltaR == NULL){ return SOM_NO_MEMORY; } memset(deltaR, 0, nbNeurons); float *deltaG = // New GREEN part of the network weight vectors malloc(sizeof(float) * nbNeurons); if(deltaG == NULL){ return SOM_NO_MEMORY; } memset(deltaG, 0, nbNeurons); float *deltaB = // New BLUE part of the network weight vectors malloc(sizeof(float) * nbNeurons); if(deltaB == NULL){ return SOM_NO_MEMORY; } memset(deltaB, 0, nbNeurons); float *absDeltaR = // Absolute value of deltaR malloc(sizeof(float) * nbNeurons); if(absDeltaR == NULL){ return SOM_NO_MEMORY; } memset(absDeltaR, 0, nbNeurons); float *absDeltaG = // Absolute value of deltaG malloc(sizeof(float) * nbNeurons); if(absDeltaG == NULL){ return SOM_NO_MEMORY; } memset(absDeltaG, 0, nbNeurons); float *absDeltaB = // Absolute value of deltaB malloc(sizeof(float) * nbNeurons); if(absDeltaB == NULL){ return SOM_NO_MEMORY; } memset(absDeltaB, 0, nbNeurons); float *dists = // Vectors euclidian distances from input form malloc(sizeof(float) * nbNeurons); if(dists == NULL){ return SOM_NO_MEMORY; } memset(dists, 0, nbNeurons); /* Randomly initialize weight vectors */ srand(time(NULL)); random_sample(WR, nbNeurons); random_sample(WG, nbNeurons); random_sample(WB, nbNeurons); while(it < noEpoch && delta >= thresh){ /* Randomly choose an input form */ pick = random_uint(nbPixels); pickRGB[0] = imgPixels[pick][0]; pickRGB[1] = imgPixels[pick][1]; pickRGB[2] = imgPixels[pick][2]; /* Compute every vectors euclidian distance from the input form */ euclidian(dists, nbNeurons, WR, WG, WB, pickRGB); /* Determine the BMU */ choosen = arr_min_idx(dists, nbNeurons); choosen_x = (int)choosen % mapWidth; choosen_y = choosen / mapHeight; /* Compute the new neighbooring radius */ rad = som_radius(it, noEpoch, mapWidth, mapHeight); /* Find the BMU neighboors */ som_neighbourhood(neigh, choosen_x, choosen_y, rad, mapWidth, mapHeight); /* Compute the new learning rate */ eta = som_learning_rate(it, noEpoch); /* Compute new value of the network weight vectors */ compute_delta(deltaR, eta, neigh, nbNeurons, pickRGB[0], WR); compute_delta(deltaG, eta, neigh, nbNeurons, pickRGB[1], WG); compute_delta(deltaB, eta, neigh, nbNeurons, pickRGB[2], WB); /* Update the network weight vectors values */ arr_add(WR, deltaR, nbNeurons); arr_add(WG, deltaG, nbNeurons); arr_add(WB, deltaB, nbNeurons); arr_abs(absDeltaR, deltaR, nbNeurons); arr_abs(absDeltaG, deltaG, nbNeurons); arr_abs(absDeltaB, deltaB, nbNeurons); delta = arr_sum(absDeltaR, nbNeurons) + arr_sum(absDeltaG, nbNeurons) + arr_sum(absDeltaB, nbNeurons); it++; } res[0] = WR; res[1] = WG; res[2] = WB; free(dists); free(deltaR); free(deltaG); free(deltaB); free(absDeltaR); free(absDeltaG); free(absDeltaB); free(neigh); return SOM_OK; }