Advertisement
Guest User

Untitled

a guest
Jan 2nd, 2023
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.13 KB | Source Code | 0 0
  1. /**************************************************************
  2.  
  3. The program reads an RGB bitmap image file and uses the K-Means algorithm
  4. algorithm to compress the image by clustering all pixels
  5. Author: Nikos Bellas, ECE Department, University of Thessaly, Volos, GR
  6. **************************************************************/
  7.  
  8. #include "qdbmp.h"
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <math.h>
  12. #include <time.h>
  13.  
  14.  
  15. /* Creates a negative image of the input bitmap file */
  16. int main( int argc, char* argv[] )
  17. {
  18. BMP* bmp;
  19. UINT* cluster; /* For each pixel position, it shows the cluster that this pixel belongs */
  20. UCHAR r, g, b;
  21. UINT width, height, row, col;
  22. UINT i;
  23. MEANS* means; /* Holds the (R, G, B) means of each cluster */
  24. UINT noClusters; /* Number of of clusters. It is given by the user */
  25. UINT dist, minDist, minCluster, iter, maxIterations;
  26. UINT noOfMoves; /* Total number of inter-cluster moves between two succesive iterations */
  27. UINT totr, totb, totg, sizeCluster;
  28. UCHAR bytes_per_pixel;
  29. UINT bytes_per_row;
  30. UCHAR* pixel;
  31. UINT* clusterPntr;
  32.  
  33. /* Check arguments */
  34. if ( argc != 4 )
  35. {
  36. fprintf( stderr, "Usage: %s <input file> <output files> <Number of Clusters>\n", argv[ 0 ] );
  37. return 1;
  38. }
  39.  
  40. /* Read the input (uncompressed) image file */
  41. bmp = BMP_ReadFile( argv[ 1 ] );
  42. BMP_CHECK_ERROR( stdout, -1 );
  43.  
  44.  
  45. /* Get image's dimensions */
  46. width = BMP_GetWidth( bmp );
  47. height = BMP_GetHeight( bmp );
  48. bytes_per_pixel = bmp->Header.BitsPerPixel >> 3;
  49. bytes_per_row = bmp->Header.ImageDataSize / height;
  50.  
  51. noClusters = ( UINT ) atoi(argv[3]);
  52. means = (MEANS *) calloc( noClusters, sizeof( MEANS ) );
  53.  
  54. /* 1. Initialize cluster means with (R, G, B) values from random coordinates of the Input Image*/
  55. srand (time(NULL));
  56. for (i = 0; i < noClusters; ++i) {
  57.  
  58. col = rand() % width;
  59. row = rand() % height;
  60.  
  61. /* Get pixel's RGB values */
  62. BMP_GetPixelRGB( bmp, col, row, &r, &g, &b );
  63.  
  64. means[i].r = r;
  65. means[i].g = g;
  66. means[i].b = b;
  67. }
  68.  
  69. /* The cluster assignement for each pixel */
  70. cluster = (UINT*) calloc( width*height, sizeof(UINT) ); /* Important to also initialize all entries to 0 */
  71. if ( cluster == NULL )
  72. {
  73. free( cluster );
  74. free( bmp );
  75. return 1;
  76. }
  77.  
  78.  
  79. maxIterations = 10;
  80. iter = 0;
  81.  
  82.  
  83. /* Main loop runs at least once */
  84.  
  85. do {
  86.  
  87. noOfMoves = 0;
  88. ++iter;
  89. printf("ITER %ld\n", iter);
  90. /* 2. Go through each pixel in the input image and calculate its nearest mean.
  91. The output of phase 2 is the cluster* data structure. */
  92.  
  93. for ( row = 0 ; row < height ; ++row) {
  94. clusterPntr= (cluster+row*width);
  95. for ( col = 0 ; col < width ; ++col ) {
  96.  
  97. /* Calculate the location of the relevant pixel (rows are flipped) */
  98. pixel = bmp->Data + ( ( bmp->Header.Height - row - 1 ) * bytes_per_row + col * bytes_per_pixel );
  99. /* Get pixel's RGB values */
  100. b=pixel[0];
  101. g=pixel[1];
  102. r=pixel[2];
  103. //BMP_GetPixelRGB( bmp, col, row, &r, &g, &b );
  104.  
  105. minDist = 10000; /* Larger than the lagest possible value */
  106. for (i = 0; i < noClusters; ++i) {
  107.  
  108. /* Distance metric. May replace with something cheaper */
  109. //dist = (UINT) sqrt((r-means[i].r)*(r-means[i].r) + (g-means[i].g)*(g-means[i].g) + (b-means[i].b)*(b-means[i].b));
  110. dist=(UINT) labs(r-means[i].r)+labs(g-means[i].g)+labs(b-means[i].b);
  111. if (dist < minDist) {
  112. minDist = dist;
  113. minCluster = i;
  114.  
  115. }
  116. }
  117.  
  118. if (clusterPntr[col] != minCluster) {
  119.  
  120. clusterPntr[col] = minCluster;
  121. ++noOfMoves;
  122. }
  123.  
  124. } /* for */
  125. } /* for */
  126.  
  127.  
  128. /* 3. Update the mean of each cluster based on the pixels assigned to them. */
  129. if (noOfMoves > 0) {
  130. for (i = 0; i < noClusters; i++) {
  131.  
  132. totr =0;
  133. totb =0;
  134. totg = 0;
  135. sizeCluster = 0;
  136.  
  137. for ( row = 0 ; row < height ; ++row) {
  138.  
  139. clusterPntr= (cluster+row*width);
  140. for ( col = 0 ; col < width ; ++col ) {
  141.  
  142. if (clusterPntr[col] == i) {
  143.  
  144. /* Calculate the location of the relevant pixel (rows are flipped) */
  145. pixel = bmp->Data + ( ( bmp->Header.Height - row - 1 ) * bytes_per_row + col * bytes_per_pixel );
  146. // /* Get pixel's RGB values */
  147. b=pixel[0];
  148. g=pixel[1];
  149. r=pixel[2];
  150. totr += r;
  151. totg += g;
  152. totb += b;
  153. //why is this SO MUCH SLOWER
  154. // totb += pixel[0];
  155. // totg += pixel[1];
  156. // totr += pixel[2];
  157. sizeCluster++;
  158.  
  159. }
  160.  
  161. }
  162. }
  163.  
  164. means[i].r = (UCHAR) (totr/sizeCluster);
  165. means[i].g = (UCHAR) (totg/sizeCluster);
  166. means[i].b = (UCHAR) (totb/sizeCluster);
  167.  
  168. }
  169.  
  170. }
  171.  
  172. /* 4. Goto 2 if not convergence and less than a max number of iterations. Else goto 5 */
  173. } while ((iter < maxIterations) && (noOfMoves > 0));
  174.  
  175.  
  176.  
  177. for (i = 0; i < noClusters; ++i) {
  178. printf("means[%ld] = (%d, %d, %d)\n", i, means[i].r, means[i].g, means[i].b);
  179. }
  180.  
  181.  
  182. /* 5. Replace the pixel of the original image with the mean of the corresponding cluster */
  183.  
  184.  
  185. for ( row = 0 ; row < height ; ++row) {
  186. for ( col = 0 ; col < width ; ++col ) {
  187.  
  188. i = *(cluster+row*width + col);
  189. r = means[i].r;
  190. g = means[i].g;
  191. b = means[i].b;
  192.  
  193. /* Note: colors are stored in BGR order */
  194. /* Calculate the location of the relevant pixel (rows are flipped) */
  195. pixel = bmp->Data + ( ( bmp->Header.Height - row - 1 ) * bytes_per_row + col * bytes_per_pixel );
  196.  
  197. /* Get pixel's RGB values */
  198. pixel[0]=b;
  199. pixel[1]=g;
  200. pixel[2]=r;
  201.  
  202. }
  203.  
  204. }
  205.  
  206.  
  207. /* Write out the output image and finish */
  208. BMP_WriteFile( bmp, argv[ 2 ] );
  209. BMP_CHECK_ERROR( stdout, -2 );
  210.  
  211.  
  212. /* Free all memory allocated for the image */
  213. BMP_Free( bmp );
  214.  
  215.  
  216.  
  217. return 0;
  218. }
  219.  
  220.  
  221.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement