leonett commited on
Commit
736c84d
·
1 Parent(s): cce7214

Actualización del código Error ELA

Browse files
Files changed (1) hide show
  1. app.py +70 -137
app.py CHANGED
@@ -8,65 +8,39 @@ import hashlib
8
  import gradio as gr
9
  import os
10
  from datetime import datetime
 
11
 
12
  def obtener_metadatos(imagen):
13
  """
14
  Obtiene los metadatos de la imagen.
15
  """
16
- metadatos = {}
17
  try:
18
  exif_data = imagen._getexif()
19
- if exif_data:
20
- for tag_id, value in exif_data.items():
21
- tag = TAGS.get(tag_id, tag_id)
22
- metadatos[tag] = value
23
  except Exception as e:
24
  print(f"Error al obtener metadatos: {e}")
25
- return metadatos
26
 
27
- def obtener_coordenadas(exif_data):
28
  """
29
- Obtiene las coordenadas GPS de los metadatos EXIF.
30
  """
31
- if not exif_data:
32
- return None
33
-
34
- gps_info = exif_data.get("GPSInfo", {})
35
- if not gps_info:
36
- return None
37
-
38
- # Convertir las coordenadas GPS a grados decimales
39
- def gps_to_degrees(value):
40
- d, m, s = value
41
- return d + (m / 60.0) + (s / 3600.0)
42
-
43
  try:
44
- latitud = gps_info.get(2) # Latitud
45
- longitud = gps_info.get(4) # Longitud
46
- latitud_ref = gps_info.get(1) # Norte/Sur
47
- longitud_ref = gps_info.get(3) # Este/Oeste
48
-
49
- if latitud and longitud and latitud_ref and longitud_ref:
50
- latitud = gps_to_degrees(latitud)
51
- longitud = gps_to_degrees(longitud)
52
- if latitud_ref == "S": # Si es Sur, convertir a negativo
53
- latitud = -latitud
54
- if longitud_ref == "W": # Si es Oeste, convertir a negativo
55
- longitud = -longitud
56
- return latitud, longitud
57
  except Exception as e:
58
- print(f"Error al procesar coordenadas GPS: {e}")
59
  return None
60
 
61
- return None
62
-
63
- def calcular_hash(imagen):
64
- """
65
- Calcula el hash MD5 de la imagen para verificar su integridad.
66
- """
67
- imagen_bytes = imagen.tobytes()
68
- return hashlib.md5(imagen_bytes).hexdigest()
69
-
70
  def analizar_manipulacion(imagen, metadatos, ela_imagen):
71
  """
72
  Analiza si la imagen ha sido manipulada.
@@ -74,119 +48,78 @@ def analizar_manipulacion(imagen, metadatos, ela_imagen):
74
  manipulada = False
75
  razones = []
76
 
77
- # Verificar si los metadatos están presentes
78
  if not metadatos:
79
- razones.append("La imagen no tiene metadatos EXIF, pero esto no es concluyente de manipulación.")
80
  else:
81
  if "Software" in metadatos:
82
  razones.append(f"La imagen fue editada con: {metadatos['Software']}")
83
  manipulada = True
84
 
85
- # Verificar si el hash de la imagen coincide con un hash conocido (simulación)
86
- hash_conocido = "1a79a4d60de6718e8e5b326e338ae533" # Hash de ejemplo
87
- hash_actual = calcular_hash(imagen)
88
- if hash_actual != hash_conocido:
89
- razones.append("El hash de la imagen no coincide con un hash conocido.")
90
-
91
- # Evaluar los resultados del análisis ELA
92
- promedio_ela = np.mean(ela_imagen)
93
- if promedio_ela > 10: # Umbral arbitrario, ajustar según los datos
94
- razones.append("El análisis ELA sugiere posibles alteraciones en la imagen.")
95
- manipulada = True
96
 
 
 
 
97
  return manipulada, razones
98
 
99
- def realizar_ela(imagen, quality=95, scale=100):
100
- """
101
- Realiza el Error Level Analysis (ELA) en la imagen utilizando OpenCV.
102
- """
103
- # Convertir la imagen a formato compatible con OpenCV
104
- imagen_cv = cv2.cvtColor(np.array(imagen), cv2.COLOR_RGB2BGR)
105
-
106
- # Guardar la imagen comprimida
107
- temp_path = "temp_image.jpg"
108
- cv2.imwrite(temp_path, imagen_cv, [cv2.IMWRITE_JPEG_QUALITY, quality])
109
-
110
- # Leer la imagen comprimida
111
- imagen_comprimida = cv2.imread(temp_path)
112
-
113
- # Calcular la diferencia absoluta entre la imagen original y la comprimida
114
- diferencia = cv2.absdiff(imagen_cv, imagen_comprimida)
115
-
116
- # Escalar la diferencia para resaltar las áreas modificadas
117
- ela_imagen = scale * diferencia
118
-
119
- # Convertir a escala de grises para mejorar la visualización
120
- ela_imagen = cv2.cvtColor(ela_imagen, cv2.COLOR_BGR2GRAY)
121
-
122
- # Eliminar el archivo temporal
123
- os.remove(temp_path)
124
-
125
- return ela_imagen
126
-
127
  def procesar_imagen(archivo_imagen):
128
- # Cargar la imagen
129
  try:
130
  imagen = Image.open(archivo_imagen)
131
- except Exception as e:
132
- return f"Error al cargar la imagen: {e}", None
133
-
134
- # Obtener información básica de la imagen
135
- nombre_archivo = os.path.basename(archivo_imagen)
136
- info_basica = f"""
137
- Información básica de la imagen:
138
- Nombre del archivo: {nombre_archivo}
139
- Formato: {imagen.format}
140
- Tamaño: {imagen.size} píxeles
141
- Modo: {imagen.mode}
142
- """
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
 
144
- # Obtener tamaño del archivo, fecha de creación y modificación
145
- stats = os.stat(archivo_imagen)
146
- tamaño_archivo = stats.st_size / 1024 # Tamaño en KB
147
- fecha_creacion = datetime.fromtimestamp(stats.st_ctime).strftime('%Y-%m-%d %H:%M:%S')
148
- fecha_modificacion = datetime.fromtimestamp(stats.st_mtime).strftime('%Y-%m-%d %H:%M:%S')
149
-
150
- info_basica += f"""
151
- Tamaño del archivo: {tamaño_archivo:.2f} KB
152
- Fecha de creación: {fecha_creacion}
153
- Fecha de modificación: {fecha_modificacion}
154
- """
155
-
156
- # Obtener metadatos
157
- metadatos = obtener_metadatos(imagen)
158
-
159
- # Realizar Error Level Analysis (ELA)
160
- ela_imagen = realizar_ela(imagen)
161
-
162
- # Analizar si la imagen ha sido manipulada
163
- manipulada, razones = analizar_manipulacion(imagen, metadatos, ela_imagen)
164
- info_manipulacion = "\nAnálisis de manipulación:\n"
165
- if manipulada:
166
- info_manipulacion += "La imagen ha sido manipulada.\n"
167
- info_manipulacion += "Razones:\n"
168
- for razon in razones:
169
- info_manipulacion += f"- {razon}\n"
170
- else:
171
- info_manipulacion += "La imagen NO ha sido manipulada.\n"
172
-
173
- # Guardar la imagen ELA en un archivo temporal
174
- with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp_file:
175
- cv2.imwrite(tmp_file.name, ela_imagen)
176
- ela_image_path = tmp_file.name
177
-
178
- return ela_image_path, info_basica + info_manipulacion
179
 
180
  # Interfaz de GRADIO
181
  iface = gr.Interface(
182
  fn=procesar_imagen,
183
  inputs=gr.Image(type="filepath", label="Sube una imagen"),
184
  outputs=[gr.Image(label="Error Level Analysis (ELA)"), gr.Textbox(label="Resultado del análisis")],
185
- title="Análisis de metadatos y Error de ELA en imágenes digitales con Gradio",
186
- description="""<div style="text-align: center;">
187
- <p>Este programa es una herramienta de computación forense diseñado para analizar imágenes en busca de evidencia de manipulación o edición. Utiliza la técnica de Error Level Analysis (ELA).</p>
188
- </div>"""
189
  )
190
 
191
- # Lanzar la interfaz de Gradio
192
  iface.launch()
 
8
  import gradio as gr
9
  import os
10
  from datetime import datetime
11
+ import tempfile
12
 
13
  def obtener_metadatos(imagen):
14
  """
15
  Obtiene los metadatos de la imagen.
16
  """
 
17
  try:
18
  exif_data = imagen._getexif()
19
+ if not exif_data:
20
+ return {}
21
+ return {TAGS.get(tag_id, tag_id): value for tag_id, value in exif_data.items()}
 
22
  except Exception as e:
23
  print(f"Error al obtener metadatos: {e}")
24
+ return {}
25
 
26
+ def realizar_ela(imagen, quality=95, scale=100):
27
  """
28
+ Realiza el Error Level Analysis (ELA) en la imagen.
29
  """
 
 
 
 
 
 
 
 
 
 
 
 
30
  try:
31
+ imagen_cv = cv2.cvtColor(np.array(imagen), cv2.COLOR_RGB2BGR)
32
+ temp_path = "temp_image.jpg"
33
+ cv2.imwrite(temp_path, imagen_cv, [cv2.IMWRITE_JPEG_QUALITY, quality])
34
+ imagen_comprimida = cv2.imread(temp_path)
35
+ diferencia = cv2.absdiff(imagen_cv, imagen_comprimida)
36
+ ela_imagen = scale * diferencia
37
+ ela_imagen = cv2.cvtColor(ela_imagen, cv2.COLOR_BGR2GRAY)
38
+ os.remove(temp_path)
39
+ return ela_imagen
 
 
 
 
40
  except Exception as e:
41
+ print(f"Error al realizar ELA: {e}")
42
  return None
43
 
 
 
 
 
 
 
 
 
 
44
  def analizar_manipulacion(imagen, metadatos, ela_imagen):
45
  """
46
  Analiza si la imagen ha sido manipulada.
 
48
  manipulada = False
49
  razones = []
50
 
 
51
  if not metadatos:
52
+ razones.append("La imagen no tiene metadatos EXIF.")
53
  else:
54
  if "Software" in metadatos:
55
  razones.append(f"La imagen fue editada con: {metadatos['Software']}")
56
  manipulada = True
57
 
58
+ if ela_imagen is None:
59
+ razones.append("No se pudo realizar el análisis ELA.")
60
+ else:
61
+ promedio_ela = np.mean(ela_imagen)
62
+ if promedio_ela > 10:
63
+ razones.append("El análisis ELA sugiere posibles alteraciones.")
64
+ manipulada = True
 
 
 
 
65
 
66
+ if not razones:
67
+ razones.append("No se encontraron indicadores claros de manipulación.")
68
+
69
  return manipulada, razones
70
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  def procesar_imagen(archivo_imagen):
 
72
  try:
73
  imagen = Image.open(archivo_imagen)
74
+ nombre_archivo = os.path.basename(archivo_imagen)
75
+ stats = os.stat(archivo_imagen)
76
+ tamaño_archivo = stats.st_size / 1024
77
+ fecha_creacion = datetime.fromtimestamp(stats.st_ctime).strftime('%Y-%m-%d %H:%M:%S')
78
+ fecha_modificacion = datetime.fromtimestamp(stats.st_mtime).strftime('%Y-%m-%d %H:%M:%S')
79
+
80
+ info_basica = f"""
81
+ Información básica de la imagen:
82
+ Nombre del archivo: {nombre_archivo}
83
+ Tamaño: {tamaño_archivo:.2f} KB
84
+ Fecha de creación: {fecha_creacion}
85
+ Fecha de modificación: {fecha_modificacion}
86
+ """
87
+
88
+ metadatos = obtener_metadatos(imagen)
89
+ ela_imagen = realizar_ela(imagen)
90
+ manipulada, razones = analizar_manipulacion(imagen, metadatos, ela_imagen)
91
+
92
+ info_manipulacion = "\nAnálisis de manipulación:\n"
93
+ if manipulada:
94
+ info_manipulacion += "La imagen ha sido manipulada.\nRazones:\n"
95
+ for razon in razones:
96
+ info_manipulacion += f"- {razon}\n"
97
+ else:
98
+ info_manipulacion += "La imagen NO ha sido manipulada.\nRazones:\n"
99
+ for razon in razones:
100
+ info_manipulacion += f"- {razon}\n"
101
+
102
+ if ela_imagen is not None:
103
+ with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tmp_file:
104
+ cv2.imwrite(tmp_file.name, ela_imagen)
105
+ ela_image_path = tmp_file.name
106
+ return ela_image_path, info_basica + info_manipulacion
107
+ else:
108
+ return None, info_basica + info_manipulacion + "\n(No se generó ELA debido a un error técnico.)"
109
 
110
+ except Exception as e:
111
+ error_msg = f"Error procesando la imagen: {e}"
112
+ print(error_msg)
113
+ return None, error_msg
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
 
115
  # Interfaz de GRADIO
116
  iface = gr.Interface(
117
  fn=procesar_imagen,
118
  inputs=gr.Image(type="filepath", label="Sube una imagen"),
119
  outputs=[gr.Image(label="Error Level Analysis (ELA)"), gr.Textbox(label="Resultado del análisis")],
120
+ title="Análisis de Manipulación de Imágenes",
121
+ description="Sube una imagen para analizar posibles manipulaciones usando metadatos y ELA."
 
 
122
  )
123
 
124
+ # Lanzar la interfaz
125
  iface.launch()