def distort_image_shepards(image_id_in=None, image_id_out=None, distortion_set_id=None): ''' Distorts an image using all the distortion pairs in a named distortion set It is necessary to call ImageMagick via command line to make this happen, no bindings in Pillow for this functionality :( Uses the Shepards algorithm for distortion ''' img_dict_in = get_document_with_exception(image_id_in, 'picture') group_id = img_dict_in['group_id'] img_filename_out = build_picture_name(image_id_out) pic_path_in = img_dict_in['uri'] pic_path_out = build_picture_path(picture_name=img_filename_out, snap_id=img_dict_in['snap_id']) command_string = build_command_string(distortion_set_id, pic_path_in, pic_path_out) os.system(command_string) img_dict_out = { '_id': str(image_id_out), 'type': 'picture', 'source': 'analysis', 'source_image_id': str(image_id_in), 'analysis_type': 'distort', 'group_id': group_id, 'snap_id': img_dict_in['snap_id'], 'filename': img_filename_out, 'uri': pic_path_out, 'created': str(datetime.datetime.now()) } save_generic(img_dict_out, 'picture')
def build_three_pictures(self, snap_id): pic_ids = [] for i in range(1, 3): pic_id = uuid.uuid4() filename = build_picture_name(pic_id) picture_path = build_picture_path(picture_name=filename, snap_id=snap_id) the_doc = { '_id': str(pic_id), 'snap_id': str(snap_id), 'uri': picture_path, 'filename': filename, 'source': 'whatever', 'type': 'picture' } save_generic(the_doc, 'picture') pic_ids.append(pic_id) # touch the picture file in the temp directory with open(picture_path, 'a'): os.utime(picture_path, None) if not item_exists(snap_id, 'snap'): snap_doc = {'_id': snap_id, 'type': 'snap', 'clean_up_files': True} save_generic(snap_doc, 'snap') return pic_ids
def generic_save_view(args_dict={}, document_type=''): ''' Takes what's in request.args, adds it to what's in args dict and saves it. Also will guarantee that the type of document that's saved is of type document_type Returns a response object ''' try: if request.headers['Content-Type'] == 'application/json': for k in request.json.keys(): args_dict[k] = request.json[k] if '_id' not in args_dict: args_dict['_id'] = cast_uuid_to_string(uuid.uuid4()) if 'type' not in args_dict: args_dict['type'] = document_type save_generic(args_dict, document_type) return Response(json.dumps(args_dict), status=200, mimetype='application/json') else: error_msg = 'problem with saving {0}: content type is not application/json'.format( document_type) return Response(json.dumps(error_msg), status=409, mimetype='application/json') except Exception as e: return Response(json.dumps(e.message), status=e.status_code, mimetype='application/json')
def merge_images(img1_primary_id_in, img1_alternate_id_in, img2_id_in, img_id_out, group_id, **kwargs): # TODO deal more elegantly with the fact that different merge methods require different parameters # the assumption is that the merged picture will be saved in the directory with the snap of image 1 # it also assumes that both images have not yet been deleted with clean_up_files merge_type = get_merge_type(group_id, **kwargs) merge_method = get_merge_method(merge_type) img1_id_in = img1_primary_id_in if item_exists(img1_alternate_id_in, 'picture'): img1_id_in = img1_alternate_id_in paths_dict = get_image_paths_and_snap_id(img1_id_in, img2_id_in, img_id_out) do_image_merge(paths_dict, merge_method) img_dict_out = { '_id': str(img_id_out), 'type': 'picture', 'source': 'merge', 'source_image_id_1': str(img1_id_in), 'source_image_id_2': str(img2_id_in), 'merge_type': merge_type, 'group_id': group_id, 'snap_id': paths_dict['snap_id'], 'filename': paths_dict['img_out_filename'], 'uri': paths_dict['img_out_path'], 'created': str(datetime.datetime.now()) } save_generic(img_dict_out, 'picture')
def create_default_settings_and_group_documents(): ''' Creates a settings object and group object with their default settings. Saves both objects. ''' group_dict = default_group_dict() settings_dict = default_settings_dict(group_dict['_id']) save_generic(settings_dict, 'settings') save_generic(group_dict, 'group') return settings_dict
def create_default_settings_and_group_documents(): """ Creates a settings object and group object with their default settings. Saves both objects. """ group_dict = default_group_dict() settings_dict = default_settings_dict(group_dict["_id"]) save_generic(settings_dict, "settings") save_generic(group_dict, "group") return settings_dict
def edge_detect_auto(img_id_in, pic_dict_in, auto_id): blurred = build_blurred_cv2_image(img_id_in) # apply Canny edge detection using an automatically determined threshold auto = auto_canny(blurred) auto_filename = build_picture_name(auto_id) auto_path_out = build_picture_path(picture_name=auto_filename, snap_id=pic_dict_in['snap_id']) cv2.imwrite(auto_path_out, auto) auto_dict_out = make_edge_picture_dict(pic_id=auto_id, pic_filename=auto_filename, pic_path=auto_path_out, snap_id=pic_dict_in['snap_id'], group_id=pic_dict_in['group_id'], source_pic_id=img_id_in, edge_detect_type='auto') save_generic(auto_dict_out, 'picture')
def edge_detect_with_canny_limits(img_id_in, pic_dict_in, new_id, limit_low, limit_high): blurred = build_blurred_cv2_image(img_id_in) # apply Canny edge detection using a custom threshold # TODO if limit_low or limit_high aren't positive ints, with high > low throw an error new_image = cv2.Canny(blurred, limit_low, limit_high) new_filename = build_picture_name(new_id) new_path_out = build_picture_path(picture_name=new_filename, snap_id=pic_dict_in['snap_id']) cv2.imwrite(new_path_out, new_image) new_dict_out = make_edge_picture_dict(pic_id=new_id, pic_filename=new_filename, pic_path=new_path_out, snap_id=pic_dict_in['snap_id'], group_id=pic_dict_in['group_id'], source_pic_id=img_id_in, edge_detect_type='custom:{0}-{1}'.format(limit_low, limit_high)) save_generic(new_dict_out, 'picture')
def test_save_generic_calls_expected_functions(self, ts_save_document): ret_val = ts.save_generic({ 'a': 'b', 'type': 'whatever', '_id': '123' }, 'whatever') assert ts_save_document.called_once_with({'a': 'b'})
def test_save_generic_throws_error_if_wrong_type(self): with pytest.raises(DocumentConfigurationError) as exception_info: ret_val = ts.save_generic({ '_id': 'flores', 'type': 'brontosaurus' }, 'tyrannosaurus_rex') assert 'trying to save the document that is not of type tyrannosaurus_rex' in str( exception_info.value)
def create_distortion_pair(): try: if 'distortion_set_id' not in request.json: distortion_set_id = cast_uuid_to_string(uuid.uuid4()) request.json['distortion_set_id'] = distortion_set_id else: distortion_set_id = request.json['distortion_set_id'] if not item_exists(distortion_set_id, 'distortion_set'): distortion_set_dict = {'_id': distortion_set_id, 'type': 'distortion_set'} save_generic(distortion_set_dict, 'distortion_set') # TODO add a lot more tests to the request json, we need start_x, y, end_x, y and they need to be ints, range tests, etc # ^^^^^ have this be a validation function which is optionally passed to save_generic return_value = generic_save_view(document_type='distortion_pair') return return_value except Exception as e: return Response(json.dumps(e.message), status=e.status_code, mimetype='application/json')
def save_group(): ''' Creates a new group record, saves it as the new current group in the settings document Won't let you specify _id, _rev or type Automatically sets settings.current_group_id to the groups id as well ''' return_value = generic_save_view(args_dict=default_group_dict(), document_type='group') if return_value.status_code == 200: try: group_id = json.loads(return_value.data)['_id'] settings = get_settings_document() settings['current_group_id'] = group_id save_generic(settings, 'settings') return return_value except Exception as e: return Response(json.dumps('error saving settings: '+e.message), status=e.status_code, mimetype='application/json') else: return return_value
def edge_detect_with_canny_limits(img_id_in, pic_dict_in, new_id, limit_low, limit_high): blurred = build_blurred_cv2_image(img_id_in) # apply Canny edge detection using a custom threshold # TODO if limit_low or limit_high aren't positive ints, with high > low throw an error new_image = cv2.Canny(blurred, limit_low, limit_high) new_filename = build_picture_name(new_id) new_path_out = build_picture_path(picture_name=new_filename, snap_id=pic_dict_in['snap_id']) cv2.imwrite(new_path_out, new_image) new_dict_out = make_edge_picture_dict( pic_id=new_id, pic_filename=new_filename, pic_path=new_path_out, snap_id=pic_dict_in['snap_id'], group_id=pic_dict_in['group_id'], source_pic_id=img_id_in, edge_detect_type='custom:{0}-{1}'.format(limit_low, limit_high)) save_generic(new_dict_out, 'picture')
def scale_image(img_id_in, img_id_out, group_id, **kwargs): # only works on black and white images for now # that should only be a problem for images that aren't of type 'L'. Add this test group_document = get_group_document(group_id) if 'scale_type' in kwargs: scale_type = kwargs['scale_type'] else: if 'scale_type' in group_document: scale_type = group_document['scale_type'] else: scale_type = 'colorize_bicubic' group_id = group_document['_id'] img_dict_in = get_document_with_exception(str(img_id_in), 'picture') img_filename_in = img_dict_in['filename'] img_filename_out = build_picture_name(img_id_out) pic_path_in = img_dict_in['uri'] pic_path_out = build_picture_path(picture_name=img_filename_out, snap_id=img_dict_in['snap_id']) image_in = Image.open(pic_path_in) image_scaled = scale_image_subtask(scale_type, image_in) image_scaled = blur_image(scale_type, image_scaled) image_colorized = colorize_image(scale_type, group_document, image_scaled) image_colorized.save(pic_path_out) img_dict_out = { '_id': str(img_id_out), 'type': 'picture', 'source': 'analysis', 'source_image_id': str(img_id_in), 'analysis_type': scale_type, 'group_id': group_id, 'snap_id': img_dict_in['snap_id'], 'filename': img_filename_out, 'uri': pic_path_out, 'created': str(datetime.datetime.now()) } save_generic(img_dict_out, 'picture')
def generic_save_view(args_dict={}, document_type=''): ''' Takes what's in request.args, adds it to what's in args dict and saves it. Also will guarantee that the type of document that's saved is of type document_type Returns a response object ''' try: if request.headers['Content-Type'] == 'application/json': for k in request.json.keys(): args_dict[k] = request.json[k] if '_id' not in args_dict: args_dict['_id'] = cast_uuid_to_string(uuid.uuid4()) if 'type' not in args_dict: args_dict['type'] = document_type save_generic(args_dict, document_type) return Response(json.dumps(args_dict), status=200, mimetype='application/json') else: error_msg = 'problem with saving {0}: content type is not application/json'.format(document_type) return Response(json.dumps(error_msg), status=409, mimetype='application/json') except Exception as e: return Response(json.dumps(e.message), status=e.status_code, mimetype='application/json')
def save_group(): ''' Creates a new group record, saves it as the new current group in the settings document Won't let you specify _id, _rev or type Automatically sets settings.current_group_id to the groups id as well ''' return_value = generic_save_view(args_dict=default_group_dict(), document_type='group') if return_value.status_code == 200: try: group_id = json.loads(return_value.data)['_id'] settings = get_settings_document() settings['current_group_id'] = group_id save_generic(settings, 'settings') return return_value except Exception as e: return Response(json.dumps('error saving settings: ' + e.message), status=e.status_code, mimetype='application/json') else: return return_value
def create_distortion_pair(): try: if 'distortion_set_id' not in request.json: distortion_set_id = cast_uuid_to_string(uuid.uuid4()) request.json['distortion_set_id'] = distortion_set_id else: distortion_set_id = request.json['distortion_set_id'] if not item_exists(distortion_set_id, 'distortion_set'): distortion_set_dict = { '_id': distortion_set_id, 'type': 'distortion_set' } save_generic(distortion_set_dict, 'distortion_set') # TODO add a lot more tests to the request json, we need start_x, y, end_x, y and they need to be ints, range tests, etc # ^^^^^ have this be a validation function which is optionally passed to save_generic return_value = generic_save_view(document_type='distortion_pair') return return_value except Exception as e: return Response(json.dumps(e.message), status=e.status_code, mimetype='application/json')
def test_save_generic_throws_error_if_wrong_type(self): with pytest.raises(DocumentConfigurationError) as exception_info: ret_val = ts.save_generic({'_id': 'flores', 'type': 'brontosaurus'}, 'tyrannosaurus_rex') assert 'trying to save the document that is not of type tyrannosaurus_rex' in str(exception_info.value)
def test_save_generic_throws_error_if_no_id(self): with pytest.raises(DocumentConfigurationError) as exception_info: ret_val = ts.save_generic({}, 'whatever') assert 'trying to save a document with no id' in str(exception_info.value)
def test_save_generic_throws_error_if_no_id(self): with pytest.raises(DocumentConfigurationError) as exception_info: ret_val = ts.save_generic({}, 'whatever') assert 'trying to save a document with no id' in str( exception_info.value)
def test_save_generic_throws_error_if_no_type(self): with pytest.raises(DocumentConfigurationError) as exception_info: ret_val = ts.save_generic({'_id': 'flores'}, 'whatever') assert 'trying to save the document with no value for type' in str(exception_info.value)
def test_save_generic_throws_error_if_no_type(self): with pytest.raises(DocumentConfigurationError) as exception_info: ret_val = ts.save_generic({'_id': 'flores'}, 'whatever') assert 'trying to save the document with no value for type' in str( exception_info.value)
def test_save_generic_calls_expected_functions(self, ts_save_document): ret_val = ts.save_generic({'a': 'b', 'type': 'whatever', '_id': '123'}, 'whatever') assert ts_save_document.called_once_with({'a': 'b'})