{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"<a id=\"0\"></a>\n# <p style=\"background-color:#281F2F;height: 60px;text-align: center;vertical-align: middle;line-height: 60px;;font-family:helvetica;color:#FFFFFF;font-size:120%;text-align:center;border-radius:12px 12px;\">~ ~ ~ ~ Libraries ~ ~ ~ ~</p>","metadata":{"_kg_hide-output":true}},{"cell_type":"code","source":"# Matrix and Arrays\nimport numpy as np\nimport pandas as pd\n\n# Random\nimport random\n\n# Graphics\nimport matplotlib.pyplot as plt\nimport seaborn as sns\nimport plotly.express as px\n\n# Signal\nfrom scipy.fftpack import rfft, irfft, fftfreq, fft\nfrom scipy.signal import butter, sosfilt, sosfreqz, filtfilt\nfrom scipy.signal import hilbert\nimport cv2\n\n# Audio\nimport librosa\nimport librosa.display\nimport IPython.display as ipd\n# import noisereduce as nr\n\n# Sklearn\nfrom sklearn.cluster import MiniBatchKMeans\nfrom sklearn.cluster import KMeans\n\n# Pytorch\nimport torch\nimport torchaudio\n\n# Math\nfrom math import ceil\n\n# Files\nimport os\nimport json\n\nfrom tqdm.auto import tqdm\nfrom functools import partial\nfrom joblib import Parallel, delayed\n\n\n#image\nfrom PIL import Image as im\n\nimport imageio\n\n# Warnings\nimport warnings\nwarnings.simplefilter('ignore')\n\nfrom skimage.util import img_as_ubyte\nfrom sklearn import preprocessing","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_kg_hide-input":true,"execution":{"iopub.status.busy":"2022-05-27T17:41:02.426073Z","iopub.execute_input":"2022-05-27T17:41:02.426430Z","iopub.status.idle":"2022-05-27T17:41:07.668757Z","shell.execute_reply.started":"2022-05-27T17:41:02.426343Z","shell.execute_reply":"2022-05-27T17:41:07.667961Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"1\"></a>\n# <p style=\"background-color:#281F2F;height: 60px;text-align: center;vertical-align: middle;line-height: 60px;;font-family:helvetica;color:#FFFFFF;font-size:120%;text-align:center;border-radius:12px 12px;\">~ ~ ~ ~ Introduction ~ ~ ~ ~</p>\n\nThis notebook implements one of the pipelines for audio transformation to Spectograms developed for the BirdCLEF 2022 competition where our team achieve the Bronze medal in 68th position. \n\n\n![image.png](attachment:aa2c2574-44d8-4728-878a-3a6302d1c129.png)\n\nThe pipeline consists of the transformation of a audio file into N melspectogram images. Some treatments into the audio\\image and image augmentation can be applyied during the process:\n* [1) Loading the audio files](#3-2)\n* [2) Applying audio treatment or noise reduce (optional)](#5)\n* [3) Break the audio file into slices of x seconds](#9)\n* [4) Transform the audio slice into a spectogram (optional)](#4)\n* [5) Applying some image treatment (optional)](#6)\n* [6) Augment the melspectogram (optional)](#7)\n* [7) Save original and augmented images](#8)\n* [8) Result example](#15)\n\nThe blocks are done separately in classes, and put together in the pipeline class.  \nAll the control parameters are can be acessed in the [Configuration Class](#3) section","metadata":{},"attachments":{"aa2c2574-44d8-4728-878a-3a6302d1c129.png":{"image/png":"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"}}},{"cell_type":"markdown","source":"<a id=\"3\"></a>\n# <p style=\"background-color:#281F2F;height: 60px;text-align: center;vertical-align: middle;line-height: 60px;;font-family:helvetica;color:#FFFFFF;font-size:120%;text-align:center;border-radius:12px 12px;\">~ ~ ~ ~ Configuration Class ~ ~ ~ ~</p>\n[back top](#1)","metadata":{}},{"cell_type":"code","source":"#==================================================================================\n# Configuration Class\n#----------------------------------------------------------------------------------\nclass Configuration:\n    \n    def __init__(self):\n\n        ################# in\\out paths\n        self.dir_path = '../input/birdclef-2022/train_audio'\n        self.save_path = './'\n        self.ext_save = 'png'\n        self.orig = './'\n\n        # Scored birds\n        self.meta_data_path = '../input/birdclef-2022/train_metadata.csv'\n        self.scored_birds    = pd.read_json('../input/birdclef-2022/scored_birds.json')[0].values\n        self.filter_birds   = True\n        \n        ######### Loader Audio \n        self.duration    = 60\n        self.sample_rate = 22050\n        self.is_mono     = True\n        \n        ################ Audio Processor\n        #_noise_reduction\n        self.n_fft_a = 2048\n        self.win_length_a = 1024\n        self.use_tqdm_a = False\n        #_limit_threshold\n        self.rate_a = 1.5\n        #_low_pass\n        self.lowcut_a = 955\n        self.highcut_a = 8005\n        self.order_a=5\n        #Hilbert \n        self.hilbert = False\n        \n        ################### Spectogram\n        #image - Spect\n        self.frame_size = 5 # seg\n        self.frame_step = 5  # seg\n        \n        # Spectogram Transformer\n        # Default Spec (librosa)\n        self.hop_length  = 128\n        self.frame_size_t  = 256\n        \n        #Mel spect (Torch)\n        self.n_mels     = 250\n        self.n_fft      = 2048\n        self.win_length = 1024\n        self.f_min      = 500\n        self.f_max      = 9000\n        \n        ###################### Image Processor\n        self.kernel_e_i = np.ones((2,2),np.uint8)\n        self.iteration_e_i = 2\n        \n        self.kernel_d_i = np.ones((3,3),np.uint8)\n        self.iteration_d_i = 2\n        \n        ################  Data Augmentation\n        self.max_ite = 4\n        self.force_tras_1 = True\n        \n        #mix up 1\n        self.mix_imgs = 3\n        \n        #################### Padding\n        self.padValue = 2\n        self.minTime = 5\n        \n        self.birds_to_filter = ['apapan']\n       \n        #beta\n        self.th_bird_files = 200\n        self.device = 'cpu'\n","metadata":{"execution":{"iopub.status.busy":"2022-05-27T17:41:07.670388Z","iopub.execute_input":"2022-05-27T17:41:07.670630Z","iopub.status.idle":"2022-05-27T17:41:07.682943Z","shell.execute_reply.started":"2022-05-27T17:41:07.670604Z","shell.execute_reply":"2022-05-27T17:41:07.682080Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"3-2\"></a>\n# <p style=\"background-color:#281F2F;height: 60px;text-align: center;vertical-align: middle;line-height: 60px;;font-family:helvetica;color:#FFFFFF;font-size:120%;text-align:center;border-radius:12px 12px;\">~ ~ ~ ~ Load Audio ~ ~ ~ ~</p>\n\n- In this section is presented the class that loads the audio files into arrays using the librosa library\n\n[back top](#1)","metadata":{}},{"cell_type":"code","source":"#==================================================================================\n# Load Audio \n#----------------------------------------------------------------------------------\n\nclass LoadAudio(Configuration):\n    \"\"\"Load Imagem from path\"\"\"\n    \n    def __init__(self):\n        super().__init__()\n        \n    def load(self, path):\n        wave, _  =  librosa.load(path, \n                              sr = self.sample_rate,\n                              mono = self.is_mono,\n                              )\n        \n        wave_params = self._getParameters(wave)\n\n        return wave, wave_params\n    \n    def _getParameters(self, wave):\n        N = len(wave)                                     # Number of samples\n        T = 1.0 / self.sample_rate                        # period\n        x_t = np.linspace(0.0, N*T, N)                    # Time\n        x_f = np.linspace(0.0, 1.0/(2.0*T), int(N/2))     # frequencies\n        \n        return (N, T, x_t, x_f)\n\n\nclass getFiles(Configuration):\n    def __init__(self):\n        super().__init__()\n        \n    def run(self):\n        path = []\n        for base, dirs, files in os.walk(self.dir_path):\n        #     print('Searching in : ',base)\n            for d in (dirs):\n\n                for i in os.listdir((self.dir_path+'/'+ d)):\n                    path.append(d+'/'+i)\n    \n        if self.birds_to_filter:\n            path = [p for p in path for bird in self.birds_to_filter if p.startswith(bird) ]\n            \n        return path\n","metadata":{"execution":{"iopub.status.busy":"2022-05-27T17:41:07.684068Z","iopub.execute_input":"2022-05-27T17:41:07.684314Z","iopub.status.idle":"2022-05-27T17:41:07.700908Z","shell.execute_reply.started":"2022-05-27T17:41:07.684285Z","shell.execute_reply":"2022-05-27T17:41:07.700101Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"2\"></a>\n# <p style=\"background-color:#281F2F;height: 60px;text-align: center;vertical-align: middle;line-height: 60px;;font-family:helvetica;color:#FFFFFF;font-size:120%;text-align:center;border-radius:12px 12px;\">~ ~ ~ ~ Meta Data ~ ~ ~ ~</p>\n\n- In this section the class reads the meta data dataframe and used as base to process the files and filters  \n[back top](#1)","metadata":{}},{"cell_type":"code","source":"#==================================================================================\n# Meta data Processor \n#---------------------------------------------------------------------------------- \nclass Process_meta(Configuration):\n\n    def __init__(self):\n        super().__init__()\n        \n    def read(self):\n        self.train_meta = pd.read_csv(self.meta_data_path)\n        if self.filter_birds:\n            self._filter_birds()\n        if True:\n            self.setFileName()\n    \n    def _filter_birds(self):\n        self.train_meta = self.train_meta[self.train_meta['primary_label'].isin(self.scored_birds)]\n        \n    def _getFiles(self):\n        return self.train_meta['filename'].values\n    \n    def _getTrain_meta(self):\n        return self.train_meta\n\n    def setFileName(self):\n        self.train_meta['name_f'] = self._getTrain_meta()['filename'].apply(lambda x:( x.split('/')[1].split('.')[0]))\n","metadata":{"execution":{"iopub.status.busy":"2022-05-27T17:41:07.703207Z","iopub.execute_input":"2022-05-27T17:41:07.703527Z","iopub.status.idle":"2022-05-27T17:41:07.717161Z","shell.execute_reply.started":"2022-05-27T17:41:07.703487Z","shell.execute_reply":"2022-05-27T17:41:07.716294Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"4\"></a>\n# <p style=\"background-color:#281F2F;height: 60px;text-align: center;vertical-align: middle;line-height: 60px;;font-family:helvetica;color:#FFFFFF;font-size:120%;text-align:center;border-radius:12px 12px;\">~ ~ ~ ~ Spectogram Trasnformers ~ ~ ~ ~</p>\n\n- In this section is presented the different spectograms transformers avaliable\n    - Spectogram\n    - Melspectogram\n    - CPEN Melsptogram  \n  \n[back top](#1)","metadata":{}},{"cell_type":"code","source":"#==================================================================================\n# Spectogram Transformers \n#----------------------------------------------------------------------------------\nclass SpectogramaTransformer_librosa(Configuration):\n    \n    def __init__(self):\n        super().__init__()\n        \n    def transform(self, wave):\n        spectrogram = librosa.stft(wave,\n                            n_fft=self.frame_size_t,\n                            hop_length=self.hop_length)[:-1]\n        \n#         spectrogram = np.abs(spectrogram)\n#         db_spectrogram = librosa.amplitude_to_db(spectrogram)\n        return spectrogram\n\n\nclass CPENSpectoramTransformer_librosa(Configuration):\n    def __init__(self):\n        super().__init__()\n\n    def transform(self, melspect):\n        spectogram = librosa.pcen(melspect * (2 ** 31), \n                                  eps = 1e-6,\n                                  gain = 0.8,\n                                  power = 0.25,\n                                  bias = 10, \n                                  sr = self.sample_rate,\n                                  hop_length = self.hop_length)\n        return spectogram\n\n\n\n\nclass melSpectogramTransformer_torch(Configuration):\n    \n    def __init__(self):\n        super().__init__()\n    \n    def transform(self,wave):\n        transfomer = torchaudio.transforms.MelSpectrogram(sample_rate = self.sample_rate,\n                                                         n_fft = self.n_fft, \n                                                         win_length = self.win_length,\n                                                         n_mels = self.n_mels,\n                                                         f_min = self.f_min,\n                                                         f_max = self.f_max ).double().to(self.device)\n        \n\n        wave = torch.from_numpy(wave.copy()).to(self.device)\n        \n        mel_spectrogram = transfomer(wave)\n        mel_spectrogram = np.array(mel_spectrogram)\n        \n        return mel_spectrogram\n \n","metadata":{"execution":{"iopub.status.busy":"2022-05-27T17:41:07.718392Z","iopub.execute_input":"2022-05-27T17:41:07.718585Z","iopub.status.idle":"2022-05-27T17:41:07.735047Z","shell.execute_reply.started":"2022-05-27T17:41:07.718562Z","shell.execute_reply":"2022-05-27T17:41:07.734229Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"5\"></a>\n# <p style=\"background-color:#281F2F;height: 60px;text-align: center;vertical-align: middle;line-height: 60px;;font-family:helvetica;color:#FFFFFF;font-size:120%;text-align:center;border-radius:12px 12px;\">~ ~ ~ ~ Audio Processor ~ ~ ~ ~</p>\n[back top](#1)","metadata":{}},{"cell_type":"code","source":"# #==================================================================================\n# # Audio Processor  (Done externaly)\n# #----------------------------------------------------------------------------------\n# class Audio_Processer(Configuration):\n    \n#     def __init__(self):\n#         super().__init__()\n        \n#     def run(self, wave, params):\n        \n#         wave = (self._remove_continuous_component(wave))\n#         wave = (self._normalization(wave))\n#         wave = (self._noise_reduction(wave))\n#         #freq_cut = fft(self._limit_threshold(wave, params))\n#         wave = (self._low_filter(wave))\n# #         wave, wave_hb = (self._hilbert_transform(wave))\n\n#         if self.hilbert:\n#             return wave_hb\n#         return wave\n    \n#     def _remove_continuous_component(self, y_t):\n#         return y_t  - np.mean(y_t)\n    \n#     def _normalization(self,y_t):\n#         return y_t/np.max(y_t)\n\n#     def _noise_reduction(self, y_t):\n#         y_ = nr.reduce_noise(y = y_t,\n#                             sr = self.sample_rate,\n#                             n_fft = self.n_fft_a,\n#                             win_length = self.win_length_a,\n#                             use_tqdm = self.use_tqdm_a,\n#                             n_jobs = 2)\n\n#         return np.array(y_)\n    \n#     def _limit_threshold(self,y_t, params):\n#         N, T, x_t, x_f = params\n        \n#         y_f = fft(y_t)\n#         y_f = 2.0/N * np.abs(y_f[:N//2])\n#         mean_yf = np.mean(y_f)\n#         std_yf = np.std(y_f)\n#         distances = np.power(y_f - mean_yf, 2) \n#         index = distances.argmin()\n\n#         if x_f[index]*taxa >= np.max(x_f):\n#             freq_cut = np.max(x_f)*0.95\n#         else:\n#             freq_cut = x_f[index]*self.rate_a \n\n#         return freq_cut\n    \n#     def _low_filter(self,y_t):\n#         nyq = 0.5 * self.sample_rate\n#         low = self.lowcut_a / nyq\n#         high = self.highcut_a / nyq\n#         b, a = butter(self.order_a, [low, high], btype='bandpass', analog=False, output='ba')\n#         y_ = filtfilt(b, a, y_t)\n\n#         return y_\n    \n#     def _hilbert_transform(self,y_t):\n#         analytical_signal = hilbert(y_t)\n#         y_ = np.abs(analytical_signal)\n#         hilbert_fft = fft(y_)\n#         return y_, hilbert_fft\n\n\n\n","metadata":{"execution":{"iopub.status.busy":"2022-05-27T17:41:07.737271Z","iopub.execute_input":"2022-05-27T17:41:07.737683Z","iopub.status.idle":"2022-05-27T17:41:07.750836Z","shell.execute_reply.started":"2022-05-27T17:41:07.737641Z","shell.execute_reply":"2022-05-27T17:41:07.750007Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"6\"></a>\n# <p style=\"background-color:#281F2F;height: 60px;text-align: center;vertical-align: middle;line-height: 60px;;font-family:helvetica;color:#FFFFFF;font-size:120%;text-align:center;border-radius:12px 12px;\">~ ~ ~ ~ Image Processor ~ ~ ~ ~</p>\n\n- This section implements some image processaments:\n    - erosion\n    - dilation\n \n[back top](#1)","metadata":{}},{"cell_type":"code","source":"\n#==================================================================================\n# Image Processor \n#----------------------------------------------------------------------------------\nclass Image_processor(Configuration):\n    def __init__(self):\n        super().__init__()\n        \n    def transform(self, spect):\n        \n        spect_type_ori =  type(spect)\n        spect = self._setSpecType(spect, np.ndarray)\n        \n        spect = self._erosion(spect)\n        spect = self._dilation(spect)\n        \n        spect = self._setSpecType(spect, spect_type_ori)\n        \n        return spect\n    \n    def _erosion(self, spect):\n        img_erosion = cv2.erode(spect, self.kernel_e_i, self.iteration_e_i)\n        return img_erosion\n    \n    def _dilation(self, spect):\n        img_dilate = cv2.dilate(spect, self.kernel_d_i, self.iteration_d_i)\n        return img_dilate\n    \n    def _setSpecType(self, spect, to_type):\n        \n        if to_type == np.ndarray:\n            return np.array(spect)\n        elif to_type == torch.Tensor:\n            return torch.from_numpy(spect)\n        else:\n            print(\"error\")\n        ","metadata":{"execution":{"iopub.status.busy":"2022-05-27T17:41:07.751856Z","iopub.execute_input":"2022-05-27T17:41:07.752387Z","iopub.status.idle":"2022-05-27T17:41:07.768335Z","shell.execute_reply.started":"2022-05-27T17:41:07.752354Z","shell.execute_reply":"2022-05-27T17:41:07.767663Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"7\"></a>\n# <p style=\"background-color:#281F2F;height: 60px;text-align: center;vertical-align: middle;line-height: 60px;;font-family:helvetica;color:#FFFFFF;font-size:120%;text-align:center;border-radius:12px 12px;\">~ ~ ~ ~ Data Augmentation ~ ~ ~ ~</p>\n\n- This section inplements strategies of data augmentation:\n    - time mask\n    - frequency mask\n    - mixup\n\n[back top](#1)","metadata":{}},{"cell_type":"code","source":"#==================================================================================\n# Data Augmentation \n#----------------------------------------------------------------------------------\nclass Data_augmentation_spect(Configuration):\n    \n    def __init__(self):\n        super().__init__()\n        \n    \n    def run_masks(self, spect):\n        prob = np.random.random(2)\n#         transformations_list = [self._time_mask, self._freq_mask]\n        transformations_list = [self._freq_mask]\n\n        transformations = [i for (i, v) in zip(transformations_list, prob > 0.5) if v]\n        \n        #at least one\n        if ((not transformations) & (self.force_tras_1)):\n            transformations = [(transformations_list[np.random.randint(len(transformations_list))])]\n        \n#         print(f'Transformations:{len(transformations)}')\n        spect = torch.from_numpy(spect.copy())\n        for t in transformations:\n            \n            spect = t(spect)\n            \n        return spect\n        \n    \n    def _time_mask(self, spect):\n        it = np.random.randint(0,(self.max_ite+1))\n        for i in range(it):\n            value = (20 - 10) * np.random.random_sample() + 10\n            t1 = torchaudio.transforms.TimeMasking(time_mask_param= value)\n            \n            spect = t1(spect)\n            \n        return spect\n    \n    def _freq_mask(self, spect):\n        it = np.random.randint(0,(self.max_ite+1))\n        for i in range(it):\n            value = (20 - 10) * np.random.random_sample() + 10\n            t2 = torchaudio.transforms.FrequencyMasking(freq_mask_param = value)\n            spect = t2(spect)\n        return spect\n\n    def mixUp(self,spect_list):\n        if len(spect_list) >=3:\n            selected   = np.random.choice(range(0, len(spect_list)), 3,replace = False)\n            spect_list =  [spect_list[i] for i in selected]\n            mix_spect = sum(spect_list)\n            return mix_spect,selected\n        return spect_list[0],0\n            \n    def mixUp_2(self,spect_list):\n        \n        selected   = np.random.choice(range(0, len(spect_list)), self.mix_imgs,replace = False)\n        spect_list =  [spect_list[i] for i in selected]\n        \n        lam = np.clip(np.random.beta(3,3),0.3,0.7)\n        lam_shuffle = 1-lam\n        mix_spect = lam*spect_list[0] + lam_shuffle*spect_list[1]\n        return mix_spect,selected","metadata":{"execution":{"iopub.status.busy":"2022-05-27T17:41:07.769737Z","iopub.execute_input":"2022-05-27T17:41:07.769967Z","iopub.status.idle":"2022-05-27T17:41:07.785092Z","shell.execute_reply.started":"2022-05-27T17:41:07.769939Z","shell.execute_reply":"2022-05-27T17:41:07.784308Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"8\"></a>\n# <p style=\"background-color:#281F2F;height: 60px;text-align: center;vertical-align: middle;line-height: 60px;;font-family:helvetica;color:#FFFFFF;font-size:120%;text-align:center;border-radius:12px 12px;\">~ ~ ~ ~ Save Function ~ ~ ~ ~</p>\n\nThis section implements the save class to save all the image generate in the pipeline.  \n[back top](#1)","metadata":{}},{"cell_type":"code","source":"#=====================================================================\n# Saver class\n#---------------------------------------------------------------------\nclass Saver(Configuration):\n    def __init__(self):\n        super().__init__()\n    \n    \n    def init_save_folder(self):\n        if not os.path.exists(self.save_path):\n            os.mkdir(self.save_path)\n    \n    def new_folder(self, folder):\n        if not os.path.exists((self.save_path +'/'+folder)):\n            os.mkdir((self.save_path +'/' + folder))\n            \n    def save_image(self, img, folder, name, t = 'jpg'):\n        self.new_folder(folder)\n        file_path = self.save_path + '/' + folder + '/' + name + '.' + t\n        print(f'saving...{file_path}')\n        # imageio.imwrite(file_path,img) #funcionando\n        np.save(file_path, img)\n        # np.savez_compressed(file_path, img)\n\n\nclass slicing_by_qt(Configuration):\n    \n    def __init__(self):\n        super().__init__()\n        \n    def generate_data(self):\n        audio_num_birds = {}\n        for base, dirs, files in os.walk(self.dir_path):\n        #     print('Searching in : ',base)\n            for d in (dirs):\n                Audio_num_birds[d] = [0]\n                for i in os.listdir((self.dir_path + '/' + d)):\n                    Audio_num_birds[d][0]+=1\n\n        data = pd.DataFrame.from_dict(Audio_num_birds, 'index', columns =['count'])\n        data['high'] = data['count'].apply(lambda x: 1 if x > self.th_bird_files else 0)\n        return data\n","metadata":{"execution":{"iopub.status.busy":"2022-05-27T17:41:07.786208Z","iopub.execute_input":"2022-05-27T17:41:07.786458Z","iopub.status.idle":"2022-05-27T17:41:07.805783Z","shell.execute_reply.started":"2022-05-27T17:41:07.786431Z","shell.execute_reply":"2022-05-27T17:41:07.804898Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"9\"></a>\n# <p style=\"background-color:#281F2F;height: 60px;text-align: center;vertical-align: middle;line-height: 60px;;font-family:helvetica;color:#FFFFFF;font-size:120%;text-align:center;border-radius:12px 12px;\">~ ~ ~ ~ Pipeline ~ ~ ~ ~</p>\n\n- This section presents the pipeline class. It is possible to pass different classes that implements other types of functions in the processors\\tranformers\\augmentation. \n- Also, the pipeline class implements some usefull methods to print images, padding the audio or get files names.\n  \n[back top](#1)","metadata":{}},{"cell_type":"code","source":"#==================================================================================\n# Pipeline \n#----------------------------------------------------------------------------------\nclass ProcessingPipiline(Configuration):\n    \"\"\"Main Class of the processing birds songs\"\"\"\n        \n    \n    def __init__(self):\n        super().__init__()\n        self.meta_processor = None\n        self.audio_treater = None\n        self.spect_transformer = None\n        self.cpen_transformer = None\n        self.image_processor = None\n        self.data_augmentation = None\n        self.slicer = slicing_by_qt()\n        self.loader = LoadAudio()\n        self.saver = Saver()\n        \n    \n    def run(self, log = True):\n        self.saver.init_save_folder()\n        # self.meta_processor.read()\n        \n        \n        # Files = self.meta_processor._getFiles()\n        Files = getFiles().run()\n        \n        for file in tqdm(Files):\n            file_path = os.path.join(self.dir_path, file)\n            \n            if log: print(f'>Processing:{file_path}')\n            print(file)\n            #file saver manager\n            folder, name = self._getFileName(file)\n            self.saver.new_folder(folder)\n            \n            self.saver.new_folder((folder+'/original'))\n            self.saver.new_folder((folder+'/image_processor'))\n            self.saver.new_folder((folder+'/augmented'))\n            self.saver.new_folder((folder+'/mix_up_ori'))\n            self.saver.new_folder((folder+'/mix_up_aug'))\n            \n            #load audio\n            print(f'>> Loading: {file_path}....')\n            wave, wave_params = self.loader.load(file_path)\n            x_t = wave_params[2][-1]\n            \n            if self.audio_treater:\n                wave = self._apply_audio_treatment(wave, wave_params)\n                \n                \n            step = int(self.frame_step * self.sample_rate)     \n            size = int(self.frame_size * self.sample_rate)    \n            \n            #padding\n            if x_t < self.minTime:\n              wave = self._padding(wave, x_t,size)\n              \n           \n            # if wave_params[2][-1]>=self.frame_size:\n            frames_original = []\n            frames_transformed = []\n            windows = ((wave.size - (size - 1) - 1)/step) + 1\n        \n            for i in range(int(windows)):\n                begin = i * step\n                frame = wave[begin:begin + size]\n                \n                #transform into spectogram\n                if self.spect_transformer:\n                    frame = self._apply_spect_transformations(frame)\n                    if self.cpen_transformer:\n                      #apply CPEN Transform into spectogram\n                      frame = self.cpen_transformer.transform(frame)\n                      \n                    \n\n                    save_name = name + '_original_' +str(i)\n                    self.saver.save_image(librosa.amplitude_to_db(frame),(folder+'/original'),save_name, t = self.ext_save)\n                    \n                    frames_original.append(librosa.amplitude_to_db(np.array(frame)).copy())\n                    \n                if self.image_processor:\n                    frame = self._apply_image_processor(frame)\n                    save_name = name + '_image_processor_' +str(i)\n                    self.saver.save_image(librosa.amplitude_to_db(frame),(folder+'/image_processor'),save_name, t = self.ext_save)\n                \n                if self.data_augmentation:\n                    frame = self.data_augmentation.run_masks(frame)\n                    save_name = name + '_aug_' +str(i)\n                    self.saver.save_image(librosa.amplitude_to_db(frame),(folder+'/augmented'),save_name, t = self.ext_save)\n            \n                \n                \n                frame = librosa.amplitude_to_db(frame)\n                frames_transformed.append((frame))\n\n                # self._printImage(frames_transformed[0], frames_original[0], compare = True)\n                # break\n                \n\n            if self.data_augmentation:\n                frame_mix_ori, select = self.data_augmentation.mixUp(frames_original)\n                save_name = name + '_mixori_' +str(i)\n                self.saver.save_image(frame_mix_ori,(folder+'/mix_up_ori'),save_name, t = self.ext_save)\n\n                frame_mix_aug, select = self.data_augmentation.mixUp(frames_transformed)\n                save_name = name + '_mixug_' +str(i)\n                self.saver.save_image(frame_mix_aug,(folder+'/mix_up_aug'),save_name, t = self.ext_save)\n        # except:\n            #         print(f'erro no audio {file_path}')\n\n                \n    def _apply_image_processor(self, spect):\n        return self.image_processor.transform(spect)\n    \n    def _apply_audio_treatment(self, wave,wave_params):\n        return self.audio_treater.run(wave,wave_params)\n    \n    def _apply_spect_transformations(self, frame):\n        #transform into spectogram\n        spect = self.spect_transformer.transform(frame)\n\n        return spect\n\n    def _printImage(self, spect_t, spect =[], compare = False):\n        if compare:\n            fig, ax = plt.subplots(nrows = 1, ncols = 2, figsize = (20,10))\n            \n            ax[0].imshow(spect, aspect = 'auto',origin='lower')\n            ax[0].set_title('original')\n            ax[1].imshow(spect_t, aspect = 'auto',origin='lower')\n            ax[1].set_title('transformed')\n\n        else:\n            plt.imshow(spect_t, aspect = 'auto',origin='lower')\n\n        \n    def _getFileName(self,file_path):\n        folder, name = file_path.split('/')\n        name = name.split('.')[0]\n        return folder, name\n\n    def _padding(self, wave, x_t, size):\n        print('>> Padding...')\n        diff = size - int(x_t*self.sample_rate)\n        wave = np.pad(wave, (0, diff+self.padValue), 'constant', constant_values = (0.0000, 0.0000))\n        return wave","metadata":{"execution":{"iopub.status.busy":"2022-05-27T17:41:07.808628Z","iopub.execute_input":"2022-05-27T17:41:07.808948Z","iopub.status.idle":"2022-05-27T17:41:07.833200Z","shell.execute_reply.started":"2022-05-27T17:41:07.808906Z","shell.execute_reply":"2022-05-27T17:41:07.832507Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"10\"></a>\n## <p style=\"background-color:#281F2F;height: 60px;text-align: center;vertical-align: middle;line-height: 60px;;font-family:helvetica;color:#FFFFFF;font-size:120%;text-align:center;border-radius:12px 12px;\">~ ~ ~ ~ Loading and Run ~ ~ ~ ~</p>\n[back top](#1)","metadata":{}},{"cell_type":"code","source":"pipeline = ProcessingPipiline()\npipeline.meta_processor = Process_meta()\n# pipeline.audio_treater = Audio_Processer()\n# pipeline.spect_transformer = SpectogramaTransformer_librosa() \npipeline.spect_transformer = melSpectogramTransformer_torch() \npipeline.cpen_transformer = CPENSpectoramTransformer_librosa()\npipeline.image_processor = Image_processor()\npipeline.data_augmentation = Data_augmentation_spect()\n","metadata":{"execution":{"iopub.status.busy":"2022-05-27T17:41:07.834178Z","iopub.execute_input":"2022-05-27T17:41:07.835622Z","iopub.status.idle":"2022-05-27T17:41:07.879214Z","shell.execute_reply.started":"2022-05-27T17:41:07.835578Z","shell.execute_reply":"2022-05-27T17:41:07.878345Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"11\"></a>\n## <p style=\"background-color:#281F2F;height: 60px;text-align: center;vertical-align: middle;line-height: 60px;;font-family:helvetica;color:#FFFFFF;font-size:120%;text-align:center;border-radius:12px 12px;\">~ ~ ~ ~ RUN ~ ~ ~ ~</p>\n[back top](#1)","metadata":{}},{"cell_type":"code","source":"pipeline.run()","metadata":{"execution":{"iopub.status.busy":"2022-05-27T17:41:07.880699Z","iopub.execute_input":"2022-05-27T17:41:07.881081Z","iopub.status.idle":"2022-05-27T17:42:46.650434Z","shell.execute_reply.started":"2022-05-27T17:41:07.881040Z","shell.execute_reply":"2022-05-27T17:42:46.649836Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"15\"></a>\n# <p style=\"background-color:#281F2F;height: 60px;text-align: center;vertical-align: middle;line-height: 60px;;font-family:helvetica;color:#FFFFFF;font-size:120%;text-align:center;border-radius:12px 12px;\">~ ~ ~ ~ RESULT EXAMPLE ~ ~ ~ ~</p>\n[back top](#1)","metadata":{}},{"cell_type":"code","source":"\nfiles = {'XC174948':6,'XC385165':35,'XC327355':18}\nfig, ax = plt.subplots(ncols = 5,nrows = len(files), figsize = (12,10))\nfor j, f in enumerate(files.keys()):\n    i = 0\n    for treat, name_ in zip(['original','image_processor','augmented','mix_up_aug', 'mix_up_ori'],['original','image_processor','aug','mixug','mixori']):\n        file_path = f'./apapan/{treat}/{f}_{name_}_{files[f]}.png.npy'\n        img = np.load(file_path)\n        ax[j,i].imshow(img)\n        ax[j,i].set_title(treat)\n        \n        if i == 0:\n            ax[j,i].set_ylabel(f)\n        \n        i+=1","metadata":{"execution":{"iopub.status.busy":"2022-05-27T17:55:46.481808Z","iopub.execute_input":"2022-05-27T17:55:46.482618Z","iopub.status.idle":"2022-05-27T17:55:48.228448Z","shell.execute_reply.started":"2022-05-27T17:55:46.482571Z","shell.execute_reply":"2022-05-27T17:55:48.227540Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id=\"12\"></a>\n# <p style=\"background-color:#281F2F;height: 60px;text-align: center;vertical-align: middle;line-height: 60px;;font-family:helvetica;color:#FFFFFF;font-size:120%;text-align:center;border-radius:12px 12px;\">~ ~ ~ ~ END ~ ~ ~ ~</p>\n[back top](#1)","metadata":{}},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}