Geolocalización mediante Inteligencia Artificial #OSINT

Joey Tribbiani (Friends) apunta a la televisión donde aparece él mismo

Si no vives debajo de una piedra y haces uso de las redes sociales, seguro has sido testigo o protagonista de esas publicaciones en tu cafetería de confianza, cerca de casa, en el trabajo, de viaje, o en esas fiestas épicas inolvidables al estilo Proyecto X. Nos encanta compartir esos momentos, ¿verdad?

A menudo, ni siquiera nos damos cuenta de la montaña de información que entregamos al mundo cada vez que publicamos algo en nuestras redes sociales. Nos exponemos ante Internet sin pensar en las posibles consecuencias. Es como aventurarse en la jungla digital sin un mapa, sin saber qué depredadores acechan.

Pero, ¿sabes qué es lo más loco? Que con cada publicación estamos arrojando pistas sobre nuestra ubicación, nuestra rutina diaria, nuestras actividades, nuestra familia, nuestros amigos, entre otras muchas cosas. Es como si estuviéramos dejando migas de pan digitales para que cualquiera las siga, revelando nuestra vida a un público invisible y potencialmente peligroso.

Y no se trata solo de la información que sabemos que compartimos, sino también de aquella que compartimos sin siquiera ser conscientes de ello, porque claro, no nos olvidemos de los metadatos. Cuando, por ejemplo, sacamos una foto con nuestro móvil, esa imagen puede contener una gran cantidad de información que, a simple vista, podríamos pasar por alto. Desde la ubicación exacta donde se tomó la foto, hasta la marca, modelo y versión del software del dispositivo utilizado, e incluso detalles sobre la configuración de la cámara. Pequeños detalles que, a primera vista, parecen inofensivos pero que, al contrario de lo que podamos pensar, revelan mucha información, que nos hacen vulnerables a posibles ataques por aquellos que saben buscarla.

Izquierda: Ejemplo de metadatos extraídos de una foto capturada con el móvil. Derecha: Ejemplo de metadatos extraídos de una foto capturada con el móvil

Si bien es cierto que muchas redes sociales han implementado medidas para limpiar gran parte de estos metadatos y proteger nuestra privacidad, siempre existen formas de extraer información. Especialmente con la ayuda de tecnologías como la Inteligencia Artificial. Por ejemplo, un algoritmo entrenado para reconocer patrones visuales en las imágenes podría identificar elementos que revelen la ubicación geográfica donde se tomó la foto.

¡Y aquí viene lo interesante! Vamos a ver un ejemplo sencillo de cómo la Inteligencia Artificial puede ayudarnos a obtener información de las publicaciones expuestas en Internet. Como mencioné antes, muchas redes sociales eliminan los metadatos, entre los que se podrían encontrar los datos de ubicación de las fotos, lo que dificulta rastrear su origen. Evitar perder tiempo revisando manualmente miles de imágenes es crucial. Así que, ¿qué tal si creamos un pequeño programa en Python? Con el que, simplemente, pasando las imágenes a una Inteligencia Artificial, podamos geolocalizarlas y visualizar en un mapa dónde fueron tomadas.

Lo primero que necesitaremos es encontrar una Inteligencia Artificial capaz de geolocalizar una ubicación a partir de las imágenes que le proporcionemos. Para ello, he seleccionado picarta.ai.

Picarta.ai

Esta Inteligencia Artificial analiza minuciosamente cada imagen, buscando en los metadatos. Sin embargo, cuando estos están ausentes, el avanzado modelo de Inteligencia Artificial interviene para predecir la ubicación precisa en el mundo donde se tomó la foto.

Servicios Picarta.ai

Además, ofrecen una API que nos permite realizar hasta 100 consultas mensuales de forma gratuita con solo crearnos una cuenta.

Precios Picarta.ai

Lo segundo que necesitaremos es un mapa interactivo donde podamos añadir marcadores de posición en las ubicaciones que nos devuelva como resultado picarta.ai. Para este propósito, he seleccionado Leaflet.js, una biblioteca JavaScript de código abierto fácil de usar.

Leaflet.js

Ahora que ya tenemos todo preparado, es el momento de programar. Primero, comenzaremos creando un archivo “.py” e importaremos los módulos que necesitaremos:

import os import requests import json import base64 import webbrowser
  • os: Proporciona funciones para interactuar con el sistema operativo, como manipulación de archivos y directorios.
  • requests: Permite realizar solicitudes HTTP en Python, como enviar solicitudes GET o POST a servidores web.
  • json: Facilita la serialización y deserialización de datos en formato JSON, comúnmente utilizado para intercambiar datos entre aplicaciones.
  • base64: Ofrece funciones para codificar y decodificar datos en formato Base64, útil para convertir datos binarios en texto legible y viceversa.
  • webbrowser: Proporciona una interfaz para abrir y controlar navegadores web desde Python, lo que permite la automatización de tareas relacionadas con la navegación en Internet.

A continuación, crearemos una función que he llamado ‘rastreator’. Esta función realizará peticiones a la API de picarta.ai para obtener los resultados de posicionamiento, los cuales serán guardados en un archivo JSON junto con la imagen en formato base64.

def rastreator(image_path, api_token): url = "https://picarta.ai/classify" headers = {"Content-Type": "application/json"} with open(image_path, "rb") as image_file: img_data = base64.b64encode(image_file.read()).decode('utf-8') payload = {"TOKEN": api_token, "IMAGE": img_data} response = requests.post(url, headers=headers, json=payload) if response.status_code == 200: result = response.json() result["image_base64"] = img_data return result else: print("La solicitud falló para la imagen", image_path) return None

Seguidamente, crearemos otra función, la cual he llamado ‘add_markers_to_html’, que se encargará de agregar los marcadores de posición al mapa de Leaflet.js, junto con la imagen de la cual se ha extraído la ubicación.

def add_markers_to_html(results): markers_script = "" for result in results: filename = list(result.keys())[0] ai_lat = result[filename]["ai_lat"] ai_lon = result[filename]["ai_lon"] markers_script += f''' var marker = L.marker([{ai_lat}, {ai_lon}]).addTo(map); marker.bindPopup('<img src="data:image/jpeg;base64,{result[filename]["image_base64"]}" style="max-width:300px;">'); ''' return markers_script

Por último, en la función principal ‘main’, definiremos la lógica para procesar todas las imágenes de la carpeta que nosotros especifiquemos al ejecutar el programa, obteniendo sus ubicaciones mediante la función ‘rastreator’, guardando los resultados en un archivo JSON y generando un archivo HTML interactivo que muestra un mapa con marcadores obtenidos mediante la función ‘add_markers_to_html’ para cada ubicación. Cuando el programa se termine de ejecutar, se abrirá automáticamente el mapa en el navegador para poder explorar visualmente los resultados.

def main(): api_token = "" ## Añadir API KEY folder_path = input("Por favor, ingresa la ruta donde se encuentran las imágenes: ") output_file = "datos.json" html_file = "mapa.html" results = [] for filename in os.listdir(folder_path): if filename.endswith((".jpg", ".jpeg", ".png")): image_path = os.path.join(folder_path, filename) print("Procesando:", image_path) result = rastreator(image_path, api_token) if result: results.append({filename: result}) with open(output_file, "w") as f: json.dump(results, f, indent=4) print("Los resultados se han guardado en", output_file) markers_script = add_markers_to_html(results) with open(html_file, "w") as html: html.write(f'''<!DOCTYPE html> <html> <head> <title>Mapa de resultados</title> <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script> <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" /> </head> <body style="margin: 0;"> <div id="map" style="width: 100%; height: 100vh;"></div> <script> var map = L.map('map').setView([0, 0], 2); L.tileLayer('https://{{s}}.tile.openstreetmap.org/{{z}}/{{x}}/{{y}}.png', {{ attribution: '© OpenStreetMap contributors' }}).addTo(map); L.control.scale().addTo(map); {markers_script} </script> </body> </html>''' ) print("Se ha generado y abierto el archivo", html_file) webbrowser.open(html_file)

Para el correcto funcionamiento del programa, añadir al final del código lo siguiente:

if __name__ == "__main__": main()

Código completo:

import os import requests import json import base64 import webbrowser def rastreator(image_path, api_token): url = "https://picarta.ai/classify" headers = {"Content-Type": "application/json"} with open(image_path, "rb") as image_file: img_data = base64.b64encode(image_file.read()).decode('utf-8') payload = {"TOKEN": api_token, "IMAGE": img_data} response = requests.post(url, headers=headers, json=payload) if response.status_code == 200: result = response.json() result["image_base64"] = img_data return result else: print("La solicitud falló para la imagen", image_path) return None def add_markers_to_html(results): markers_script = "" for result in results: filename = list(result.keys())[0] ai_lat = result[filename]["ai_lat"] ai_lon = result[filename]["ai_lon"] markers_script += f''' var marker = L.marker([{ai_lat}, {ai_lon}]).addTo(map); marker.bindPopup('<img src="data:image/jpeg;base64,{result[filename]["image_base64"]}" style="max-width:300px;">'); ''' return markers_script def main(): api_token = "" ## Añadir API KEY folder_path = input("Por favor, ingresa la ruta donde se encuentran las imágenes: ") output_file = "datos.json" html_file = "mapa.html" results = [] for filename in os.listdir(folder_path): if filename.endswith((".jpg", ".jpeg", ".png")): image_path = os.path.join(folder_path, filename) print("Procesando:", image_path) result = rastreator(image_path, api_token) if result: results.append({filename: result}) with open(output_file, "w") as f: json.dump(results, f, indent=4) print("Los resultados se han guardado en", output_file) markers_script = add_markers_to_html(results) with open(html_file, "w") as html: html.write(f'''<!DOCTYPE html> <html> <head> <title>Mapa de resultados</title> <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script> <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" /> </head> <body style="margin: 0;"> <div id="map" style="width: 100%; height: 100vh;"></div> <script> var map = L.map('map').setView([0, 0], 2); L.tileLayer('https://{{s}}.tile.openstreetmap.org/{{z}}/{{x}}/{{y}}.png', {{ attribution: '© OpenStreetMap contributors' }}).addTo(map); L.control.scale().addTo(map); {markers_script} </script> </body> </html>''' ) print("Se ha generado y abierto el archivo", html_file) webbrowser.open(html_file) if __name__ == "__main__": main()

Para ejecutar el programa, solo necesitamos ejecutar el archivo “.py” que yo he llamado “CapCap.py” utilizando Python, y luego proporcionar la ruta donde se encuentran almacenadas las imágenes.

Ejecución del programa
Fin ejecución del programa

Es importante destacar que este programa no se enfoca específicamente en la recopilación de información ni imágenes de usuarios en redes sociales, como Instagram, por ejemplo. Está más orientado a explorar posibles usos posteriores de dicha información.

Por lo tanto, no veremos cómo crear un scrapper para recuperar grandes cantidades de imágenes ni la información relacionada con ellas en redes sociales; ¿quizás en futuros posts? Además, esta es la razón por la cual el resultado no resulta tan impactante, ya que carecemos de información como la fecha de publicación de las imágenes, lo que nos impide crear una cronología temporal completa. Dicha cronología nos proporcionaría una visión más amplia de los movimientos, actividades y relaciones de una persona. Además, cabe aclarar que la Inteligencia Artificial puede cometer errores y que no debemos tomar el resultado como algo 100% fiable.

Dicho esto, este es el resultado basado en 64 imágenes extraídas de las publicaciones de un usuario en redes sociales.

Resultado mapa
Resultado más información marcadores

Con todas estas consideraciones, podemos observar cómo la combinación de tecnologías como la Inteligencia Artificial y herramientas de mapeo interactivo pueden proporcionar una perspectiva fascinante sobre la información que inadvertidamente compartimos en Internet.

Speak Your Mind

*