Advertisement
Guest User

Untitled

a guest
Feb 21st, 2018
52
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.57 KB | None | 0 0
  1. //
  2. // tp2.cpp
  3. // Exemple de convolution d'image avec lodepng
  4. //
  5. // Créé par Julien-Charles Lévesque
  6. // Copyright 2015 Université Laval. Tous droits réservés.
  7. //
  8.  
  9.  
  10. #include "lodepng.h"
  11. #include <iostream>
  12. #include <stdlib.h>
  13. #include <fstream>
  14. #include <thread>
  15. #include <omp.h>
  16. #include <cstring>
  17. #include <cmath>
  18.  
  19. #include "Chrono.hpp"
  20. #include "PACC/Tokenizer.hpp"
  21.  
  22. using namespace std;
  23.  
  24. //Aide pour le programme
  25. void usage(char* inName) {
  26. cout << endl << "Utilisation> " << inName << " fichier_image fichier_noyau [fichier_sortie=output.png]" << endl;
  27. exit(1);
  28. }
  29.  
  30. //Décoder à partir du disque dans un vecteur de pixels bruts en un seul appel de fonction
  31. void decode(const char* inFilename, vector<unsigned char>& outImage, unsigned int& outWidth, unsigned int& outHeight)
  32. {
  33. //Décoder
  34. unsigned int lError = lodepng::decode(outImage, outWidth, outHeight, inFilename);
  35.  
  36. //Montrer l'erreur s'il y en a une.
  37. if(lError)
  38. cout << "Erreur de décodage " << lError << ": " << lodepng_error_text(lError) << endl;
  39.  
  40. //Les pixels sont maintenant dans le vecteur outImage, 4 octets par pixel, organisés RGBARGBA...
  41. }
  42.  
  43. //Encoder à partir de pixels bruts sur le disque en un seul appel de fonction
  44. //L'argument inImage contient inWidth * inHeight pixels RGBA ou inWidth * inHeight * 4 octets
  45. void encode(const char* inFilename, vector<unsigned char>& inImage, unsigned int inWidth, unsigned int inHeight)
  46. {
  47. //Encoder l'image
  48. unsigned lError = lodepng::encode(inFilename, inImage, inWidth, inHeight);
  49.  
  50. //Montrer l'erreur s'il y en a une.
  51. if(lError)
  52. cout << "Erreur d'encodage " << lError << ": "<< lodepng_error_text(lError) << endl;
  53. }
  54.  
  55. int main(int inArgc, char *inArgv[])
  56. {
  57. if(inArgc < 3 or inArgc > 4) usage(inArgv[0]);
  58. string lFilename = inArgv[1];
  59. string lOutFilename;
  60. if (inArgc == 4)
  61. lOutFilename = inArgv[3];
  62. else
  63. lOutFilename = "output.png";
  64.  
  65. // Lire le noyau.
  66. ifstream lConfig;
  67. lConfig.open(inArgv[2]);
  68. if (!lConfig.is_open()) {
  69. cerr << "Le fichier noyau fourni (" << inArgv[2] << ") est invalide." << endl;
  70. exit(1);
  71. }
  72.  
  73. PACC::Tokenizer lTok(lConfig);
  74. lTok.setDelimiters(" \n","");
  75.  
  76. string lToken;
  77. lTok.getNextToken(lToken);
  78.  
  79. int lK = atoi(lToken.c_str());
  80. int lHalfK = lK/2;
  81.  
  82. cout << "Taille du noyau: " << lK << endl;
  83.  
  84. //Lecture du filtre
  85. double* lFilter = new double[lK*lK];
  86.  
  87. for (int i = 0; i < lK; i++) {
  88. for (int j = 0; j < lK; j++) {
  89. lTok.getNextToken(lToken);
  90. lFilter[i*lK+j] = atof(lToken.c_str());
  91. }
  92. }
  93.  
  94. //Lecture de l'image
  95. //Variables à remplir
  96. unsigned int lWidth, lHeight;
  97. vector<unsigned char> lImage; //Les pixels bruts
  98. //Appeler lodepng
  99. decode(lFilename.c_str(), lImage, lWidth, lHeight);
  100.  
  101. // Démarrer le chronomètre
  102. Chrono lChrono(true);
  103.  
  104. //Variables contenant des indices
  105.  
  106. //Variables temporaires pour les canaux de l'image
  107.  
  108. vector<unsigned char> oImage(lImage);
  109.  
  110. int numberOfProcessor = std::thread::hardware_concurrency();
  111. if (numberOfProcessor == 0){
  112. printf("No processor detected!");
  113. numberOfProcessor = 2;
  114. }
  115.  
  116. int workingSize = lHeight - lK + 1;
  117.  
  118. #pragma omp parallel for
  119. for (int iteration = 0; iteration < numberOfProcessor; ++iteration)
  120. {
  121. const size_t startIndex = lHalfK*4 + (iteration * ceil(workingSize / numberOfProcessor) + lHalfK) * lWidth * 4;
  122.  
  123. vector<unsigned char> oCopyImage(lImage.cbegin() + startIndex,
  124. lImage.cbegin() + ((iteration + 1) * ceil(workingSize / numberOfProcessor) + lHalfK) * lWidth * 4);
  125.  
  126. for(int y = iteration * ceil(workingSize / numberOfProcessor) + lHalfK; y < (iteration + 1) * ceil(workingSize / numberOfProcessor) + lHalfK && y < workingSize + lHalfK; y++)
  127. {
  128. for (int x = lHalfK; x < (int)lWidth - lHalfK; x++)
  129. {
  130. double lR, lG, lB;
  131. lR = 0.;
  132. lG = 0.;
  133. lB = 0.;
  134. for (int j = -lHalfK; j <= lHalfK; j++) {
  135. int fy, fx;
  136. fy = j + lHalfK;
  137. for (int i = -lHalfK; i <= lHalfK; i++) {
  138. fx = i + lHalfK;
  139.  
  140. lR += double(lImage[(y + j)*lWidth*4 + (x + i)*4]) * lFilter[fx + fy*lK];
  141. lG += double(lImage[(y + j)*lWidth*4 + (x + i)*4 + 1]) * lFilter[fx + fy*lK];
  142. lB += double(lImage[(y + j)*lWidth*4 + (x + i)*4 + 2]) * lFilter[fx + fy*lK];
  143. }
  144. }
  145. //Placer le résultat dans l'image.
  146.  
  147. oCopyImage[y*lWidth*4 + x*4 - startIndex] = (unsigned char)lR;
  148. oCopyImage[y*lWidth*4 + x*4 + 1 - startIndex] = (unsigned char)lG;
  149. oCopyImage[y*lWidth*4 + x*4 + 2 - startIndex] = (unsigned char)lB;
  150. }
  151. }
  152.  
  153. #pragma omp critical // Whatch out, all unnamed critical sections have the same lock
  154.  
  155. memcpy(&oImage[startIndex], &oCopyImage[0], oCopyImage.size() * sizeof(unsigned char));
  156. }
  157.  
  158. // Arrêter le chronomètre
  159. lChrono.pause();
  160.  
  161. // Afficher le temps d'exécution dans le stderr
  162. fprintf(stderr, "Temps d'execution = %f sec\n", lChrono.get());
  163.  
  164. //Sauvegarde de l'image dans un fichier sortie
  165. encode(lOutFilename.c_str(), oImage, lWidth, lHeight);
  166.  
  167. cout << "L'image a été filtrée et enregistrée dans " << lOutFilename << " avec succès!" << endl;
  168.  
  169. delete lFilter;
  170. return 0;
  171. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement