ajflorez/WLAN_coverage_estimation_DL
1
1import gradio as gr2from PIL import Image3import os4from tensorflow import keras5from keras.models import load_model6import numpy as np7import matplotlib.pyplot as plt8from matplotlib.colors import Normalize9from io import BytesIO10import re11 12# import gradio13# import PIL14# import tensorflow as tf15# import numpy as np16# import matplotlib17 18# print("Gradio:", gradio.__version__)19# print("Pillow (PIL):", PIL.__version__)20# print("TensorFlow:", tf.__version__)21# print("NumPy:", np.__version__)22# print("Matplotlib:", matplotlib.__version__)23 24# Images path25path_main = 'Data/'26images_file = path_main + 'Scennarios init/Scennarios W'27 28# Load DL models29modelo_1ap = load_model(path_main + 'Models/modelo_1ap_app.keras')30modelo_2ap = load_model(path_main + 'Models/modelo_2ap_app.keras')31 32fontsize_t = 1533 34# Plan visualization35def load_plan_vi(mapa_seleccionado, uploaded_file):36 37 if mapa_seleccionado == "Upload your own image" and uploaded_file is not None:38 plan_image = Image.open(uploaded_file.name)39 elif mapa_seleccionado == "Upload your own image" and uploaded_file is None:40 # raise gradio.Warning("Deafult plan. Image was not loaded 😒.", duration=5)41 42 image_plan_path1 = os.path.join(images_file, "80.JPG")43 plan_image = Image.open(image_plan_path1)44 else:45 image_plan_path1 = os.path.join(images_file, mapa_seleccionado)46 plan_image = Image.open(image_plan_path1)47 48 plan_n = np.array(plan_image.convert('RGB'))49 50 plt.imshow(plan_n)51 plt.xticks(np.arange(0, 256, 50), fontsize=fontsize_t)52 plt.yticks(np.arange(0, 256, 50), fontsize=fontsize_t)53 plt.xlabel("X Coordinate [Pixels]", fontsize=fontsize_t)54 plt.ylabel("Y Coordinate [Pixels]", fontsize=fontsize_t)55 plt.show()56 57 buf = BytesIO()58 plt.savefig(buf, format='png')59 buf.seek(0)60 plt.close()61 62 plan_im = Image.open(buf)63 64 tick_positions = np.linspace(0, 256, 11)65 tick_labels = ["0", "2", "4", "6", "8", "10", "12", "14", "16", "18", "20"]66 67 plt.xticks(tick_positions, tick_labels)68 69 buf = BytesIO()70 plt.imshow(plan_n)71 plt.xticks(tick_positions, tick_labels, fontsize=fontsize_t)72 plt.yticks(tick_positions, tick_labels, fontsize=fontsize_t)73 plt.xlabel("X Coordinate [meters]", fontsize=fontsize_t)74 plt.ylabel("Y Coordinate [meters]", fontsize=fontsize_t)75 plt.show()76 77 plt.savefig(buf, format='png')78 buf.seek(0)79 plt.close()80 81 plan_im_meters = Image.open(buf)82 83 return plan_im, plan_im_meters84 85def validate_coords(num_aps, coords):86 matches = re.findall(r"\(\s*\d+\s*,\s*\d+\s*\)", coords)87 88 if len(matches) > int(num_aps):89 new_coords = ", ".join(matches[:int(num_aps)])90 return new_coords91 return coords92 93import re94 95def coordinates_process(texto, interference):96 a = False97 98 texto = re.sub(r'\s*,\s*', ', ', texto) # Normalizar espacios entre comas99 texto = re.sub(r'\)\s*,\s*\(', '), (', texto) # Asegurarse de que las tuplas estén separadas por "), ("100 texto = texto.strip() # Eliminar cualquier espacio en exceso al principio o al final101 102 coordinates = texto.split("), ")103 104 resultado = []105 for coord in coordinates:106 try:107 coord = coord.replace("(", "").replace(")", "") # Eliminar paréntesis108 x, y = map(int, coord.split(",")) # Convertir a enteros109 110 if 0 <= x <= 255 and 0 <= y <= 255:111 resultado.append((x, y))112 else:113 a = True114 except ValueError:115 a = True116 117 if a:118 resultado = [(0, 0), (0, 0), (0, 0)]119 120 while len(resultado) < 3 and interference == True:121 resultado.append((0, 0))122 while len(resultado) < 5 and interference == False:123 resultado.append((0, 0))124 125 return resultado # Devolver como arreglo de tuplas126 127# plan images path128def plan_images_list():129 return [file_ for file_ in os.listdir(images_file) if file_.endswith((".JPG", ".jpg", ".jpeg", ".png", ".PNG"))]130 131# MAIN FUNCTION ****************************************************************132def main_function(plan_name, uploaded_file, interference = True, aps_int = 0, aps_coor = '(0,0)',133 apch1 = 0, apch6 = 0, apch11 = 0, coord1 = '(0,0)', coord6 = '(0,0)', coord11 = '(0,0)'):134 135 plan_name = str(plan_name)136 interference = bool(interference)137 aps_int = int(aps_int)138 aps_coor = str(aps_coor)139 apch1 = int(apch1)140 apch6 = int(apch6)141 apch11 = int(apch11)142 coord1 = str(coord1)143 coord6 = str(coord6)144 coord11 = str(coord11)145 146 aps_coor = validate_coords(aps_int, aps_coor)147 coord1 = validate_coords(apch1, coord1)148 coord6 = validate_coords(apch6, coord6)149 coord11 = validate_coords(apch11, coord11)150 151 # **************************************************************************152 imagencober = {}153 154 prediction_rgb = np.zeros((256, 256))155 156 for k in range(5):157 plt.imshow(prediction_rgb, cmap='gray')158 plt.title(f'No coverage', fontsize=fontsize_t + 2)159 plt.axis("off")160 # plt.show()161 162 buf = BytesIO()163 plt.savefig(buf, format='png')164 buf.seek(0)165 plt.close()166 167 imagencober[k] = Image.open(buf)168 # **************************************************************************169 170 # Load plan171 if plan_name == "Upload your own image" and uploaded_file is not None:172 plan_image = np.array(Image.open(uploaded_file.name))/255173 174 dimensiones = plan_image.shape175 if len(dimensiones) > 2:176 # raise gradio.Error("Error in dimensions of the uploaded image. Must [256,256,3] 💣🎆.", duration=5)177 raise ValueError("Error in image size. Must [256,256].")178 179 plan_grayscale = plan_image[:, :, 0]180 plan_in = 1 - plan_grayscale181 182 elif plan_name == "Upload your own image" and uploaded_file is None:183 # raise gradio.Warning("Deafult plan processed. Image was not loaded 😒.", duration=5)184 numero = "80"185 plan_in = np.array(Image.open(f"{path_main}Scennarios init/Scennarios B/{numero}.png")) / 255186 187 else:188 numero = plan_name.split('.')[0]189 plan_in = np.array(Image.open(f"{path_main}Scennarios init/Scennarios B/{numero}.png")) / 255190 191 # Some variables init192 deep_count = 0193 deep_coverage = []194 dimension = 256195 196 if interference:197 # if apch1 == 0 and apch6 == 0 and apch11 == 0:198 # raise gradio.Warning("There are not APs for estimation 😒.", duration=5)199 200 channels_c = [1, 6 , 11]201 channels = 3202 num_APs = np.zeros(channels, dtype=int)203 num_APs[0] = apch1204 num_APs[1] = apch6205 num_APs[2] = apch11206 aps_chs = np.zeros((dimension, dimension, channels))207 coords = [coord1, coord6, coord11]208 209 for att, channel in enumerate(range(channels)):210 if num_APs[att] > 0:211 coordinates = coordinates_process(coords[att], interference)212 for x, y in coordinates:213 if x != 0 and y != 0:214 aps_chs[int(y), int(x), att] = 1215 216 if not interference:217 channels = aps_int218 aps_chs = np.zeros((dimension, dimension, 5)) # Crear la matriz219 coordinates = coordinates_process(aps_coor, interference)220 221 for att, (x, y) in enumerate(coordinates):222 if x != 0 and y != 0:223 aps_chs[int(y), int(x), att] = 1224 225 # Coverage process226 deep_coverage = []227 ap_images = []228 layer_indices = []229 230 for k in range(channels):231 capa = aps_chs[:, :, k]232 filas, columnas = np.where(capa == 1)233 234 if len(filas) == 2:235 # For 2 AP236 deep_count += 1237 layer_1 = np.zeros_like(capa)238 layer_2 = np.zeros_like(capa)239 layer_1[filas[0], columnas[0]] = 1240 layer_2[filas[1], columnas[1]] = 1241 242 datos_entrada = np.stack([plan_in, layer_1, layer_2], axis=-1)243 prediction = modelo_2ap.predict(datos_entrada[np.newaxis, ...])[0]244 245 elif len(filas) == 1:246 # For 1 AP247 deep_count += 1248 layer_1 = np.zeros_like(capa)249 layer_1[filas[0], columnas[0]] = 1250 251 datos_entrada = np.stack([plan_in, layer_1], axis=-1)252 prediction = modelo_1ap.predict(datos_entrada[np.newaxis, ...])[0]253 254 else:255 # Whitout AP256 prediction = np.zeros((dimension,dimension,1))257 258 # print(prediction.shape)259 deep_coverage.append(prediction)260 prediction_rgb = np.squeeze((Normalize()(prediction)))261 ap_images.append(prediction_rgb)262 263 if np.all(prediction == 0):264 plt.imshow(prediction_rgb, cmap='gray')265 plt.title(f'No coverage', fontsize=fontsize_t)266 plt.axis("off")267 plt.show()268 else:269 plt.imshow(prediction_rgb, cmap='jet')270 if interference:271 plt.title(f'Coverage CH {channels_c[k]}', fontsize=fontsize_t)272 cbar = plt.colorbar(ticks=np.linspace(0, 1, num=6),)273 cbar.set_label('SINR [dB]', fontsize=fontsize_t)274 cbar.set_ticklabels(['-3.01', '20.29', '43.60', '66.90', '90.20', '113.51'])275 if not interference:276 plt.title(f'Coverage AP {k}', fontsize=fontsize_t)277 cbar = plt.colorbar(ticks=np.linspace(0, 1, num=6),)278 cbar.set_label('Power [dBm]', fontsize=fontsize_t)279 cbar.set_ticklabels(['-94.94', '-70.75', '-46.56', '-22.38', '1.81', '26.00'])280 cbar.ax.tick_params(labelsize=fontsize_t)281 plt.axis("off")282 plt.show()283 284 # Save the plot to a buffer285 buf = BytesIO()286 plt.savefig(buf, format='png')287 buf.seek(0)288 plt.close()289 290 # Convert buffer to an image291 imagencober[k] = Image.open(buf)292 293 # Final coverage294 if deep_coverage:295 deep_coverage = np.array(deep_coverage)296 nor_matrix = np.max(deep_coverage, axis=0)297 celdas = np.argmax(deep_coverage, axis=0)298 299 resultado_rgb = np.squeeze((Normalize()(nor_matrix)))300 301 plt.imshow(resultado_rgb, cmap='jet')302 cbar = plt.colorbar(ticks=np.linspace(0, 1, num=6))303 if interference:304 cbar.set_label('SINR [dB]', fontsize=fontsize_t)305 cbar.set_ticklabels(['-3.01', '20.29', '43.60', '66.90', '90.20', '113.51'])306 if not interference:307 cbar.set_label('Power [dBm]', fontsize=fontsize_t)308 cbar.set_ticklabels(['-94.94', '-70.75', '-46.56', '-22.38', '1.81', '26.00'])309 cbar.ax.tick_params(labelsize=fontsize_t)310 plt.axis("off")311 plt.show()312 313 # Save the plot to a buffer314 buf = BytesIO()315 plt.savefig(buf, format='png')316 buf.seek(0)317 plt.close()318 319 # Convert buffer to an image320 imagen3 = Image.open(buf)321 322 # **************************************************************************323 if interference == True:324 if num_APs[0] > 0 and num_APs[1] > 0 and num_APs[2] > 0:325 cmap = plt.cm.colors.ListedColormap(['blue', 'red', 'green'])326 plt.imshow(celdas, cmap=cmap)327 cbar = plt.colorbar()328 cbar.set_ticks([0, 1, 2])329 cbar.set_ticklabels(['1', '6', '11'])330 cbar.set_label('Cell ID', fontsize=fontsize_t)331 cbar.ax.tick_params(labelsize=fontsize_t)332 plt.axis("off")333 plt.show()334 335 # Save the plot to a buffer336 buf = BytesIO()337 plt.savefig(buf, format='png')338 buf.seek(0)339 plt.close()340 341 # Convert buffer to an image342 imagen4 = Image.open(buf)343 344 elif num_APs[0] > 0 and num_APs[1] > 0:345 cmap = plt.cm.colors.ListedColormap(['blue', 'red'])346 plt.imshow(celdas, cmap=cmap)347 cbar = plt.colorbar()348 cbar.set_ticks([0, 1])349 cbar.set_ticklabels(['1', '6'])350 cbar.set_label('Cell ID', fontsize=fontsize_t)351 cbar.ax.tick_params(labelsize=fontsize_t)352 plt.axis("off")353 plt.show()354 355 # Save the plot to a buffer356 buf = BytesIO()357 plt.savefig(buf, format='png')358 buf.seek(0)359 plt.close()360 361 # Convert buffer to an image362 imagen4 = Image.open(buf)363 364 elif num_APs[0] > 0 and num_APs[2] > 0:365 cmap = plt.cm.colors.ListedColormap(['blue', 'red'])366 plt.imshow(celdas, cmap=cmap)367 cbar = plt.colorbar()368 cbar.set_ticks([0, 1])369 cbar.set_ticklabels(['1', '11'])370 cbar.set_label('Cell ID', fontsize=fontsize_t)371 cbar.ax.tick_params(labelsize=fontsize_t)372 plt.axis("off")373 plt.show()374 375 # Save the plot to a buffer376 buf = BytesIO()377 plt.savefig(buf, format='png')378 buf.seek(0)379 plt.close()380 381 # Convert buffer to an image382 imagen4 = Image.open(buf)383 384 elif num_APs[1] > 0 and num_APs[2] > 0:385 cmap = plt.cm.colors.ListedColormap(['blue', 'red'])386 plt.imshow(celdas, cmap=cmap)387 cbar = plt.colorbar()388 cbar.set_ticks([0, 1])389 cbar.set_ticklabels(['6', '11'])390 cbar.set_label('Cell ID', fontsize=fontsize_t)391 cbar.ax.tick_params(labelsize=fontsize_t)392 plt.axis("off")393 plt.show()394 395 # Save the plot to a buffer396 buf = BytesIO()397 plt.savefig(buf, format='png')398 buf.seek(0)399 plt.close()400 401 # Convert buffer to an image402 imagen4 = Image.open(buf)403 404 else:405 cmap = plt.cm.colors.ListedColormap(['blue'])406 plt.imshow(celdas, cmap=cmap)407 cbar = plt.colorbar()408 cbar.set_ticks([0])409 cbar.set_ticklabels(['1'])410 cbar.set_label('Cell ID', fontsize=fontsize_t)411 cbar.ax.tick_params(labelsize=fontsize_t)412 plt.axis("off")413 plt.show()414 415 # Save the plot to a buffer416 buf = BytesIO()417 plt.savefig(buf, format='png')418 buf.seek(0)419 plt.close()420 421 # Convert buffer to an image422 imagen4 = Image.open(buf)423 424 # **************************************************************************425 426 if interference == False:427 if aps_int == 5:428 cmap = plt.cm.colors.ListedColormap(['blue', 'red', 'green', 'yellow', 'violet'])429 plt.imshow(celdas, cmap=cmap)430 cbar = plt.colorbar()431 cbar.set_ticks([0, 1, 2, 3, 4])432 cbar.set_ticklabels(['1', '2', '3', '4', '5'])433 cbar.set_label('Cell ID', fontsize=fontsize_t)434 cbar.ax.tick_params(labelsize=fontsize_t)435 plt.axis("off")436 plt.show()437 438 # Save the plot to a buffer439 buf = BytesIO()440 plt.savefig(buf, format='png')441 buf.seek(0)442 plt.close()443 444 # Convert buffer to an image445 imagen4 = Image.open(buf)446 447 elif aps_int == 4:448 cmap = plt.cm.colors.ListedColormap(['blue', 'red', 'green', 'yellow'])449 plt.imshow(celdas, cmap=cmap)450 cbar = plt.colorbar()451 cbar.set_ticks([0, 1, 2, 3])452 cbar.set_ticklabels(['1', '2', '3', '4'])453 cbar.set_label('Cell ID', fontsize=fontsize_t)454 cbar.ax.tick_params(labelsize=fontsize_t)455 plt.axis("off")456 plt.show()457 458 # Save the plot to a buffer459 buf = BytesIO()460 plt.savefig(buf, format='png')461 buf.seek(0)462 plt.close()463 464 # Convert buffer to an image465 imagen4 = Image.open(buf)466 467 elif aps_int == 3:468 cmap = plt.cm.colors.ListedColormap(['blue', 'red', 'green'])469 plt.imshow(celdas, cmap=cmap)470 cbar = plt.colorbar()471 cbar.set_ticks([0, 1, 2])472 cbar.set_ticklabels(['1', '2', '3'])473 cbar.set_label('Cell ID', fontsize=fontsize_t)474 cbar.ax.tick_params(labelsize=fontsize_t)475 plt.axis("off")476 plt.show()477 478 # Save the plot to a buffer479 buf = BytesIO()480 plt.savefig(buf, format='png')481 buf.seek(0)482 plt.close()483 484 # Convert buffer to an image485 imagen4 = Image.open(buf)486 487 elif aps_int == 2:488 cmap = plt.cm.colors.ListedColormap(['blue', 'red'])489 plt.imshow(celdas, cmap=cmap)490 cbar = plt.colorbar()491 cbar.set_ticks([0, 1])492 cbar.set_ticklabels(['1', '2'])493 cbar.set_label('Cell ID', fontsize=fontsize_t)494 cbar.ax.tick_params(labelsize=fontsize_t)495 plt.axis("off")496 plt.show()497 498 # Save the plot to a buffer499 buf = BytesIO()500 plt.savefig(buf, format='png')501 buf.seek(0)502 plt.close()503 504 # Convert buffer to an image505 imagen4 = Image.open(buf)506 507 else:508 cmap = plt.cm.colors.ListedColormap(['blue'])509 plt.imshow(celdas, cmap=cmap)510 cbar = plt.colorbar()511 cbar.set_ticks([0])512 cbar.set_ticklabels(['1'])513 cbar.set_label('Cell ID', fontsize=fontsize_t)514 cbar.ax.tick_params(labelsize=fontsize_t)515 plt.axis("off")516 plt.show()517 518 # Save the plot to a buffer519 buf = BytesIO()520 plt.savefig(buf, format='png')521 buf.seek(0)522 plt.close()523 524 # Convert buffer to an image525 imagen4 = Image.open(buf)526 527 # **************************************************************************528 529 return [imagencober[0], imagencober[1], imagencober[2], imagencober[3], imagencober[4], imagen3, imagen4]530 531def update_interface(enable_interference):532 if enable_interference:533 return {534 map_dropdown : gr.update(visible=True),535 upload_image : gr.update(visible=True),536 ch1_input: gr.update(visible=True),537 ch6_input: gr.update(visible=True),538 ch11_input: gr.update(visible=True),539 coords_ch1_input: gr.update(visible=True),540 coords_ch6_input: gr.update(visible=True),541 coords_ch11_input: gr.update(visible=True),542 button1: gr.update(visible=True),543 button2: gr.update(visible=True),544 image_ap1 : gr.update(visible=False),545 image_ap2 : gr.update(visible=False),546 image_ch1 : gr.update(visible=True),547 image_ch6 : gr.update(visible=True),548 image_ch11 : gr.update(visible=True),549 simple_dropdown: gr.update(visible=False),550 simple_coords: gr.update(visible=False)551 }552 else:553 return {554 map_dropdown: gr.update(visible=True),555 upload_image : gr.update(visible=True),556 ch1_input: gr.update(visible=False),557 ch6_input: gr.update(visible=False),558 ch11_input: gr.update(visible=False),559 coords_ch1_input: gr.update(visible=False),560 coords_ch6_input: gr.update(visible=False),561 coords_ch11_input: gr.update(visible=False),562 simple_dropdown: gr.update(visible=True, interactive=True),563 simple_coords: gr.update(visible=True, interactive=True),564 image_ap1 : gr.update(visible=True),565 image_ap2 : gr.update(visible=True),566 image_ch1 : gr.update(visible=True),567 image_ch6 : gr.update(visible=True),568 image_ch11 : gr.update(visible=True)569 }570 571with gr.Blocks() as demo:572 gr.Markdown(573 """574 ## Fast Indoor Radio Propagation Prediction using Deep Learning575 This app uses deep learning models for radio map estimation (RME) with and without interference, simulating 2.4 GHz and 5 GHz bands. RME involves estimating the received RF power based on spatial information maps.576 577 Instructions for use:578 579 - A predefined list of indoor floor plans is available for use.580 - You can upload your own indoor floor plan.581 - Negative numbers are not allowed.582 - The established format for the coordinates of each access point (AP) must be followed.583 - A maximum of 2 APs per channel is allowed for the interference case.584 - A maximum of 5 APs is allowed for the non-interference case.585 - The uploaded plan must meet the dimensions [256,256], with free spaces as white pixels and walls as black pixels.586 """587 )588 589 enable_interference = gr.Checkbox(label="Enable Interference Analysis", value=True)590 591 with gr.Row():592 with gr.Column(scale=1):593 map_dropdown = gr.Dropdown(choices=plan_images_list() + ["Upload your own image"], label="Select indoor plan", value="80.JPG")594 upload_image = gr.File(label="Or upload your own image", file_types=[".JPG", ".jpg", ".jpeg", ".png", ".PNG"])595 ch1_input = gr.Dropdown(choices=[i for i in range(0, 3)], label="Select APs CH 1", value=0)596 ch6_input = gr.Dropdown(choices=[i for i in range(0, 3)], label="Select APs CH 6", value=0)597 ch11_input = gr.Dropdown(choices=[i for i in range(0, 3)], label="Select APs CH 11", value=0)598 coords_ch1_input = gr.Textbox(label="Coordinate CH 1", placeholder="Format (Pixels): (x1, y1), (x2, y2)")599 coords_ch6_input = gr.Textbox(label="Coordinate CH 6", placeholder="Format (Pixels): (x1, y1), (x2, y2)")600 coords_ch11_input = gr.Textbox(label="Coordinate CH 11", placeholder="Format (Pixels): (x1, y1), (x2, y2)")601 602 simple_dropdown = gr.Dropdown(choices=[str(i) for i in range(1, 6)], label="Select APs number", visible=False)603 simple_coords = gr.Textbox(label="Enter APs coordinates", placeholder="Format (Pixels): (x1, y1), (x1, y1)...", visible=False,)604 605 button1 = gr.Button("Load plan")606 button2 = gr.Button("Predict coverage")607 608 with gr.Column(scale=3):609 with gr.Row():610 first_image_output = gr.Image(label="Plan image pixels")611 second_image_output = gr.Image(label="Plan image meters")612 with gr.Row():613 image_ch1 = gr.Image(label="Coverage 1")614 image_ch6 = gr.Image(label="Coverage 2")615 image_ch11 = gr.Image(label="Coverage 3")616 617 image_ap1 = gr.Image(label="Coverage 4", visible=False)618 image_ap2 = gr.Image(label="Coverage 5", visible=False)619 with gr.Row():620 image_cover_final = gr.Image(label="Final coverage")621 image_cells = gr.Image(label="Cells coverage")622 623 enable_interference.change(update_interface, inputs=[enable_interference],624 outputs=[map_dropdown, upload_image,625 ch1_input, ch6_input, ch11_input,626 coords_ch1_input, coords_ch6_input, coords_ch11_input,627 button1, button2,628 simple_dropdown, simple_coords,629 image_ch1, image_ch6, image_ch11,630 image_ap1, image_ap2])631 632 button1.click(load_plan_vi,633 inputs=[map_dropdown, upload_image], outputs=[first_image_output, second_image_output])634 635 # Único bloque para el clic de button2636 button2.click(main_function,637 inputs=[map_dropdown,638 upload_image,639 enable_interference,640 simple_dropdown,641 simple_coords,642 ch1_input, ch6_input, ch11_input,643 coords_ch1_input, coords_ch6_input, coords_ch11_input],644 outputs=[image_ch1, image_ch6, image_ch11, image_ap1, image_ap2, image_cover_final, image_cells])645 646demo.launch()