grapevine_classification / utilitarios /prepara_dataset_segmentacao.py
gabri14el's picture
Upload with huggingface_hub
e6b3e35
# -*- coding: utf-8 -*-
"""
Created on Tue Jan 19 13:24:25 2021
Código utilizado para gerar as máscaras e as imagens a partir dos videos e marcações XML geradas pelo sensarea.
@author: Gabriel
"""
import cv2
import glob
import os
import pandas as pd
import datetime
import shapely
import xml.etree.ElementTree as et
from shapely.geometry import Polygon
#import geopandas as gpd
from shapely.ops import unary_union
import numpy as np
import cv2
def get_polygons(path):
xtree = et.parse(path)
xroot = xtree.getroot()
masks = xroot.find("masks")
df = pd.DataFrame(columns=['frame', 'polygon'])
for mask in masks:
dic = {}
dic['frame'] = int(mask.find('frame').text)
pontos = mask.find('polygon').attrib.get('points')
tokens = pontos.split(' ')
poly = []
for token in tokens[:-1]:
ponto = token.split(',')
poly.append((int(ponto[0]), int(ponto[1])))
dic['polygon'] = poly
df = df.append(dic, ignore_index=True)
return df
#fonte: https://www.pyimagesearch.com/2015/09/07/blur-detection-with-opencv/
def variance_of_laplacian(image):
# compute the Laplacian of the image and then return the focus
# measure, which is simply the variance of the Laplacian
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
return cv2.Laplacian(image, cv2.CV_64F).var()
path = "C:\\Users\\Gabriel\\OneDrive - Universidade de Tras-os-Montes e Alto Douro\\UTAD\\2020-2021\\Pesquisa\\Dataset\\Vídeos\\organizado\\dividido"
path_xml = "C:\\Users\\Gabriel\\OneDrive - Universidade de Tras-os-Montes e Alto Douro\\UTAD\\2020-2021\\Pesquisa\\Dataset\\Vídeos\\mascaras"
os.chdir(path)
#image_quantity=20
#configuracoes de tamanho: [tamanho da imagem, tamanho do stride, percentual minimo de planta para salvar a imagem]
configs = [[512, int(512/2), 0.80, 0.5], [800, int(800/3), 0.80, 0.5]]
#quantidade de frames que serão "pulados"
next_frame = 30
#dimensoes para salvar
dim_salvar = 512
tam_salvar = (dim_salvar, dim_salvar)
columns = ['path', 'class', 'name', 'data_str', 'dia', 'mes', 'ano', 'set']
df=pd.DataFrame(columns=columns)
parser = {'junho':'06',
'mai':'05',
'agosto':'08',
'julho':'07',
'set':'09',
'maio':'05',
'ago':'08'}
for root, dirs, files in os.walk(path):
for file in files:
if file.endswith(".MTS"):
dic = {}
dic['path'] = os.path.join(root, file)
dic['name'] = dic['path'].split(os.path.sep)[-1]
dic['class'] = dic['path'].split(os.path.sep)[-2]
dic['set'] = dic['path'].split(os.path.sep)[-3]
df=df.append(dic, ignore_index=True)
print(df.head())
#verifiva se diritorio existe
path_to_save = 'C:\\Users\\Gabriel\\Downloads\\teste_masks_crop3'
if not os.path.exists(path_to_save):
os.mkdir(path_to_save)
for i, row in df.iterrows():
for folder in ['image', 'mask']:
#verificar se diretorio para salvar imagem existe: diretorio/conjunto/classe
if not os.path.exists(os.path.join(path_to_save, row['set'], folder)):
#os.mkdir(os.path.join(path_to_save, folder, row['set']))
os.makedirs(os.path.join(path_to_save, row['set'], folder), exist_ok=True)
#if not os.path.exists(os.path.join(path_to_save, folder, row['set'],row['class'])):
#os.mkdir(os.path.join(path_to_save, folder, row['set'], row['class']))
#os.makedirs(os.path.join(path_to_save, folder, row['set'], row['class']), exist_ok=True)
#le video
cap = cv2.VideoCapture(row['path'])
#captura quantidade de frames do video
length = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
#define path e le arquivo de poligonos
path_polygon = os.path.join(path_xml, row['class'], row['name'].split('.')[0]+'.xml')
#verifica se o arquivo existe
df_polygon = None
if os.path.isfile(path_polygon):
df_polygon = get_polygons(os.path.join(path_xml, row['class'], row['name'].split('.')[0]+'.xml'))
n_frame = 0
continua = True
print('Video: ', row['path'])
while(continua):
#cap.set(cv2.CAP_PROP_POS_FRAMES, (step*i)-1)
res, frame = cap.read()
if res:
try:
#captura altura e largura do frame
altura_imagem, largura_imagem = frame.shape[:2]
#como o indice e igual ao numero do frame pode-se usar a busca direta no dataframe para se obter o poligono
#e entao gerar uma representacao com a biblioteca shapely
frame_polygon = None
#verifica se arquivo existe
if not df_polygon is None:
frame_polygon = Polygon(df_polygon.iloc[n_frame]['polygon']).buffer(0)
#transformar multipoligono num poligono so
if frame_polygon.geom_type == 'MultiPolygon':
frame_polygon =unary_union(list(frame_polygon))
if frame_polygon.geom_type == 'MultiPolygon':
polys = list(frame_polygon)
area = 0
index = None
for i, pl in enumerate(polys):
if pl.area > area:
area = pl.area
index = i
frame_polygon = polys[index]
#mask = np.zeros((altura_imagem, largura_imagem))
mask = np.full((altura_imagem, largura_imagem), 0, dtype=np.uint8)
coords = np.array([[x[0], x[1]] for x in list(frame_polygon.exterior.coords)], dtype=np.int32)
coords = coords.reshape((-1,1,2))
mask = cv2.fillPoly(mask,[coords], 1)
#itera sobre as configuracoes de recorte
for c, config in enumerate(configs):
#definicao de tamanho de recorte para os quadrados
image_size_side = config[0]
#para definir o overlaping entre as imagens, nesse caso sem overlaping
stride = config[1]
#percentual minimo de planta necessario no poligono para salvar
percentual_maximo = config[2]
percentual_minimo = config[3]
altura = 0
#itera sobre a altura da imagem
k = 0
while(altura+image_size_side < altura_imagem):
largura = 0
#itera sobre a largura da imagem
while(largura+image_size_side < largura_imagem):
#corta imagem
crop_img = frame[altura:altura+image_size_side, largura:largura+image_size_side]
#corta poligono
crop_polygon = Polygon([(altura, largura), (altura, largura+image_size_side), (altura+image_size_side, largura+image_size_side), (altura+image_size_side, largura)])
#corta mascara
crop_mask = mask[altura:altura+image_size_side, largura:largura+image_size_side]
#resize das imagens
resized = cv2.resize(crop_img, tam_salvar, interpolation = cv2.INTER_AREA)
resized_mask = cv2.resize(crop_mask, tam_salvar, interpolation = cv2.INTER_AREA)
#se o poligono existir faz os calculos para verificar se salva os crops
if (crop_polygon.intersects(frame_polygon)):
area_interseccao = crop_polygon.intersection(frame_polygon).area
area_crop_polygon = crop_polygon.area
if(area_interseccao/area_crop_polygon > percentual_minimo and area_interseccao/area_crop_polygon <= percentual_maximo):
cv2.imwrite(os.path.join(path_to_save, row['set'], 'image', row['class']+'-'+ row['name'].split('.')[0]+'-{}-{}-{}-{},{}_{},{}.jpg'.format(n_frame, c, k, largura, altura, largura+image_size_side, altura+image_size_side)), resized)
cv2.imwrite(os.path.join(path_to_save, row['set'], 'mask', row['class']+'-'+ row['name'].split('.')[0]+'-{}-{}-{}-{},{}_{},{}.png'.format(n_frame, c, k, largura, altura, largura+image_size_side, altura+image_size_side)), resized_mask)
# print('nome: ', os.path.join(path_to_save, row['set'], row['class'], row['name']+'-{}-{}.jpg'.format(n_frame, k)))
# print('area interseccao: ', area_interseccao)
# print('area crop: ', area_crop_polygon)
# print('percentual de area: ', area_interseccao/area_crop_polygon)
# print('blurry: ', variance_of_laplacian(crop_img))
# print('---------------------------------\n')
#atualiza a largura com o valor do passo
largura = largura + stride
k = k+1
#atualiza a altura com o valor do passo
altura = altura+stride
#caso o resultado nao exista significa que nao há mais frames e portanto e hora de parar
except:
print("Something else went wrong")
else:
continua = False
print('read falso')
#avanca frames manualmente em 15 frames
for i in range(next_frame):
cap.read()
#conta o avanco mais um, porque no proximo read o avanco nao e contabilizado...
n_frame = n_frame + next_frame + 1
#se avanco se estender aos últimos 10 frames ignora
if n_frame > length-10:
continua = False
#print('ignorando os 10 ultimos frames para evitar perda de processamento e imagens borradas nos videos que nao foram marcados')
#print('=======================================\n')
#libera o video
cap.release()