@@ -35,7 +35,7 @@ def __init__(self, image_path, num_of_segments=75, a_compactness=10):
3535 :type image_path: str
3636 :param num_of_segments: The desired number of segments to divide the
3737 image into for segmentation. Default is 100.
38- :type num_of_segments: int, optional
38+ :type num_of_segments: int, optionally
3939 :param a_compactness: Controls the compactness of Superpixels. Higher
4040 values result in more square-like segments. Default is 10.
4141 :type a_compactness: int, optional
@@ -60,15 +60,15 @@ def __init__(self, image_path, num_of_segments=75, a_compactness=10):
6060 self .superpixels_images = [gray_image , image_for_super_process ]
6161
6262 @staticmethod
63- def plot_wireframe (actual_algorithm , rotated_gray_image_meth , x_grid_meth , y_grid_meth , rotated_segments_meth , h_rot_meth , w_rot_meth , X_meth , Y_meth ):
63+ def plot_wireframe (actual_algorithm , rotated_gray_image_meth , x_grid_meth , y_grid_meth , rotated_segments_meth , h_rot_meth , w_rot_meth , x_meth , y_meth , stride = 10 ):
6464 # Plot the center using a wireframe
6565
6666 # Create 3D plot
6767 fig_3d = plt .figure (f"3D Visualization -- { actual_algorithm } " , figsize = (15 , 15 ))
6868 ax_3d = fig_3d .add_subplot (111 , projection = '3d' )
6969
7070 # Plot the 3D surface
71- stride = 1 # Use a smaller stride for more detail
71+ # Use a smaller stride for more detail
7272 # Scale the z-axis (intensity) to 256
7373 scaled_intensity = rotated_gray_image_meth [::stride , ::stride ] * 256
7474 ax_3d .plot_wireframe (x_grid_meth [::stride , ::stride ], y_grid_meth [::stride , ::stride ],
@@ -86,12 +86,12 @@ def plot_wireframe(actual_algorithm, rotated_gray_image_meth, x_grid_meth, y_gri
8686 z_contour = rotated_gray_image_meth [y_contour , x_contour ] * 256 + 2.5 # Raise slightly
8787 ax_3d .plot (x_contour , y_contour , z_contour , color = 'black' , linewidth = 1.5 )
8888
89- ax_3d .scatter (Y_meth , 1280 - X_meth , 256 , c = 'red' , s = 250 , marker = 'o' , depthshade = True ,
89+ ax_3d .scatter (y_meth , 1280 - x_meth , 256 , c = 'red' , s = 250 , marker = 'o' , depthshade = True ,
9090 label = 'Centroid' )
9191
92- ax_3d .set_xlabel ('X' )
93- ax_3d .set_ylabel ('Y' )
94- ax_3d .set_zlabel ('Intensity' )
92+ # ax_3d.set_xlabel('X')
93+ # ax_3d.set_ylabel('Y')
94+ # ax_3d.set_zlabel('Intensity')
9595 ax_3d .view_init (elev = 50 , azim = 280 )
9696 ax_3d .legend (fontsize = 20 )
9797 plt .savefig (f'{ actual_algorithm } wireframe.png' )
@@ -113,25 +113,25 @@ def calculate_superpixels_slic(self):
113113 gray_image_2d , image = self .superpixels_images
114114
115115 segments = slic (image , n_segments = self .n_segments , compactness = self .compactness , sigma = 5 )
116- X , Y = self .center_of_spot (image , segments )
117- print ('SLIC centroid coordinates are in X = ' + str (X ) + ' & Y = ' + str (Y ))
116+ x , y = self .center_of_spot (image , segments )
117+ print ('SLIC centroid coordinates are in X = ' + str (x ) + ' & Y = ' + str (y ))
118118
119119 # Show the output of SLIC
120120 plt .rcParams .update ({'font.size' : 30 })
121- fig = plt .figure ("Superpixels -- SLIC (%d segments)" % ( self .n_segments ) , figsize = (11 , 12.8 ))
121+ fig = plt .figure ("Superpixels -- SLIC (%d segments)" % self .n_segments , figsize = (11 , 12.8 ))
122122 ax = fig .add_subplot (1 , 1 , 1 )
123123 ax .imshow (np .rot90 (mark_boundaries (image , segments )), origin = 'lower' )
124- plt .plot (Y , 1280 - X , marker = 'o' , markersize = 15 , color = 'red' ) # Swap X and Y for the rotated plot
124+ plt .plot (y , 1280 - x , marker = 'o' , markersize = 15 , color = 'red' ) # Swap X and Y for the rotated plot
125125 # plt.title("Superpixels -- SLIC (%d segments)" % (self.n_segments))
126- plt .xlabel ("pixeles " )
127- plt .ylabel ("pixeles " )
126+ plt .xlabel ("pixels " )
127+ plt .ylabel ("pixels " )
128128 plt .axis ("on" )
129129 plt .savefig ('SLIC.png' )
130130 plt .show ()
131131
132132 # Show the output of slic as 3d graphic
133133
134- h , w = gray_image_2d .shape
134+ # h, w = gray_image_2d.shape
135135
136136 # Rotate image and segments for consistency with 2D plot
137137 rotated_gray_image = np .rot90 (gray_image_2d )
@@ -166,7 +166,7 @@ def calculate_superpixels_slic(self):
166166
167167 # Plot the center using a wireframe
168168 self .plot_wireframe ("SLIC" , rotated_gray_image , x_grid , y_grid , rotated_segments ,
169- h_rot , w_rot , X , Y )
169+ h_rot , w_rot , x , y )
170170
171171
172172 def calculate_superpixels_quickshift (self ):
@@ -184,25 +184,25 @@ def calculate_superpixels_quickshift(self):
184184 gray_image_2d , image = self .superpixels_images
185185
186186 segments = quickshift (image , kernel_size = 21 , max_dist = 50 , ratio = 5 )
187- X , Y = self .center_of_spot (image , segments )
188- print ('Quick-shift centroid coordinates are in X = ' + str (X ) + ' & Y = ' + str (Y ) )
187+ x , y = self .center_of_spot (image , segments )
188+ print ('Quick-shift centroid coordinates are in X = ' + str (x ) + ' & Y = ' + str (y ) )
189189 # Show the output of Quickshift
190190 plt .rcParams .update ({'font.size' : 30 })
191191 plt .rcParams ['figure.figsize' ] = 11 , 12.8
192192 fig = plt .figure ("Superpixels -- Quickshift" )
193193 ax = fig .add_subplot (1 , 1 , 1 )
194194 ax .imshow (np .rot90 (mark_boundaries (image , segments )), origin = 'lower' )
195- plt .plot (Y , 1280 - X , marker = 'o' , markersize = 15 , color = 'red' )
195+ plt .plot (y , 1280 - x , marker = 'o' , markersize = 15 , color = 'red' )
196196 # plt.title("Superpixels -- Quickshift")
197- plt .xlabel ("pixeles " )
198- plt .ylabel ("pixeles " )
197+ plt .xlabel ("pixels " )
198+ plt .ylabel ("pixels " )
199199 plt .axis ("on" )
200200 plt .savefig ('Quickshift.png' )
201201 plt .show ()
202202
203- # Show the output of quickshift as 3d graphic
203+ # Show the output of quickshift as a 3d graphic
204204
205- h , w = gray_image_2d .shape
205+ # h, w = gray_image_2d.shape
206206
207207 # Rotate image and segments for consistency with 2D plot
208208 rotated_gray_image = np .rot90 (gray_image_2d )
@@ -237,7 +237,7 @@ def calculate_superpixels_quickshift(self):
237237
238238 # Plot the center using a wireframe
239239 self .plot_wireframe ("Quickshift" , rotated_gray_image , x_grid , y_grid , rotated_segments ,
240- h_rot , w_rot , X , Y )
240+ h_rot , w_rot , x , y )
241241
242242 def calculate_superpixels_felzenszwalb (self ):
243243 """
@@ -254,25 +254,25 @@ def calculate_superpixels_felzenszwalb(self):
254254 gray_image_2d , image = self .superpixels_images
255255
256256 segments = felzenszwalb (image , scale = 300 , sigma = 0.5 , min_size = 200 )
257- X , Y = self .center_of_spot (image , segments )
258- print ('Felzenszwalb centroid coordinates are in X = ' + str (X ) + ' & Y = ' + str (Y ) )
257+ x , y = self .center_of_spot (image , segments )
258+ print ('Felzenszwalb centroid coordinates are in X = ' + str (x ) + ' & Y = ' + str (y ) )
259259 # Show the output of Felzenszwalb
260260 plt .rcParams .update ({'font.size' : 30 })
261261 plt .rcParams ['figure.figsize' ] = 11 , 12.8
262262 fig = plt .figure ("Superpixels -- Felzenszwalb" )
263263 ax = fig .add_subplot (1 , 1 , 1 )
264264 ax .imshow (np .rot90 (mark_boundaries (image , segments )), origin = 'lower' )
265- plt .plot (Y , 1280 - X , marker = 'o' , markersize = 15 , color = 'red' )
265+ plt .plot (y , 1280 - x , marker = 'o' , markersize = 15 , color = 'red' )
266266 # plt.title("Superpixels -- Felzenszwalb")
267- plt .xlabel ("pixeles " )
268- plt .ylabel ("pixeles " )
267+ plt .xlabel ("pixels " )
268+ plt .ylabel ("pixels " )
269269 plt .axis ("on" )
270270 plt .savefig ('Felzenszwalb.png' )
271271 plt .show ()
272272
273273 # Show the output of felzenszwalb as 3d graphic
274274
275- h , w = gray_image_2d .shape
275+ # h, w = gray_image_2d.shape
276276
277277 # Rotate image and segments for consistency with 2D plot
278278 rotated_gray_image = np .rot90 (gray_image_2d )
@@ -307,7 +307,7 @@ def calculate_superpixels_felzenszwalb(self):
307307 plt .show ()
308308 # Plot the center using a wireframe
309309 self .plot_wireframe ("Felzenszwalb" , rotated_gray_image , x_grid , y_grid , rotated_segments ,
310- h_rot , w_rot , X , Y )
310+ h_rot , w_rot , x , y )
311311
312312 @staticmethod
313313 def center_of_spot (image , segments ):
@@ -343,26 +343,26 @@ def center_of_spot(image, segments):
343343 meansum = []
344344 for j in range (arrsiz ):
345345 # individualCoor = [coor[0][j],coor[1][j]]#coordenada individual de cda pixel del segemento
346- coorVal = image [coor [0 ][j ]][coor [1 ][j ]][0 ] # valaor de cada pixel del segmento
347- meansum .append (coorVal ) # se agrega el valor a un vector
348- segmentVal = np .mean (meansum ) # promedio de valores para cada segmento
349- values .append (segmentVal ) # agrega ese valor a una variable (la media de cada segmento)
346+ coor_val = image [coor [0 ][j ]][coor [1 ][j ]][0 ] # valaor de cada pixel del segmento
347+ meansum .append (coor_val ) # se agrega el valor a un vector
348+ segment_val = np .mean (meansum ) # promedio de valores para cada segmento
349+ values .append (segment_val ) # agrega ese valor a una variable (la media de cada segmento)
350350 maxsegment = np .where (values == np .amax (values )) # elige segmento con valor maximo
351- maxS = maxsegment [0 ] + 1 # compensacion del 0 en el indice del array
352- maxseg = maxS [0 ]
351+ max_s = maxsegment [0 ] + 1 # compensacion del 0 en el indice del array
352+ maxseg = max_s [0 ]
353353 # print(maxseg)
354- maxVC = np .where (
354+ max_vc = np .where (
355355 segments == maxseg ) # selecciona todas las coordenadas del segmento con valor maximo
356356 # calcular la distancia desde el segmento hasta el centro
357- arraysz = maxVC [0 ].shape # dimencion del conjunto de coordenadas del segmento
357+ arraysz = max_vc [0 ].shape # dimencion del conjunto de coordenadas del segmento
358358 arsz = int (arraysz [0 ] / 2 ) # la mitad de ese conjunto
359- XselectCoor = maxVC [1 ][arsz ] # coordenada intermedia en x
360- X = XselectCoor
361- YselectCoor = maxVC [0 ][arsz ] # coordenada intermedia en y
362- Y = YselectCoor
363- return X , Y
359+ x_select_coor = max_vc [1 ][arsz ] # coordenada intermedia en x
360+ x = x_select_coor
361+ y_select_coor = max_vc [0 ][arsz ] # coordenada intermedia en y
362+ y = y_select_coor
363+ return x , y
364364
365- def calculate_centroid (image_path ):
365+ def calculate_centroid (fbm_image_path ):
366366 """
367367 Calculates the centroid of the largest object in the provided image.
368368
@@ -372,14 +372,14 @@ def calculate_centroid(image_path):
372372 enhance object detection. Once the largest object is identified via contours,
373373 the centroid is computed using image moments.
374374
375- :param image_path : Path to the image file.
376- :type image_path : str
375+ :param fbm_image_path : Path to the image file.
376+ :type fbm_image_path : str
377377 :return: A tuple containing the x and y coordinates of the centroid of the
378378 largest object, or None if no objects are detected.
379379 :rtype: tuple[int, int] | None
380380 """
381381 # Step 1: Read the image
382- image = cv2 .imread (image_path , cv2 .IMREAD_COLOR )
382+ image = cv2 .imread (fbm_image_path , cv2 .IMREAD_COLOR )
383383
384384 # Step 2: Convert to grayscale
385385 gray = cv2 .cvtColor (image , cv2 .COLOR_BGR2GRAY )
@@ -411,7 +411,7 @@ def calculate_centroid(image_path):
411411 cx = int (moments ['m10' ] / moments ['m00' ]) # X-coordinate of the centroid
412412 cy = int (moments ['m01' ] / moments ['m00' ]) # Y-coordinate of the centroid
413413 else :
414- # In case of a single point as an object (unlikely in this case)
414+ # In the case of a single point as an object (unlikely in this case)
415415 cx , cy = 0 , 0
416416
417417 print (f"Centroid of the object is at: ({ cx } , { cy } )" )
@@ -430,22 +430,46 @@ def calculate_centroid(image_path):
430430 plt .savefig ('FBM.png' )
431431 plt .show ()
432432
433+ # 3D visualization for FBM
434+ # Prepare rotated grayscale image normalized to [0,1]
435+ rotated_gray_image = np .rot90 (gray .astype (np .float32 ) / 255.0 )
436+ h_rot , w_rot = rotated_gray_image .shape
437+ y_grid , x_grid = np .mgrid [0 :h_rot , 0 :w_rot ]
438+
439+ # Build segmentation from morph mask for boundary plotting
440+ label_image = label (morph > 0 )
441+ rotated_segments = np .rot90 (label_image )
442+
443+ # Plot 3D surface
444+ fig_3d = plt .figure ("3D Visualization -- FBM" , figsize = (15 , 15 ))
445+ ax_3d = fig_3d .add_subplot (111 , projection = '3d' )
446+ stride = 1
447+ scaled_intensity = rotated_gray_image [::stride , ::stride ] * 256
448+ ax_3d .plot_surface (x_grid [::stride , ::stride ], y_grid [::stride , ::stride ],
449+ scaled_intensity ,
450+ cmap = 'viridis' , alpha = 0.7 , linewidth = 0 )
451+ plt .savefig ('FBM-surface.png' )
452+ plt .show ()
453+
454+ # Plot wireframe with centroid overlay
455+ Superpixels .plot_wireframe ("FBM" , rotated_gray_image , x_grid , y_grid , rotated_segments , h_rot , w_rot , cx , cy , 100 )
456+
433457 return cx , cy
434458
435- def calculate_centroid_scikit (image_path ):
459+ def calculate_centroid_scikit (ccl_image_path ):
436460 """
437461 Calculates the centroid of the largest connected region in a given image using scikit-image.
438462
439463 This function performs preprocessing on the image, including Gaussian Blur and morphological
440464 operations, and then identifies the largest connected region. The centroid of this region
441465 is computed and displayed. If no connected regions are found, it returns None.
442466
443- :param str image_path : The path to the image file to be processed.
467+ :param str ccl_image_path : The path to the image file to be processed.
444468 :return: A tuple containing the x and y coordinates of the centroid as integers.
445469 :rtype: tuple[int, int] | None
446470 """
447471 # Read the image using scikit-image
448- image = imread (image_path )
472+ image = imread (ccl_image_path )
449473
450474 if len (image .shape ) == 2 :
451475 gray = image
@@ -491,12 +515,47 @@ def calculate_centroid_scikit(image_path):
491515 # plt.title("Centrid calculated with CCL")
492516 plt .savefig ('CCL.png' )
493517 plt .show ()
518+
519+ # 3D visualization for CCL
520+ # Prepare rotated grayscale image normalized to [0,1]
521+ rotated_gray_image = np .rot90 (img_as_float (gray ))
522+ h_rot , w_rot = rotated_gray_image .shape
523+ y_grid , x_grid = np .mgrid [0 :h_rot , 0 :w_rot ]
524+
525+ # Use the label_image for boundaries
526+ rotated_segments = np .rot90 (label_image )
527+
528+ # Plot the 3D surface with boundaries overlay
529+ fig_3d = plt .figure ("3D Visualization -- CCL" , figsize = (15 , 15 ))
530+ ax_3d = fig_3d .add_subplot (111 , projection = '3d' )
531+ stride = 1
532+ scaled_intensity = rotated_gray_image [::stride , ::stride ] * 256
533+ ax_3d .plot_surface (x_grid [::stride , ::stride ], y_grid [::stride , ::stride ],
534+ scaled_intensity ,
535+ cmap = 'viridis' , alpha = 0.7 , linewidth = 0 )
536+
537+ for label_val in np .unique (rotated_segments ):
538+ contours = find_contours (rotated_segments , level = label_val )
539+ for contour in contours :
540+ y_contour , x_contour = contour [:, 0 ].astype (int ), contour [:, 1 ].astype (int )
541+ y_contour = np .clip (y_contour , 0 , h_rot - 1 )
542+ x_contour = np .clip (x_contour , 0 , w_rot - 1 )
543+ z_contour = rotated_gray_image [y_contour , x_contour ] * 256 + 2.5
544+ ax_3d .plot (x_contour , y_contour , z_contour , color = 'black' , linewidth = 1.5 )
545+
546+ plt .savefig ('CCL-surface.png' )
547+ plt .show ()
548+
549+ # Plot wireframe with centroid overlay
550+ Superpixels .plot_wireframe ("CCL" , rotated_gray_image , x_grid , y_grid , rotated_segments , h_rot , w_rot , int (cx ),
551+ int (cy ), 1 )
552+
494553 return int (cx ), int (cy )
495554
496555
497556if __name__ == '__main__' :
498- image_path = "images/l0/image100.png"
499- superpixels_centroid = Superpixels (image_path , 50 , 10 )
557+ path_to_image = "images/l0/image100.png"
558+ superpixels_centroid = Superpixels (path_to_image , 50 , 10 )
500559
501560 # Superpixels
502561 # SLIC
@@ -523,14 +582,14 @@ def calculate_centroid_scikit(image_path):
523582 # cv2 centroid
524583
525584 reset = time .time ()
526- calculate_centroid (image_path )
585+ calculate_centroid (path_to_image )
527586 end = time .time ()
528587 cv2_centroid_time = end - reset
529588
530589 # Scikit centroid
531590
532591 reset = time .time ()
533- calculate_centroid_scikit (image_path )
592+ calculate_centroid_scikit (path_to_image )
534593 end = time .time ()
535594 scikit_centroid_time = end - reset
536595
0 commit comments