2 # -*- coding: utf-8 -*-
3 # ===============LICENSE_START=======================================================
5 # ===================================================================================
6 # Copyright (C) 2017-2018 AT&T Intellectual Property & Tech Mahindra. All rights reserved.
7 # ===================================================================================
8 # This Acumos software file is distributed by AT&T and Tech Mahindra
9 # under the Apache License, Version 2.0 (the "License");
10 # you may not use this file except in compliance with the License.
11 # You may obtain a copy of the License at
13 # http://www.apache.org/licenses/LICENSE-2.0
15 # This file is distributed on an "AS IS" BASIS,
16 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 # See the License for the specific language governing permissions and
18 # limitations under the License.
19 # ===============LICENSE_END=========================================================
21 Wrapper for face privacy transform task
31 def model_create_pipeline(transformer, funcName, inputIsSet, outputIsSet):
32 from acumos.session import Requirements
33 from acumos.modeling import Model, List, create_namedtuple
34 from face_privacy_filter._version import MODEL_NAME, __version__ as VERSION
39 # derive the input type from the transformer
40 input_type, type_name = transformer._type_in # it looked like this [('test', int), ('tag', str)]
41 type_in = create_namedtuple(type_name, input_type)
43 name_multiple_in = type_name
45 name_multiple_in = type_name + "s"
46 input_set = create_namedtuple(type_name + "Set", [(name_multiple_in, List[type_in])])
48 # derive the output type from the transformer
49 output_type, type_name = transformer._type_out
50 type_out = create_namedtuple(type_name, output_type)
53 name_multiple_out = type_name + "s"
54 output_set = create_namedtuple(type_name + "Set", [(name_multiple_out, List[type_out])])
56 def transform(val_wrapped: input_set) -> output_set:
57 '''Transform from image or detection and return score or image'''
58 # print("-===== input -===== ")
61 df = pd.DataFrame(getattr(val_wrapped, name_multiple_in), columns=type_in._fields)
63 df = pd.DataFrame([val_wrapped], columns=type_in._fields)
64 # print("-===== df -===== ")
66 result_df = transformer.predict(df)
67 # print("-===== out df -===== ")
70 result_parts = result_df.to_dict('split')
71 print("[{} - {}:{}]: Input {} row(s) ({}), output {} row(s) ({}))".format(
72 "classify", MODEL_NAME, VERSION, len(df), type_in, len(result_df), output_set))
76 output_obj = output_set([type_out(*r) for r in result_parts['data']])
78 output_obj = output_set(*result_parts['data'][0])
79 # print("-===== out list -===== ")
83 # compute path of this package to add it as a dependency
84 package_path = path.dirname(path.realpath(__file__))
86 objModelDeclare[funcName] = transform
87 # add the model dependency manually because of the way we constructed the package;
88 # the opencv-python/cv2 dependency is not picked up automagically
89 return Model(**objModelDeclare), Requirements(packages=[package_path], reqs=[pd, np, sklearn, 'opencv-python'],
90 req_map={cv2: 'opencv-python'})
94 from face_privacy_filter.transform_detect import FaceDetectTransform
95 from face_privacy_filter.transform_region import RegionTransform
96 from face_privacy_filter._version import MODEL_NAME
98 parser = argparse.ArgumentParser()
99 submain = parser.add_argument_group('main execution and evaluation functionality')
100 submain.add_argument('-p', '--predict_path', type=str, default='', help="save detections from model (model must be provided via 'dump_model')")
101 submain.add_argument('-i', '--input', type=str, default='', help='absolute path to input data (image or csv, only during prediction / dump)')
102 submain.add_argument('-c', '--csv_input', dest='csv_input', action='store_true', default=False, help='input as CSV format not an image')
103 submain.add_argument('-f', '--function', type=str, default='detect', help='which type of model to generate', choices=['detect', 'pixelate'])
104 submain.add_argument('-s', '--suppress_image', dest='suppress_image', action='store_true', default=False, help='do not create an extra row for a returned image')
105 subopts = parser.add_argument_group('model creation and configuration options')
106 subopts.add_argument('-a', '--push_address', help='server address to push the model (e.g. http://localhost:8887/v2/models)', default=os.getenv('ACUMOS_PUSH', ""))
107 subopts.add_argument('-A', '--auth_address', help='server address for login and push of the model (e.g. http://localhost:8887/v2/auth)', default=os.getenv('ACUMOS_AUTH', ""))
108 subopts.add_argument('-d', '--dump_model', help='dump model to a pickle directory for local running', default='')
109 config.update(vars(parser.parse_args())) # pargs, unparsed = parser.parse_known_args()
111 if not config['predict_path']:
112 print("Attempting to create new model for dump or push...")
113 elif not os.path.exists(config['input']):
114 print("Prediction requested but target input '{:}' was not found, please check input arguments.".format(config['input']))
117 # refactor the raw samples from upstream image classifier
118 if config['function'] == "detect":
119 transform = FaceDetectTransform(include_image=not config['suppress_image'])
120 pipeline, reqs = model_create_pipeline(transform, config['function'], False, True)
121 elif config['function'] == "pixelate":
122 transform = RegionTransform()
123 pipeline, reqs = model_create_pipeline(transform, config['function'], True, False)
125 print("Error: Functional mode '{:}' unknown, aborting create".format(config['function']))
127 print(getattr(pipeline, config['function']))
129 # formulate the pipeline to be used
130 model_name = MODEL_NAME + "_" + config['function']
131 if config['push_address'] and config['auth_address']:
132 from acumos.session import AcumosSession
133 print("Pushing new model to '{:}'...".format(config['push_address']))
134 session = AcumosSession(push_api=config['push_address'], auth_api=config['auth_address'])
135 session.push(pipeline, model_name, reqs) # pushes model directly to servers
137 if config['dump_model']:
138 from acumos.session import AcumosSession
139 from os import makedirs
140 if not os.path.exists(config['dump_model']):
141 makedirs(config['dump_model'])
142 print("Dumping new model to '{:}'...".format(config['dump_model']))
143 session = AcumosSession()
144 session.dump(pipeline, model_name, config['dump_model'], reqs) # creates model subdirectory
146 if config['predict_path']:
147 print("Using newly created model for local prediction...")
148 if not config['csv_input']:
149 inputDf = FaceDetectTransform.generate_in_df(config['input'])
151 inputDf = pd.read_csv(config['input'], converters={FaceDetectTransform.COL_IMAGE_DATA: FaceDetectTransform.read_byte_arrays})
153 func_action = getattr(pipeline, config['function']) # simplify to just use loaded model 6/1
154 pred_raw = func_action.wrapped(inputDf)
155 transform_out = func_action.from_wrapped(pred_raw).as_wrapped()
156 dfPred = pd.DataFrame(list(zip(*transform_out)), columns=transform_out._fields)
158 if not config['csv_input']:
159 dfPred = FaceDetectTransform.suppress_image(dfPred)
161 if config['predict_path']:
162 print("Writing prediction to file '{:}'...".format(config['predict_path']))
163 if not config['csv_input']:
164 dfPred.to_csv(config['predict_path'], sep=",", index=False)
166 FaceDetectTransform.generate_out_image(dfPred, config['predict_path'])
168 if dfPred is not None:
169 print("Predictions:\n{:}".format(dfPred))
172 if __name__ == '__main__':
173 # patch the path to include this object
174 pathRoot = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
175 if pathRoot not in sys.path:
176 sys.path.append(pathRoot)