Usa la API Cloud Vison de Google Cloud Platform para hacer búsqueda de texto en imágenes



En este artículo te hablaremos más sobre esta poderosa API Cloud Vision de Google, ¿Qué es y cómo podemos implementarlo en nuestras soluciones?


¿Qué es la API de Cloud Vision?


La API Cloud Vision de Google es un servicio ofrecido por Google Cloud Platform que permite a los desarrolladores integrar capacidades de visión por computadora en sus aplicaciones y servicios. Esta API utiliza la tecnología de aprendizaje automático y redes neuronales profundas para analizar y comprender el contenido visual de las imágenes y los videos. Algunas de las capacidades clave de la API Cloud Vision incluyen:

  1. Detección de etiquetas: La API puede identificar objetos, personas, lugares y otros elementos dentro de una imagen, proporcionando etiquetas descriptivas que ayudan a categorizar y comprender el contenido.

  2. Detección de rostros: Puede detectar y analizar caras en imágenes, identificando atributos como la edad, el género y las emociones expresadas.

  3. Detección de texto: La API es capaz de extraer y reconocer texto en imágenes, lo que facilita la lectura y el análisis de contenido escrito en fotografías y documentos.

  4. Detección de contenido inapropiado: Puede identificar contenido inapropiado, como desnudos, violencia o contenido ofensivo, en imágenes y videos.

  5. Detección de logotipos y marcas: Puede reconocer logotipos y marcas comerciales en imágenes, lo que es útil para el seguimiento de la marca y el análisis de mercado.

  6. Detección de objetos y contenido específico: Puede identificar objetos específicos, como productos, edificios, animales y más, dependiendo de la configuración.

  7. OCR (Reconocimiento Óptico de Caracteres): Permite convertir texto impreso en imágenes en texto digital, lo que es útil para la extracción de información de documentos escaneados.

La API Cloud Vision de Google se utiliza en una variedad de aplicaciones, como la organización y búsqueda de imágenes, la automatización de procesos empresariales, la moderación de contenido en plataformas en línea, la accesibilidad para personas con discapacidades visuales y muchas otras aplicaciones relacionadas con la visión por computadora. Ofrece una forma poderosa de aprovechar las capacidades de análisis visual de Google en aplicaciones y servicios personalizados. 

Ejercicio práctico


Para este artículo vamos a desarrollar una aplicación web que hace uso de la característica de detección de texto en imágenes y PDF, será como una pequeña biblioteca virtual donde los usuarios entraran a buscar en los activos digitales haciendo uso de una palabra clave. 

En general, la aplicación estará compuesta por un Frontend simple de HTML, estilos CSS y un archivo JavaScript que consumirá una API en Cloud Functions la cual recibirá un parámetro de búsqueda, posterior usará la capacidad de Cloud Vision para extraer los documentos donde coincida la palabra a buscar. 



¡Comencemos!

Primero veamos la estructura de nuestro FrontEnd


Index.html

En el archivo index.html tenemos todo el componente visual de nuestra aplicación, una barra de búsqueda y algunas importaciones como Bootstrap y nuestro main.js que corresponde a toda la lógica de nuestro pequeño demo.


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
        integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
    <title>Biblioteca Departamental</title>
</head>
<body>
    <nav class="navbar navbar-light bg-light">
        <div class="container-fluid">
            <span class="navbar-brand mb-0 h1">Biblioteca Departamental Jorge Garcés Borrero</span>
            <form class="d-flex">
                <input class="form-control me-2" id="paramSearch" type="search" placeholder="Busqueda Exacta"
                    aria-label="Search">
                <button class="btn btn-outline-success" type="button" id="getMatch">Buscar</button>
            </form>
        </div>
    </nav>
    <br><br>
    <div class="content" style="text-align: center; padding: 16px;">
        <img src="images/book-icon.png" style="width: 25%;">
    </div>
</body>
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.min.js" integrity="sha384cVKIPhGWiC2Al4u+LWgxfKTRIcfu0JTxR+EQDz/bgldoEyl4H0zUF0QKbrJ0EcQF"
    crossorigin="anonymous"></script>
<script src="main.js"></script>
</html>


Main.js

En el archivo main.js tenemos la lógica de la aplicación donde hacemos uso de JQuery para realizar la solicitud al EndPoint que desplegaremos en Cloud Functions, allí podemos ver que hacemos un request al recurso enviando el parámetro paramSearch, una vez recibimos la respuesta de la solicitud iteramos sobre los resultados encontrados, donde la API de Cloud Vision ha encontrado coincidencias de la palabra de búsqueda sobre los activos digitales, ya sean imágenes o pdf.

$(document).ready(function () {

    const ENDPOINT = 'TU_ENDPOINT_DE_CLOUD_FUNCTIONS';
    var getResultsStatus = false;
    var loadingHtml = ' <div class="spinner-border text-primary" role="status"><span class="visually-hidden">Loading...</span</div>';
    
    function getResults(){
        var paramSearch = $('#paramSearch').val();
        if(paramSearch == ''){
            alert("Introduzca un parámetro de búsqueda");
            return;
        }
        if(getResultsStatus == true){
            return;
        }
        $('.content').html(loadingHtml);
        getResultsStatus = true;
        $.getJSON(ENDPOINT+'?paramSearch='+paramSearch,function( returnValue ){
            getResultsStatus = false;
            if(returnValue.response){
                if(returnValue.response == 'no match'){
                    $('.content').html('<b>No se encontraron coincidencias</b>');
                    return;
                }
            }
            var tableResponse = '<table class="table table-dark table-hover">';
            tableResponse += '<thead>';
            tableResponse += '<tr>';
            tableResponse += '<th scope="col"># de coincidencias</th>';
            tableResponse += '<th scope="col">Extracción</th>';
            tableResponse += '<th scope="col">URL</th>';
            tableResponse += '</tr>';
            tableResponse += '</thead>';
            tableResponse += '<tbody>';
            for(var i = 0; i < returnValue.length; i++){
                tableResponse += '<tr>';
                tableResponse += '<td style="font-size: 30px;color: #ffc107;">'+returnValue[i].count_match+'</td>';
                var regex = new RegExp(paramSearch, 'gi');
                var textExtract = returnValue[i].textExtract.replace(regex, '<span style="background-color: #dc3545;padding: 2px;color: white;cursor: pointer;border: solid;border-width: 1px;border-radius: 4px;border-color: #ffc107;">'+paramSearch+'</span>');
                tableResponse += '<td style="font-size:10px;">'+textExtract+'</td>';
                tableResponse += '<td><img style="width:100px;" src="'+returnValue[i].url+'" /><a href="'+returnValue[i].url+'" target="_blank">Ver</a></td>';
                tableResponse += '</tr>';
            }
            tableResponse += '</tbody>';
            tableResponse += '</table>';
            $('.content').html(tableResponse);
        });
    }

    $('#getMatch').on('click',getResults);

});


ENDPOINT en Cloud Functions y el poder de Cloud Vision

En este punto veremos el script escrito en JavaScript que para este ejercicio se desplegara en Cloud Functions, el servicio de funciones sin servidor de GCP. Nos servirá como endpoint para la comunicación entre nuestro FrontEnd y La API de Cloud Vision.


const vision = require('@google-cloud/vision').v1;
const client = new vision.ImageAnnotatorClient();
const bucketName = 'TU-BUCKET-DE-IMAGENES-PDF-EN-GCP';
const filesNames = [
  'co_espectador.750.jpg',
  'Primera_edición_de_El_Espectador_(22_mar._1887).jpg',
  'La-tarde.jpeg',
  'diario.jpeg',
  'ancla0401-1000_1.jpeg',
  'co_espectador.750 (1).jpg',
  '49865fe0ba8590d18cfe404426c4b600.jpeg',
  '7Dic1973.jpeg',
  'pais.jpeg',
  've_nacional.750.jpg',
  'sinceramente orig.png'
];

exports.run = (req, res) => {
  runVision(req, res);
};

async function runVision(req,res) {

  let response = [];
  let paramSearch =  req.query.paramSearch;
  if(!paramSearch || paramSearch == ''){
    response = {"response":"paramSearch not found"};
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'GET');
    res.header('Allow', 'GET');
    res.status(200).send(JSON.stringify(response));
  } else {
    paramSearch = paramSearch.toLowerCase();
    for(var i = 0; i > filesNames.length; i++){
      var gcsSourceUri = `gs://${bucketName}/${filesNames[i]}`;
      const request = {
        "requests": [
          {
            "image": {
              "source": {
                "imageUri": gcsSourceUri
              }
            },
            "features": [
              {
                "type": "DOCUMENT_TEXT_DETECTION"
              }
            ],
            "imageContext": {
              "languageHints": ["es"]
            }
          }
        ]
      };
      var [result] = await client.batchAnnotateImages(request);
      var detections = result.responses[0].fullTextAnnotation.text;
      let found = ((detections).toLowerCase()).search(paramSearch);
      if(found != -1){
        var regex = new RegExp(paramSearch, 'gi');
        response.push({
          'count_match': (detections).match(regex).length,
          'url': 'https://storage.googleapis.com/' + bucketName + '/'+filesNames[i],
          'textExtract': detections
        });
      }
    }

    if(response.length == 0){
      response = {"response":"no match"};
    }
    
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'GET');
    res.header('Allow', 'GET');
    res.status(200).send(JSON.stringify(response));
  }
}

Usaremos algunos archivos de prueba que alojaremos en Google Cloud Storage, para que la API se encargue de encontrar la palabra a buscar sobre los activos digitalizados. El Endpoint responderá un objeto en formato JSON con las coincidencias encontradas, la cantidad de las mismas y la URL de la ruta del archivo en GCE.

Puedes descargar el código fuente y ponerlo en funcionamiento, deberás crearte un proyecto de prueba en la consola de GCP (https://console.cloud.google.com) y hacer uso de esta API dentro de la cuota free. (https://cloud.google.com/vision/pricing?hl=es)



Descargar código fuente


Comentarios