def test(self): resetManualDb() rest = ImagingInterface() # table should be empty self.assertIsNone(rest.getNextCroppedImage()) # push image into the table so that we can get it ret = rest.getNextRawImage() self.assertIsNotNone(ret) resp = rest.postCroppedImage(ret[1], ret[0], [22, 22], [236, 236]) cropId = int(resp.headers['X-Crop-Id']) # post a second image so we can confirm it gets the first posted one first resp = rest.postCroppedImage(ret[1], ret[0], [33, 33], [789, 789]) cropId2 = int(resp.headers['X-Crop-Id']) self.assertNotEqual(cropId, cropId2) result = rest.getNextCroppedImage() self.assertIsNotNone(result) self.assertIsNotNone(result[0]) self.assertEqual(result[1], cropId) result = rest.getNextCroppedImage() self.assertIsNotNone(result) self.assertIsNotNone(result[0]) self.assertEqual(result[1], cropId2)
def test(self): resetDb() rest = ImagingInterface() ret = rest.getNextRawImage() self.assertIsNotNone(ret) # get stuff into the cropped and classification table resp = rest.postCroppedImage(ret[1], ret[0], [22, 22], [236, 236]) self.assertIsNotNone(resp) self.assertEqual(resp.status_code, 200) # assert successful post to cropped _, cropId, _ = rest.getNextCroppedImage( ) # get the cropId as they would in the gui classToPost = Classification(cropId, 'standard', 'NE', 'circle', 'white', 'T', 'yellow') resp = rest.postClass(classToPost) self.assertIsNotNone(resp) classId = int(resp.headers['X-Class-Id']) resp = rest.getClassById(classId) self.assertIsNotNone(resp) self.assertIsInstance(resp, Classification) # check data integrity from our previous post self.assertEqual(resp.crop_id, cropId) self.assertEqual(resp.class_id, classId) self.assertEqual(resp.type, 'standard') self.assertEqual(resp.orientation, 'NE') self.assertEqual(resp.shape, 'circle') self.assertEqual(resp.background_color, 'white') self.assertEqual(resp.alphanumeric, 'T') self.assertEqual(resp.alphanumeric_color, 'yellow') self.assertEqual(resp.submitted, 'unsubmitted') self.assertEqual(resp.description, '') self.assertIsNotNone(resp.target)
def test(self): resetDb() rest = ImagingInterface() ret = rest.getNextRawImage() self.assertIsNotNone(ret) resp = rest.postCroppedImage(ret[1], ret[0], [22, 22], [236, 236]) self.assertIsNotNone(resp) self.assertEqual(resp.status_code, 200) # assert successful post to cropped _, cropId, _ = rest.getNextCroppedImage( ) # get the cropId as they would in the gui classToPost = Classification(cropId, 'standard', 'NE', 'circle', 'white', 'T', 'yellow') resp = rest.postClass(classToPost) self.assertIsNotNone(resp) classId = resp.headers['X-Class-Id'] self.assertIsNotNone(classId) self.assertNotEqual(int(classId), -1) resp = rest.deleteClass(classId) self.assertIsNotNone(resp) self.assertEqual(resp.status_code, 200) # we should fail to get the classification self.assertIsNone(rest.getClassById(classId))
def test(self): resetDb() rest = ImagingInterface() ret = rest.getNextRawImage() self.assertIsNotNone(ret) resp = rest.postCroppedImage(ret[1], ret[0], [22, 22], [236, 236]) self.assertIsNotNone(resp) self.assertEqual(resp.status_code, 200) # assert successful post to cropped _, cropId, _ = rest.getNextCroppedImage( ) # get the cropId as they would in the gui classToPost = Classification(cropId, 'standard', 'NE', 'circle', 'white', 'T', 'yellow') resp = rest.postClass(classToPost) self.assertIsNotNone(resp) classId = resp.headers['X-Class-Id'] self.assertIsNotNone(classId) self.assertNotEqual(int(classId), -1) # should fail to update stuff that doesn't exist stuffToUpdate = Classification(None, None, "SE", "square", None, "Y", "purple") self.assertIsNone(rest.updateClass(int(classId) + 20, stuffToUpdate)) resp = rest.updateClass(classId, stuffToUpdate) # confirm update claims success self.assertIsNotNone(resp) self.assertEqual(resp.status_code, 200) # confirm update was acutlaly successful updated = rest.getClassById(classId) self.assertIsNotNone(updated) self.assertEqual(updated.crop_id, cropId) self.assertEqual(updated.type, 'standard') self.assertEqual(updated.orientation, 'SE') self.assertEqual(updated.shape, 'square') self.assertEqual(updated.background_color, 'white') self.assertEqual(updated.alphanumeric, "Y") self.assertEqual(updated.alphanumeric_color, "purple")
def test(self): resetDb() rest = ImagingInterface() ret = rest.getNextRawImage() self.assertIsNotNone(ret) # get stuff into the cropped and classification table resp = rest.postCroppedImage(ret[1], ret[0], [22, 22], [236, 236]) self.assertIsNotNone(resp) self.assertEqual(resp.status_code, 200) # assert successful post to cropped _, cropId, _ = rest.getNextCroppedImage( ) # get the cropId as they would in the gui classToPost = Classification(cropId, 'standard', 'NE', 'circle', 'white', 'T', 'yellow') resp = rest.postClass(classToPost) self.assertIsNotNone(resp) classId = int(resp.headers['X-Class-Id']) # post a second crop and classification: resp = rest.postCroppedImage(ret[1], ret[0], [22, 22], [236, 236]) self.assertIsNotNone(resp) self.assertEqual(resp.status_code, 200) # assert successful post to cropped _, cropId2, _ = rest.getNextCroppedImage( ) # get the cropId as they would in the gui classToPost = Classification(cropId2, 'off_axis', 'NE', 'square', 'orange', 'T', 'black') resp = rest.postClass(classToPost) self.assertIsNotNone(resp) classId2 = int(resp.headers['X-Class-Id']) # get all: resp = rest.getAllClass() self.assertIsNotNone(resp) self.assertEqual(len(resp), 2) modelA = resp[0] modelB = resp[1] if modelA.class_id == classId: #check model A self.assertEqual(modelA.crop_id, cropId) self.assertEqual(modelA.class_id, classId) self.assertEqual(modelA.type, 'standard') self.assertEqual(modelA.orientation, 'NE') self.assertEqual(modelA.shape, 'circle') self.assertEqual(modelA.background_color, 'white') self.assertEqual(modelA.alphanumeric, 'T') self.assertEqual(modelA.alphanumeric_color, 'yellow') self.assertEqual(modelA.submitted, 'unsubmitted') self.assertEqual(modelA.description, '') self.assertIsNotNone(modelA.target) # check model B self.assertEqual(modelB.crop_id, cropId2) self.assertEqual(modelB.class_id, classId2) self.assertEqual(modelB.type, 'off_axis') self.assertEqual(modelB.orientation, 'NE') self.assertEqual(modelB.shape, 'square') self.assertEqual(modelB.background_color, 'orange') self.assertEqual(modelB.alphanumeric, 'T') self.assertEqual(modelB.alphanumeric_color, 'black') self.assertEqual(modelB.submitted, 'unsubmitted') self.assertEqual(modelB.description, '') self.assertIsNotNone(modelB.target) elif modelA.class_id == classId2: #check model B self.assertEqual(modelB.crop_id, cropId) self.assertEqual(modelB.class_id, classId) self.assertEqual(modelB.type, 'standard') self.assertEqual(modelB.orientation, 'NE') self.assertEqual(modelB.shape, 'circle') self.assertEqual(modelB.background_color, 'white') self.assertEqual(modelB.alphanumeric, 'T') self.assertEqual(modelB.alphanumeric_color, 'yellow') self.assertEqual(modelB.submitted, 'unsubmitted') self.assertEqual(modelB.description, '') self.assertIsNotNone(modelB.target) # check model A self.assertEqual(modelA.crop_id, cropId2) self.assertEqual(modelA.class_id, classId2) self.assertEqual(modelA.type, 'off_axis') self.assertEqual(modelA.orientation, 'NE') self.assertEqual(modelA.shape, 'square') self.assertEqual(modelA.background_color, 'orange') self.assertEqual(modelA.alphanumeric, 'T') self.assertEqual(modelA.alphanumeric_color, 'black') self.assertEqual(modelA.submitted, 'unsubmitted') self.assertEqual(modelA.description, '') self.assertIsNotNone(modelA.target) else: self.fail()
class AutonomousManager(): def __init__(self, serverHost, serverPort, detection=True, classification=True, img_start=None, submit_interval=120, show=False): """ Initialize a top-level autonomous manager @param serverHost: Local ip address of the machine the imaging server is running on @param serverPort: Port the server is running on. Default 5000 @param detection: Whether the detector should be run by this manager. Default: True @param classification: Whether the classifiers should be run by this manager. Default: False """ print("Autonomous Startup") self._should_shutdown = False self.client = ImagingInterface(serverHost, serverPort, isDebug=False, isManual=False) self.submit_interval = submit_interval self.show = show # for manually specifying which image in the server to start detection on self.img_start = img_start self.img_num = img_start # we give the option of having a machine thats running this Manager run # ONLY the detection algorithm, or ONLY the classification algorithm, # or both self.doDetection = detection self.doClassification = classification if detection and classification: self.detector = AutonomousDetection() self.classifier = AutonomousClassification() elif not detection: print("Turning off classification for this autonomous process") self.detector = AutonomousDetection() self.doClassification = False self.doDetection = True elif not classification: print("Turning off detection for this autonomous process") self.classifier = AutonomousClassification() self.doDetection = False self.doClassification = True if not classification and not detection: print("ERROR:: Cant disable both detection and classification!") exit(1) def submitTargets(self): """ submit all pending autonomous targets """ print("Submitting all pending targets...") self.client.postSubmitAllTargets() def runClassification(self): """ If this autonomous manager is set todo so, run classification on an available cropped image, if any. """ toClassify = self.client.getNextCroppedImage() if toClassify is not None: imgToClassify = np.array(toClassify[0])[:, :, ::-1] cropId = toClassify[1] cropInfo = self.client.getCroppedImageInfo(cropId) if cropInfo is None: print("Failed to get cropped image info!") return # couldnt get info on the cropped image? weird.. rawInfo = self.client.getImageInfo(cropInfo.imgId) stateMeas = None if rawInfo is None: print( "Failed to get raw image info while attempting to classify!" ) else: # get the state measurement closest to the raw image timestamp stateMeas = self.client.getStateByTs(rawInfo.time_stamp) classified = None if stateMeas is not None: # if we were able to get a state measurement close to our raw img timestamp use it to try and decide orientation classified = self.classifier.classify(imgToClassify, show=False, yaw=stateMeas.yaw) else: # attempt to classify without orientation data classified = self.classifier.classify(imgToClassify, show=False) # print("Crop #: %i" % (cropId)) if self.show: to_display = self.classifier.blur_crop.copy() cv2.putText(to_display, str(cropId), (5, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 1, cv2.LINE_AA) cv2.imshow('Crop', to_display) key = cv2.waitKey(1) & 0xFF if classified is not None: print("Successfully classified crop {}!".format(cropId)) print( "\tshape={},letter={},shapeClr={}letterClr={},orientation={}" .format(classified['shape'], classified['letter'], classified['shapeColor'], classified['letterColor'], classified['orientation'])) # TODO: Always assuming standard target for now.. toPost = Classification(cropId, "standard", orientation=classified['orientation'], shape=classified['shape'], bgColor=classified['shapeColor'], alpha=classified['letter'], alphaColor=classified['letterColor']) self.client.postClass(toPost) else: print("Crop # %i rejected as false positive" % (cropId)) def runDetection(self): """ If this autonomous manager is set todo so, run detection on an available raw image, if any. One issue here is client_rest expects/returns a PIL image and the detector expects/returns an opencv image (aka numpy array). So this method has to deal with converting between the two """ if self.img_start is not None: toDetect = self.client.getRawImage( self.img_num) #returns None if the image id doesn't exist if toDetect is not None: self.img_num += 1 else: toDetect = self.client.getNextRawImage( ) # returns tuple of (image, image_id) # if there are new raw images to process if toDetect is not None: imgToDetect = np.array(toDetect[0])[:, :, ::-1] imgId = toDetect[1] results = self.detector.detect(imgToDetect, 0) print('Img #: %i' % (imgId), ' Results: %i' % (len(results))) print(hasattr(self.detector, 'keypoints_image')) if self.show: # and hasattr(self.detector, 'keypoints_image'): to_display = self.detector.keypoints_image.copy() cv2.putText(to_display, str(imgId), (10, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 1, cv2.LINE_AA) cv2.imshow('Detected', to_display) key = cv2.waitKey(1) & 0xFF # if the detector actually returned something that's not an empty list if results is not None and results: # then lets post each of its cropped images to the server for detectedTarget in results: pilCrop = cv2.cvtColor(detectedTarget.crop, cv2.COLOR_BGR2RGB) pilCrop = Image.fromarray(pilCrop) self.client.postCroppedImage(imgId, pilCrop, detectedTarget.topLeft, detectedTarget.bottomRight) def run(self): """ Sit and spin, checking for new images and processing them as necessary """ last_submit = time.time() while 1: if not self.client.ping( ): # confirm we can still connect to the server print("WARN:: Cannot connect to server") time.sleep(5) if self.doDetection: self.runDetection() if self.doClassification: self.runClassification() if (time.time() - last_submit) > self.submit_interval: self.submitTargets() last_submit = time.time() time.sleep(0.1) def shutdown(self): self._should_shutdown = True