DHEIVER's picture
Update app.py
5deade9 verified
import gradio as gr
import cv2
import numpy as np
import tensorflow as tf
from PIL import Image
import torch
import torch.nn as nn
from torchvision import transforms
from scipy import signal
from skimage import feature
import matplotlib.pyplot as plt
import io
from datetime import datetime
import pandas as pd
import json
class GasAnalyzer:
"""Classe principal para análise de gás e chama"""
def __init__(self):
self.analyzer = FlameAnalyzer()
self.consumption_history = []
self.maintenance_records = []
def save_analysis(self, analysis_data):
"""Salva histórico de análise"""
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
analysis_data['timestamp'] = timestamp
self.consumption_history.append(analysis_data)
return json.dumps(analysis_data, indent=2)
def calculate_efficiency(self, consumption_data):
"""Calcula eficiência do consumo"""
if not consumption_data:
return 0
recent_usage = float(consumption_data['daily_usage'])
baseline = 0.8 # consumo base ideal
efficiency = (baseline / recent_usage) * 100
return min(100, efficiency)
def predict_replacement(self, consumption_history):
"""Prevê data de substituição do gás"""
if not consumption_history:
return None
avg_consumption = np.mean([float(h['daily_usage']) for h in consumption_history])
remaining_days = 13 / avg_consumption # 13kg é o padrão do botijão
replacement_date = datetime.now() + pd.Timedelta(days=remaining_days)
return replacement_date.strftime("%Y-%m-%d")
def generate_maintenance_report(self):
"""Gera relatório de manutenção"""
if not self.maintenance_records:
return "Nenhum registro de manutenção encontrado."
report = "📋 Histórico de Manutenção:\n\n"
for record in self.maintenance_records:
report += f"Data: {record['date']}\n"
report += f"Tipo: {record['type']}\n"
report += f"Observações: {record['notes']}\n"
report += "───────────────────\n"
return report
class FlameAnalyzer:
"""Classe para análise específica da chama"""
def __init__(self):
self.model = self._initialize_model()
def _initialize_model(self):
"""Inicializa o modelo de análise de chama"""
model = tf.keras.Sequential([
tf.keras.layers.Conv2D(32, 3, activation='relu', input_shape=(64, 64, 3)),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Conv2D(64, 3, activation='relu'),
tf.keras.layers.MaxPooling2D(),
tf.keras.layers.Conv2D(64, 3, activation='relu'),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(64, activation='relu'),
tf.keras.layers.Dense(4, activation='softmax')
])
return model
def analyze_flame(self, image):
"""Análise completa da chama"""
img = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR)
features = self.extract_features(img)
health_score = self.calculate_health_score(features)
return features, health_score
def extract_features(self, image):
"""Extrai características da chama"""
features = {}
# Análise de cores em múltiplos espaços de cor
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
lab = cv2.cvtColor(image, cv2.COLOR_BGR2LAB)
# Características de cor
features['color'] = {
'mean_hue': np.mean(hsv[:,:,0]),
'mean_saturation': np.mean(hsv[:,:,1]),
'mean_value': np.mean(hsv[:,:,2]),
'brightness': np.mean(lab[:,:,0]),
'color_a': np.mean(lab[:,:,1]),
'color_b': np.mean(lab[:,:,2])
}
# Análise de forma
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_OTSU)
contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
largest_contour = max(contours, key=cv2.contourArea)
features['shape'] = {
'area': cv2.contourArea(largest_contour),
'perimeter': cv2.arcLength(largest_contour, True),
'circularity': 4 * np.pi * cv2.contourArea(largest_contour) /
(cv2.arcLength(largest_contour, True) ** 2) if cv2.arcLength(largest_contour, True) > 0 else 0
}
# Análise de textura usando GLCM
glcm = feature.graycomatrix(gray, [1], [0], 256, symmetric=True, normed=True)
features['texture'] = {
'contrast': feature.graycoprops(glcm, 'contrast')[0][0],
'homogeneity': feature.graycoprops(glcm, 'homogeneity')[0][0],
'energy': feature.graycoprops(glcm, 'energy')[0][0],
'correlation': feature.graycoprops(glcm, 'correlation')[0][0]
}
return features
def calculate_health_score(self, features):
"""Calcula score de saúde da chama com critérios refinados"""
# Pesos ajustados para características mais relevantes
weights = {
'color': 0.5, # Cor é o indicador mais importante
'shape': 0.3, # Forma da chama
'texture': 0.2 # Textura como complemento
}
# Análise de cor melhorada
color_score = 0
if 'color' in features:
hue = features['color']['mean_hue']
sat = features['color']['mean_saturation']
val = features['color']['mean_value']
# Chama azul ideal: tom azul (200-240), boa saturação (>50), bom brilho (>150)
color_score = (
(0.5 if 200 <= hue <= 240 else 0.3 if 180 <= hue <= 260 else 0.1) +
(0.3 if sat > 50 else 0.1) +
(0.2 if val > 150 else 0.1)
)
# Análise de forma refinada
shape_score = 0
if 'shape' in features:
circularity = features['shape']['circularity']
area = features['shape']['area']
# Chama deve ser razoavelmente circular e ter área adequada
shape_score = (
(0.6 if 0.7 <= circularity <= 0.9 else 0.3) +
(0.4 if area > 1000 else 0.2)
)
else:
shape_score = 0.5 # Valor neutro se não puder calcular
# Análise de textura com limiares ajustados
texture_score = 0
if 'texture' in features:
homogeneity = features['texture']['homogeneity']
energy = features['texture']['energy']
correlation = features['texture']['correlation']
# Chama saudável tem boa homogeneidade e energia moderada
texture_score = (
(0.4 if homogeneity > 0.7 else 0.2) +
(0.3 if 0.2 <= energy <= 0.8 else 0.1) +
(0.3 if correlation > 0.8 else 0.1)
)
# Score final ponderado com normalização
raw_score = (
color_score * weights['color'] +
shape_score * weights['shape'] +
texture_score * weights['texture']
)
# Aplica curva sigmoide para suavizar as transições entre categorias
normalized_score = 1 / (1 + np.exp(-5 * (raw_score - 0.5)))
# Ajusta limiares para evitar falsos positivos
if normalized_score > 0.8:
# Verifica condições adicionais para confirmar ótima condição
if color_score > 0.7 and shape_score > 0.6:
return normalized_score
return 0.75 # Rebaixa para "boa" se não atender critérios estritos
return normalized_score
def create_visualization(image, features, health_score):
"""Cria visualização da análise"""
fig = plt.figure(figsize=(12, 8))
gs = plt.GridSpec(2, 3, figure=fig)
# Imagem original
ax1 = fig.add_subplot(gs[0, 0])
ax1.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
ax1.set_title('Imagem Original')
ax1.axis('off')
# Análise HSV
ax2 = fig.add_subplot(gs[0, 1])
hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
ax2.imshow(hsv[:,:,0], cmap='hsv')
ax2.set_title('Análise de Matiz (HSV)')
ax2.axis('off')
# Detecção de bordas
ax3 = fig.add_subplot(gs[0, 2])
edges = cv2.Canny(cv2.cvtColor(image, cv2.COLOR_BGR2GRAY), 100, 200)
ax3.imshow(edges, cmap='gray')
ax3.set_title('Detecção de Bordas')
ax3.axis('off')
# Gráfico de métricas
ax4 = fig.add_subplot(gs[1, :])
metrics = {
'Saúde da Chama': health_score,
'Homogeneidade': features['texture']['homogeneity'],
'Energia': features['texture']['energy'],
'Correlação': features['texture']['correlation']
}
bars = ax4.bar(metrics.keys(), metrics.values())
ax4.set_ylim(0, 1)
ax4.set_title('Métricas da Análise')
# Colorir barras
for bar in bars:
if bar.get_height() > 0.7:
bar.set_color('green')
elif bar.get_height() > 0.4:
bar.set_color('yellow')
else:
bar.set_color('red')
plt.tight_layout()
# Converter para imagem
buf = io.BytesIO()
plt.savefig(buf, format='png', dpi=300, bbox_inches='tight')
buf.seek(0)
plt.close()
return Image.open(buf)
def analyze_flame_tab(image):
"""Função principal para aba de análise da chama"""
analyzer = FlameAnalyzer()
features, health_score = analyzer.analyze_flame(image)
# Determinar condição
if health_score > 0.8:
condition = "Ótima"
recommendations = [
"✅ Continue o uso normal",
"📅 Faça manutenção preventiva regular",
"📊 Registre o consumo para melhor previsão"
]
elif health_score > 0.6:
condition = "Boa"
recommendations = [
"✅ Monitore semanalmente",
"⚠️ Planeje verificação mensal",
"🔍 Observe mudanças na cor"
]
elif health_score > 0.4:
condition = "Regular"
recommendations = [
"⚠️ Agende troca de gás",
"⏰ Evite uso prolongado",
"🔧 Verifique regulagem"
]
else:
condition = "Preocupante"
recommendations = [
"🚨 Troque o gás imediatamente",
"⚠️ Use apenas se necessário",
"📞 Chame um técnico"
]
# Gerar relatório
report = f"""
📊 Análise da Chama
─────────────────
🔥 Condição: {condition}
💯 Índice de Saúde: {health_score:.2f}
📈 Métricas Técnicas:
• Homogeneidade: {features['texture']['homogeneity']:.3f}
• Energia: {features['texture']['energy']:.3f}
• Correlação: {features['texture']['correlation']:.3f}
📋 Recomendações:
""" + "\n".join(recommendations)
# Criar visualização
viz = create_visualization(np.array(image), features, health_score)
return report, viz
def calculate_consumption(daily_usage, num_people, cooking_hours):
"""Calcula consumo de gás"""
base_consumption = float(daily_usage) * float(cooking_hours)
per_person_factor = float(num_people) * 0.2
total_consumption = base_consumption * (1 + per_person_factor)
efficiency = 100 - (total_consumption / (13 * 0.8) * 100)
report = f"""
📊 Análise de Consumo
─────────────────────
📈 Consumo Diário: {total_consumption:.2f}kg
👥 Fator Pessoas: {per_person_factor:.2f}
⚡ Eficiência: {efficiency:.1f}%
💡 Recomendações:
"""
if efficiency < 60:
report += """
• Verifique vazamentos
• Otimize tempo de cozimento
• Considere manutenção
"""
else:
report += """
• Mantenha o padrão
• Continue monitorando
• Faça manutenção preventiva
"""
return report
def safety_check(pressure, connection_age, last_inspection):
"""Realiza verificação de segurança"""
try:
pressure = float(pressure)
connection_age = int(connection_age)
last_inspection = datetime.strptime(last_inspection, "%Y-%m-%d")
risks = []
if pressure < 1.8 or pressure > 2.2:
risks.append("⚠️ Pressão fora do ideal")
if connection_age > 5:
risks.append("⚠️ Conexões antigas")
days_since_inspection = (datetime.now() - last_inspection).days
if days_since_inspection > 180:
risks.append("⚠️ Inspeção vencida")
risk_level = len(risks)
report = f"""
🔒 Relatório de Segurança
────────────────────────
📊 Nível de Risco: {"Alto" if risk_level > 2 else "Médio" if risk_level > 0 else "Baixo"}
📝 Verificações:
• Pressão: {pressure} kgf/cm² {"✅" if 1.8 <= pressure <= 2.2 else "❌"}
• Conexões: {connection_age} anos {"✅" if connection_age <= 5 else "❌"}
• Inspeção: {last_inspection.strftime("%d/%m/%Y")} {"✅" if days_since_inspection <= 180 else "❌"}
⚠️ Pontos de Atenção:
"""
if risks:
report += "\n".join(risks)
else:
report += "✅ Nenhum risco identificado"
return report
except ValueError:
return "❌ Erro: Verifique os valores inseridos. Formato de data deve ser YYYY-MM-DD"
except Exception as e:
return f"❌ Erro inesperado: {str(e)}"
def maintenance_schedule(installation_date, last_maintenance):
"""Gera cronograma de manutenção"""
try:
install_date = datetime.strptime(installation_date, "%Y-%m-%d")
last_maint = datetime.strptime(last_maintenance, "%Y-%m-%d")
next_maintenance = last_maint + pd.Timedelta(days=180)
system_age = (datetime.now() - install_date).days / 365
schedule = f"""
🔧 Cronograma de Manutenção
──────────────────────────
📅 Instalação: {install_date.strftime("%d/%m/%Y")}
🔄 Última Manutenção: {last_maint.strftime("%d/%m/%Y")}
⏰ Próxima Manutenção: {next_maintenance.strftime("%d/%m/%Y")}
📊 Status do Sistema:
• Idade: {system_age:.1f} anos
• Ciclos de Manutenção: {int((datetime.now() - install_date).days / 180)}
📋 Verificações Necessárias:
• Teste de vazamento
• Limpeza dos queimadores
• Verificação das conexões
• Calibração da pressão
⚡ Otimizações Recomendadas:
"""
if system_age > 5:
schedule += """
• Considerar substituição
• Avaliação completa
• Upgrade de segurança
"""
else:
schedule += """
• Limpeza preventiva
• Ajustes de eficiência
• Verificação de rotina
"""
return schedule
except ValueError:
return "❌ Erro: Formato de data inválido. Use YYYY-MM-DD"
except Exception as e:
return f"❌ Erro inesperado: {str(e)}"
except ValueError:
return "❌ Erro: Formato de data inválido (use YYYY-MM-DD)"
def efficiency_history():
"""Gera gráfico de histórico de eficiência"""
dates = pd.date_range(start='2024-01-01', periods=10, freq='D')
efficiencies = np.random.normal(80, 10, size=10) # Simulação de dados
plt.figure(figsize=(10, 6))
plt.plot(dates, efficiencies, marker='o')
plt.title('Histórico de Eficiência')
plt.xlabel('Data')
plt.ylabel('Eficiência (%)')
plt.grid(True)
buf = io.BytesIO()
plt.savefig(buf, format='png')
buf.seek(0)
plt.close()
return Image.open(buf)
# Interface Gradio com múltiplas abas
with gr.Blocks(theme=gr.themes.Soft()) as iface:
gr.Markdown("""
# 🔥 Sistema Completo de Análise de Gás e Chama
Sistema avançado para análise, monitoramento e manutenção do seu sistema de gás.
""")
with gr.Tabs():
# Aba de Análise da Chama
with gr.Tab("📸 Análise da Chama"):
with gr.Row():
with gr.Column():
input_image = gr.Image(label="Upload da Foto", type="pil")
analyze_btn = gr.Button("🔍 Analisar Chama", variant="primary")
with gr.Column():
output_text = gr.Textbox(label="Relatório de Análise", lines=10)
output_viz = gr.Image(label="Visualização Técnica")
analyze_btn.click(
fn=analyze_flame_tab,
inputs=[input_image],
outputs=[output_text, output_viz]
)
# Aba de Consumo
with gr.Tab("📊 Análise de Consumo"):
with gr.Row():
with gr.Column():
daily_usage = gr.Number(label="Consumo Diário (kg)", value=0.5)
num_people = gr.Number(label="Número de Pessoas", value=1)
cooking_hours = gr.Number(label="Horas de Cozimento/Dia", value=2)
calc_btn = gr.Button("📊 Calcular Consumo")
with gr.Column():
consumption_output = gr.Textbox(label="Análise de Consumo", lines=10)
calc_btn.click(
fn=calculate_consumption,
inputs=[daily_usage, num_people, cooking_hours],
outputs=[consumption_output]
)
# Aba de Segurança
with gr.Tab("🔒 Verificação de Segurança"):
with gr.Row():
with gr.Column():
pressure = gr.Number(label="Pressão (kgf/cm²)", value=2.0)
connection_age = gr.Number(label="Idade das Conexões (anos)", value=1)
last_inspection = gr.Textbox(
label="Data Última Inspeção (YYYY-MM-DD)",
value=datetime.now().strftime("%Y-%m-%d")
)
safety_btn = gr.Button("🔍 Verificar Segurança")
with gr.Column():
safety_output = gr.Textbox(label="Relatório de Segurança", lines=15)
safety_btn.click(
fn=safety_check,
inputs=[pressure, connection_age, last_inspection],
outputs=[safety_output]
)
# Aba de Manutenção
with gr.Tab("🔧 Cronograma de Manutenção"):
with gr.Row():
with gr.Column():
installation_date = gr.Textbox(
label="Data de Instalação (YYYY-MM-DD)",
value="2023-01-01"
)
last_maintenance = gr.Textbox(
label="Data Última Manutenção (YYYY-MM-DD)",
value=datetime.now().strftime("%Y-%m-%d")
)
maint_btn = gr.Button("📅 Gerar Cronograma")
with gr.Column():
maintenance_output = gr.Textbox(label="Cronograma de Manutenção", lines=15)
maint_btn.click(
fn=maintenance_schedule,
inputs=[installation_date, last_maintenance],
outputs=[maintenance_output]
)
# Aba de Histórico
with gr.Tab("📝 Histórico"):
with gr.Row():
with gr.Column():
gr.DataFrame(
value=[
["2024-01-01", "Ótima", 95.5, 25],
["2024-01-15", "Boa", 85.2, 20],
["2024-02-01", "Regular", 75.8, 15]
],
headers=["Data", "Condição", "Eficiência", "Dias Restantes"],
datatype=["str", "str", "number", "number"],
label="Histórico de Análises"
)
with gr.Column():
gr.Image(value=efficiency_history(), label="Gráfico de Eficiência")
# Aba de Dicas
with gr.Tab("💡 Dicas e Informações"):
gr.Markdown("""
### 📚 Guia Completo de Uso do Gás
#### 🔥 Boas Práticas
1. **Manutenção Regular**
- Limpeza mensal dos queimadores
- Verificação trimestral das conexões
- Teste de vazamento a cada 6 meses
2. **Economia de Gás**
- Use panelas com fundo plano
- Mantenha as panelas tampadas
- Evite chama alta desnecessária
3. **Segurança**
- Mantenha área ventilada
- Verifique conexões regularmente
- Troque mangueiras a cada 5 anos
#### ⚠️ Sinais de Alerta
- Chama amarelada
- Fuligem nas panelas
- Cheiro de gás
- Ruídos estranhos
#### 📱 Contatos Úteis
- Emergência: 193
- Companhia de Gás: 0800-XXX-XXXX
- Assistência Técnica: (XX) XXXX-XXXX
""")
gr.Markdown("""
### 📌 Notas Importantes
- Mantenha registro das análises
- Siga as recomendações de segurança
- Em caso de dúvida, consulte um técnico
""")
if __name__ == "__main__":
iface.launch()