So, I am trying to extract all the colors out of a rubicks cube, Right now, I have tried the following: import cv2 import PIL import numpy as np import math import matplotlib.pyplot as plt def detect_colored_cubes(image_path): img = cv2.imread(image_path) hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) h, w, c = img.shape area_min = h*w//(30*30) area_max = h*w//5 print(area_min, area_max) color_ranges = { 'red': ([0, 50, 50], [6, 255, 255]), 'orange': ([7., 50, 50], [16.9, 255, 255]), 'yellow': ([17.0, 50, 50], [34., 255, 255]), 'green': ([34., 50, 50], [70., 255, 255]), 'blue': ([71, 50, 50], [135, 255, 255]), 'pink': ([136, 50, 50], [180, 255, 255]), 'white': ([0, 0, 100], [180, 30, 255]) } detected_cubes = [] for color_name, (lower, upper) in color_ranges.items(): # Create mask for color mask = cv2.inRange(hsv, np.array(lower), np.array(upper)) masked_img = cv2.bitwise_and(img, img, mask=mask) bw_masked_img = cv2.cvtColor(masked_img, cv2.COLOR_BGR2GRAY) # _, bw_masked_img = cv2.threshold(bw_masked_img, 100, 255, cv2.THRESH_BINARY) bw_masked_img_rgb = cv2.cvtColor(bw_masked_img, cv2.COLOR_GRAY2RGB) cv2_imshow(bw_masked_img) small_kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3)) medium_kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)) large_kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (7, 7)) cleaned = cv2.morphologyEx(bw_masked_img, cv2.MORPH_OPEN, small_kernel, iterations=2) cleaned = cv2.morphologyEx(cleaned, cv2.MORPH_CLOSE, medium_kernel, iterations=1) dist = cv2.distanceTransform(cleaned, cv2.DIST_L2, 5) thres = cv2.threshold(dist, 0.15*dist.max(), 255, 0)[1].astype(np.uint8) #cv2_imshow(dist) #cv2_imshow(thres) contours, _ = cv2.findContours(thres, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) print(color_name) # cv2_imshow(cleaned) markers = np.zeros_like(img) for i, contour in enumerate(contours): x, y, w, h = cv2.boundingRect(contour) area = w*h # print(area) # print("area", area) if area > area_min and area < area_max: detected_cubes.append({ 'color': color_name, 'position': cv2.boundingRect(contour), 'area': area }) return detected_cubes img_file = 'cube4.jpg' cubes = detect_colored_cubes(img_file) Basically, I am looking at all colors seperately and trying to get components from them by using distance transform. However, I am having difficulty in removing outliers and getting only the useful data from them. Sometimes, it detects components which span multiple cubes since same colored subes are adjacent. So, I want to ask, how do I exactly get the set of 9 colors from one face as well as leave out the outliers? img_face = cv2.imread(img_file) cubes = sorted(cubes, key=lambda x: x['area'], reverse=True) new = np.zeros((img_face.shape[0], img_face.shape[1], 3), dtype=np.uint8) for cube in cubes: new[cube['position'][1]:cube['position'][1] + cube['position'][3], cube['position'][0]:cube['position'][0] + cube['position'][2]] = color_codes[cube['color']] cv2.putText(new, cube['color'], (cube['position'][0], cube['position'][1] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, color_codes[cube['color']], 2) cv2_imshow(new) gives me the following which is majorly correct but has outliers: Real image: cube4.jpg Continue reading...