Se ha probado la librería OpenCV.js para la identificación de diferentes patrones en un vídeo: caras, ojos, coches, el cuerpo humano, etc. El ejemplo se ha montado con sobre una página web 'index.html' y un pequeño código 'script.js'.
index.html
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="utf-8">
<title>Prueba de OpenCV.js usando (https://github.com/opencv) y (https://huningxin.github.io/opencv.js)</title>
</head>
<body>
<table>
<tr>
<td><video id="video"></video></td>
</tr>
<tr>
<td><canvas id="canvasOutput" width=320 height=240></canvas></td>
</tr>
</table>
</body>
<script>
var Module = {
wasmBinaryFile: 'https://huningxin.github.io/opencv.js/build/wasm/opencv_js.wasm',
preRun: [function () {
Module.FS_createPreloadedFile('/',
'haarcascade_frontalface_default.xml',
'https://raw.githubusercontent.com/opencv/opencv/master/data/haarcascades/haarcascade_frontalface_default.xml',
true, false);
Module.FS_createPreloadedFile('/',
'haarcascade_eye.xml',
'https://raw.githubusercontent.com/opencv/opencv/master/data/haarcascades/haarcascade_eye.xml',
true, false);
Module.FS_createPreloadedFile('/',
'haarcascade_fullbody.xml',
'https://raw.githubusercontent.com/opencv/opencv/master/data/haarcascades/haarcascade_fullbody.xml',
true, false);
Module.FS_createPreloadedFile('/',
'cas4.xml',
'https://raw.githubusercontent.com/abhi-kumar/CAR-DETECTION/master/cas4.xml',
true, false);
}],
_main: function () { opencvIsReady(); }
};
</script>
<script async src="https://huningxin.github.io/opencv.js/build/wasm/opencv.js"></script>
<script src="./script.js"></script>
</html>
script.js
/**
* Instanciamos variables
*/
let hayWebcam = false; // Indicador de la existencia de señal de vídeo desde la cámara
let videoWidth; // Anchura de la imagen de vídeo
let videoHeight; // Altura de la imagen de vídeo
let stream = null; // Stream de vídeo
let detector = null; // Detector de objetos en las imágenes
let canvasInput = null; // Panel de dibujo
let canvasInputCtx = null;
/**
* Capturamos los componentes <html> asociados al vídeo
*/
let video = document.getElementById('video');
let canvasOutput = document.getElementById('canvasOutput');
let canvasOutputCtx = canvasOutput.getContext('2d');
/**
* Captura la webcam y su señal de stream, volcando esa imagen
* en el componente <video>
* @returns
*/
function startCamera() {
if (hayWebcam) {
// Si se ha detectado ya la webcam salimos
return;
}
// Capturamos la señal de la webcam
navigator.mediaDevices.getUserMedia({ video: true, audio: false })
.then(function (s) {
stream = s;
video.srcObject = s;
video.play();
})
.catch(function (err) {
console.log("Error: " + err);
});
// Lanzamos el procesamiento de la señal de vídeo
video.addEventListener("canplay", function (ev) {
if (!hayWebcam) {
videoWidth = video.videoWidth;
videoHeight = video.videoHeight;
canvasOutput.width = videoWidth;
canvasOutput.height = videoHeight;
hayWebcam = true;
}
startVideoProcessing();
}, false);
}
/**
* Prepara lo necesario para el procesamiento inicial del vídeo
* @returns
*/
function startVideoProcessing() {
// Si no hay señal de vídeo terminamos
if (!hayWebcam) {
console.warn("Webcam no detectada...");
return;
}
// Ajustamos el canvas de la página
canvasInput = document.createElement('canvas');
canvasInput.width = videoWidth;
canvasInput.height = videoHeight;
canvasInputCtx = canvasInput.getContext('2d');
// Preparamos las matrices
srcMat = new cv.Mat(videoHeight, videoWidth, cv.CV_8UC4);
grayMat = new cv.Mat(videoHeight, videoWidth, cv.CV_8UC1);
// Instanciamos el detector y cargamos el patrón que deseemos
detector = new cv.CascadeClassifier();
detector.load('haarcascade_frontalface_default.xml'); // caras
//detector.load('haarcascade_eye.xml'); // ojos
//detector.load('haarcascade_fullbody.xml'); // cuerpo humano
//detector.load('cas4.xml'); // coches
// Lanzamos el procesamiento del vídeo
requestAnimationFrame(processVideo);
}
/**
* Realiza el procesamiento de la señal de vídeo para detectar patrones
*/
function processVideo() {
// Preparamos el panel donde se vocarán los fotogramas con el vídeo
canvasInputCtx.drawImage(video, 0, 0, videoWidth, videoHeight);
let imageData = canvasInputCtx.getImageData(0, 0, videoWidth, videoHeight);
srcMat.data.set(imageData.data);
cv.cvtColor(srcMat, grayMat, cv.COLOR_RGBA2GRAY);
let patronesDetectados = [];
let size;
// Inicializa la matriz de coordenadas de los patrones
let faceVect = new cv.RectVector();
// Inicializa la matriz de patrones
let faceMat = new cv.Mat();
cv.pyrDown(grayMat, faceMat);
cv.pyrDown(faceMat, faceMat);
size = faceMat.size();
// Lanza el detector de patrones
detector.detectMultiScale(faceMat, faceVect);
// Recorre la matriz de coordenadas de los patrones detectados y dibuja los cuadrados
for (let i = 0; i < faceVect.size(); i++) {
let face = faceVect.get(i);
patronesDetectados.push(new cv.Rect(face.x, face.y, face.width, face.height));
}
// Borra las matrices de patrones y de coordenadas
faceMat.delete();
faceVect.delete();
// Dibuja cada frame con patrones en el panel resultante
canvasOutputCtx.drawImage(canvasInput, 0, 0, videoWidth, videoHeight);
// Dibuja los rectangulos en cada frame en el panel resultante
dibujaRectangulos(canvasOutputCtx, patronesDetectados, 'yellow', size);
// Continúa el procesamiento de los siguientes frames
requestAnimationFrame(processVideo);
}
/**
* Dibuja un rectangulo en cada patrón detectado
*/
function dibujaRectangulos(ctx, patronesDetectados, color, size) {
for (let i = 0; i < patronesDetectados.length; ++i) {
let rect = patronesDetectados[i];
let xRatio = videoWidth / size.width;
let yRatio = videoHeight / size.height;
ctx.lineWidth = 1;
ctx.strokeStyle = color;
ctx.strokeRect(rect.x * xRatio, rect.y * yRatio, rect.width * xRatio, rect.height * yRatio);
}
}
/**
* Cuando se carga la librería y el fichero de entrenamiento para la detección de patrones
* se lanza la función que desencadena la activación de la webcam y el procesamiento del
* stream de vídeo
*/
function opencvIsReady() {
console.log('OpenCV.js cargado');
startCamera();
}
No hay comentarios:
Publicar un comentario