├── .DS_Store
├── __pycache__
├── video.cpython-37.pyc
├── combiner.cpython-37.pyc
├── normalizer.cpython-37.pyc
└── colordetection.cpython-37.pyc
├── images
├── Screenshot 2021-08-27 at 8.26.33 AM.png
├── Screenshot 2021-08-27 at 8.34.35 AM.png
├── Screenshot 2021-08-27 at 8.47.24 AM.png
├── Screenshot 2021-08-27 at 8.53.58 AM.png
├── Screenshot 2021-08-27 at 8.55.30 AM.png
├── Screenshot 2021-08-27 at 9.19.43 AM.png
└── Screenshot 2021-08-27 at 9.26.25 AM.png
├── testInput.txt
├── combiner.py
├── normalizer.py
├── README.md
├── solve-manual.json
├── solver.py
├── colordetection.py
└── video.py
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshaynarisetti/RubiksCube_Solver/HEAD/.DS_Store
--------------------------------------------------------------------------------
/__pycache__/video.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshaynarisetti/RubiksCube_Solver/HEAD/__pycache__/video.cpython-37.pyc
--------------------------------------------------------------------------------
/__pycache__/combiner.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshaynarisetti/RubiksCube_Solver/HEAD/__pycache__/combiner.cpython-37.pyc
--------------------------------------------------------------------------------
/__pycache__/normalizer.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshaynarisetti/RubiksCube_Solver/HEAD/__pycache__/normalizer.cpython-37.pyc
--------------------------------------------------------------------------------
/__pycache__/colordetection.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshaynarisetti/RubiksCube_Solver/HEAD/__pycache__/colordetection.cpython-37.pyc
--------------------------------------------------------------------------------
/images/Screenshot 2021-08-27 at 8.26.33 AM.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshaynarisetti/RubiksCube_Solver/HEAD/images/Screenshot 2021-08-27 at 8.26.33 AM.png
--------------------------------------------------------------------------------
/images/Screenshot 2021-08-27 at 8.34.35 AM.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshaynarisetti/RubiksCube_Solver/HEAD/images/Screenshot 2021-08-27 at 8.34.35 AM.png
--------------------------------------------------------------------------------
/images/Screenshot 2021-08-27 at 8.47.24 AM.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshaynarisetti/RubiksCube_Solver/HEAD/images/Screenshot 2021-08-27 at 8.47.24 AM.png
--------------------------------------------------------------------------------
/images/Screenshot 2021-08-27 at 8.53.58 AM.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshaynarisetti/RubiksCube_Solver/HEAD/images/Screenshot 2021-08-27 at 8.53.58 AM.png
--------------------------------------------------------------------------------
/images/Screenshot 2021-08-27 at 8.55.30 AM.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshaynarisetti/RubiksCube_Solver/HEAD/images/Screenshot 2021-08-27 at 8.55.30 AM.png
--------------------------------------------------------------------------------
/images/Screenshot 2021-08-27 at 9.19.43 AM.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshaynarisetti/RubiksCube_Solver/HEAD/images/Screenshot 2021-08-27 at 9.19.43 AM.png
--------------------------------------------------------------------------------
/images/Screenshot 2021-08-27 at 9.26.25 AM.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/akshaynarisetti/RubiksCube_Solver/HEAD/images/Screenshot 2021-08-27 at 9.26.25 AM.png
--------------------------------------------------------------------------------
/testInput.txt:
--------------------------------------------------------------------------------
1 | FLR FUB RLB
2 | RRF RRR FRD
3 | BDU BFU UUL
4 | RFD FDF LLL
5 | LLD BLU UDF
6 | DUU DBD BBB
7 |
8 |
9 | FRF BFB LDL
10 | LFD RRL BUD
11 | UBR LLD UDF
12 | FDR UUU DFD
13 | UFU RDR BFL
14 | BLR UBB BLR
--------------------------------------------------------------------------------
/combiner.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 |
4 | class Combine:
5 |
6 | def sides(self, sides):
7 | """Join all the sides together into one single string.
8 |
9 | :param sides: dictionary with all the sides
10 | :returns: string
11 | """
12 | combined = ''
13 | for face in 'URFDLB':
14 | combined += ''.join(sides[face])
15 | return combined
16 |
17 | combine = Combine()
18 |
--------------------------------------------------------------------------------
/normalizer.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 |
4 | from sys import exit as Die
5 | try:
6 | import sys
7 | import json
8 | except ImportError as err:
9 | Die(err)
10 |
11 |
12 | class Normalizer:
13 |
14 | def algorithm(self, alg, language):
15 | """ Noramlize an algorithm from the
16 | json-written manual.
17 |
18 | :param alg: The algorithm itself
19 | :returns: list
20 | """
21 | with open('solve-manual.json') as f:
22 | manual = json.load(f)
23 |
24 | solution = []
25 | for notation in alg.split(' '):
26 | solution.append(manual[language][notation])
27 | return solution
28 |
29 | normalize = Normalizer()
30 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Computer Vision Rubik's Cube Solver
2 |
3 |
4 |
5 |
6 | This is a Computer Vision based Rubik's Cube Solver which will solve the Rubik's cube in 20 Moves
7 |
8 |
9 | # Usage
10 |
11 | `python3 solver.py`
12 |
13 |
14 | This will open a live feed and you can scan the faces of the cube.
15 |
16 |
17 | You may change the calibration values with the live Calibration Feature!
18 |
19 | ### Press 'C' to Start Live calibration
20 |
21 |
22 | Calibrate all 6 Faces using the Opencv Tackers provided
23 |
24 | #### An Example of a perfect scan looks like this
25 |
26 |
27 |
28 |
29 | Once the scanning is done press `esc` to get the solution.
30 |
31 | #### An Example Solution Looks like this, Follow the instructions to solve the cube
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/solve-manual.json:
--------------------------------------------------------------------------------
1 | {
2 | "en": {
3 | "R" : "Turn the right side a quarter turn away from you." ,
4 | "R'" : "Turn the right side a quarter turn towards you." ,
5 | "R2" : "Turn the right side 180 degrees." ,
6 | "L" : "Turn the left side a quarter turn towards you." ,
7 | "L'" : "Turn the left side a quarter turn away from you." ,
8 | "L2" : "Turn the left side 180 degrees." ,
9 | "U" : "Turn the top layer a quarter turn to the left." ,
10 | "U'" : "Turn the top layer a quarter turn to the right." ,
11 | "U2" : "Turn the top layer 180 degrees.",
12 | "D" : "Turn the bottom layer a quarter turn to the right." ,
13 | "D'" : "Turn the bottom layer a quarter turn to the left." ,
14 | "D2" : "Turn the bottom layer 180 degrees." ,
15 | "B" : "Turn the back side a quarter turn to the left." ,
16 | "B'" : "Turn the back side a quarter turn to the right." ,
17 | "B2" : "Turn the back side 180 degrees." ,
18 | "F" : "Turn the front side a quarter turn to the right." ,
19 | "F'" : "Turn the front side a quarter turn to the left." ,
20 | "F2" : "Turn the front side 180 degrees."
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/solver.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 |
4 | from sys import exit as Die
5 | try:
6 | import sys
7 | import kociemba
8 | import argparse
9 | import video as webcam
10 |
11 | from combiner import combine
12 | from normalizer import normalize
13 | except ImportError as err:
14 | Die(err)
15 |
16 |
17 | class Solver:
18 |
19 | def __init__(self, normalize, language):
20 | self.humanize = normalize
21 | self.language = (language[0]) if isinstance(language, list) else language
22 |
23 | def run(self):
24 | state = webcam.scan()
25 | if not state:
26 | print('\033[0;33m[Solver SCAN ERROR] Ops, you did not scan in all 6 sides.')
27 | print('Please try again.\033[0m')
28 | Die(1)
29 |
30 | unsolvedState = combine.sides(state)
31 | try:
32 | algorithm = kociemba.solve(unsolvedState)
33 | length = len(algorithm.split(' '))
34 | except Exception as err:
35 | print('\033[0;33m[Solver SOLVE ERROR] Ops, you did not scan in all 6 sides correctly.')
36 | print('Please try again.\033[0m')
37 | Die(1)
38 |
39 | print('-- SOLUTION --')
40 | print('Starting position:\n front: green\n top: white\n')
41 | print(algorithm, '({0} moves)'.format(length), '\n')
42 |
43 | # if self.humanize:
44 | manual = normalize.algorithm(algorithm, self.language)
45 | for index, text in enumerate(manual):
46 | print('{}. {}'.format(index+1, text))
47 | Die(0)
48 |
49 | if __name__ == '__main__':
50 | # define argument parser.
51 | parser = argparse.ArgumentParser()
52 | parser.add_argument('-n', '--normalize', default=False, action='store_true',
53 | help='Shows the solution normalized. For example "R2" would be: \
54 | "Turn the right side 180 degrees".')
55 | parser.add_argument('-l', '--language', nargs=1, default='en',
56 | help='You can pass in a single \
57 | argument which will be the language for the normalization output. \
58 | Default is "en".')
59 | args = parser.parse_args()
60 |
61 | # run Solver with its arguments.
62 | Solver(
63 | args.normalize,
64 | args.language
65 | ).run()
--------------------------------------------------------------------------------
/colordetection.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 |
4 | from sys import exit as Die
5 | try:
6 | import sys
7 | import numpy as np
8 | except ImportError as err:
9 | Die(err)
10 |
11 | class ColorDetection:
12 |
13 | def get_color_name(self, hsv, cal):
14 | """ Get the name of the color based on the hue.
15 |
16 | :returns: string
17 | """
18 | (h,s,v) = hsv
19 | for color in cal:
20 | if color == 'red' or color == 'orange':
21 | if (h < cal[color][1][0] or h > cal[color][0][0]) and s in range(cal[color][1][1],cal[color][0][1]) and v in range(cal[color][1][2],cal[color][0][2]):
22 | return color
23 | elif h in range(cal[color][1][0],cal[color][0][0]) and s in range(cal[color][1][1],cal[color][0][1]) and v in range(cal[color][1][2],cal[color][0][2]):
24 | return color
25 |
26 |
27 | return 'white'
28 |
29 | def name_to_rgb(self, name):
30 | """
31 | Get the main RGB color for a name.
32 |
33 | :param name: the color name that is requested
34 | :returns: tuple
35 | """
36 | color = {
37 | 'red' : (0,0,255),
38 | 'orange' : (0,165,255),
39 | 'blue' : (255,0,0),
40 | 'green' : (0,255,0),
41 | 'white' : (255,255,255),
42 | 'yellow' : (0,255,255)
43 | }
44 | return color[name]
45 |
46 | def average_hsv(self, roi):
47 | """ Average the HSV colors in a region of interest.
48 |
49 | :param roi: the image array
50 | :returns: tuple
51 | """
52 | h = 0
53 | s = 0
54 | v = 0
55 | num = 0
56 | for y in range(len(roi)):
57 | if y % 10 == 0:
58 | for x in range(len(roi[y])):
59 | if x % 10 == 0:
60 | chunk = roi[y][x]
61 | num += 1
62 |
63 | if chunk[0] != 0:
64 | h += chunk[0]
65 | s += chunk[1]
66 | v += chunk[2]
67 | h /= num
68 | s /= num
69 | v /= num
70 | return (int(h), int(s), int(v))
71 |
72 | def median_hsv(self, roi):
73 | """ Average the HSV colors in a region of interest.
74 |
75 | :param roi: the image array
76 | :returns: tuple
77 | """
78 | h = []
79 | s = []
80 | v = []
81 | num = 0
82 | for y in range(len(roi)):
83 | if y % 10 == 0:
84 | for x in range(len(roi[y])):
85 | if x % 10 == 0:
86 | chunk = roi[y][x]
87 | num += 1
88 | h.append(chunk[0])
89 | s.append(chunk[1])
90 | v.append(chunk[2])
91 |
92 | return (int(np.median(h)), int(np.median(s)), int(np.median(v)))
93 |
94 | ColorDetector = ColorDetection()
95 |
--------------------------------------------------------------------------------
/video.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 |
4 | ## Import the relevant files
5 | from sys import exit as Die
6 | try:
7 | import sys
8 | import cv2
9 | import numpy as np
10 | from colordetection import ColorDetector
11 | except ImportError as err:
12 | Die(err)
13 |
14 | #Variable Used For testing
15 | cameratesting = False
16 |
17 | '''
18 | Initialize the camera here
19 | '''
20 | #change cam_port if Video in Live feed is not being Displayed
21 | cam_port = 2
22 | #create a my camera object to read from
23 | cam = cv2.VideoCapture(cam_port)
24 |
25 |
26 |
27 | """
28 | We are going to want to draw some stickers. In the solution
29 | we have 3 sets of stickers. Each set has 9 stickers to represent
30 | each sticker on any given face of the rubik's cube.
31 |
32 | The 'stickers' set of stickers are physical markers used to help the
33 | user see where to place the cube for color scanning.
34 |
35 | The 'current_stickers' set show which colors are currently being detected
36 | for each position on the face.
37 |
38 | The 'preview_stickers' set shows the most recently recorded face.
39 | You can rescan a face if the preview does not match the actual colors
40 | on the face of the rubik's cube.
41 |
42 | These are the coordinates of each sticker for each set. Feel free to play
43 | with these values if you don't like the sticker placement.
44 |
45 |
46 | """
47 | detector_stickers = [[200, 120], [300, 120], [400, 120],
48 | [200, 220], [300, 220], [400, 220],
49 | [200, 320], [300, 320], [400, 320]]
50 |
51 | current_stickers = [[20, 20], [54, 20], [88, 20],
52 | [20, 54], [54, 54], [88, 54],
53 | [20, 88], [54, 88], [88, 88]]
54 |
55 | recorded_stickers = [[20, 130], [54, 130], [88, 130],
56 | [20, 164], [54, 164], [88, 164],
57 | [20, 198], [54, 198], [88, 198]]
58 |
59 | #Draws the 9 static stickers in the frame
60 | def draw_detector_stickers(frame):
61 | for (x,y) in (detector_stickers):
62 | cv2.rectangle(frame, (x,y), (x+50, y+50), (255,255,255), 1)
63 |
64 | #Draws the 9 detected stickers in the frame
65 | def draw_current_stickers(frame, state):
66 |
67 | for index,(x,y) in enumerate(current_stickers):
68 | cv2.rectangle(frame, (x,y), (x+32, y+32), ColorDetector.name_to_rgb(state[index]), -1)
69 |
70 | #Draws the 9 Recorded stickers in the frame
71 | def draw_recorded_stickers(frame, state):
72 |
73 |
74 | for index,(x,y) in enumerate(recorded_stickers):
75 | cv2.rectangle(frame, (x,y), (x+32, y+32), ColorDetector.name_to_rgb(state[index]), -1)
76 |
77 |
78 | def color_to_notation(color):
79 | """
80 | Helper function for converting colors to notation
81 | used by solver.
82 | """
83 | notation = {
84 | 'green' : 'F',
85 | 'white' : 'U',
86 | 'blue' : 'B',
87 | 'red' : 'R',
88 | 'orange' : 'L',
89 | 'yellow' : 'D'
90 | }
91 | return notation[color]
92 |
93 | def empty_callback(x):
94 | '''
95 | Empty function for callback when slider positions change. Need input x, this is the value
96 | the slider has changed to.
97 | '''
98 | pass
99 |
100 | def scan():
101 | """
102 | Opens up the webcam and scans the 9 regions in the center
103 | and show a preview.
104 |
105 | After hitting the space bar to confirm, the block below the
106 | current stickers shows the current state that you have.
107 | This is show every user can see what the computer took as input.
108 |
109 | :returns: dictionary
110 | """
111 |
112 | sides = {} # collection of scanned sides
113 | preview = ['white','white','white', # default starting preview sticker colors
114 | 'white','white','white',
115 | 'white','white','white']
116 | state = [0,0,0, # current sticker colors
117 | 0,0,0,
118 | 0,0,0]
119 |
120 | defaultcal = { # default color calibration
121 | 'white':[[179,67,255],[0,0,0]],
122 | 'green':[[72,255,218],[47,61,21]],
123 | 'red':[[179,255,240],[6,0,102]],
124 | 'orange':[[179,255,255],[17,147,207]],
125 | 'yellow':[[49,242,255],[18,61,211]],
126 | 'blue':[[127,255,212],[82,72,51]]
127 | }
128 |
129 | colorcal = {} # color calibration dictionary
130 | color = ['white', 'green', 'red', 'orange', 'yellow', 'blue'] # list of valid colors
131 |
132 | cv2.namedWindow('default',0)
133 | # create trackbars here
134 | cv2.createTrackbar('H Upper','default',defaultcal[color[len(colorcal)]][0][0], 179, empty_callback)
135 | cv2.createTrackbar('S Upper','default',defaultcal[color[len(colorcal)]][0][1], 255, empty_callback)
136 | cv2.createTrackbar('V Upper','default',defaultcal[color[len(colorcal)]][0][2], 255, empty_callback)
137 | cv2.createTrackbar('H Lower','default',defaultcal[color[len(colorcal)]][1][0], 179, empty_callback)
138 | cv2.createTrackbar('S Lower','default',defaultcal[color[len(colorcal)]][1][1], 255, empty_callback)
139 | cv2.createTrackbar('V Lower','default',defaultcal[color[len(colorcal)]][1][2], 255, empty_callback)
140 |
141 | # Remember that the range for S and V are not 0 to 179
142 |
143 |
144 | colorcal = defaultcal
145 |
146 | # Creates a window named 'my_window_name'
147 | cv2.createTrackbar('My track bar','my_window_name',125,255, empty_callback)
148 |
149 | while cameratesting:
150 | #--------------- Used for Testing ------------------------
151 | # Captures a frame of video from the camera object
152 | _,frame = cam.read()
153 | hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
154 |
155 | # create a mask
156 | # Bounds for HSV values we are interested in (Blue)
157 | lower_hsv = np.array([89,178,51]) #hmin,smin,vmin
158 | upper_hsv = np.array([118,255,194]) #hmax,smax,vmax
159 |
160 | mask = cv2.inRange(hsv, lower_hsv, upper_hsv)
161 | frame = cv2.bitwise_and(frame,frame, mask= mask)
162 |
163 | # Draw rectangle on the frame
164 | cv2.rectangle(frame, (200,200), (250, 250), (255,0,0), 2)
165 |
166 | # -1 borderwidth is a fill
167 | cv2.rectangle(frame, (300,200), (350, 250), (0,0,255), -1)
168 |
169 | # Note the construction of a rectangle
170 | # arg1 = frame to draw on
171 | # arg2 = x,y coordinates of the rectangle's top left corner
172 | # arg3 = x,y coordinates of the rectangle's bottom right corner
173 | # arg4 = r,g,b values
174 | # arg5 = borderwidth => width of the border or make a fill using -1
175 |
176 | # cv2.rectangle(frame, (xtop_left,ytop_left), (xbot_right,ybot_right), (r,g,b), borderwidth)
177 |
178 | # Displays the frame on the window we made
179 | value = cv2.getTrackbarPos('My track bar','my_window_name')
180 | print(value)
181 | cv2.imshow('my_window_name', frame)
182 |
183 | # Sets the amount of time to display a frame in milliseconds
184 | key = cv2.waitKey(10)
185 |
186 |
187 |
188 |
189 | while not cameratesting:
190 |
191 | _, frame = cam.read()
192 | hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
193 | key = cv2.waitKey(10)
194 |
195 | # init certain stickers.
196 | draw_detector_stickers(frame)
197 | draw_recorded_stickers(frame, preview)
198 |
199 | for index,(x,y) in enumerate(detector_stickers):
200 | roi = hsv[y:y+32, x:x+32] # extracts hsv values within sticker
201 | avg_hsv = ColorDetector.median_hsv(roi) # filters the hsv values into one hsv
202 | color_name = ColorDetector.get_color_name(avg_hsv,colorcal) # extracts the color based on hsv
203 | state[index] = color_name # stores the color
204 |
205 | # update when space bar is pressed.
206 | if key == 32:
207 | preview = list(state)
208 | draw_recorded_stickers(frame, state) # draw the saved colors on the preview
209 | face = color_to_notation(state[4]) # convert the color to notation of the middle sticker and label this as the face
210 | notation = [color_to_notation(color) for color in state] # convert all colors to notation
211 | sides[face] = notation # update the face in the sides dictionary
212 |
213 | # show the new stickers
214 | draw_current_stickers(frame, state) # draw live sampling of face colors
215 |
216 | # append amount of scanned sides
217 | text = 'scanned sides: {}/6'.format(len(sides))
218 | cv2.putText(frame, text, (20, 460), cv2.FONT_HERSHEY_TRIPLEX, 0.5, (255,255,0), 1, cv2.LINE_AA)
219 |
220 | # indicate the scanning instruction
221 | textInstruction = 'scan and rotate the cube with white on the top and green on the front (towards camera)'
222 | textInstruction2 = 'the color of center brick is used as the side identifier (since the center brick does not move)'
223 | textInstruction3 = 'you can scan as many times as you want'
224 | textInstruction4 = 'the program will overwrite the old scan when same side is detected, press esc key get the solution'
225 | cv2.putText(frame, textInstruction, (20, 600), cv2.FONT_HERSHEY_TRIPLEX, 0.5, (255,255,0), 1, cv2.LINE_AA)
226 | cv2.putText(frame, textInstruction2, (20, 620), cv2.FONT_HERSHEY_TRIPLEX, 0.5, (255,255,0), 1, cv2.LINE_AA)
227 | cv2.putText(frame, textInstruction3, (20, 640), cv2.FONT_HERSHEY_TRIPLEX, 0.5, (255,255,0), 1, cv2.LINE_AA)
228 | cv2.putText(frame, textInstruction4, (20, 660), cv2.FONT_HERSHEY_TRIPLEX, 0.5, (255,255,0), 1, cv2.LINE_AA)
229 |
230 | # quit on escape.
231 | if key == 27:
232 | break
233 |
234 | # show result
235 | cv2.imshow("default", frame)
236 |
237 | if key == 99:
238 | colorcal = {}
239 | while len(colorcal) < 6:
240 | _, frame = cam.read()
241 |
242 |
243 | hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
244 | key = cv2.waitKey(10) & 0xff
245 |
246 | # hue upper lower
247 | hu = cv2.getTrackbarPos('H Upper','default')
248 | hl = cv2.getTrackbarPos('H Lower','default')
249 | # saturation upper lower
250 | su = cv2.getTrackbarPos('S Upper','default')
251 | sl = cv2.getTrackbarPos('S Lower','default')
252 | # value upper lower
253 | vu = cv2.getTrackbarPos('V Upper','default')
254 | vl = cv2.getTrackbarPos('V Lower','default')
255 | print("H upper", hu)
256 | print("H Lower", hl)
257 | print("S upper", su)
258 | print("S Lower", sl)
259 | print("V upper", vu)
260 | print("V Lower", vl)
261 |
262 |
263 | if color[len(colorcal)] == 'red' or color[len(colorcal)] == 'orange':
264 | lower_hsv = np.array([0,sl,vl])
265 | upper_hsv = np.array([hl,su,vu])
266 | mask1 = cv2.inRange(hsv, lower_hsv, upper_hsv)
267 | lower_hsv = np.array([hu,sl,vl])
268 | upper_hsv = np.array([179,su,vu])
269 | mask2 = cv2.inRange(hsv, lower_hsv, upper_hsv)
270 | mask = cv2.bitwise_or(mask1, mask2)
271 | res = cv2.bitwise_and(frame,frame, mask= mask)
272 | lower_hsv = np.array([hl,sl,vl])
273 | upper_hsv = np.array([hu,su,vu])
274 | else:
275 | lower_hsv = np.array([hl,sl,vl])
276 | upper_hsv = np.array([hu,su,vu])
277 |
278 |
279 | mask = cv2.inRange(hsv, lower_hsv, upper_hsv)
280 | res = cv2.bitwise_and(frame,frame, mask = mask)
281 |
282 | if key == 32:
283 | defaultcal[color[len(colorcal)]] = [upper_hsv,lower_hsv]
284 | colorcal[color[len(colorcal)]] = [upper_hsv,lower_hsv]
285 |
286 | if(len(colorcal) < 6):
287 | cv2.setTrackbarPos('H Upper','default',defaultcal[color[len(colorcal)]][0][0])
288 | cv2.setTrackbarPos('S Upper','default',defaultcal[color[len(colorcal)]][0][1])
289 | cv2.setTrackbarPos('V Upper','default',defaultcal[color[len(colorcal)]][0][2])
290 | cv2.setTrackbarPos('H Lower','default',defaultcal[color[len(colorcal)]][1][0])
291 | cv2.setTrackbarPos('S Lower','default',defaultcal[color[len(colorcal)]][1][1])
292 | cv2.setTrackbarPos('V Lower','default',defaultcal[color[len(colorcal)]][1][2])
293 |
294 | if(len(colorcal) < 6):
295 | text = 'calibrating {}'.format(color[len(colorcal)])
296 | cv2.putText(res, text, (20, 460), cv2.FONT_HERSHEY_TRIPLEX, 0.5, (255,255,255), 1, cv2.LINE_AA)
297 |
298 | cv2.imshow("default", res)
299 | # quit on escape key.
300 | if key == 27:
301 | break
302 |
303 | cam.release()
304 | cv2.destroyAllWindows()
305 | return sides if len(sides) == 6 else False
306 |
307 |
--------------------------------------------------------------------------------