Cómo usamos algoritmos de visión por computadora: procesamiento de video en un navegador móvil usando OpenCV.js

Ya existen todas las posibilidades para identificar a una persona en línea, pero hasta ahora rara vez se usan. Tal vez fuimos uno de los primeros en implementar el escenario óptimo para el usuario: inicie sesión en el sitio desde un teléfono inteligente, tome una foto de su licencia de conducir o pasaporte y envíe datos al sistema.

Consideremos cómo los algoritmos de visión por computadora ayudan a reconocer documentos en una transmisión de video directamente en navegadores móviles. En este artículo, compartimos nuestra experiencia de cómo usamos OpenCV.js para esto en SimbirSoft, qué dificultades son posibles, cómo garantizar la velocidad y obtener una experiencia de usuario "suave" sin disminuir la velocidad.




Cual era la tarea


El escenario empresarial para el algoritmo que se desarrolla es el siguiente. Un usuario que acceda al sitio desde un teléfono móvil debería poder fotografiar sus documentos y enviarlos al sistema para su posterior procesamiento. Esto puede ser parte del proceso de identidad al solicitar el uso de cualquier servicio.

Una aplicación web en este escenario es preferible a una aplicación móvil debido a su disponibilidad y tiempo reducido para completar la operación. La página web no necesita instalación y está lista para funcionar inmediatamente después de la carga. El usuario puede realizar las acciones que necesita, enviar una solicitud, inmediatamente después de recibir el enlace, sin distraerse con acciones adicionales. Desde una perspectiva comercial, estos factores aumentan la conversión y la efectividad comercial del proceso.

Desde un punto de vista arquitectónico, se requiere el algoritmo para detectar directamente los límites del documento y recortar el exceso de fondo en la imagen. La verificación de identidad, autenticación y verificación de fraude será implementada por otros componentes. Sin embargo, es recomendable llevar a cabo al menos controles mínimos para excluir el envío de tarjetas de visita, rectángulos de papel vacíos y otras imágenes obviamente irrelevantes para procesar imágenes.

Requisitos


Como parte de nuestro proyecto, existían los siguientes requisitos adicionales para el algoritmo:

  • la capacidad de trabajar en tiempo real: el flujo de video de la cámara no debe "reducir la velocidad" durante el funcionamiento del algoritmo;
  • la capacidad de trabajar en una amplia gama de contraste y textura de fondo: bajo contraste y contraste, fondo homogéneo y heterogéneo;
  • Compatibilidad con una amplia gama de modelos de teléfonos inteligentes, incluidos los modelos económicos lanzados hace varios años.

Finalmente, no había un conjunto de datos para entrenar algoritmos de aprendizaje automático en el proyecto, y no había forma de recopilarlo y marcarlo. Solo tuvimos algunas muestras de prueba de los resultados de búsqueda de Google.

Dada esta declaración del problema, decidimos desarrollarnos en base a los algoritmos clásicos de visión por computadora de la biblioteca opencv. Una posibilidad alternativa era el uso de algoritmos de aprendizaje automático y redes neuronales, sin embargo, ya se descartó en las primeras etapas del trabajo debido a los requisitos de rendimiento: cuando se aplica, no sería posible proporcionar procesamiento de trama en tiempo real en todos los dispositivos de destino.

Enfoque general y estructura de algoritmo


La idea principal del algoritmo es un marco de referencia, a lo largo del cual es necesario alinear el documento. Su uso persigue varios objetivos a la vez. En primer lugar, proporcionará un tamaño de imagen adecuado, suficiente para el procesamiento posterior de documentos. En segundo lugar, como veremos más adelante, se puede usar como uno de los filtros candidatos cuando se buscan bordes de documentos. En tercer lugar, se puede utilizar para capturar y recortar la imagen si no se pueden encontrar los bordes del documento.



Higo. 1. La estructura general del algoritmo.

La estructura general del algoritmo se muestra en la Fig. 1. Los cuadros de la transmisión de video se procesan en un ciclo, entre iteraciones de las cuales se establece un tiempo de espera para cumplir con el FPS deseado; nos detuvimos a 30 cuadros por segundo. Esto le permite evitar "ralentizaciones" y reducir la carga en el procesador y el consumo de energía del dispositivo.

Cada marco procesado se somete a un preprocesamiento, durante el cual se realizan dos operaciones principales. En primer lugar, se crea una copia de un marco de un tamaño fijo de 640x480, con el que funcionan los pasos adicionales del algoritmo. La imagen original también permanece, el documento detectado se cortará. Esto ahorrará la calidad de la imagen final. En segundo lugar, la copia creada se traduce en tonos de gris. El algoritmo ignora el color del documento que se está procesando, ya que puede variar de un país a otro e incluso en diferentes regiones del país; un ejemplo es una licencia de conducir en los Estados Unidos.

El primer paso para detectar un documento es buscar la cara en la imagen. El uso de esta heurística elimina la captura de tarjetas de presentación y otras imágenes obviamente irrelevantes. La búsqueda se realiza utilizando el estándar opencv'shash CascadeClassifier.detectMultiScale () y la cascada pre- entrenada haarcascade_frontalface_default . Los tamaños mínimos y máximos de las caras detectadas son limitados, lo que permite reducir los costos computacionales y también limita aún más la escala del documento en la imagen. Una cara se considera detectada en la imagen cuando está en la parte izquierda o inferior izquierda, para pasaportes, del área dentro del marco de referencia (Fig. 2). Esta es una medida adicional para garantizar la alineación correcta del documento en la imagen.

Los ejemplos en este artículo no contienen datos personales.



Higo. 2. El área de la posición esperada de la cara en la imagen. El marco de soporte se muestra en rojo, los bordes del área de la ubicación esperada de la cara se muestran en verde.Después de la

detección de la cara, procedemos a la detección del borde. A menudo, findContours () se usa aquí . Sin embargo, este enfoque funciona bien solo en casos contrastantes, por ejemplo, para una hoja de papel sobre un escritorio oscuro. Si el contraste es más bajo, o la iluminación es peor, o alguien sostiene una sábana en sus manos, cubriendo parte del borde con los dedos, los contornos detectados se dividen en componentes separados, "pierden" secciones significativas o no se detectan en absoluto.

Por lo tanto, tomamos un enfoque diferente. Después de la binarización, primero pasamos la imagen a través del filtro de borde usando Canny () , y luego miramos la imagen resultante para la línea usando la transformación Huff HoughLines () . El parámetro umbral se establece inmediatamente lo suficientemente grande, igual a 30, para filtrar segmentos cortos y otros segmentos irrelevantes detectados.

El conjunto resultante de líneas se filtra adicionalmente, dejando solo líneas cerca del marco de referencia. Para hacer esto, primero traducimos las ecuaciones de las líneas del marco a puntos en el sistema de coordenadas polares (rho, theta): theta siempre será 0 o pi / 2, y rho será único para cada línea. Después de eso, seleccionamos de las líneas obtenidas de la transformación Huff solo aquellas que se encuentran cerca de los puntos de control, de acuerdo con la métrica euclidiana, teniendo en cuenta la diferencia en la escala de los valores.

Distribuimos el conjunto de líneas obtenidas después del filtrado en cuatro grupos correspondientes a las cuatro líneas del marco de referencia, encontramos las intersecciones de las líneas en pares entre los grupos, promediamos y obtenemos las coordenadas de los cuatro puntos: las esquinas del documento detectado (Fig.3).



Higo. 3. Filtrar líneas y definir esquinas de documentos. Las líneas verdes, resultado del filtrado, los puntos amarillos, detectaron las esquinas del documento.

A continuación, debe asegurarse de la calidad del marco. Para hacer esto, verificamos que el marco ha permanecido estacionario por última vez. Para hacer esto, reste el marco al comienzo del período del marco actual usando absdiff () y compárelo con el umbral. Antes de la resta, también suavizamos las imágenes con un filtro Gaussiano GaussianBlur () para reducir la influencia del ruido y otros factores aleatorios. También evaluamos el enfoque del marco calculando su Laplacian Laplacian () , estimando su varianza y comparando el valor obtenido con un umbral.

Si todas las verificaciones son exitosas, puede pasar a la parte final. Recalculamos las coordenadas detectadas de los ángulos en el sistema de coordenadas de la imagen subexpuesta original y cortamos la región resultante utilizando el método roi () . El documento fue detectado con éxito.

Características de implementación


Durante el desarrollo del algoritmo, sus componentes principales se ensamblaron en un script de Python. Después de eso, el algoritmo fue portado a opencv.js y javascript, y luego a wasm. Este enfoque está dictado por consideraciones de conveniencia en todas las etapas. En Python, fue más conveniente para nuestro equipo experimentar con varias variantes del algoritmo y llevar a cabo ajustes de parámetros aproximados. La migración a JavaScript permitió probar el funcionamiento del algoritmo en la plataforma de destino, incluidos varios dispositivos y navegadores. En función de los resultados de estas comprobaciones, se realizó un ajuste fino de los parámetros del algoritmo. Finalmente, reescribir secciones críticas de código en wasm nos permitió obtener un aumento de rendimiento adicional.

Durante la migración, se descubrieron varias diferencias en la API de OpenCV, lo que resultó en cambios menores en la implementación. Por ejemplo, la varianza de un laplaciano en python se considera simplemente como laplaciano (). Var () . Con OpenCV.js, no hay forma de usar NumPy, pero no se ha proporcionado una implementación alternativa del método var () . Solución: Cuente la función meanStdDev () como la desviación estándar (Listado 1).

private isImageBlurry(image: cv.Mat): boolean {
		const laplacian = new cv.Mat();
		cv.Laplacian(image, laplacian, cv.CV_64F);
		const s_mat = new cv.Mat();
		cv.meanStdDev(laplacian, new cv.Mat(), s_mat);
		const s = s_mat.data64F[0];
		const v = Math.pow(s, 2);
		return (v < this.laplacianVarianceThreshold);
	}

Listado 1. Evaluación del enfoque en la imagen a través de la varianza de Laplacian en opencv.js (TypeScript)

Otra característica fue la necesidad de reducir el tamaño de la biblioteca. En su forma original, OpenCV.js tiene una capacidad de 7.9 MB. Su descarga a través de Internet ralentiza la inicialización del algoritmo. La solución a este problema es "recortar" los módulos no utilizados durante el proceso de ensamblaje de la biblioteca, lo que puede reducir significativamente el tamaño del archivo de salida: logramos un tamaño de 1.8 MB. La lista de componentes incluidos en el ensamblaje se puede configurar en el archivo de configuración plataformas / js / opencv_js.config.py (Listado 2).

white_list = makeWhiteList([core, imgproc, objdetect, video, dnn, features2d, photo, aruco, calib3d])

Listado 2. La lista blanca original de módulos opencv incluidos en el ensamblaje para javascript

Finalmente, se realizó una contribución importante para garantizar el rendimiento requerido del algoritmo al pasarlo a Web Worker. Este paso, junto con la restricción de FPS, nos permitió deshacernos de las "ralentizaciones" de la transmisión de video durante la operación del algoritmo, que tuvo un efecto positivo en UX.

resultados


Los ejemplos de captura y recorte de imágenes se muestran en la Fig. 4. Se puede ver que el cultivo de la más alta calidad se logra sobre un fondo uniforme oscuro, y la calidad más baja se obtiene con un fondo no homogéneo claro. Este es el efecto esperado asociado con los gradientes obtenidos en diferentes fondos y utilizados para detectar los bordes de un documento. Sobre un fondo oscuro, los gradientes son más grandes que sobre un fondo claro, un fondo uniforme conduce a una menor variabilidad de los valores de gradiente. Esto conduce a una detección confiable de los límites y, como resultado, a un mejor cultivo.




Higo. 4. Ejemplos de recorte de documentos utilizando un algoritmo.

Conclusión


El artículo presenta un algoritmo para detectar documentos en cuadros de una transmisión de video adecuada para su uso en navegadores móviles, y también analiza las características de su implementación utilizando la biblioteca opencv.js. El algoritmo le permite obtener la imagen de salida de los documentos en una calidad suficiente para su uso posterior por los algoritmos de autenticación, verificación de identidad, etc. La velocidad de la implementación resultante le permite obtener un UX "suave" sin "ralentizaciones" y pérdida de cuadros.

¡Gracias por la atención! Esperamos que encuentre útil este artículo.

All Articles