Lambang commited on
Commit
f848d35
1 Parent(s): 682c690
__pycache__/train_pred.cpython-39.pyc CHANGED
Binary files a/__pycache__/train_pred.cpython-39.pyc and b/__pycache__/train_pred.cpython-39.pyc differ
 
hairstyle_recommendation.py ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class HairstyleRecommendation:
2
+ def __init__(self):
3
+ self.hairstyle_recommendations = {
4
+ 'male': {
5
+ 'Oval': ['Pompadour', 'Quiff', 'Classic Tapered Cut'],
6
+ 'Diamond': ['Side Swept Bangs', 'Messy Textured Top', 'Classic Tapered Cut'],
7
+ 'Square': ['Side-Parted Undercut', 'Textured Crop', 'Medium-Length Waves'],
8
+ 'Triangle': ['Textured Fringe', 'Classic Side Part', 'Medium-Length Textured'],
9
+ 'Oblong': ['Classic Short Back', 'Long Comb Over', 'Messy Textured Fringe'],
10
+ 'Round': ['Textured Quiff', 'Undercut with Textured Comb Over', 'Slicked Back']
11
+ },
12
+ 'female': {
13
+ 'Oval': ['Long Layers with Side-Swept Bangs', 'Soft Waves', 'Bob Hair Cut'],
14
+ 'Diamond': ['Layered Pixie Cut', 'Asymmetrical Long Hair', 'Layered Shag Cut'],
15
+ 'Square': ['Shoulder-Length Bob', 'Textured Pixie Cut', 'Layered Shaggy Cut'],
16
+ 'Triangle': ['Long Layers with Volume on Top', 'Medium-Length Waves', 'Pixie Cut with Soft Fringe'],
17
+ 'Oblong': ['Layered Pixie Cut', 'Long Bob', 'Side-Swept Bangs'],
18
+ 'Round': ['High Ponytail', 'Asymmetrical Bob', 'Curtain Bangs']
19
+ }}
20
+ self.hairstyle_images = {
21
+ 'male': {
22
+ 'Oval': ['pompadour.jpg', 'quiff.jpg', 'classic_tapered_cut.jpg'],
23
+ 'Diamond': ['side_swept_bangs.jpg', 'messy_textured_top.jpg', 'classic_tapered_cut.jpg'],
24
+ 'Square': ['side_parted_undercut.jpg', 'textured_crop.jpg', 'medium_length_waves.jpg'],
25
+ 'Triangle': ['textured_fringe.jpg', 'classic_side_part.jpg', 'medium_length_textured.jpg'],
26
+ 'Oblong': ['classic_short_back.jpg', 'long_comb_over.jpg', 'messy_textured_fringe.jpg'],
27
+ 'Round': ['textured_quiff.jpg', 'undercut_with_textured_comb_over.jpg', 'slicked_back.jpg']
28
+ },
29
+ 'female': {
30
+ 'Oval': ['long_layers_with_swept_bangs.jpg', 'soft_waves.jpg', 'bob_hair_cut.jpg'],
31
+ 'Diamond': ['layered_pixie_cut.jpg', 'asymmetrical_long_hair.jpg', 'layered_shag_cut.jpg'],
32
+ 'Square': ['should_length_bob.jpg', 'textured_pixie_cut.jpg', 'layered_shaggy_cut.jpg'],
33
+ 'Triangle': ['long_layers_with_volume_on_top.jpg', 'medium_length_wave.jpg', 'pixie_cut_with_soft_fringe.jpg'],
34
+ 'Oblong': ['long_layers_with_swept_bangs.jpg', 'soft_waves.jpg', 'bob_hair_cut.jpg'],
35
+ 'Round': ['long_layers_with_swept_bangs.jpg', 'soft_waves.jpg', 'bob_hair_cut.jpg']
36
+ }}
37
+
38
+ def get_recommendation(self, gender, face_shape):
39
+ recommended_styles = self.hairstyle_recommendations[gender][face_shape]
40
+ style_images = self.hairstyle_images[gender][face_shape]
41
+ return recommended_styles, style_images
main.py CHANGED
@@ -22,41 +22,43 @@ app = FastAPI()
22
  public_url = "https://lambang0902-test-space.hf.space"
23
  app.mount("/static", StaticFiles(directory="static"), name="static")
24
 
 
25
  # Tempat deklarasi variabel-variabel penting
26
  filepath = ""
27
  list_class = ['Diamond','Oblong','Oval','Round','Square','Triangle']
28
  list_folder = ['Training', 'Testing']
 
 
29
  face_crop_img = True
30
  face_landmark_img = True
31
  landmark_extraction_img = True
32
- # -----------------------------------------------------
33
 
34
- # -----------------------------------------------------
35
  # Tempat deklarasi model dan sejenisnya
36
  selected_model = tf.keras.models.load_model(f'models/fc_model_1.h5', compile=False)
37
- # face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_alt2.xml')
38
- # mp_drawing = mp.solutions.drawing_utils
39
- # mp_face_mesh = mp.solutions.face_mesh
40
- # drawing_spec = mp_drawing.DrawingSpec(thickness=1, circle_radius=1)
41
- # -----------------------------------------------------
42
 
43
 
44
- # -----------------------------------------------------
45
  # Tempat setting server
46
  UPLOAD_FOLDER = './upload'
47
  UPLOAD_MODEL = './models'
48
  ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg','zip','h5'}
49
- # -----------------------------------------------------
50
- #Endpoints
51
- #Root endpoints
52
- @app.get("/")
53
- async def root():
54
- # Dapatkan URL publik dari ngrok
55
- ngrok_url = "Tidak Ada URL Publik (ngrok belum selesai memulai)"
56
-
57
- return {"message": "Hello, World!", "ngrok_url": ngrok_url}
58
-
59
 
 
 
 
 
 
60
  #-----------------------------------------------------
61
 
62
  data_processor = DataProcessing()
@@ -69,7 +71,6 @@ def preprocessing(filepath):
69
  shutil.rmtree(folder_path)
70
  os.mkdir(folder_path)
71
 
72
-
73
  data_processor.detect_landmark(data_processor.face_cropping_pred(filepath))
74
  # data_processor.enhance_contrast_histeq(data_processor.face_cropping_pred(filepath))
75
 
@@ -81,14 +82,40 @@ def preprocessing(filepath):
81
  os.rename(os.path.join(folder_path, file_name), os.path.join(folder_path, new_file_name))
82
  index += 1
83
 
84
- # print("Tungu sampai selesaiii")
85
 
86
- # train_datagen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1 / 255.)
87
- # test_datagen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1 / 255.)
88
 
89
- # ## -------------------------------------------------------------------------
90
- # ## API UNTUK MELAKUKAN PROSES PREDIKSI
91
- # ## -------------------------------------------------------------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
 
93
  @app.post('/upload/file',tags=["Predicting"])
94
  async def upload_file(picture: UploadFile):
@@ -99,14 +126,12 @@ async def upload_file(picture: UploadFile):
99
  raise HTTPException(status_code=400, detail='Invalid file extension')
100
 
101
  os.makedirs(UPLOAD_FOLDER, exist_ok=True)
102
- file_path = os.path.join(UPLOAD_FOLDER, (picture.filename))
103
-
104
-
105
  with open(file_path, 'wb') as f:
106
  f.write(picture.file.read())
107
  try:
108
- cv2.imwrite("./static/test_upload.jpg", cv2.imread(file_path))
109
- processed_img = preprocessing(cv2.imread(file_path))
110
  except Exception as e:
111
  os.remove(file_path)
112
  raise HTTPException(status_code=500, detail=f'Error processing image: {str(e)}')
@@ -118,14 +143,185 @@ def get_images():
118
  folder_path = "./static/temporary"
119
  files = [f for f in os.listdir(folder_path) if os.path.isfile(os.path.join(folder_path, f))]
120
  urls = []
 
 
121
  for i in range(0, 3):
122
  url = f'{public_url}/static/temporary/{files[i]}'
123
  urls.append(url)
124
- bentuk, persentase = data_train_pred.prediction(selected_model)
125
- return {'urls': urls, 'bentuk_wajah':bentuk[0], 'persen':persentase}
126
-
127
- # if __name__ == '__main__':
128
- # import uvicorn
129
- # public_url = ngrok.connect(8080).public_url
130
- # print(f' * Running on {public_url}')
131
- # uvicorn.run(app, host="0.0.0.0", port=8080)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  public_url = "https://lambang0902-test-space.hf.space"
23
  app.mount("/static", StaticFiles(directory="static"), name="static")
24
 
25
+ #-----------------------------------------------------
26
  # Tempat deklarasi variabel-variabel penting
27
  filepath = ""
28
  list_class = ['Diamond','Oblong','Oval','Round','Square','Triangle']
29
  list_folder = ['Training', 'Testing']
30
+ recommendation = HairstyleRecommendation()
31
+
32
  face_crop_img = True
33
  face_landmark_img = True
34
  landmark_extraction_img = True
35
+ #-----------------------------------------------------
36
 
37
+ #-----------------------------------------------------
38
  # Tempat deklarasi model dan sejenisnya
39
  selected_model = tf.keras.models.load_model(f'models/fc_model_1.h5', compile=False)
40
+ face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_alt2.xml')
41
+ mp_drawing = mp.solutions.drawing_utils
42
+ mp_face_mesh = mp.solutions.face_mesh
43
+ drawing_spec = mp_drawing.DrawingSpec(thickness=1, circle_radius=1)
44
+ # #-----------------------------------------------------
45
 
46
 
47
+ # #-----------------------------------------------------
48
  # Tempat setting server
49
  UPLOAD_FOLDER = './upload'
50
  UPLOAD_MODEL = './models'
51
  ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg','zip','h5'}
52
+ # app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
53
+ # app.config['UPLOAD_MODEL'] = UPLOAD_MODEL
54
+ # app.config['MAX_CONTENT_LENGTH'] = 500 * 1024 * 1024 # 500 MB
55
+ # #-----------------------------------------------------
 
 
 
 
 
 
56
 
57
+ #
58
+ from file_processing import FileProcess
59
+ from get_load_data import GetLoadData
60
+ from data_preprocess import DataProcessing
61
+ from train_pred import TrainPred
62
  #-----------------------------------------------------
63
 
64
  data_processor = DataProcessing()
 
71
  shutil.rmtree(folder_path)
72
  os.mkdir(folder_path)
73
 
 
74
  data_processor.detect_landmark(data_processor.face_cropping_pred(filepath))
75
  # data_processor.enhance_contrast_histeq(data_processor.face_cropping_pred(filepath))
76
 
 
82
  os.rename(os.path.join(folder_path, file_name), os.path.join(folder_path, new_file_name))
83
  index += 1
84
 
85
+ print("Tungu sampai selesaiii")
86
 
87
+ train_datagen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1 / 255.)
88
+ test_datagen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=1 / 255.)
89
 
90
+ #-----------------------------------------------------
91
+ # Fungsi untuk menjalankan ngrok
92
+ def run_ngrok():
93
+ try:
94
+ # Jalankan ngrok dan simpan prosesnya
95
+ ngrok_process = subprocess.Popen(['ngrok', 'http', '8000'])
96
+ return ngrok_process
97
+ except Exception as e:
98
+ print(f"Error running ngrok: {e}")
99
+
100
+
101
+ @app.get("/")
102
+ async def root():
103
+ # Dapatkan URL publik dari ngrok
104
+ ngrok_url = "Tidak Ada URL Publik (ngrok belum selesai memulai)"
105
+ try:
106
+ ngrok_url = subprocess.check_output(['ngrok', 'http', '8000']).decode('utf-8').strip()
107
+ except Exception as e:
108
+ print(f"Error getting ngrok URL: {e}")
109
+
110
+ return {"message": "Hello, World!", "ngrok_url": ngrok_url}
111
+
112
+ # -------------------------------------------------------------------------
113
+ # API UNTUK MELAKUKAN PROSES PREDIKSI
114
+ # -------------------------------------------------------------------------
115
+ # Use a pipeline as a high-level helper
116
+ from transformers import pipeline
117
+
118
+ pipe = pipeline("image-classification", model="rizvandwiki/gender-classification-2")
119
 
120
  @app.post('/upload/file',tags=["Predicting"])
121
  async def upload_file(picture: UploadFile):
 
126
  raise HTTPException(status_code=400, detail='Invalid file extension')
127
 
128
  os.makedirs(UPLOAD_FOLDER, exist_ok=True)
129
+ file_path = os.path.join(UPLOAD_FOLDER, secure_filename(picture.filename))
 
 
130
  with open(file_path, 'wb') as f:
131
  f.write(picture.file.read())
132
  try:
133
+ preprocessing(cv2.imread(file_path))
134
+
135
  except Exception as e:
136
  os.remove(file_path)
137
  raise HTTPException(status_code=500, detail=f'Error processing image: {str(e)}')
 
143
  folder_path = "./static/temporary"
144
  files = [f for f in os.listdir(folder_path) if os.path.isfile(os.path.join(folder_path, f))]
145
  urls = []
146
+
147
+ # Image preprocessed url
148
  for i in range(0, 3):
149
  url = f'{public_url}/static/temporary/{files[i]}'
150
  urls.append(url)
151
+
152
+ # Face shape classification
153
+ bentuk, persentase = data_train_pred.prediction(selected_model)
154
+
155
+ # Gender classification
156
+ gender_classify = pipe('./static/result_upload0.jpg')
157
+ output_gender = max(gender_classify, key=lambda x: x['score'])['label']
158
+
159
+
160
+ # Hairstyle recommendation
161
+ recommended_styles, style_images = recommendation.get_recommendation(output_gender, bentuk[0])
162
+ hairstyleImage = [f'{public_url}/static/hairstyle_image/{file}' for file in style_images]
163
+
164
+ response = {'urls': urls,
165
+ 'bentuk_wajah': bentuk[0],
166
+ 'persen': persentase,
167
+ 'gender': output_gender,
168
+ 'hair_style': recommended_styles,
169
+ 'hair_image': hairstyleImage}
170
+ return response
171
+
172
+
173
+ # -------------------------------------------------------------------------
174
+ # API UNTUK MELAKUKAN PROSES TRAINING
175
+ # -------------------------------------------------------------------------
176
+
177
+ # Model pydantic untuk validasi body
178
+ class TrainingParams(BaseModel):
179
+ optimizer: str
180
+ epoch: int
181
+ batchSize: int
182
+
183
+ @app.post('/upload/dataset', tags=["Training"])
184
+ async def upload_data(dataset: UploadFile):
185
+ if dataset.filename == '':
186
+ raise HTTPException(status_code=400, detail='No file selected for uploading')
187
+
188
+ # Buat path lengkap untuk menyimpan file
189
+ file_path = os.path.join(UPLOAD_FOLDER, dataset.filename)
190
+
191
+ # Simpan file ke folder yang ditentukan
192
+ with open(file_path, "wb") as file_object:
193
+ file_object.write(dataset.file.read())
194
+
195
+ # Panggil fungsi untuk mengekstrak file jika perlu
196
+ FileProcess.extract_zip(file_path)
197
+
198
+ return {'message': 'File successfully uploaded'}
199
+
200
+ @app.post('/set_params', tags=["Training"])
201
+ async def set_params(request: Request, params: TrainingParams):
202
+ global optimizer, epoch, batch_size
203
+
204
+ optimizer = params.optimizer
205
+ epoch = params.epoch
206
+ batch_size = params.batchSize
207
+
208
+ response = {'message': 'Set parameter sukses'}
209
+ return response
210
+
211
+ @app.get('/get_info_data', tags=["Training"])
212
+ def get_info_prepro():
213
+ global optimizer, epoch, batch_size
214
+ training_counts = GetLoadData.get_training_file_counts().json
215
+ testing_counts = GetLoadData.get_testing_file_counts().json
216
+ response = {
217
+ "optimizer": optimizer,
218
+ "epoch": epoch,
219
+ "batch_size": batch_size,
220
+ "training_counts": training_counts,
221
+ "testing_counts": testing_counts
222
+ }
223
+ return response
224
+
225
+ @app.get('/get_images_preprocess', tags=["Training"])
226
+ def get_random_images_crop():
227
+ images_face_landmark = GetLoadData.get_random_images(tahap="Face Landmark",public_url=public_url)
228
+ images_face_extraction = GetLoadData.get_random_images(tahap="landmark Extraction", public_url=public_url)
229
+
230
+ response = {
231
+ "face_landmark": images_face_landmark,
232
+ "landmark_extraction": images_face_extraction
233
+ }
234
+ return response
235
+
236
+ @app.get('/do_preprocessing', tags=["Training"])
237
+ async def do_preprocessing():
238
+ try:
239
+ data_train_pred.do_pre1(test="")
240
+ data_train_pred.do_pre2(test="")
241
+ return {'message': 'Preprocessing sukses'}
242
+ except Exception as e:
243
+ # Tangani kesalahan dan kembalikan respons kesalahan
244
+ error_message = f'Error during preprocessing: {str(e)}'
245
+ raise HTTPException(status_code=500, detail=error_message)
246
+
247
+ @app.get('/do_training', tags=["Training"])
248
+ def do_training():
249
+ global epoch
250
+ folder = ""
251
+ if (face_landmark_img == True and landmark_extraction_img == True):
252
+ folder = "Landmark Extraction"
253
+ elif (face_landmark_img == True and landmark_extraction_img == False):
254
+ folder = "Face Landmark"
255
+ # --------------------------------------------------------------
256
+ train_dataset_path = f"./static/dataset/{folder}/Training/"
257
+ test_dataset_path = f"./static/dataset/{folder}/Testing/"
258
+
259
+ train_image_df, test_image_df = GetLoadData.load_image_dataset(train_dataset_path, test_dataset_path)
260
+
261
+ train_gen, test_gen = data_train_pred.data_configuration(train_image_df, test_image_df)
262
+ model = data_train_pred.model_architecture()
263
+
264
+ result = data_train_pred.train_model(model, train_gen, test_gen, epoch)
265
+
266
+ # Mengambil nilai akurasi training dan validation dari objek result
267
+ train_acc = result.history['accuracy'][-1]
268
+ val_acc = result.history['val_accuracy'][-1]
269
+
270
+ # Plot accuracy
271
+ data_train_pred.plot_accuracy(result=result, epoch=epoch)
272
+ acc_url = f'{public_url}/static/accuracy_plot.png'
273
+
274
+ # Plot loss
275
+ data_train_pred.plot_loss(result=result, epoch=epoch)
276
+ loss_url = f'{public_url}/static/loss_plot.png'
277
+
278
+ # Confusion Matrix
279
+ data_train_pred.plot_confusion_matrix(model, test_gen)
280
+ conf_url = f'{public_url}/static/confusion_matrix.png'
281
+
282
+ return jsonify({'train_acc': train_acc, 'val_acc': val_acc, 'plot_acc': acc_url, 'plot_loss':loss_url,'conf':conf_url})
283
+
284
+
285
+ # -------------------------------------------------------------------------
286
+ # API UNTUK PEMILIHAN MODEL
287
+ # -------------------------------------------------------------------------
288
+
289
+
290
+ @app.post('/upload/model', tags=["Model"])
291
+ def upload_model():
292
+ if 'file' not in request.files:
293
+ return {'message': 'No file part in the request'}, 400
294
+
295
+ file = request.files['file']
296
+
297
+ if file.filename == '':
298
+ return {'message': 'No file selected for uploading'}, 400
299
+
300
+ if file and FileProcess.allowed_file(file.filename):
301
+ filename = secure_filename(file.filename)
302
+ filepath = os.path.join(app.config['UPLOAD_MODEL'], filename)
303
+ file.save(filepath)
304
+
305
+ return {'message': 'File successfully uploaded'}
306
+
307
+ return {'message': 'File failed to uploaded'}
308
+
309
+ @app.post('/selected_models')
310
+ def select_models(index: int):
311
+ global selected_model
312
+ try:
313
+ global selected_model
314
+ selected_model = tf.keras.models.load_model(f'models/fc_model_{index}.h5')
315
+
316
+ # Lakukan sesuatu dengan indeks yang diterima
317
+
318
+ return {'message': 'Request berhasil diterima'}
319
+ except Exception as e:
320
+ raise HTTPException(status_code=500, detail=f'Error: {str(e)}')
321
+
322
+ if __name__ == '__main__':
323
+ import uvicorn
324
+ public_url = ngrok.connect(8080).public_url
325
+ print(f' * Running on {public_url}')
326
+ uvicorn.run(app, host="0.0.0.0", port=8080)
327
+ # app = FastAPI()
static/result_upload0.jpg ADDED
static/result_upload1.jpg ADDED
static/result_upload2.jpg ADDED
static/result_upload3.jpg ADDED
static/temporary/0_71504.jpg ADDED
static/temporary/1_787.jpg ADDED
static/temporary/2_38360.jpg ADDED
static/temporary/3_47688.jpg ADDED
static/temporary/temp DELETED
File without changes
static/test_upload.jpg ADDED
upload/8c7adb01a434d51087aef4d57cd13071.jpg ADDED