from skimage import io from skimage.measure import label, regionprops from skimage.filters import threshold_otsu from skimage.color import rgb2gray from skimage import io from skimage.color import rgb2gray from skimage.filters import threshold_sauvola from skimage.exposure import equalize_adapthist from skimage.measure import label, regionprops from skimage.morphology import closing, square def get_heights(filename: str) -> list: """Open an image and return a list of the bar heights.""" # Load image and convert to grayscale image = io.imread(filename) im = rgb2gray(image) # Apply adaptive histogram equalization to enhance contrast im_eq = equalize_adapthist(im, clip_limit=0.03) # Adaptive thresholding using Sauvola method window_size = 25 # Adjust window size if needed thresh_sauvola = threshold_sauvola(im_eq, window_size=window_size) binary_im = im_eq > thresh_sauvola # Morphological closing to fill gaps and clean noise binary_im = closing(binary_im, square(3)) # Label connected components labeled = label(binary_im) # Get bounding boxes for each detected object bar_dimensions = [r.bbox for r in regionprops(labeled)] # Sort bounding boxes by horizontal position (xmin) bar_dimensions.sort(key=lambda x: x[1]) # Use the first detected object (logo) as max height reference logo = bar_dimensions[0] max_height = logo[2] - logo[0] sequence = [] for bar in bar_dimensions[1:]: height = bar[2] - bar[0] ratio = height / max_height ratio *= 8 ratio = int(ratio) # truncate decimal part sequence.append(ratio - 1) return sequence