double a_plus() { // Allocate patches float *patches = (float*)malloc(N*K*sizeof(float)); // Allocate patches_sr float *patches_sr = (float*)malloc(N*F*sizeof(float)); // Allocate LR dictionary float *dict_lr = (float*)malloc(K*C*sizeof(float)); // Allocate Projections float* projs = (float*)malloc(C*K*F*sizeof(float)); // Allocate nearest indices int *nn_inds = (int*)malloc(N*sizeof(int)); // Allocate similarities float *similarities = (float*)malloc(N*C*sizeof(float)); // Calculate nearest dictionary atoms double start_time = omp_get_wtime(); dot(patches, dict_lr, similarities, N, K, C); arr_abs(similarities, N, C); nearest_atoms(similarities, nn_inds, N, C); // Project back to HR space for (int n=0; n<N; n++) { int ind = nn_inds[n]; for (int f=0; f<F; f++) { float acc = 0; for (int k=0; k<K; k++) acc += patches[n*K+k] * projs[ind*K*F+k*F+f]; patches_sr[n*F+f] = acc; } } double duration = omp_get_wtime(); // Deallocate free(patches); free(patches_sr); free(dict_lr); free(projs); free(nn_inds); free(similarities); return duration; }
/** 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; }