11from __future__ import division
22
33import multiprocessing
4- import time
54import queue
65
7- # TODO: tidy up
8- from dls_util .image import Image
9- from dls_util import Beeper
10- from dls_util .message import MessageType , Message
11- from dls_barcode .scan import GeometryScanner , SlotScanner , OpenScanner
12- from dls_barcode .datamatrix import DataMatrix
136from .capture_worker import CaptureWorker
7+ from .scanner_worker import ScannerWorker
148from .camera_position import CameraPosition
159from .stream_action import StreamAction
1610from .capture_command import CaptureCommand
17- from .plate_overlay import PlateOverlay
18-
19- Q_LIMIT = 1
20- SCANNED_TAG = "Scan Complete"
21- NO_PUCK_TIME = 2
22-
23- EXIT_KEY = 'q'
24-
25- # Maximum frame rate to sample at (rate will be further limited by speed at which frames can be processed)
26- MAX_SAMPLE_RATE = 10.0
27- INTERVAL = 1.0 / MAX_SAMPLE_RATE
2811
2912
3013class CameraScanner :
@@ -58,7 +41,7 @@ def __init__(self, result_queue, view_queue, message_queue, config):
5841 self ._camera_configs )
5942
6043 # The capture process is always running: we initialise the cameras only once because it's time consuming
61- self ._capture_process = multiprocessing .Process (target = _capture_worker , args = capture_args )
44+ self ._capture_process = multiprocessing .Process (target = CameraScanner . _capture_worker , args = capture_args )
6245 self ._capture_process .start ()
6346
6447 self ._scanner_process = None
@@ -68,7 +51,7 @@ def start_scan(self, cam_position):
6851 """
6952 print ("\n MAIN: start triggered" )
7053 scanner_args = (self ._task_q , self ._overlay_q , self ._result_q , self ._message_q , self ._scanner_kill_q , self ._config , cam_position )
71- self ._scanner_process = multiprocessing .Process (target = _scanner_worker , args = scanner_args )
54+ self ._scanner_process = multiprocessing .Process (target = CameraScanner . _scanner_worker , args = scanner_args )
7255
7356 self ._capture_command_q .put (CaptureCommand (StreamAction .START , cam_position ))
7457 self ._scanner_process .start ()
@@ -134,93 +117,14 @@ def _process_cleanup(self, process, queues):
134117
135118 print ("MAIN: sub-process terminated!" )
136119
120+ @staticmethod
121+ def _capture_worker (task_queue , view_queue , overlay_queue , command_queue , kill_queue , camera_configs ):
122+ """ Function used as the main loop of a worker process.
123+ """
124+ CaptureWorker (camera_configs ).run (task_queue , view_queue , overlay_queue , command_queue , kill_queue )
137125
138- def _capture_worker (task_queue , view_queue , overlay_queue , command_queue , kill_queue , camera_configs ):
139- """ Function used as the main loop of a worker process.
140- """
141- worker = CaptureWorker (camera_configs )
142- worker .run (task_queue , view_queue , overlay_queue , command_queue , kill_queue )
143-
144-
145- def _scanner_worker (task_queue , overlay_queue , result_queue , message_queue , kill_queue , config , cam_position ):
146- """ Function used as the main loop of a worker process. Scan images for barcodes,
147- combining partial scans until a full puck is reached.
148-
149- Keep the record of the last scan which was at least partially successful (aligned geometry
150- and some barcodes scanned). For each new frame, we can attempt to merge the results with
151- this previous plates so that we don't have to re-read any of the previously captured barcodes
152- (because this is a relatively expensive operation).
153- """
154- print ("SCANNER start" )
155- last_plate_time = time .time ()
156-
157- SlotScanner .DEBUG = config .slot_images .value ()
158- SlotScanner .DEBUG_DIR = config .slot_image_directory .value ()
159-
160- if cam_position == CameraPosition .SIDE :
161- plate_type = "None"
162- barcode_sizes = DataMatrix .DEFAULT_SIDE_SIZES
163- else :
164- plate_type = config .plate_type .value ()
165- barcode_sizes = [config .top_barcode_size .value ()]
166-
167- if plate_type == "None" :
168- scanner = OpenScanner (barcode_sizes )
169- else :
170- scanner = GeometryScanner (plate_type , barcode_sizes )
171-
172- display = True
173- while kill_queue .empty ():
174- if display :
175- print ("--- scanner inside loop" )
176- display = False
177- if task_queue .empty ():
178- continue
179-
180- frame = task_queue .get (True )
181-
182- # Make grayscale version of image
183- image = Image (frame )
184- gray_image = image .to_grayscale ()
185-
186- # If we have an existing partial plate, merge the new plate with it and only try to read the
187- # barcodes which haven't already been read. This significantly increases efficiency because
188- # barcode read is expensive.
189- scan_result = scanner .scan_next_frame (gray_image )
190-
191- if config .console_frame .value ():
192- scan_result .print_summary ()
193-
194- if scan_result .success ():
195- # Record the time so we can see how long its been since we last saw a plate
196- last_plate_time = time .time ()
197-
198- plate = scan_result .plate ()
199-
200- if scan_result .already_scanned ():
201- pass
202- # message_queue.put(Message(MessageType.INFO, SCANNED_TAG))
203- # overlay_queue.put(TextOverlay(SCANNED_TAG, Color.Green()))
204- elif scan_result .any_valid_barcodes ():
205- overlay_queue .put (PlateOverlay (plate , config ))
206- _plate_beep (plate , config .scan_beep .value ())
207-
208- if scan_result .any_new_barcodes ():
209- result_queue .put ((plate , image ))
210- elif scan_result .error () is not None :
211- time_since_plate = time .time () - last_plate_time
212- if time_since_plate > NO_PUCK_TIME :
213- message_queue .put (Message (MessageType .WARNING , scan_result .error ()))
214- # overlay_queue.put(TextOverlay(scan_result.error(), Color.Red()))
215-
216- print ("SCANNER stop & kill" )
217-
218-
219- def _plate_beep (plate , do_beep ):
220- if not do_beep :
221- return
222-
223- empty_fraction = (plate .num_slots - plate .num_valid_barcodes ()) / plate .num_slots
224- frequency = int (10000 * empty_fraction + 37 )
225- duration = 200
226- Beeper .beep (frequency , duration )
126+ @staticmethod
127+ def _scanner_worker (task_queue , overlay_queue , result_queue , message_queue , kill_queue , config , cam_position ):
128+ """ Function used as the main loop of a worker process.
129+ """
130+ ScannerWorker ().run (task_queue , overlay_queue , result_queue , message_queue , kill_queue , config , cam_position )
0 commit comments