keinne commited on
Commit
b0f4df1
·
verified ·
1 Parent(s): 303051d

Upload 3 files

Browse files
Files changed (2) hide show
  1. app.py +12 -11
  2. livro.py +3 -22
app.py CHANGED
@@ -4,16 +4,18 @@ from livro import processar_e_mostrar, verificar_contraste, gerar_preview_kdp
4
 
5
  with gr.Blocks() as demo:
6
  with gr.Row():
7
- imagem_input = gr.Image(label="Imagem Original", type="numpy")
8
- with gr.Row():
9
- mascara = gr.ImageEditor(label="Marcar áreas para preservar (opcional)", type="numpy", interactive=True)
10
  with gr.Row():
11
  idade = gr.Slider(minimum=4, maximum=12, step=1, value=6, label="Idade da criança (ajusta número de pontos)")
12
  posicao = gr.Radio(["Topo da página", "Centro da página", "Base da página"], value="Centro da página", label="Posicionamento do desenho")
 
13
  contraste_alerta = gr.Textbox(label="Aviso de Contraste", interactive=False)
 
14
  with gr.Row():
15
  imagem_resultado = gr.Image(label="Prévia com Pontos Numerados")
16
  sobreposicao = gr.Image(label="Preview com Sobreposição")
 
17
  with gr.Row():
18
  gerar_btn = gr.Button("Gerar Pontos")
19
  salvar_btn = gr.Button("Salvar como PDF")
@@ -25,13 +27,14 @@ with gr.Blocks() as demo:
25
 
26
  resultado = {}
27
 
28
- def gerar(imagem_array, mask_array, idade, posicao):
29
  global resultado
30
- if imagem_array is None:
31
- return "⚠️ Nenhuma imagem enviada.", None, None
32
- aviso = verificar_contraste(imagem_array)
 
33
  try:
34
- resultado = processar_e_mostrar(imagem_array, mask_array, idade, posicao)
35
  return aviso, resultado["preview"], resultado["overlay"]
36
  except Exception as e:
37
  return f"Erro: {str(e)}", None, None
@@ -45,9 +48,7 @@ with gr.Blocks() as demo:
45
  def gerar_capa():
46
  return gerar_preview_kdp()
47
 
48
- imagem_input.change(fn=lambda img: img, inputs=imagem_input, outputs=mascara)
49
-
50
- gerar_btn.click(gerar, inputs=[imagem_input, mascara, idade, posicao], outputs=[contraste_alerta, imagem_resultado, sobreposicao])
51
  salvar_btn.click(salvar_pdf, outputs=saida_pdf)
52
  salvar_png.click(salvar_imagem, outputs=saida_png)
53
  capa_btn.click(gerar_capa, outputs=saida_capa)
 
4
 
5
  with gr.Blocks() as demo:
6
  with gr.Row():
7
+ desenho = gr.ImageEditor(label="Desenhe aqui sua imagem com caneta", type="numpy", interactive=True)
8
+
 
9
  with gr.Row():
10
  idade = gr.Slider(minimum=4, maximum=12, step=1, value=6, label="Idade da criança (ajusta número de pontos)")
11
  posicao = gr.Radio(["Topo da página", "Centro da página", "Base da página"], value="Centro da página", label="Posicionamento do desenho")
12
+
13
  contraste_alerta = gr.Textbox(label="Aviso de Contraste", interactive=False)
14
+
15
  with gr.Row():
16
  imagem_resultado = gr.Image(label="Prévia com Pontos Numerados")
17
  sobreposicao = gr.Image(label="Preview com Sobreposição")
18
+
19
  with gr.Row():
20
  gerar_btn = gr.Button("Gerar Pontos")
21
  salvar_btn = gr.Button("Salvar como PDF")
 
27
 
28
  resultado = {}
29
 
30
+ def gerar(desenho_array, idade, posicao):
31
  global resultado
32
+ if desenho_array is None or desenho_array.sum() < 1000:
33
+ return "⚠️ Por favor, desenhe uma imagem para gerar os pontos.", None, None
34
+
35
+ aviso = verificar_contraste(desenho_array)
36
  try:
37
+ resultado = processar_e_mostrar(desenho_array, None, idade, posicao)
38
  return aviso, resultado["preview"], resultado["overlay"]
39
  except Exception as e:
40
  return f"Erro: {str(e)}", None, None
 
48
  def gerar_capa():
49
  return gerar_preview_kdp()
50
 
51
+ gerar_btn.click(gerar, inputs=[desenho, idade, posicao], outputs=[contraste_alerta, imagem_resultado, sobreposicao])
 
 
52
  salvar_btn.click(salvar_pdf, outputs=saida_pdf)
53
  salvar_png.click(salvar_imagem, outputs=saida_png)
54
  capa_btn.click(gerar_capa, outputs=saida_capa)
livro.py CHANGED
@@ -4,7 +4,6 @@ import numpy as np
4
  from reportlab.pdfgen import canvas
5
  from reportlab.lib.units import inch
6
  from PIL import Image, ImageDraw, ImageFont
7
- from sklearn.neighbors import NearestNeighbors
8
  import tempfile
9
 
10
  PAGE_WIDTH = 8.67 * inch
@@ -16,29 +15,18 @@ def verificar_contraste(imagem_array):
16
  contrast = gray.std()
17
  return "⚠️ Baixo contraste detectado!" if contrast < 30 else "✅ Contraste adequado."
18
 
19
- def detectar_pontos(imagem_array, mascara_array, idade, distancia_maxima=50):
20
  gray = cv2.cvtColor(imagem_array, cv2.COLOR_BGR2GRAY)
21
  _, thresh = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY_INV)
22
-
23
- if mascara_array is not None and isinstance(mascara_array, np.ndarray):
24
- try:
25
- mask_gray = cv2.cvtColor(mascara_array, cv2.COLOR_BGR2GRAY)
26
- _, mask_thresh = cv2.threshold(mask_gray, 10, 255, cv2.THRESH_BINARY)
27
- thresh[mask_thresh > 0] = 0
28
- except Exception as e:
29
- print("Erro ao processar máscara:", e)
30
-
31
  contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
32
  if not contours:
33
  return [], None
34
-
35
  main_contour = max(contours, key=cv2.contourArea)
36
  epsilon = 1.0
37
  simplified = cv2.approxPolyDP(main_contour, epsilon, closed=False)
38
  max_pontos = min(30 + (idade - 4) * 10, 100)
39
  step = max(1, len(simplified) // max_pontos)
40
  pontos = [tuple(pt[0]) for pt in simplified[::step]]
41
-
42
  if len(pontos) > 2:
43
  ordenados = [pontos[0]]
44
  restantes = pontos[1:]
@@ -55,14 +43,12 @@ def detectar_pontos(imagem_array, mascara_array, idade, distancia_maxima=50):
55
  def normalizar_para_preview(pontos, largura=600, altura=800, margem=50, posicao="Centro da página"):
56
  if not pontos:
57
  return [], 0
58
-
59
  x_coords, y_coords = zip(*pontos)
60
  min_x, max_x = min(x_coords), max(x_coords)
61
  min_y, max_y = min(y_coords), max(y_coords)
62
  escala_x = (largura - 2 * margem) / (max_x - min_x + 1e-5)
63
  escala_y = (altura - 2 * margem) / (max_y - min_y + 1e-5)
64
  escala = min(escala_x, escala_y)
65
-
66
  altura_desenho = (max_y - min_y) * escala
67
  if posicao == "Topo da página":
68
  offset_y = margem
@@ -70,7 +56,6 @@ def normalizar_para_preview(pontos, largura=600, altura=800, margem=50, posicao=
70
  offset_y = altura - margem - altura_desenho
71
  else:
72
  offset_y = (altura - altura_desenho) // 2
73
-
74
  pontos_normalizados = [(
75
  int((x - min_x) * escala + margem),
76
  int((y - min_y) * escala + offset_y)
@@ -82,11 +67,9 @@ def gerar_preview_com_pontos(pontos, posicao):
82
  margem = 50
83
  img = np.ones((altura, largura, 3), dtype=np.uint8) * 255
84
  pontos_norm, _ = normalizar_para_preview(pontos, largura, altura, margem, posicao)
85
-
86
  for i, (x, y) in enumerate(pontos_norm):
87
  cv2.circle(img, (x, y), 4, (0, 0, 0), -1)
88
  cv2.putText(img, str(i+1), (x + 6, y - 6), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 0, 0), 1)
89
-
90
  path = tempfile.NamedTemporaryFile(delete=False, suffix=".png").name
91
  cv2.imwrite(path, img)
92
  return path, img, pontos_norm
@@ -96,12 +79,10 @@ def gerar_overlay(original, pontos_norm):
96
  h, w = overlay.shape[:2]
97
  resize = cv2.resize(overlay, (w, h))
98
  transparente = cv2.addWeighted(resize, 0.5, np.ones_like(resize) * 255, 0.5, 0)
99
-
100
  for i, (x, y) in enumerate(pontos_norm):
101
  if x < w and y < h:
102
  cv2.circle(transparente, (x, y), 4, (0, 0, 0), -1)
103
  cv2.putText(transparente, str(i+1), (x + 6, y - 6), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 0, 0), 1)
104
-
105
  path = tempfile.NamedTemporaryFile(delete=False, suffix=".png").name
106
  cv2.imwrite(path, transparente)
107
  return path
@@ -129,8 +110,8 @@ def gerar_preview_kdp():
129
  img.save(path)
130
  return path
131
 
132
- def processar_e_mostrar(imagem_array, mascara_array, idade, posicao):
133
- pontos, original_masked = detectar_pontos(imagem_array, mascara_array, idade)
134
  preview_path, preview_img, pontos_norm = gerar_preview_com_pontos(pontos, posicao)
135
  overlay_path = gerar_overlay(cv2.resize(imagem_array, (600, 800)), pontos_norm)
136
  pdf_path = gerar_pdf(pontos_norm)
 
4
  from reportlab.pdfgen import canvas
5
  from reportlab.lib.units import inch
6
  from PIL import Image, ImageDraw, ImageFont
 
7
  import tempfile
8
 
9
  PAGE_WIDTH = 8.67 * inch
 
15
  contrast = gray.std()
16
  return "⚠️ Baixo contraste detectado!" if contrast < 30 else "✅ Contraste adequado."
17
 
18
+ def detectar_pontos(imagem_array, idade, distancia_maxima=50):
19
  gray = cv2.cvtColor(imagem_array, cv2.COLOR_BGR2GRAY)
20
  _, thresh = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY_INV)
 
 
 
 
 
 
 
 
 
21
  contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
22
  if not contours:
23
  return [], None
 
24
  main_contour = max(contours, key=cv2.contourArea)
25
  epsilon = 1.0
26
  simplified = cv2.approxPolyDP(main_contour, epsilon, closed=False)
27
  max_pontos = min(30 + (idade - 4) * 10, 100)
28
  step = max(1, len(simplified) // max_pontos)
29
  pontos = [tuple(pt[0]) for pt in simplified[::step]]
 
30
  if len(pontos) > 2:
31
  ordenados = [pontos[0]]
32
  restantes = pontos[1:]
 
43
  def normalizar_para_preview(pontos, largura=600, altura=800, margem=50, posicao="Centro da página"):
44
  if not pontos:
45
  return [], 0
 
46
  x_coords, y_coords = zip(*pontos)
47
  min_x, max_x = min(x_coords), max(x_coords)
48
  min_y, max_y = min(y_coords), max(y_coords)
49
  escala_x = (largura - 2 * margem) / (max_x - min_x + 1e-5)
50
  escala_y = (altura - 2 * margem) / (max_y - min_y + 1e-5)
51
  escala = min(escala_x, escala_y)
 
52
  altura_desenho = (max_y - min_y) * escala
53
  if posicao == "Topo da página":
54
  offset_y = margem
 
56
  offset_y = altura - margem - altura_desenho
57
  else:
58
  offset_y = (altura - altura_desenho) // 2
 
59
  pontos_normalizados = [(
60
  int((x - min_x) * escala + margem),
61
  int((y - min_y) * escala + offset_y)
 
67
  margem = 50
68
  img = np.ones((altura, largura, 3), dtype=np.uint8) * 255
69
  pontos_norm, _ = normalizar_para_preview(pontos, largura, altura, margem, posicao)
 
70
  for i, (x, y) in enumerate(pontos_norm):
71
  cv2.circle(img, (x, y), 4, (0, 0, 0), -1)
72
  cv2.putText(img, str(i+1), (x + 6, y - 6), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 0, 0), 1)
 
73
  path = tempfile.NamedTemporaryFile(delete=False, suffix=".png").name
74
  cv2.imwrite(path, img)
75
  return path, img, pontos_norm
 
79
  h, w = overlay.shape[:2]
80
  resize = cv2.resize(overlay, (w, h))
81
  transparente = cv2.addWeighted(resize, 0.5, np.ones_like(resize) * 255, 0.5, 0)
 
82
  for i, (x, y) in enumerate(pontos_norm):
83
  if x < w and y < h:
84
  cv2.circle(transparente, (x, y), 4, (0, 0, 0), -1)
85
  cv2.putText(transparente, str(i+1), (x + 6, y - 6), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 0, 0), 1)
 
86
  path = tempfile.NamedTemporaryFile(delete=False, suffix=".png").name
87
  cv2.imwrite(path, transparente)
88
  return path
 
110
  img.save(path)
111
  return path
112
 
113
+ def processar_e_mostrar(imagem_array, _, idade, posicao):
114
+ pontos, _ = detectar_pontos(imagem_array, idade)
115
  preview_path, preview_img, pontos_norm = gerar_preview_com_pontos(pontos, posicao)
116
  overlay_path = gerar_overlay(cv2.resize(imagem_array, (600, 800)), pontos_norm)
117
  pdf_path = gerar_pdf(pontos_norm)