gabri14el's picture
Upload with huggingface_hub
e6b3e35
# -*- coding: utf-8 -*-
"""
Created on Mon Apr 19 16:11:11 2021
Código utilizado para diminuir a quantidade de imagens do dataset. A ideia foi limitar em termos do tamanho do crop e da data.
@author: Gabriel
"""
import os
import datetime
import pandas as pd
import random
from shutil import copy2
from keras.preprocessing.image import ImageDataGenerator, array_to_img,img_to_array, load_img
img_path = 'C:\\Users\\Gabriel\\OneDrive - Universidade de Tras-os-Montes e Alto Douro\\UTAD\\2020-2021\\Pesquisa\\Dataset\\Gerado\\dataset_versao_manual - ga'
#img_path = 'C:\\Users\\Gabriel\\Downloads\\imagens_geradas_menor_zoom800-800-v3'
teste_path = os.path.join(img_path, 'test')
validacao_path = os.path.join(img_path, 'validation')
treino_path = os.path.join(img_path, 'train')
outpath = 'C:\\Users\\Gabriel\\Downloads\\ga'
sep = os.path.sep
teste_path_out = os.path.join(outpath, 'test')
validacao_path_out = os.path.join(outpath, 'validation')
treino_path_out = os.path.join(outpath, 'train')
#verifica se as paths de saida existem
paths = [outpath, teste_path_out, validacao_path_out, treino_path_out]
for path in paths:
if not os.path.lexists(path):
os.mkdir(path)
#exemplo de nome de arquivo: 2017-05-09_1-0-0-13-300,600_600,900.jpg
def directory_from_df_with_class(df, directory):
"""
Método responsável por transformar as imagens de um dataset num dataframe.
Parameters
----------
df : Dataframe pandas
dataframe que será utilizado para povoar com os elementos. O dataframe será preenchido com os seguintes campos:
['path', 'class', 'date', 'zoom']
directory : String
diretório de onde as imagens serão retiradas.
Returns
-------
df : dataframe pandas
O dataframe povoado.
"""
for r, d, f in os.walk(directory):
for file in f:
row = {}
row['path'] = os.path.join(r, file)
row['class'] = row['path'].split(os.path.sep)[-2]
date_info = file.split('_')[0].split('-')
#captura a data,
row['date'] = datetime.datetime(int(date_info[0]), int(date_info[1]), int(date_info[2]))
row['zoom'] = int(file.split('_')[1].split('-')[2])
#print(row['class'])
df= df.append(row, ignore_index=True)
return df
#exemplo de nome de arquivo: 2017-05-09_1-0-0-13-300,600_600,900.jpg
def directory_from_df_with_class2(df, directory):
"""
Método responsável por transformar as imagens de um dataset num dataframe.
Parameters
----------
df : Dataframe pandas
dataframe que será utilizado para povoar com os elementos. O dataframe será preenchido com os seguintes campos:
['path', 'class', 'date', 'zoom']
directory : String
diretório de onde as imagens serão retiradas.
Returns
-------
df : dataframe pandas
O dataframe povoado.
"""
for r, d, f in os.walk(directory):
for file in f:
row = {}
row['path'] = os.path.join(r, file)
row['class'] = row['path'].split(os.path.sep)[-2]
#print(row['class'])
df= df.append(row, ignore_index=True)
return df
def rand_images_from_df(df, coluna_classe, quantidade=20, zooms = [0, 1, 2]):
"""
Método responsável por sortear aliatoriamente uma quantidade de imagens definidas, por zoom, por data e por classe.
Isso implica que a quantidade de imagens retornadas é: QUANTIDADE DE CLASSES * QUANTIDADE DATAS DE AQUISIÇÃO * QUANTIDADE DE ZOOMS * QUANTIDADE DE IMAGENS PASSADAS POR PARÂMETRO.
Parameters
----------
df : dataframe pandas
Dataframe contendo as seguintes colunas: ['path', 'class', 'date', 'zoom'].
coluna_classe : string
Nome da coluna que representa a classe no dataset.
quantidade : integer, optional
DESCRIPTION. The default is 20. Quantidade de imagens que serão sorteadas, por zoom, por data e por tipo
Returns
-------
df_result : dataframe pandas
Dataframe contendo as seguintes colunas: ['path', 'class', 'date', 'zoom'] com as imagens sorteadas.
"""
#captura as classes
classes = df[coluna_classe].unique()
columns_df = ['path', 'class', 'date', 'zoom']
df_result = pd.DataFrame(columns=columns_df)
#itera sobre as classes
for classe in classes:
df_classe = df[df[coluna_classe] == classe]
#captura a as datas presentes para essa classe
dates = df_classe['date'].unique()
#itera sobre as datas
for date in dates:
df_date = df_classe[df_classe['date'] == date]
#itera sobre os zooms
for zoom in zooms:
df_zoom = df_date[df_date['zoom'] == zoom]
#se o dataset for menor que a quantidade, pula o sorteio adicionando todo ele ao dataset resultante
if len(df_zoom) > quantidade:
#sorteia aleatoriamente
for i in range(quantidade):
indice = random.randint(0, len(df_zoom)-1)
df_result = df_result.append(df_zoom.iloc[[indice]])
#lista_imagens.append(df_classe.iloc[[indice]][path_classe].values[0])
df_zoom.drop(df_zoom.index[[indice]], inplace=True)
else:
df_result = df_result.append(df_zoom, ignore_index=True)
#retorna o dataset
return df_result
def save_images_from_df(df, class_column, path_column, outpath):
"""
Método responsável por copiar as imagens para o novo diretório
Parameters
----------
df : dataframe pandas
Dataframe contendo as imagens que serão copiadas.
class_column : string
nome da coluna que representa a classe no dataframe.
path_column : string
nome da coluna que representa a path par a imagem no dataframe.
outpath : string
path para onde serão copiadas as novas imagens.
Returns
-------
None.
"""
for i, row in df.iterrows():
if not row[path_column] is None:
nome = row[path_column].split(os.path.sep)[-1]
path_destino = os.path.join(outpath, row[class_column])
if not os.path.lexists(path_destino):
os.mkdir(path_destino)
arquivo_path = os.path.join(path_destino, nome)
copy2(row[path_column], arquivo_path)
def augment_dataset(df, path_output, path_column='path', quantity=10):
filenames=df[path_column].values
for img in filenames:
src_fname, ext = os.path.splitext(img)
datagen = ImageDataGenerator(rotation_range=50,
width_shift_range=0.2,
height_shift_range=0.2,
horizontal_flip=True,
brightness_range=[0.6,1.0],
vertical_flip=True)
img = load_img(img)
x = img_to_array(img)
x = x.reshape((1,) + x.shape)
img_name = src_fname.split(os.path.sep)[-1]
class_name = src_fname.split(os.path.sep)[-2]
new_dir = os.path.join(path_output, class_name)
if not os.path.lexists(new_dir):
os.mkdir(new_dir)
#save_fname = os.path.join(new_dir, os.path.basename(img_name))
i = 0
for batch in datagen.flow (x, batch_size=1, save_to_dir = new_dir,
save_prefix = img_name, save_format='jpg'):
i+=1
if i>quantity:
break
#criacao da dataframe
columns_df = ['path', 'class', 'date', 'zoom']
df = pd.DataFrame(columns=columns_df)
#faz dataset para treino
df_train = directory_from_df_with_class(df, treino_path)
print('finalizada a análise do diretório de treino')
#no conjunto de treino se captura 2.5x mais imagens
df_train_random = rand_images_from_df(df_train, 'class', quantidade=10, zooms = [1,2])
print('finalizado o sorteio do diretório de treino')
#faz dataset para validacao
df = pd.DataFrame(columns=columns_df)
df_val = directory_from_df_with_class(df, validacao_path)
print('finalizada a análise do diretório de validação')
df_val_random = rand_images_from_df(df_val, 'class', quantidade=5, zooms = [1,2])
print('finalizado o sorteio do diretório de validação')
#faz dataset para teste
df = pd.DataFrame(columns=columns_df)
df_test = directory_from_df_with_class(df, teste_path)
print('finalizada a análise do diretório de teste')
df_test_random = rand_images_from_df(df_test, 'class', quantidade=5, zooms = [1,2])
print('finalizado o sorteio do diretório de teste')
#salva as imagens
save_images_from_df(df=df_train_random, class_column='class', path_column='path', outpath=treino_path_out)
save_images_from_df(df=df_val_random, class_column='class', path_column='path', outpath=validacao_path_out)
save_images_from_df(df=df_test_random, class_column='class', path_column='path', outpath=teste_path_out)
df_train_random = directory_from_df_with_class2(df, treino_path)
augment_dataset(df_train_random, treino_path_out, quantity=10)