import cv2 import numpy as np import kociemba import colorsys # Define the colors for comparison color_ranges = [ # c h1 h2 s1 s2 invert ['O', .04, 0.12, .4, 2, False], # Orange ['R', .9, .02, .4, 2, True], # Red ['G', .33, .45, .7, 2, False], # Green ['Y', .12, .24, .5, .8, False], # Yellow ['B', .55, .61, .6, 2, False], # Blue ['W', -1, 1, -1, .4, False] # White ] # Define the coordinates of the 9 squares on the Rubik's Cube squares = { 1: [(100, 100), (200, 200)], 2: [(225, 100), (325, 200)], 3: [(350, 100), (450, 200)], 4: [(100, 225), (200, 325)], 5: [(225, 225), (325, 325)], 6: [(350, 225), (450, 325)], 7: [(100, 350), (200, 450)], 8: [(225, 350), (325, 450)], 9: [(350, 350), (450, 450)] } # Initialize the Rubik's Cube faces rubiks_cube = { 'U': [''] * 9, 'F': [''] * 9, 'R': [''] * 9, 'B': [''] * 9, 'L': [''] * 9, 'D': [''] * 9 } # Initialize the current face index current_face_index = 0 faces = list(rubiks_cube.keys()) current_face = faces[current_face_index] # Callback function for key press event def key_press(event): global current_face_index, current_face if event == ord('q'): cv2.destroyAllWindows() elif event == ord(' '): current_face_index += 1 if current_face_index >= len(faces): current_face_index = 0 current_face = faces[current_face_index] # Capture video from webcam cap = cv2.VideoCapture(3) print('e') # Set the resolution of the video cap.set(3, 640) cap.set(4, 480) # Flag to track if all faces are scanned all_faces_scanned = False while True: # Read the current frame from the video capture ret, frame = cap.read() # Draw the Rubik's Cube squares overlay on the frame for square, coords in squares.items(): x1, y1 = coords[0] x2, y2 = coords[1] # Extract the region of interest (square) roi = frame[y1:y2, x1:x2] # Calculate the average color of the square avg_color = np.median(roi, axis=(0, 1)) # Compare the average color with the predefined colors hsv_color = colorsys.rgb_to_hsv(avg_color[2]/255, avg_color[1]/255, avg_color[0]/255) print(hsv_color[0]) closest_color = "aaa" for color in color_ranges: if not color[5]: if color[1] < hsv_color[0] < color[2] and color[3] < hsv_color[1] < color[4]: closest_color = color[0] break else: if (hsv_color[0] > color[1] or hsv_color[0] < color[2]) and color[3] < hsv_color[1] < color[4]: closest_color = color[0] break # color_diffs = [np.linalg.norm(avg_color - np.array(color)) for color in colors.values()] # closest_color = list(colors.keys())[color_diffs.index(min(color_diffs))] # Draw the square overlay cv2.rectangle(frame, coords[0], coords[1], (0, 255, 0), 2) cv2.putText(frame, closest_color, (int((x1 + x2) / 2 - 10), int((y1 + y2) / 2 + 10)), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) cv2.putText(frame, "(" + str(round(hsv_color[0] * 1000)) + ", " + str(round(hsv_color[1] * 100)) + ")", (int((x1 + x2) / 2 - 10), int((y1 + y2) / 2 + 40)), cv2.FONT_HERSHEY_SIMPLEX, .5, (0, 255, 0), 1) # Store the color for the corresponding square on the current face rubiks_cube[current_face][square - 1] = closest_color # Display the current face on the frame cv2.putText(frame, 'Scanning Face: ' + current_face, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2) # Show the frame cv2.imshow('Rubik\'s Cube Scanner', frame) # Wait for key press event key = cv2.waitKey(1) & 0xFF # Process key press event if key != 255: key_press(key) # Check if 'q' key is pressed to quit if key == ord('q'): break # Check if all faces are scanned if all(rubiks_cube[face] != [''] * 9 for face in rubiks_cube): all_faces_scanned = True # Break the loop if all faces are scanned and current face is 'U' if all_faces_scanned and current_face == 'U': break # Release the video capture and close windows cap.release() cv2.destroyAllWindows() # Combine the face colors to form the cube state cube_state = [rubiks_cube['U'], rubiks_cube['R'], rubiks_cube['F'], rubiks_cube['D'], rubiks_cube['L'], rubiks_cube['B']] # Map the color changes color_mapping = { rubiks_cube['U'][4]: 'U', rubiks_cube['L'][4]: 'L', rubiks_cube['F'][4]: 'F', rubiks_cube['R'][4]: 'R', rubiks_cube['B'][4]: 'B', rubiks_cube['D'][4]: 'D' } # Convert the cube state to a single line of 54 letters without spaces state_line = ''.join([color_mapping[color] for face in cube_state for color in face]) # Print the cube state print(state_line) # Define the initial state of the Rubik's Cube using the colors/pieces initial_state = state_line # Solve the cube using the kociemba package solution = kociemba.solve(initial_state) # solution = "R2 D2 F2 D2 B3 R2 B1 D3 R2 F1 L3 B2 F3 D3 L1 F3 R3 F2 D3 (19f)" # Reformat the string into a list final_solution = [] i = 0 while True: # woo if statement spam if solution[i] == "1": final_solution[-1] += "n" i += 2 elif solution[i] == "3": final_solution[-1] += "p" i += 2 elif solution[i] == "2": final_solution[-1] += "n" final_solution.append(final_solution[-1]) i += 2 elif solution[i] == "(": break else: final_solution.append(solution[i]) i += 1 # check for edge case if final move was a normal move if len(final_solution[-1]) == 1: final_solution[-1] += "n" # Print the original solution and the final solution print("Original Solution:", solution) print("Modified Solution: ", final_solution)