François Gautrais %!s(int64=9) %!d(string=hai) anos
pai
achega
01a454e25a
Modificáronse 20 ficheiros con 1255 adicións e 0 borrados
  1. 25 0
      Makefile
  2. 63 0
      src/common.c
  3. 11 0
      src/common.h
  4. 83 0
      src/convol.c
  5. 10 0
      src/convol.h
  6. 78 0
      src/image.c
  7. 77 0
      src/image.h
  8. 149 0
      src/main.c
  9. 27 0
      src/main.h
  10. 27 0
      src/main.h~
  11. 106 0
      src/matrix.c
  12. 27 0
      src/matrix.h
  13. 87 0
      src/paint.c
  14. 15 0
      src/paint.h
  15. 94 0
      src/process.c
  16. 8 0
      src/process.h
  17. 102 0
      src/sdl.c
  18. 26 0
      src/sdl.h
  19. 189 0
      src/vd.c
  20. 51 0
      src/vd.h

+ 25 - 0
Makefile

@@ -0,0 +1,25 @@
+TARGET=webcam
+
+OBJECTS=obj/vd.o obj/sdl.o obj/main.o obj/matrix.o obj/convol.o obj/process.o obj/common.o obj/image.o obj/paint.o
+CFLAGS=-Wall -g
+CPPFLAGS=
+LDFLAGS=-lSDL2 -lSDL2_image -lv4l2 -lm -g
+CC=gcc
+
+all: $(TARGET)
+
+
+$(TARGET): $(OBJECTS)
+	$(CC) $(OBJECTS) -o $(TARGET) $(LDFLAGS)
+
+
+obj/%.o: src/%.c
+	$(CC) -c $< -o $@ $(CPPFLAGS) $(CFLAGS)
+
+
+clean:
+	rm -rf obj/*  $(TARGET) || true
+
+exec: $(TARGET)
+	./$(TARGET)
+	

+ 63 - 0
src/common.c

@@ -0,0 +1,63 @@
+#include "main.h"
+#include "common.h"
+#include "image.h"
+
+
+void sat(image_t* out, const image_t *in, uint8_t thresold) 
+{
+  int i;
+  for(i=0; i<in->w*in->h; i++)
+  {
+    //float aa = 0.299*a[i*3]+ 0.587*a[i*3+1]+ 0.114 *a[i*3+2];
+    float aa = IMG_GET_Mi(in,i);
+    float dab=aa/3;
+    IMG_SET_Mi(out, i, (dab<thresold)?0:0xFF);
+  }
+}
+
+/*
+void sat2(image_t* out, const image_t* a, const image_t* b)
+{
+  int i;
+  for(i=0; i<w*h; i++)
+  {
+    float aa = 0.299*a[i*3]+ 0.587*a[i*3+1]+ 0.114 *a[i*3+2];
+    float ab = 0.299*b[i*3]+ 0.587*b[i*3+1]+ 0.114 *b[i*3+2];
+    float dab=((aa>ab)?(aa-ab):(ab-aa))/3;
+    s[i*3]=s[i*3+1]=s[i*3+2]=(dab<20)?0:0xFF;
+  }
+}
+
+
+
+void diff(image_t* out, const image_t* a, const image_t* b)
+{
+  int i;
+  for(i=0; i<w*h*3; i++)
+  {
+    s[i]=b[i]-a[i]<0?0:b[i]-a[i];
+  }
+}
+
+
+void diffg(image_t* out, const image_t* a, const image_t* b)
+{
+  int i;
+  for(i=0; i<w*h; i++)
+  {
+    float aa = 0.299*a[i*3]+ 0.587*a[i*3+1]+ 0.114 *a[i*3+2];
+    float ab = 0.299*b[i*3]+ 0.587*b[i*3+1]+ 0.114 *b[i*3+2];
+    float dab=((aa>ab)?(aa-ab):(ab-aa))/3;
+    s[i*3]=s[i*3+1]=s[i*3+2]=dab;
+  }
+}
+
+void moy(image_t* out, const image_t* a, const image_t* b)
+{
+  int i;
+  for(i=0; i<w*h*3; i++)
+  {
+    s[i]=(b[i]+a[i])>>1;
+  }
+}
+*/

+ 11 - 0
src/common.h

@@ -0,0 +1,11 @@
+#ifndef COMMON_H
+#define COMMON_H
+
+struct image_t;
+void sat			(struct image_t* out, const struct image_t* in, uint8_t thresold);
+void sat2			(struct image_t* out, const struct image_t* a, const struct image_t* b);
+void diff			(struct image_t* out, const struct image_t* a, const struct image_t* b);
+void diffg		(struct image_t* out, const struct image_t* a, const struct image_t* b);
+void moy			(struct image_t* out, const struct image_t* a, const struct image_t* b);
+
+#endif

+ 83 - 0
src/convol.c

@@ -0,0 +1,83 @@
+#include "convol.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "matrix.h"
+
+void convol(int w, int h, uint8_t* s, const uint8_t* a, matrix_t* mat)
+{
+  static int kk=0;
+  int i, j, k, l, n=mat->w;
+  for(i=0; i<h; i++)
+  {
+    for(j=0; j<w; j++)
+    {
+      int aa =0, bb=0, cc=0;
+      
+      for(k=-n/2; k<n/2+1; k++)
+      {
+        if(i+k<0 || i+k>=h) continue;
+        for(l=-n/2; l<n/2+1; l++)
+        {
+          int m;
+          if(j+l<0 || j+l>=w) continue;
+          m=mat->mat[(n/2+k)*n+n/2+l];
+          aa+=a[((i+k)*w+j+l)*3]*m;
+          bb+=a[((i+k)*w+j+l)*3+1]*m;
+          cc+=a[((i+k)*w+j+l)*3+2]*m;
+          
+        }
+      }
+      if(1)
+      {
+        s[(i*w+j)*3]=aa;
+        s[(i*w+j)*3+1]=bb;
+        s[(i*w+j)*3+2]=cc;
+      }else{
+        s[(i*w+j)*3]=aa/n/n;
+        s[(i*w+j)*3+1]=bb/n/n;
+        s[(i*w+j)*3+2]=cc/n/n;
+      }
+    }
+  }
+  kk++;
+}
+
+void convol_monochrome(int w, int h, uint8_t* s, const uint8_t* a, matrix_t* mat)
+{
+  static int kk=0;
+  int i, j, k, l, n=mat->w;
+  for(i=0; i<h; i++)
+  {
+    for(j=0; j<w; j++)
+    {
+      int aa =0, bb=0, cc=0, dd;
+      
+      for(k=-n/2; k<n/2+1; k++)
+      {
+        if(i+k<0 || i+k>=h) continue;
+        for(l=-n/2; l<n/2+1; l++)
+        {
+          int m;
+          if(j+l<0 || j+l>=w) continue;
+          m=mat->mat[(n/2+k)*n+n/2+l];
+          aa+=a[((i+k)*w+j+l)*3]*m;
+          bb+=a[((i+k)*w+j+l)*3+1]*m;
+          cc+=a[((i+k)*w+j+l)*3+2]*m;
+          
+        }
+      }
+      if(1)
+      {
+        dd=(aa+bb+cc)/n/n/3;
+        s[(i*w+j)*3]=s[(i*w+j)*3+1]=s[(i*w+j)*3+2]=dd;
+      }else{
+        s[(i*w+j)*3]=aa/n/n;
+        s[(i*w+j)*3+1]=bb/n/n;
+        s[(i*w+j)*3+2]=cc/n/n;
+      }
+    }
+  }
+  kk++;
+}

+ 10 - 0
src/convol.h

@@ -0,0 +1,10 @@
+#ifndef CONVOL_H
+#define CONVOL_H
+
+
+#include <stdint.h>
+struct matrix_t;
+void convol(int w, int h, uint8_t* s, const uint8_t* a, struct matrix_t* mat);
+void convol_monochrome(int w, int h, uint8_t* s, const uint8_t* a, struct matrix_t* mat);
+
+#endif

+ 78 - 0
src/image.c

@@ -0,0 +1,78 @@
+#include "image.h"
+
+
+
+pixel_t* pixel_set(pixel_t* p, uint8_t r, uint8_t g, uint8_t b)
+{
+	p->r=r;
+	p->g=g;
+	p->b=b;
+	return p;
+}
+
+image_t* image_set(image_t* p, int w, int h, pixel_t* data)
+{
+	if(!p)
+	{
+		p=malloc(sizeof(image_t));
+		p->isstatic=0;
+	}else p->isstatic=1;
+	p->w=w;
+	p->h=h;
+	p->mat=(pixel_t*)data;
+	p->isallocated=0;
+	return p;
+}
+
+image_t* image_clear(image_t* p)
+{
+	memset(p->mat, 0, p->w*p->h*sizeof(pixel_t));
+}
+
+image_t* image_copy(image_t* p, int w, int h, pixel_t* data)
+{
+	if(!p)
+	{
+		p=malloc(sizeof(image_t));
+		p->isstatic=0;
+	}else p->isstatic=1;
+	p->w=w;
+	p->h=h;
+	p->mat=malloc(sizeof(pixel_t)*w*h);
+	memcpy(p->mat, data, sizeof(pixel_t)*w*h);
+	p->isallocated=1;
+	return p;
+}
+
+
+image_t* image_mem_copy(image_t* out, const image_t* in)
+{
+	if(out->w>=in->w && out->h>=in->h)
+	{
+		memset(out->mat, in->mat, in->w*in->h*sizeof(image_t));
+	}
+	return out;
+}
+
+
+image_t* image_empty(image_t* p, int w, int h)
+{
+	if(!p)
+	{
+		p=malloc(sizeof(image_t));
+		p->isstatic=0;
+	}else p->isstatic=1;
+	p->w=w;
+	p->h=h;
+	p->mat=malloc(sizeof(pixel_t)*w*h);
+	memset(p->mat, 0, sizeof(pixel_t)*w*h);
+	p->isallocated=1;
+	return p;
+}
+
+
+void image_free(image_t* p)
+{
+	if(p->isallocated) free(p->mat);
+	if(p->isstatic) free(p);
+}

+ 77 - 0
src/image.h

@@ -0,0 +1,77 @@
+#ifndef IMAGE_H
+#define IMAGE_H
+#include "main.h"
+
+typedef struct point_t point_t;
+struct point_t
+{
+	int x;
+	int y;
+};
+
+#define POINT(x,y) ((point_t){x,y})
+
+typedef struct image_t image_t;
+
+
+typedef struct pixel_t pixel_t;
+typedef struct pixel_t color_t;
+struct pixel_t
+{
+	uint8_t r;
+	uint8_t g;
+	uint8_t b;
+};
+
+#define PIXEL_RGB(r,g,b) ((pixel_t){r,g,b})
+#define COLOR_RGB(r,g,b) ((pixel_t){r,g,b})
+
+#define PIXEL(x) ((pixel_t){(x>>16)&0xff,(x>>8)&0xff,(x)&0xff})
+#define COLOR(x) ((pixel_t){(x>>16)&0xff,(x>>8)&0xff,(x)&0xff})
+
+pixel_t* pixel_set(pixel_t* p, uint8_t r, uint8_t g, uint8_t b);
+
+struct image_t
+{
+	int 			w;
+	int 			h;
+	uint8_t 	isallocated;
+	uint8_t 	isstatic;
+	pixel_t*	mat;
+};
+
+image_t* image_set	(image_t* p, int w, int h, pixel_t* data);
+image_t* image_copy	(image_t* p, int w, int h, pixel_t* data);
+image_t* image_empty(image_t* p, int w, int h);
+image_t* image_clear(image_t* p);
+void		 image_free	(image_t* p);
+image_t* image_mem_copy(image_t* out, const image_t* in);
+
+#define IMG_GET(img, i, j)				((img)->mat[(img)->w*(j)+(i)])
+#define IMG_GET_R(img, i, j) 			(((img)->mat[(img)->w*(j)+(i)]).r)
+#define IMG_GET_G(img, i, j) 			(((img)->mat[(img)->w*(j)+(i)]).g)
+#define IMG_GET_B(img, i, j) 			(((img)->mat[(img)->w*(j)+(i)]).b)
+#define IMG_GET_M(img, i, j)			(IMG_GET_R(img,i,j)+ IMG_GET_G(img,i,j)+ IMG_GET_B(img,i,j))
+#define IMG_GET_Y(img, i, j)			(0.299*IMG_GET_R(img,i,j)+ 0.587*IMG_GET_G(img,i,j)+ 0.114 *IMG_GET_B(img,i,j))
+
+#define IMG_GETi(img, i) 					((img)->mat[i])
+#define IMG_GET_Ri(img, i) 				(((img)->mat[i]).r)
+#define IMG_GET_Gi(img, i) 				(((img)->mat[i]).g)
+#define IMG_GET_Bi(img, i) 				(((img)->mat[i]).b)
+#define IMG_GET_Mi(img, i) 				(IMG_GET_Ri(img,i)+ IMG_GET_Gi(img,i)+ IMG_GET_Bi(img,i))
+#define IMG_GET_Yi(img, i) 				(0.299*IMG_GET_Ri(img,i)+ 0.587*IMG_GET_Gi(img,i)+ 0.114 *IMG_GET_Bi(img,i))
+
+
+#define IMG_SET(img, i, j, pix) 	((img)->mat[(img)->w*(j)+(i)]=(pix))
+#define IMG_SET_M(img, i, j, pix) IMG_SET_R(img,i,j,pix)+ IMG_SET_G(img,i,j,pix)+ IMG_SET_B(img,i,j,pix)
+#define IMG_SET_R(img, i, j, pix) ((img)->mat[(img)->w*(j)+(i)].r=(pix))
+#define IMG_SET_G(img, i, j, pix) ((img)->mat[(img)->w*(j)+(i)].g=(pix))
+#define IMG_SET_B(img, i, j, pix) ((img)->mat[(img)->w*(j)+(i)].b=(pix))
+
+#define IMG_SETi(img, i, pix) 		(img)->mat[i]=(pix)
+#define IMG_SET_Mi(img, i, pix) 	{IMG_SET_Ri(img,i,pix); IMG_SET_Gi(img,i,pix); IMG_SET_Bi(img,i,pix);}
+#define IMG_SET_Ri(img, i, pix) 	(img)->mat[i].r=(pix)
+#define IMG_SET_Gi(img, i, pix) 	(img)->mat[i].g=(pix)
+#define IMG_SET_Bi(img, i, pix) 	(img)->mat[i].b=(pix)
+
+#endif

+ 149 - 0
src/main.c

@@ -0,0 +1,149 @@
+/* V4L2 video picture grabber
+   Copyright (C) 2009 Mauro Carvalho Chehab <mchehab@infradead.org>
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation version 2 of the License.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+ */
+#include "main.h"
+#include "common.h"
+#include "image.h"
+#include "process.h"
+
+
+image_t tmpimage;
+
+
+int sign(int w, int h, uint8_t* s, const uint8_t* a)
+{
+  int i;
+  int max=0;
+  int histogramme[257]={0};
+  histogramme[256]=1000;
+  for(i=0; i<w*h; i++)
+  {
+    float aa = 0.299*a[i*3]+ 0.587*a[i*3+1]+ 0.114 *a[i*3+2];
+    histogramme[(int)aa]++;
+  }
+  memset(s, 0, w*h*3);
+  for(i=0; i<256; i++) 
+    if( histogramme[i]>max) max=histogramme[i];
+  
+  for(i=0; i<257 ;i++)
+  {
+    histogramme[i]=(histogramme[i]*(h+2))/max;
+    s[((h-1)*w+i*2)*3]=0xFF;
+    s[((h-1)*w+i*2+1)*3]=0xFF;
+    s[((h-1-histogramme[i])*w+i*2)*3]=s[((h-1-histogramme[i])*w+i*2)*3+1]=s[((h-1-histogramme[i])*w+i*2)*3+2]=0xFF;
+    s[((h-histogramme[i])*w+i*2)*3]=s[((h-histogramme[i])*w+i*2)*3+1]=s[((h-histogramme[i])*w+i*2)*3+2]=0xFF;
+  }
+  return 0;
+}
+
+int hsm[256]={0};
+int sign_moy(int w, int h, uint8_t* s, const uint8_t* in, const uint8_t* a)
+{
+  int i;
+  int max=0;
+  int histogramme[257]={0};
+  int n=1,x=256;
+  double fault=0.0, res;
+  histogramme[256]=1000;
+  for(i=0; i<w*h; i++)
+  {
+    float aa = 0.299*a[i*3]+ 0.587*a[i*3+1]+ 0.114 *a[i*3+2];
+    histogramme[(int)aa]++;
+  }
+  memcpy(s, in, w*h*3);
+  
+  if(1)for(i=n/2;i<256-n/2; i++)
+  {
+      int moy=0;
+      int j;
+      for(j=-n/2; j<n/2+1; j++)
+        moy+=histogramme[i+j];
+      histogramme[i]=moy/n;
+  }
+  
+  for(i=0; i<256; i++) 
+    if( histogramme[i]>max) max=histogramme[i];
+  
+  for(i=0; i<257 ;i++)
+  {
+    histogramme[i]=(histogramme[i]*(h+2))/max;
+    s[((h-1)*w+i*2)*3]=0xFF;
+    s[((h-1)*w+i*2+1)*3]=0xFF;
+    s[((h-1-histogramme[i])*w+i*2)*3]=s[((h-1-histogramme[i])*w+i*2)*3+1]=s[((h-1-histogramme[i])*w+i*2)*3+2]=0xFF;
+    s[((h-2-histogramme[i])*w+i*2)*3]=s[((h-2-histogramme[i])*w+i*2)*3+1]=s[((h-2-histogramme[i])*w+i*2)*3+2]=0xff;
+  }
+  for(i=0; i<256; i++)
+  {
+    if(hsm[i] && histogramme[i]) fault+=(histogramme[i]>hsm[i])?(histogramme[i]-hsm[i])/hsm[i]:(hsm[i]-histogramme[i])/histogramme[i];
+    else x--;
+  }
+  res=(100-fault/x);
+  printf("Success=%lf %% => ", res);
+  if(res>99.9) printf(" OK \n"); else printf(" FAILED\n");
+  memcpy(hsm, histogramme, 256);
+  return 0;
+}
+
+int cb2(sdl_t* sdl, void* data)
+{
+  vd_t* v = (vd_t*) data;
+ /* const int co[25]={1,1,1,1,1,1,1,
+                    1,1,1,1,1,1,1,
+                    1,1,1,1,1,1,1,
+                    1,1,1,1,1,1,1,
+                    1,1,1,1,1,1,1,
+                    1,1,1,1,1,1,1,
+                    1,1,1,1,1,1,1};*/
+  vd_shot(v);
+  uint8_t tmp[WIDTH*HEIGHT*3];
+  /*diff(sdl->width, sdl->height, tmp, 
+            (uint8_t*)v->buffers[vd_get_relative_buffer_index(v,0)].start, 
+            (uint8_t*)v->buffers[vd_get_relative_buffer_index(v,-1)].start);
+*/
+            
+  sign_moy(sdl->width, sdl->height, (uint8_t*)v->buffertmp, v->buffers[vd_get_relative_buffer_index(v,0)].start, tmp);
+  sdl_setimage(sdl,v->buffertmp);
+
+  return 0;
+}
+
+
+int cb(vd_t* v, image_t* out, const image_t* in)
+{
+
+  process(out, in);
+  
+  
+
+  return 0;
+}
+
+int main(int argc, char** argv)
+{
+  vd_t v;
+  sdl_t sdl;
+  image_empty(&tmpimage, WIDTH, HEIGHT);
+  vd_init(&v, DEVICE, WIDTH, HEIGHT, cb);
+  sdl_init(&sdl, v.width, v.height);
+  sdl_mainloop(&sdl, vd_callback, &v);
+  
+  sdl_close(&sdl);
+  vd_close(&v);
+  return 0;
+  
+}
+
+
+
+
+
+

+ 27 - 0
src/main.h

@@ -0,0 +1,27 @@
+#ifndef MAIN_H
+#define MAIN_H
+
+#define WIDTH  1280
+#define HEIGHT 720
+#define DEVICE "/dev/video0"
+
+#include "vd.h"
+#include "sdl.h"
+#include "matrix.h"
+#include "convol.h"
+#include "process.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <time.h>
+#include <stdint.h>
+#include <signal.h>
+
+struct point_t;
+struct pixel_t;
+struct image_t;
+
+#endif

+ 27 - 0
src/main.h~

@@ -0,0 +1,27 @@
+#ifndef MAIN_H
+#define MAIN_H
+
+#define WIDTH  1280
+#define HEIGHT 720
+#define DEVICE "/dev/video1"
+
+#include "vd.h"
+#include "sdl.h"
+#include "matrix.h"
+#include "convol.h"
+#include "process.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+#include <time.h>
+#include <stdint.h>
+#include <signal.h>
+
+struct point_t;
+struct pixel_t;
+struct image_t;
+
+#endif

+ 106 - 0
src/matrix.c

@@ -0,0 +1,106 @@
+#include "matrix.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+
+matrix_t* 	matrix_3_3_init	 (matrix_t* m, float a, float b, float c,
+														  float d, float e, float f,
+															float g, float h, float i)
+{
+	if(!m)
+	{
+		m=malloc(sizeof(matrix_t));
+		if(!m) return NULL;
+		m->isstatic=0;
+	}else m->isstatic=1;
+	m->w=m->h=3;
+	m->mat[0]=a;
+	m->mat[1]=b;
+	m->mat[2]=c;
+	m->mat[3]=d;
+	m->mat[4]=e;
+	m->mat[5]=f;
+	m->mat[6]=g;
+	m->mat[7]=h;
+	m->mat[8]=i;
+	return m;
+}
+
+matrix_t*		matrix_init				(matrix_t* m, int width)
+{
+	if(!m)
+	{
+		m=malloc(sizeof(matrix_t));
+		if(!m) return NULL;
+		m->isstatic=0;
+	}else m->isstatic=1;
+	m->w=width;
+	m->h=0;
+	return m;
+}
+
+
+matrix_t*		matrix_init_array (matrix_t* m, int width, int height, const float* data)
+{
+	if(!m)
+	{
+		m=malloc(sizeof(matrix_t));
+		if(!m) return NULL;
+		m->isstatic=0;
+	}else m->isstatic=1;
+	m->w=width;
+	m->h=height;
+	memcpy(m->mat, data, width*height*sizeof(float));
+	return m;
+}
+
+void	matrix_insert_row3(matrix_t* m, float a, float b, float c)
+{
+	int start=m->w*m->h;
+	if(m->w!=3) return;
+	m->mat[start]=a;
+	m->mat[start+1]=b;
+	m->mat[start+2]=c;
+	m->h++;
+}
+
+void 	matrix_insert_row5(matrix_t* m, float a, float b, float c, float d, float e)
+{
+	int start=m->w*m->h;
+	if(m->w!=5) return;
+	m->mat[start]=a;
+	m->mat[start+1]=b;
+	m->mat[start+2]=c;
+	m->mat[start+3]=d;
+	m->mat[start+4]=e;
+	m->h++;
+}
+
+void 	matrix_insert_row7(matrix_t* m, float a, float b, float c, float d, float e, float f, float g)
+{
+	int start=m->w*m->h;
+	if(m->w!=7) return;
+	m->mat[start]=a;
+	m->mat[start+1]=b;
+	m->mat[start+2]=c;
+	m->mat[start+3]=d;
+	m->mat[start+4]=e;
+	m->mat[start+5]=f;
+	m->mat[start+6]=g;
+	m->h++;
+}
+
+void	matrix_delete			(matrix_t* m)
+{
+	if(!m->isstatic)
+	{
+		free(m);
+	}
+}
+
+
+float matrix_get(matrix_t* m, int w, int h)
+{
+	return m->mat[h*m->w+w];
+}

+ 27 - 0
src/matrix.h

@@ -0,0 +1,27 @@
+#ifndef MATRIX_H
+#define MATRIX_H
+
+typedef struct matrix_t matrix_t;
+
+struct matrix_t
+{
+	int w;
+	int h;
+	float mat[81];
+	int isstatic;
+};
+
+matrix_t* 	matrix_3_3_init	 (matrix_t* m, float a, float b, float c,
+														  float d, float e, float f,
+															float g, float h, float i);
+
+matrix_t*		matrix_init				(matrix_t* m, int width);
+
+matrix_t*		matrix_init_array (matrix_t* m, int width, int height, const float* data);
+
+void 				matrix_insert_row3(matrix_t* m, float a, float b, float c);
+void			 	matrix_insert_row5(matrix_t* m, float a, float b, float c, float d, float e);
+void			 	matrix_insert_row7(matrix_t* m, float a, float b, float c, float d, float e, float f, float g);
+void				matrix_delete			(matrix_t* m);
+float 			matrix_get				(matrix_t* m, int w, int h);
+#endif

+ 87 - 0
src/paint.c

@@ -0,0 +1,87 @@
+#include "main.h"
+#include "paint.h"
+#include "image.h"
+#include <math.h>
+
+
+void draw_circle(image_t* img, point_t a, int r, pixel_t c)
+{
+	int x,y;
+	float alpha;
+	for(alpha=0.0; alpha<2*3.14159; alpha+=0.01)
+	{
+		x=cos(alpha)*r+a.x;
+		y=sin(alpha)*r+a.y;
+		if(x<img->w && y<img->h && x>=0 && y>=0) IMG_SET(img,x,y,c);
+	}
+}
+
+void fill_circle(image_t* img, point_t a, int r, pixel_t c)
+{
+	int x,y, i;
+	float alpha;
+	for(i=0; i<r; i++)
+		for(alpha=0.0; alpha<2*3.14159; alpha+=0.1/r)
+		{
+			x=cos(alpha)*i+a.x;
+			y=sin(alpha)*i+a.y;
+			if(x<img->w && y<img->h && x>=0 && y>=0) IMG_SET(img,x,y,c);
+		}
+}
+
+
+void draw_rect( image_t* img, point_t a, point_t b, pixel_t c)
+{
+	int i;
+	for(i=a.x; i<=a.x+b.x; i++) 
+	{
+		
+		if(i<img->w && a.y<img->h && i>=0 && a.y>=0) IMG_SET(img,i,a.y,c);
+		if(i<img->w && b.y+a.y<img->h && i>=0 && b.y+a.y>=0) IMG_SET(img,i,b.y+a.y,c);
+	}
+	for(i=a.y; i<=a.y+b.y; i++) 
+	{
+		if(a.x<img->w && i<img->h && a.x>=0 && i>=0) IMG_SET(img,a.x,i,c);
+		if(a.x+b.x<img->w && i<img->h && a.x+b.x>=0 && i>=0) IMG_SET(img,a.x+b.x,i,c);
+	}
+}
+
+void fill_rect(image_t* img, point_t a, point_t b, pixel_t c)
+{
+	int i,j;
+	for(i=a.x; i<=a.x+b.x; i++) 
+	{
+		for(j=a.y; j<a.y+b.y; j++)
+		{
+			if(i>=img->w || j>=img->h || i<0 || j<0) continue;
+			IMG_SET(img,i,j,c);
+		}
+	}
+}
+
+
+void draw_line(image_t* img, point_t a, point_t b, pixel_t c)
+{
+	double dx = b.x;
+	double dy = b.y;
+	double err = 0;
+	double derr =(dx==0)?0:dy/dx;
+	if(derr<0) derr=-derr;
+	int y = a.y;
+	int x;
+	//printf("%f = %f / %f\n", derr, dy, dx);
+	for(x=a.x; x<a.x+b.x; x++)
+	{
+		if(x>=img->w || y>=img->h || x<0 || y<0) continue;
+		IMG_SET(img, x, y, c);
+		err+=derr;
+		while(err>=0.5)
+		{
+			if(x>=img->w || y>=img->h || x<0 || y<0) break;
+			IMG_SET(img, x, y, c);
+			y+=(b.y<0)?-1:1;
+			err-=1;
+		}
+	}
+
+}

+ 15 - 0
src/paint.h

@@ -0,0 +1,15 @@
+#ifndef PAINT_H
+#define PAINT_H
+
+struct pixel_t;
+struct image_t;
+struct point_t;
+struct pixel_t;
+
+void draw_circle(struct image_t* img, struct point_t a, int r, struct pixel_t c);
+void draw_rect(struct image_t* img, struct point_t a, struct point_t b, struct pixel_t c);
+void fill_rect(struct image_t* img, struct point_t a, struct point_t b, struct pixel_t c);
+void draw_line(struct image_t* img, struct point_t a, struct point_t b, struct pixel_t c);
+void fill_circle(struct image_t* img, struct point_t a, int r, struct pixel_t c);
+
+#endif

+ 94 - 0
src/process.c

@@ -0,0 +1,94 @@
+#include "process.h"
+#include "main.h"
+#include "common.h"
+#include "image.h"
+#include "paint.h"
+
+double get_s() 
+{
+	double ret;
+	struct timespec t;
+	clock_gettime(CLOCK_REALTIME, &t);
+	ret=((double)t.tv_nsec)/1000000000.0+((double)t.tv_sec);
+	return ret;	
+}
+
+
+void minimise(int w, int h, uint8_t* out, image_t* iout, const image_t* in)
+{
+	int i,j,x,y;
+	int dx=in->w/w;
+	int dy=in->h/h;
+	for(i=0, x=0; i<in->w; i+=dx, x++)
+	{
+		for(j=0, y=0; j<in->h; j+=dy, y++)
+		{
+			int k,l, nr=0, ng=0, nb=0, nm=0;
+			for(k=i; k<i+dx && k<in->w; k++)
+			{
+				for(l=j; l<j+dy && l<in->h; l++)
+				{
+					//IMG_SET(iout, k,l, IMG_GET(in,k,l));
+					nr+=IMG_GET_R(in, k,l);
+					ng+=IMG_GET_G(in, k,l);
+					nb+=IMG_GET_B(in, k,l);
+					nm+=IMG_GET_M(in, k,l);
+				}
+			}
+			ng/=(dx*dy);
+			nr/=(dx*dy);
+			nb/=(dx*dy);
+			nm/=(dx*dy);
+			if(nr>200) nr=255; else nr=0;
+			if(ng>200) ng=255; else ng=0;
+			if(nb>200) nb=255; else nb=0;
+			fill_rect(iout,POINT(i,j), POINT(dx,dy), COLOR_RGB(nr,ng,nb));
+			if(ng>200 && nr+ng<200)
+			{
+				out[y*w+x]|=1;
+				//fill_rect(iout,POINT(i,j), POINT(dx,dy), COLOR(0xFF00));
+			}
+		}
+	}
+}
+
+void process(image_t* out, const image_t* in)
+{
+	uint8_t tab[64*48]={0};
+	//image_mem_copy(out, in);
+	//sat(out, in,80);
+	minimise(320,240,tab, out,in);
+	/*draw_line(out, POINT(0,0), POINT(640,480), COLOR(0xFF0000));
+	draw_line(out, POINT(0,479), POINT(640,-480), COLOR(0xFF0000));
+	fill_circle(out, POINT(300,300), 70, COLOR(0xFF0000));*/
+	int i,j;
+	int xmin=out->w, ymin=out->h, xmax=0, ymax=0; 
+	int ya=0,xa=0,xb=0,yb=9; 
+	for(i=0; i<out->w; i++)
+	{
+		for(j=0; j<out->h; j++)
+		{
+			int g = IMG_GET_G(out, i, j);
+			int r = IMG_GET_R(out, i, j);
+			int b = IMG_GET_B(out, i, j);
+			if(g==255 && !r && !b)
+			{
+				if(i>xmax) {xmax=i; ya=j;}
+				if(j>ymax) {ymax=j; xa=i;}
+				if(i<xmin) {xmin=i; yb=j;}
+				if(j<ymin) {ymin=j; xb=i;}
+			}
+		}
+	}
+	//draw_rect(out, POINT(xmin, ymin), POINT(xmax-xmin,ymax-ymin), COLOR(0xff0000));
+	draw_line(out, POINT(xmax,ya), POINT(xa-xmax, ymax-ya), COLOR(0xffffff));
+	printf("%d,%d -> %d,%d\n", xmax,ya, xa, ymax);
+	draw_line(out, POINT(xa, ymax), POINT(xmin-xa, yb-ymax), COLOR(0));
+	draw_line(out, POINT(xmin, yb), POINT(xb-xmin,ymin-yb), COLOR(0));
+	draw_line(out, POINT(xb,ymin),POINT(xmax-xb,ya-ymin), COLOR(0));
+	
+	draw_circle(out, POINT(xmax,ya), 5, COLOR(0xFF0000));
+	draw_circle(out, POINT(xmin,yb), 5, COLOR(0xFF0000));
+	draw_circle(out, POINT(xa,ymin), 5, COLOR(0xFF0000));
+	draw_circle(out, POINT(xb,ymax), 5, COLOR(0xFF0000));
+}

+ 8 - 0
src/process.h

@@ -0,0 +1,8 @@
+#ifndef PROCESS_H
+#define PROCESS_H
+
+#include <stdint.h>
+struct image_t;
+void process(struct image_t* out, const struct  image_t* in);
+
+#endif

+ 102 - 0
src/sdl.c

@@ -0,0 +1,102 @@
+#include "sdl.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "image.h"
+
+
+
+
+int sdl_init(sdl_t *sdl, int w, int h) 
+{
+	SDL_Init( SDL_INIT_EVERYTHING );
+	atexit( SDL_Quit );
+	sdl->width=w;
+	sdl->height=h;
+	sdl->window = SDL_CreateWindow
+			(
+			"SDL2",
+			SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
+			sdl->width, sdl->height,
+			SDL_WINDOW_SHOWN
+			);
+
+	sdl->renderer = SDL_CreateRenderer
+			(
+			sdl->window,
+			-1,
+			SDL_RENDERER_ACCELERATED
+			);
+
+
+	sdl->texture = SDL_CreateTexture
+			(
+			sdl->renderer,
+			SDL_PIXELFORMAT_RGB24,
+			SDL_TEXTUREACCESS_TARGET,
+			sdl->width, sdl->height
+			);
+	return 0;
+}
+
+
+int sdl_close(sdl_t* sdl)
+{
+	 SDL_DestroyRenderer( sdl->renderer );
+   SDL_DestroyWindow( sdl->window );
+   SDL_Quit();
+   return 0;
+}
+
+int sdl_mainloop(sdl_t* sdl, sdl_mainloop_cb cb, void* data)
+{
+	SDL_Event event;
+	time(NULL);
+	int running = 1, x, state =0;
+	image_t out;
+	image_empty(&out, sdl->width, sdl->height);
+	while( running )
+	{
+
+			
+			SDL_RenderClear( sdl->renderer );
+			
+			while( SDL_PollEvent( &event ) )
+			{
+					if( ( SDL_QUIT == event.type ) ||
+							( SDL_KEYDOWN == event.type && SDL_SCANCODE_ESCAPE == event.key.keysym.scancode ) )
+					{
+							running = 0;
+							break;
+					}
+					else if( ( SDL_MOUSEBUTTONUP == event.type || SDL_MOUSEBUTTONDOWN == event.type ) )
+					{
+					    state=!state;
+					    
+					}
+			}
+			if(state) printf("%d,%d = r=%02x g=%02x b=%02x\n",event.button.x,event.button.y,	
+							  IMG_GET_R(&out, event.button.x,event.button.y),
+							  IMG_GET_G(&out, event.button.x,event.button.y),
+							  IMG_GET_B(&out, event.button.x,event.button.y));
+			x=cb(&out, data);
+			sdl_setimage(sdl,(uint8_t*)out.mat);
+			if(x) running=0;
+	}
+	return 0;
+}
+
+
+int sdl_setimage(sdl_t* sdl, const void* pixels)
+{
+	SDL_UpdateTexture
+            (
+            sdl->texture,
+            NULL,
+            pixels,
+            sdl->width*3
+            );
+  
+  SDL_RenderCopy( sdl->renderer, sdl->texture, NULL, NULL );
+  SDL_RenderPresent( sdl->renderer );
+  return 0;
+}

+ 26 - 0
src/sdl.h

@@ -0,0 +1,26 @@
+#ifndef SDL2_WRAPPER_H
+#define SDL2_WRAPPER_H
+
+#include <SDL2/SDL.h>
+#include <SDL2/SDL_render.h>
+
+struct image_t;
+
+typedef struct sdl_t sdl_t;
+struct sdl_t
+{
+  int width;
+  int height;
+  SDL_Window* window;
+  SDL_Renderer* renderer;
+  SDL_Texture* texture;
+};
+
+
+typedef int (*sdl_mainloop_cb)(struct image_t*, void*);
+
+int sdl_init(sdl_t* sdl, int w, int h);
+int sdl_close(sdl_t* sdl);
+int sdl_mainloop(sdl_t* sdl, sdl_mainloop_cb cb, void* data);
+int sdl_setimage(sdl_t* sdl, const void* pixels);
+#endif

+ 189 - 0
src/vd.c

@@ -0,0 +1,189 @@
+
+#include "vd.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include "sdl.h"
+#include "image.h"
+static void xioctl(int fh, int request, void *arg)
+{
+        int r;
+
+        do {
+                r = v4l2_ioctl(fh, request, arg);
+        } while (r == -1 && ((errno == EINTR) || (errno == EAGAIN)));
+
+        if (r == -1) {
+                fprintf(stderr, "error %d, %s\n", errno, strerror(errno));
+                exit(EXIT_FAILURE);
+        }
+}
+
+
+
+int vd_init( vd_t* v, const char* dev, int w, int h, vd_cb cb)
+{
+  int i;
+  v->width=w;
+  v->height=h;
+  v->callback=cb;
+  strcpy(v->dev_name, dev);
+  v->fd = v4l2_open(v->dev_name, O_RDWR | O_NONBLOCK, 0);
+  if (v->fd < 0) {
+          perror("Cannot open device");
+            return -errno;
+  }
+  v->buffertmp=malloc(w*h*3);
+  CLEAR(v->fmt);
+  v->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+  v->fmt.fmt.pix.width       = w;
+  v->fmt.fmt.pix.height      = h;
+  v->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
+  v->fmt.fmt.pix.field       = V4L2_FIELD_INTERLACED;
+  xioctl(v->fd, VIDIOC_S_FMT, &v->fmt);
+  if (v->fmt.fmt.pix.pixelformat != V4L2_PIX_FMT_RGB24) {
+          printf("Libv4l didn't accept RGB24 format. Can't proceed.\n");
+            return -errno;
+  }
+  if ((v->fmt.fmt.pix.width != w) || (v->fmt.fmt.pix.height != h))
+          printf("Warning: driver is sending image at %dx%d\n",
+                  v->fmt.fmt.pix.width, v->fmt.fmt.pix.height);
+  v->width=v->fmt.fmt.pix.width;
+  v->height= v->fmt.fmt.pix.height;
+  CLEAR(v->req);
+  v->req.count = 2;
+  v->req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+  v->req.memory = V4L2_MEMORY_MMAP;
+  xioctl(v->fd, VIDIOC_REQBUFS, &v->req);
+  v->buffers = calloc(v->req.count, sizeof(*v->buffers));
+  
+  for (v->n_buffers = 0; v->n_buffers < v->req.count; ++v->n_buffers) {
+    CLEAR(v->buf);
+
+    v->buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    v->buf.memory      = V4L2_MEMORY_MMAP;
+    v->buf.index       = v->n_buffers;
+
+    xioctl(v->fd, VIDIOC_QUERYBUF, &v->buf);
+
+    v->buffers[v->n_buffers].length =v->buf.length;
+    v->buffers[v->n_buffers].start = v4l2_mmap(NULL, v->buf.length,
+                  PROT_READ | PROT_WRITE, MAP_SHARED,
+                  v->fd, v->buf.m.offset);
+
+    if (MAP_FAILED == v->buffers[v->n_buffers].start) {
+            perror("mmap");
+            return -errno;
+    }
+  }
+
+  for (i = 0; i < v->n_buffers; ++i) {
+    CLEAR(v->buf);
+    v->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+    v->buf.memory = V4L2_MEMORY_MMAP;
+    v->buf.index = i;
+    xioctl(v->fd, VIDIOC_QBUF, &v->buf);
+  }
+  v->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+  xioctl(v->fd, VIDIOC_STREAMON, &v->type);
+  return 0;
+}
+
+int vd_close(vd_t* v)
+{
+  int i;
+  v->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+  xioctl(v->fd, VIDIOC_STREAMOFF, &v->type);
+  for (i = 0; i < v->n_buffers; ++i)
+          v4l2_munmap(v->buffers[i].start, v->buffers[i].length);
+  v4l2_close(v->fd);
+  free(v->buffertmp);
+  return 0;
+}
+
+int vd_callback(image_t* out, void* data)
+{
+  vd_t *vd = (vd_t*) data;
+  image_t in;
+  
+  vd_shot(vd);
+  vd_image_current(vd, &in);
+  return vd->callback(vd, out, &in);
+}
+
+int vd_shot(vd_t* v)
+{
+  static int i=0, r;
+  do {
+          FD_ZERO(&v->fds);
+          FD_SET(v->fd, &v->fds);
+
+          /* Timeout. */
+          v->tv.tv_sec = 2;
+          v->tv.tv_usec = 0;
+
+          r = select(v->fd + 1, &v->fds, NULL, NULL, &v->tv);
+  } while ((r == -1 && (errno = EINTR)));
+  if (r == -1) {
+          perror("select");
+          return -errno;
+  }
+
+  CLEAR(v->buf);
+  v->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+  v->buf.memory = V4L2_MEMORY_MMAP;
+  xioctl(v->fd, VIDIOC_DQBUF, &v->buf);
+/*
+  sprintf(v->out_name, "out%03d.ppm", i);
+  v->fout = fopen(v->out_name, "w");
+  if (!v->fout) {
+          perror("Cannot open image");
+          exit(EXIT_FAILURE);
+  }
+  
+  fprintf(v->fout, "P6\n%d %d 255\n",
+          v->fmt.fmt.pix.width, v->fmt.fmt.pix.height);
+  fwrite(v->buffers[v->buf.index].start, v->buf.bytesused, 1, v->fout);
+  
+  fclose(v->fout);*/
+  xioctl(v->fd, VIDIOC_QBUF, &v->buf);
+        
+  i++;
+        
+
+  return 0;
+}
+
+int vd_get_relative_buffer_index(vd_t* v, int offset)
+{
+  offset+=v->buf.index;
+  offset%=v->n_buffers;
+  if(offset<0) offset+=v->n_buffers;
+  return offset;
+}
+
+image_t*	vd_get_image							(vd_t* v, image_t* im, int i)
+{
+	return image_set(im, v->width, v->height, (pixel_t*)v->buffers[vd_get_relative_buffer_index(v,i)].start);
+}
+
+image_t*	vd_image_current						(vd_t* v, image_t* im)
+{
+		return vd_get_image(v,im,0);
+}
+
+image_t*	vd_image_prev							(vd_t* v, image_t* im)
+{
+		return vd_get_image(v,im,-1);
+}
+
+image_t*	vd_image_prev_prev					(vd_t* v, image_t* im)
+{
+		return vd_get_image(v,im,-1);
+}

+ 51 - 0
src/vd.h

@@ -0,0 +1,51 @@
+#ifndef VD_H
+#define VD_H
+
+#include <linux/videodev2.h>
+#include <libv4l2.h>
+#include <sys/types.h>
+#include <sys/time.h>
+struct image_t;
+
+#define CLEAR(x) memset(&(x), 0, sizeof(x))
+typedef struct buffer buffer;
+struct buffer {
+        void   *start;
+        size_t length;
+};
+
+typedef struct vd_t vd_t;
+typedef int (*vd_cb)(vd_t*, struct image_t*, const struct image_t*);
+struct vd_t 
+{
+  struct v4l2_format              fmt;
+  struct v4l2_buffer              buf;
+  struct v4l2_requestbuffers      req;
+  enum v4l2_buf_type              type;
+  fd_set                          fds;
+  struct timeval                  tv;
+  int                             fd;
+  unsigned int                    n_buffers;
+  char                            dev_name[256];
+  char                            out_name[256];
+  FILE                            *fout;
+  struct buffer                   *buffers;
+  void														*buffertmp;
+  int 														width;
+  int 														height;
+  vd_cb														callback;
+};
+
+
+
+int							vd_init											( vd_t* v, const char* dev, int w, int h, vd_cb cb);
+int							vd_close										(vd_t* v);
+int							vd_shot											(vd_t* v);
+int							vd_get_relative_buffer_index(vd_t *v, int offset);
+struct image_t*	vd_get_image								(vd_t* v, struct image_t* im, int i);
+struct image_t*	vd_image_current						(vd_t* v, struct image_t* im);
+struct image_t*	vd_image_prev								(vd_t* v, struct image_t* im);
+struct image_t*	vd_image_prev_prev					(vd_t* v, struct image_t* im);
+int 						vd_callback									(struct image_t* out, void* data);
+
+#endif