def test_1d_column(self): r = RingBuffer(5, dtype=(np.int, 1)) r.append(1) r.append(2) r.appendleft(3) self.assertEqual(np.shape(r), (3, 1)) np.testing.assert_equal(r, np.array([[3], [1], [2]]))
def test_degenerate(self): r = RingBuffer(0) np.testing.assert_equal(r, np.array([])) # this does not error with deque(maxlen=0), so should not error here try: r.append(0) r.appendleft(0) except IndexError: self.fail()
def test_appendleft(self): r = RingBuffer(5) r.appendleft(1) np.testing.assert_equal(r, np.array([1])) self.assertEqual(len(r), 1) r.appendleft(2) np.testing.assert_equal(r, np.array([2, 1])) self.assertEqual(len(r), 2) r.appendleft(3) r.appendleft(4) r.appendleft(5) np.testing.assert_equal(r, np.array([5, 4, 3, 2, 1])) self.assertEqual(len(r), 5) r.appendleft(6) np.testing.assert_equal(r, np.array([6, 5, 4, 3, 2])) self.assertEqual(len(r), 5)
def test_2d(self): r = RingBuffer(5, dtype=(np.float, 2)) r.append([1, 2]) np.testing.assert_equal(r, np.array([[1, 2]])) self.assertEqual(len(r), 1) self.assertEqual(np.shape(r), (1, 2)) r.append([3, 4]) np.testing.assert_equal(r, np.array([[1, 2], [3, 4]])) self.assertEqual(len(r), 2) self.assertEqual(np.shape(r), (2, 2)) r.appendleft([5, 6]) np.testing.assert_equal(r, np.array([[5, 6], [1, 2], [3, 4]])) self.assertEqual(len(r), 3) self.assertEqual(np.shape(r), (3, 2)) np.testing.assert_equal(r[0], [5, 6]) np.testing.assert_equal(r[0, :], [5, 6]) np.testing.assert_equal(r[:, 0], [5, 1, 3])
def test_pops(self): r = RingBuffer(3) r.append(1) r.appendleft(2) r.append(3) np.testing.assert_equal(r, np.array([2, 1, 3])) self.assertEqual(r.pop(), 3) np.testing.assert_equal(r, np.array([2, 1])) self.assertEqual(r.popleft(), 2) np.testing.assert_equal(r, np.array([1])) # test empty pops empty = RingBuffer(1) with self.assertRaisesRegex(IndexError, "pop from an empty RingBuffer"): empty.pop() with self.assertRaisesRegex(IndexError, "pop from an empty RingBuffer"): empty.popleft()
def test_no_overwrite(self): r = RingBuffer(3, allow_overwrite=False) r.append(1) r.append(2) r.appendleft(3) with self.assertRaisesRegex(IndexError, 'overwrite'): r.appendleft(4) with self.assertRaisesRegex(IndexError, 'overwrite'): r.extendleft([4]) r.extendleft([]) np.testing.assert_equal(r, np.array([3, 1, 2])) with self.assertRaisesRegex(IndexError, 'overwrite'): r.append(4) with self.assertRaisesRegex(IndexError, 'overwrite'): r.extend([4]) r.extend([]) # works fine if we pop the surplus r.pop() r.append(4) np.testing.assert_equal(r, np.array([3, 1, 4]))
class Case: def __init__(self): # case_position is, for example, (8,8) for the case at the bottom right # physical_position is the pixel at the center of the case, so we know where to write self.image = None self.number = 0 # NOTE: Edit capacity for bigger buffer? # With a bigger self.maxtimer we need a smaller buffer self.prev_guesses = RingBuffer(capacity=5, dtype=(float, (10))) self.fontsize = 0 self.case_position = (0, 0) self.physical_position = (0, 0) self.n = 0 # Guesses the number every self.maxtimer frames (10?), to not overuse resources self.maxtimer = 10 self.timer = self.maxtimer - 1 def update(self, image, case_position, physical_position): self.image = image self.case_position = case_position top, right, bottom, left = physical_position average_dimension = (bottom - top + right - left) / 2 # NOTE edit this for better fontsize, positioning of the number self.fontsize = average_dimension / 40 self.n = average_dimension / 4 # NOTE edit this for better positioning of the number self.physical_position = ( physical_position[3] + 1 + int(self.fontsize * self.n), physical_position[2] - int(self.fontsize * self.n), ) # For testing, simply saves the image of its number into a file def print_image(self): if self.image is not None: cv2.imwrite( f"number-{self.case_position[0]}-{self.case_position[1]}.jpg", self.image, ) def guess_number(self, kind=2, confidence_threshold=0): """ Uses neural networks to guess the number in the image. kind=1 is more primitive, just guesses the image (less reliable) kind=2 consumes more memory and CPU but is more reliable (averages out a bunch of guesses) """ if kind == 1: if self.image is None: number = 0 else: guy = NeuralNetwork.instance() prediction = guy.guess(self.image) number = np.argmax(prediction, axis=0) self.number = number if kind == 2: # Saves a bunch of guesses (see Case.__init__ for the number) # Guesses every self.maxtimer frames self.timer += 1 if self.timer >= self.maxtimer: self.timer = 0 if self.image is None: self.prev_guesses.appendleft( np.array([1, 0, 0, 0, 0, 0, 0, 0, 0, 0])) else: guy = NeuralNetwork.instance() prediction = guy.guess(self.image) self.prev_guesses.appendleft(np.array(prediction)) m = np.mean(self.prev_guesses, axis=0) number = np.argmax(m, axis=0) if m[number] > confidence_threshold: self.number = number return self.number # For testing, ignore def testwrite(self, sudoku_image): font = cv2.FONT_HERSHEY_DUPLEX if self.image is not None: cv2.putText( sudoku_image, str(self.case_position[0]), self.physical_position, font, self.fontsize, (0, 0, 0), 1, cv2.LINE_AA, ) # For testing, ignore def write_number(self, sudoku_image): font = cv2.FONT_HERSHEY_DUPLEX number = self.number if number != 0: cv2.putText( sudoku_image, str(number), self.physical_position, font, self.fontsize, (0, 0, 0), 1, cv2.LINE_AA, ) def write(self, sudoku_image, text): "Writes the given number into the position of the case" # NOTE change font, colour if needed font = cv2.FONT_HERSHEY_DUPLEX cv2.putText( sudoku_image, text, tuple(self.physical_position), font, self.fontsize, (130, 60, 0), 1, cv2.LINE_AA, )
class Grid: def __init__(self): # physical_position = pixel pos of center in grid , pos to to write self.accuracy = 0 self.image = None self.number = 0 self.prev_guesses = RingBuffer(capacity=5, dtype=(float, (10))) self.fontsize = 0 self.grid_position = (0, 0) self.grid_physical_position = (0, 0) self.n = 0 # Guesses the number every self.maxtimer frames (10), # to reduce noise and not overuse resources self.maxtimer = 10 self.timer = self.maxtimer - 1 def update(self, image, grid_position, physical_position): self.image = image self.grid_position = grid_position top, right, bottom, left = physical_position average_dimension = (bottom - top + right - left) / 2 # NOTE edit this for better fontsize, positioning of the number self.fontsize = average_dimension / 40 self.n = average_dimension / 4 # NOTE edit this for better positioning of the number self.physical_position = (physical_position[3] + 1 + int(self.fontsize * self.n), physical_position[2] - int(self.fontsize * self.n)) def guess_number(self, confidence_threshold=0): # Saves a buffer of guesses # Guesses every self.maxtimer frames( i.e predicts once in 10 frames) self.timer += 1 if self.timer >= self.maxtimer: self.timer = 0 if self.image is None: self.prev_guesses.appendleft( np.array([1, 0, 0, 0, 0, 0, 0, 0, 0, 0])) else: neuron = NeuralModel.instance() prediction, number, accuracy = neuron.guess(self.image) self.accuracy = accuracy self.prev_guesses.appendleft(np.array(prediction)) m = np.mean(self.prev_guesses, axis=0) number = np.argmax(m, axis=0) self.number = number if m[number] > confidence_threshold: self.number = number return self.number def write(self, sudoku_image, text): 'Writes the given number into the position of the grid obtained ' font = cv2.FONT_HERSHEY_DUPLEX cv2.putText(sudoku_image, text, tuple(self.physical_position), font, self.fontsize, (220, 90, 20), 1, cv2.LINE_AA) #130,60,0 #220, 108, 50
print(np.zeros((8, 8))) print(random.randint(0, 7)) for i in range(8): print(i) print(np.zeros((8, 8))) print(f'{6:010b}') q = 10 n = 5 print(bin(n)[2:].zfill(q)) print(10**2) print(np.random.randint(-100, 100, 10)) print(np.zeros(10)) r = RingBuffer(capacity=4, dtype=np.bool) r.append(True) r.appendleft(False) print(r) # array([False, True]) print( statistics.mean([ 368.949361876861, 350.3572455395853, 341.16454304194644, 375.16492047621455, 345.379276797754, 342.7643689536626, 346.27615368543616, 382.9399145537665, 355.31408783462985, 364.50904311719535, 343.7794332221605, 336.9650782132827, 359.42725319652754, 355.00409159492057, 359.9256729821614, 380.6843264381487, 353.6034868388485, 351.7706260834341, 346.0974349862848, 361.11585113450343, 363.2379185512581, 374.2628855784896, 344.74880119159013, 357.5722106932264, 361.19752332868353, 349.962097373042, 368.63530792394903, 354.5639054967499, 348.51387037737766, 345.1013007758508, 359.0349724680091
class Block: def __init__(self): self.img = None self.number = 0 self.prev_guesses = RingBuffer(capacity=5, dtype=(float, (10))) self.fontsize = 0 self.block_pos = (0, 0) self.physical_pos = (0, 0) self.n = 0 # Guesses the number every self.maxtimer frames (10), to not overuse resources self.maxtimer = 10 self.timer = self.maxtimer - 1 def update(self, img, block_pos, physical_pos): self.img = img self.block_pos = block_pos top, right, bot, left = physical_pos average_dimension = (bot - top + right - left) / 2 # NOTE edit this for better fontsize, positioning of the number self.fontsize = average_dimension / 40 self.n = average_dimension / 4 # NOTE edit this for better positioning of the number self.physical_pos = (physical_pos[3] + 1 + int(self.fontsize * self.n), physical_pos[2] - int(self.fontsize * self.n)) def guess_number(self, kind=2, confidence_threshold=0): ''' Uses neural networks to guess the number in the image. kind=1 is more primitive, just guesses the image (less reliable) kind=2 consumes more memory and CPU but is more reliable (averages out a bunch of guesses) ''' if kind == 1: if self.img is None: number = 0 else: guy = NeuralNetwork.instance() prediction = guy.guess(self.img) number = np.argmax(prediction, axis=0) self.number = number if kind == 2: # Guesses every self.maxtimer frames self.timer += 1 if self.timer >= self.maxtimer: self.timer = 0 if self.img is None: self.prev_guesses.appendleft( np.array([1, 0, 0, 0, 0, 0, 0, 0, 0, 0])) else: guy = NeuralNetwork.instance() prediction = guy.guess(self.img) self.prev_guesses.appendleft(np.array(prediction)) m = np.mean(self.prev_guesses, axis=0) number = np.argmax(m, axis=0) if m[number] > confidence_threshold: self.number = number return self.number def write(self, sudoku_image, text): font = cv2.FONT_HERSHEY_DUPLEX cv2.putText(sudoku_image, text, tuple(self.physical_pos), font, self.fontsize, (0, 0, 255), 1, cv2.LINE_AA)