def _scanner_worker(task_queue, overlay_queue, result_queue, options): """ Function used as the main loop of a worker process. Scan images for barcodes, combining partial scans until a full puck is reached. Keep the record of the last scan which was at least partially successful (aligned geometry and some barcodes scanned). For each new frame, we can attempt to merge the results with this previous plates so that we don't have to re-read any of the previously captured barcodes (because this is a relatively expensive operation). """ last_plate_time = time.time() SlotScanner.DEBUG = options.slot_images.value() SlotScanner.DEBUG_DIR = options.slot_image_directory.value() plate_type = options.plate_type.value() barcode_size = options.barcode_size.value() if plate_type == "None": scanner = OpenScanner(barcode_size) else: scanner = GeometryScanner(plate_type, barcode_size) while True: # Get next image from queue (terminate if a queue contains a 'None' sentinel) frame = task_queue.get(True) if frame is None: break # Make grayscale version of image image = Image(frame) gray_image = image.to_grayscale() # If we have an existing partial plate, merge the new plate with it and only try to read the # barcodes which haven't already been read. This significantly increases efficiency because # barcode read is expensive. scan_result = scanner.scan_next_frame(gray_image) if options.console_frame.value(): scan_result.print_summary() if scan_result.success(): # Record the time so we can see how long its been since we last saw a plate last_plate_time = time.time() plate = scan_result.plate() if scan_result.already_scanned(): overlay_queue.put(TextOverlay(SCANNED_TAG, Color.Green())) elif scan_result.any_valid_barcodes(): overlay_queue.put(PlateOverlay(plate, options)) _plate_beep(plate, options) if scan_result.any_new_barcodes(): result_queue.put((plate, image)) else: time_since_plate = time.time() - last_plate_time if time_since_plate > NO_PUCK_TIME: overlay_queue.put(TextOverlay(scan_result.error(), Color.Red()))
def _process_frame(self, frame, config, overlay_queue, result_queue, message_queue): image = Image(frame) gray_image = image.to_grayscale() # If we have an existing partial plate, merge the new plate with it and only try to read the # barcodes which haven't already been read. This significantly increases efficiency because # barcode read is expensive. scan_result = self._scanner.scan_next_frame(gray_image) if config.console_frame.value(): scan_result.print_summary() if scan_result.success(): # Record the time so we can see how long its been since we last saw a puck self._last_puck_time = time.time() plate = scan_result.plate() if scan_result.any_valid_barcodes(): overlay_queue.put(PlateOverlay(plate, config)) self._plate_beep(plate, config.scan_beep.value()) if scan_result.any_new_barcodes(): result_queue.put((plate, image)) elif scan_result.any_valid_barcodes(): # We have read valid barcodes but they are not new, so the scanner didn't even output a plate self._last_puck_time = time.time() message_queue.put(NoNewBarcodeMessage()) elif scan_result.error() is not None and ( time.time() - self._last_puck_time > NO_PUCK_TIME): message_queue.put(ScanErrorMessage(scan_result.error()))
class Frame: def __init__(self, original_frame): self._frame = original_frame self._image = Image(self._frame) def get_copy(self): return self._frame.copy() def get_frame(self): return self._frame def frame_to_image(self): return self._image def get_image(self): return self._image def convert_to_gray(self): return self._image.to_grayscale()