
Aquí Xianur0. Este es un algoritmo simple, se genera una imagen del fondo y se comparan los pixeles "agregados" de modo que si algo no coincide entonces tenemos que ese algo no estaba ahí, por tanto reconocemos presencias.
Aparte se incluye un algoritmo de corrección de falsos positivos (elimina manchas pequeñas) de este modo es ideal para utilizar con cámaras de baja calidad (por ejemplo en la imagen estoy utilizando una de 1.3 Mpx xD), del mismo modo ese mismo algoritmo se podría utilizar para corregir defectos de cámaras (mejorar imágenes) pero eso sera para otro día :P
#include <opencv2/video/background_segm.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <stdio.h>
// By Xianur0
// http://hackingtelevision.blogspot.com/
using namespace cv;
void mensaje()
{
printf("./presencia [camara]\n\n");
}
int main(int argc, char** argv)
{
VideoCapture cap;
bool updatebg = true;
if( argc < 2 )
cap.open(0);
else
cap.open(atoi(argv[1]));
mensaje();
if( !cap.isOpened() )
{
printf("No se puede abrir :S\n");
return -1;
}
BackgroundSubtractorMOG2 bg_model;
Mat frame, variaciones;
for(;;)
{
cap >> frame;
if( frame.empty() )
break;
bg_model(frame, variaciones, updatebg ? -1 : 0);
updatebg = false;
IplImage *in = new IplImage(variaciones);
IplImage *in2 = new IplImage(frame);
char *data = in->imageData;
int x,y,i = 0;
int inicio[in->width*in->height][4];
int contador = 0;
// limpiesa previa
inicio[0][0] = 0;
for(y=0;y<in->height;y++) {
for(x=0;x<in->width;x++) {
if(data[y*in->widthStep+x*in->nChannels] != 0) {
if(inicio[contador][0] == 0) {
inicio[contador][0] = x;
inicio[contador][1] = y;
}
} else {
if(inicio[contador][0] != 0) {
inicio[contador][2] = x;
inicio[contador][3] = y;
contador++;
inicio[contador][0] = 0;
}
}
}
}
printf("Limpiando: %i manchas\n",contador);
int manchas = 0;
for(i = 0;i<contador;i++) {
if(inicio[i][1] == inicio[i][3] && (inicio[i][2]-inicio[i][0]) < 5) {
for(x=inicio[i][0]-1;x<inicio[i][2];x++) {
data[(inicio[i][1])*in->widthStep+x*in->nChannels] = 0;
}
} else {
manchas++;
}
}
printf("Se ignoraron %i manchas\n",manchas);
// ultimo bucle para localizar puntos (confiando en que el filtro anterior lo dejo muy "bonito")
int masalto = 0;
int masbajo = 0;
int masizquierda = 0;
int masderecha = 0;
for(x=1;x<in->width;x++) {
for(y=0;y<in->height;y++) {
if(data[y*in->widthStep+x*in->nChannels] != 0) {
if(x > masderecha) {
masderecha = x;
}
if(x < masizquierda) {
masizquierda = x;
}
if(y > masalto) {
masalto = y;
}
if(y < masbajo) {
masbajo = y;
}
}
}
}
int centrox = (masderecha+masizquierda)/2;
int centroy = (masalto+masbajo)/2;
int radius = abs(masalto-centroy);
cvCircle(in2, cvPoint(centrox,centroy), radius, cvScalar(0,255,0), 1);
imshow("RGB", in2);
imshow("Presencia", in);
char k = (char)waitKey(30);
if( k == 27 ) break;
if( k == ' ' )
{
updatebg = !updatebg;
if(updatebg)
printf("Background update activado\n");
else
printf("Background update desactivado\n");
}
}
return 0;
}
No hay comentarios:
Publicar un comentario en la entrada