Mostrando entradas con la etiqueta Redes neuronales. Mostrar todas las entradas
Mostrando entradas con la etiqueta Redes neuronales. Mostrar todas las entradas

Seguimiento de personas, animales y objetos con OpenCV en Delphi




OpenCV para los que no la conozcan, es una biblioteca libre enfocada hacia la visión artificial, inicialmente desarrollada por Intel bajo licencia BSD lo que permite que sea usada libremente para un propósito comercial o de investigación.






OpenCV es multiplataforma con versiones para Windows, Linux y Mac y contiene funciones que tratan los temas de proceso de visión, reconocimiento facial, calibrado de cámaras o robótica.


Esta biblioteca es la base de la herramienta Swistrack que sirve para hacer un seguimiento de personas, animales y objetos.





El siguiente código se puede ejecutar en Delphi XE2 o superior y lo que hace es, como veis en la imagen, un seguimiento de las personas que circulan por la calle rodeándolas con un rectángulo de color rojo a medida que se van desplazando.




(* /*****************************************************************
// Delphi-OpenCV Demo
// Copyright (C) 2013 Project Delphi-OpenCV
// ****************************************************************
// Contributor:
// Mikhail Grigorev
// email: sleuthhound@gmail.com
// ****************************************************************
// You may retrieve the latest version of this file at the GitHub,
// located at git://github.com/Laex/Delphi-OpenCV.git
// ****************************************************************
// The contents of this file are used with permission, subject to
// the Mozilla Public License Version 1.1 (the "License"); you may
// not use this file except in compliance with the License. You may
// obtain a copy of the License at
// http://www.mozilla.org/MPL/MPL-1_1Final.html
//
// Software distributed under the License is distributed on an
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
// implied. See the License for the specific language governing
// rights and limitations under the License.
******************************************************************* *)

// JCL_DEBUG_EXPERT_GENERATEJDBG OFF
// JCL_DEBUG_EXPERT_INSERTJDBG OFF
// JCL_DEBUG_EXPERT_DELETEMAPFILE OFF
program MotionDetect;

{$APPTYPE CONSOLE}
{$POINTERMATH ON}
{$R *.res}

uses
System.SysUtils,
Math,
uLibName in '..\..\..\include\uLibName.pas',
highgui_c in '..\..\..\include\highgui\highgui_c.pas',
imgproc.types_c in '..\..\..\include\imgproc\imgproc.types_c.pas',
imgproc_c in '..\..\..\include\imgproc\imgproc_c.pas',
imgproc in '..\..\..\include\imgproc\imgproc.pas',
core in '..\..\..\include\core\core.pas',
core.types_c in '..\..\..\include\core\Core.types_c.pas',
core_c in '..\..\..\include\core\core_c.pas';

var
storage: pCvMemStorage = nil;
capture: pCvCapture = nil;
frame: pIplImage = nil;
frame_grey: pIplImage = nil;
difference_img: pIplImage = nil;
oldframe_grey: pIplImage = nil;
contours: pCvSeq = nil;
c: pCvSeq = nil;
// rect: TCvRect;
rect2d: TCvBox2D;
key: integer;
first: boolean = true;

begin
try
capture := cvCreateCameraCapture(0);
storage := cvCreateMemStorage(0);
frame := cvQueryFrame(capture);
frame_grey := cvCreateImage(cvSize(frame^.width, frame^.height), IPL_DEPTH_8U, 1);

while true do
begin
frame := cvQueryFrame(capture);
if frame = nil then
break;
cvCvtColor(frame, frame_grey, CV_RGB2GRAY);
if first then
begin
difference_img := cvCloneImage(frame_grey);
oldframe_grey := cvCloneImage(frame_grey);
cvConvertScale(frame_grey, oldframe_grey, 1.0, 0.0);
first := false;
end;
cvAbsDiff(oldframe_grey, frame_grey, difference_img);
cvSmooth(difference_img, difference_img, CV_BLUR);
cvThreshold(difference_img, difference_img, 25, 255, CV_THRESH_BINARY);
contours := AllocMem(SizeOf(TCvSeq));
cvFindContours(difference_img, storage, @contours, SizeOf(TCvContour), CV_RETR_LIST, CV_CHAIN_APPROX_NONE,
cvPoint(0, 0));
c := contours;
while (c <> nil) do
begin
rect2d := cvMinAreaRect2(c);
cvRectangle(frame, cvPoint(Round(rect2d.center.x - rect2d.size.width / 2),
Round(rect2d.center.y - rect2d.size.height / 2)), cvPoint(Round(rect2d.center.x + rect2d.size.width / 2),
Round(rect2d.center.y + rect2d.size.height / 2)), cvScalar(0, 0, 255, 0), 2, 8, 0);
c := c.h_next;
end;
cvShowImage('Output Image', frame);
cvShowImage('Difference Image', difference_img);
cvConvertScale(frame_grey, oldframe_grey, 1.0, 0.0);
cvClearMemStorage(storage);
c := nil;
FreeMem(contours, SizeOf(TCvSeq));
key := cvWaitKey(33);
if (key = 27) then
break;
end;
cvReleaseMemStorage(storage);
cvReleaseCapture(capture);
cvReleaseImage(oldframe_grey);
cvReleaseImage(difference_img);
cvReleaseImage(frame_grey);
cvDestroyAllWindows();
except
on E: Exception do
WriteLn(E.ClassName, ': ', E.Message);
end;

end.















Utilizar redes neuronales para resolver un captcha


Aquí tienen una unit llamada CaptchaTrainer que se utiliza para resolver un captcha . Para ello utilizamos la biblioteca open source FANN http://leenissen.dk/fann/wp/ que sirve para implementar redes neuronales artificiales multicapa.





FANN ha sido traducido a 15 lenguajes de programación diferentes, entre ellos no podía faltar Delphi (http://leenissen.dk/fann/wp/language-bindings/ )




Una red neuronal se compone de unidades llamadas neuronas y esta formada por tres capas:

1) Capa de entrada (input layer) que recibe las señales del entorno

2) Capa oculta (hidden layer)

3) Capa de salida (ouput layer)

Cada neurona recibe una o varias entradas y tiene una o varias salidas que viene dada por una serie de funciones:

- Función de propagación: (también conocida como función de excitación), que por lo general consiste en la entrada (suma de todas las señales de entrada) multiplicada por el peso de su interconexión.

- Función de activación, que modifica a la anterior. Puede no existir, siendo en este caso 

- Función de transferencia, que se aplica al valor devuelto por la función de activación. 

Se utiliza para acotar la salida de la neurona. Algunas de las más utilizadas son la función sigmoide (genera outputs de valores en el intervalo [0,1]) y la tangente hiperbólica (genera outputs de valores en el intervalo [-1,1])



El número de neuronas de entrada se selecciona en función de las variables de entrada del problema que queramos predecir.

Número de capas ocultas: Las capas ocultas proporcionarán a la red la capacidad de generalizar. En la práctica, se suelen usar redes neuronales con una o dos capas ocultas. Sin embargo, no hay un criterio natural acerca de la fórmula de selección óptima del número de neuronas ocultas. Baily y Thompson (1990) sugieren que el número de neuronas ocultas en una red neuronal de tres capas debe ser de 75% del número de neuronas de entrada mientras que Ersoy (1990) propone duplicar el número de neuronas ocultas hasta que el rendimiento de la red comience a deteriorarse.




Bien, después de esta introducción a las redes neuronales pasamos a comentar lo que hace esta unit:

Inicialmente se crea la red neuronal definiendo el número de entradas en las  3 capas:  entrada, salida y oculta. 


Como la entrada de la red es el bitmap del captcha, el número de neuronas de la entrada sería el tamaño del bitmap bitmapWidth * bitmapHeight.


Hay que tener en cuenta que los valores de cada una de las entradas / salidas siempre serán 1 o 0 (  fInputs[i]:= [1/0]     fOutputs[i]:= [1/0]   )  



Después necesitamos entrenar la red y para ello utilizamos la función Learn que tiene 2 parámetros de entrada: el captcha en formato bitmap y el número que representa y cuando terminemos el entrenamiento utilizaremos la función Guess  para probar la precisión de ese reconocimiento.



Otro aspecto a comentar es la línea 


 result := FANN.Train(fInputs, fOutputs);

del procedimiento Learn, y es que la variable result representa el error cuadrático medio del valor obtenido por la red respecto del valor esperado, por lo que debemos intentar que este error sea lo más pequeño posible para hacer que la red sea lo más precisa posible.





unit CaptchaTrainer;

interface

uses
SysUtils, Graphics, FannNetwork;

type
TCaptchaTrainer = class
private
fInputs, fOutputs: array of single;
public
FANN: TFannNetwork;
constructor Create;
procedure CreateNN(numInputs, numOutputs: integer); overload;
procedure CreateNN(bitmapWidth, bitmapHeight, numOutputs: integer); overload;
procedure LoadNN(fileName: string);
procedure SaveNN(fileName: string);
function Learn(bitmap: TBitmap; value: integer): single;
function Guess(bitmap: TBitmap): integer;
destructor Destroy; override;
end;

implementation

{ TCaptchaTrainer }

function MaxValueIndex(const Data: array of Single): integer;
var I: Integer;
maxvalue: single;
begin
maxvalue := Data[Low(Data)];
result := Low(Data);
for I := Low(Data) + 1 to High(Data) do
if maxvalue < Data[I] then
begin
maxvalue := Data[I];
result := I;
end;
end;

constructor TCaptchaTrainer.Create;
begin
FANN := TFannNetwork.Create(nil);
with FANN do
begin
ActivationFunctionHidden := afFANN_SIGMOID;
ActivationFunctionOutput := afFANN_SIGMOID;
TrainingAlgorithm := taFANN_TRAIN_RPROP;
ConnectionRate := 1;
LearningRate := 0.1;
end;
end;

procedure TCaptchaTrainer.CreateNN(numInputs, numOutputs: integer);
begin
SetLength(fInputs, numInputs);
SetLength(fOutputs, numOutputs);
with FANN.Layers do
begin
Add(IntToStr(numInputs));
Add(IntToStr(50));
Add(IntToStr(numOutputs));
end;
FANN.Build;
end;

procedure TCaptchaTrainer.CreateNN(bitmapWidth, bitmapHeight,
numOutputs: integer);
begin
SetLength(fInputs, bitmapWidth * bitmapHeight);
SetLength(fOutputs, numOutputs);
with FANN.Layers do
begin
Add(IntToStr(bitmapWidth * bitmapHeight));
Add(IntToStr(50));
Add(IntToStr(numOutputs));
end;
FANN.Build;
end;

destructor TCaptchaTrainer.Destroy;
begin
FANN.UnBuild;
FANN.Free;
inherited;
end;

function TCaptchaTrainer.Guess(bitmap: TBitmap): integer;
var x,y,i: integer;
begin
i:=0;
for x:=0 to bitmap.Width-1 do
for y:=0 to bitmap.Height-1 do
begin
if bitmap.Canvas.Pixels[x,y]=$00000000 then fInputs[i]:=1 else fInputs[i]:=0;
inc(i);
end;
FANN.Run(fInputs, fOutputs);
result := MaxValueIndex(fOutputs);
end;

function TCaptchaTrainer.Learn(bitmap: TBitmap; value: integer): single;
var x,y,i: integer;
begin
i:=0;
for x:=0 to bitmap.Width-1 do
for y:=0 to bitmap.Height-1 do
begin
if bitmap.Canvas.Pixels[x,y]=$00000000 then fInputs[i]:=1 else fInputs[i]:=0;
inc(i);
end;
for i:=0 to high(fOutputs) do if i=value then fOutputs[i]:=1 else fOutputs[i]:=0;
result := FANN.Train(fInputs, fOutputs);
end;

procedure TCaptchaTrainer.LoadNN(fileName: string);
begin
FANN.LoadFromFile(fileName);
end;

procedure TCaptchaTrainer.SaveNN(fileName: string);
begin
FANN.SaveToFile(fileName);
end;

end.





Además me gustaría recordarles que si quieren iniciarse en la programación con Delphi pueden utilizar una versión totalmente gratuita llamada Delphi Starter Edition que la pueden descargar desde aquí.
Te puede interesar:


Red neuronal backpropagation 

Redes neuronales con delphi

Crear un captcha con delphi



Pulsa aquí si quieres un buen libro sobre redes neuronales. 





Red neuronal Backpropagation






Codificación de una red neuronal Backpropagation con dos neuronas de entrada, dos de salida y una capa oculta.


El ejemplo proporciona dos conjuntos de datos con los que se puede entrenar la red y ver lo preciso que ha sido el aprendizaje minimizando el error que se muestra en un gráfico.

Modificando el programa podemos variar el número de veces que entrenamos a la red con los datos de prueba (epochs), de tal forma que llega un momento en el que a partir de un cierto número de epochs el error se mantiene siempre constante e incluso aumenta.









Pantalla del programa





Descargar codigo fuente





La propagación hacia atrás de errores o retropropagación (del inglés backpropagation) es un algoritmo deaprendizaje supervisado que se usa para entrenar redes neuronales artificiales.

El algoritmo emplea un ciclo propagación – adaptación de dos fases. Una vez que se ha aplicado un patrón a la entrada de la red como estímulo, este se propaga desde la primera capa a través de las capas superiores de la red, hasta generar una salida.

La señal de salida se compara con la salida deseada y se calcula una señal de error para cada una de las salidas.

Las salidas de error se propagan hacia atrás, partiendo de la capa de salida, hacia todas las neuronas de la capa oculta que contribuyen directamente a la salida. Sin embargo las neuronas de la capa oculta solo reciben una fracción de la señal total del error, basándose aproximadamente en la contribución relativa que haya aportado cada neurona a la salida original.

Este proceso se repite, capa por capa, hasta que todas las neuronas de la red hayan recibido una señal de error que describa su contribución relativa al error total. La importancia de este proceso consiste en que, a medida que se entrena la red, las neuronas de las capas intermedias se organizan a sí mismas de tal modo que las distintas neuronas aprenden a reconocer distintas características del espacio total de entrada.

Después del entrenamiento, cuando se les presente un patrón arbitrario de entrada que contenga ruido o que esté incompleto, las neuronas de la capa oculta de la red responderán con una salida activa si la nueva entrada contiene un patrón que se asemeje a aquella característica que las neuronas individuales hayan aprendido a reconocer durante su entrenamiento.

(fuente: wikipedia) 




-----------------------

 Clase TBackProp

------------------------

Archivo:    BackPropCls.pas

Lenguaje:  Delphi 2005

Autor:        Theo Zacharias (theo_yz@yahoo.com)

Descripción : TBackProp es una clase que encapsula un objeto de red neuronal backpropagation




Eventos: OnTraining, OnTrainingFinish
Propiedades: ErrorThreshold (r/w), InputLayer (r/w),
                  InputPatternHeight (r/o), InputPatternWidth (r/o),
                  KnownSymbol (r/o), LearningRate (r/w), MaxEpoch (r/w),
                  Modified (r/o), NHiddenNeuron (r/o), NInputNeuron (r/o),
                  NNeuronError (r/o), NOutputNeuron (r/o), NTrainingEpoch (r/o),
                  NTrainingNeuron (r/o), NTrainingPair (r/o), OutputLayer (r/o),
                  StopTraining (r/w), TargetClassificationError (r/w),
                  TargetPatternHeight (r/o), TargetPatternWidth (r/0),
                  TargetSquaredError (r/o), TrainingError (r/o),
                  WeightsInitFactor (r/w)
Métodos: : AddTrainingPairs, Apply, GetResult, NewKnowledge,
                  OpenKnowledge, Retrain, SaveKnowledge, Train




Descargar clase tBackProp


 









Reconocimiento facial con Delphi


Hace unos días me pidieron que hiciese un programa de reconocimiento facial para identificar a los alumnos de una escuela.


Dándole vueltas al tema me di cuenta que tenía que dividirlo en dos partes, la primera sería la extracción de la cara del alumno de la imagen inicial eliminando el fondo y detalles innecesarios y la segunda la del tratamiento de esa imagen para identificar al alumno en cuestión utilizando técnicas de inteligencia artificial.


Inicialmente pensé en utilizar OpenCV (aquí tienen cómo instalarlo), pero por más intentos que hice  no conseguí que funcionase en mi equipo, me decía que no encontraba unas dlls, o que "no era una aplicación win32 válida", así que investigando en Google encontré que Android tiene incorporado un objeto llamado JFaceDetector para hacer reconocimiento facial, que lo podemos utilizar desde la unit Androidapi.JNI.Media.


Para utilizarlo se hace de la siguiente forma:


Desde nuestro Delphi Tokyo 10.2.2 accedo a File - Multi-Device Application y creo un nuevo proyecto.

En Tipo de proyecto seleccionamos Android








Desde la paleta de herramientas "Tool Palette" voy arrastrando hacia el form 3 objetos:  tButton, tLabel, tImage.






En el objeto tImage cargo una imagen de prueba (se hace clic sobre el componente tImage y desde Object Inspector, selecciono la propiedad Multiresbitmap)






para conseguir que quede de la siguiente forma:








En el componente Label1 mostraremos el número de caras que ha detectado el programa.


y dentro del tbutton en el evento Onclic colocaremos el siguiente código:

procedure TForm12.Button1Click(Sender: TObject);
var
LDetector: JFaceDetector;
LFaces: TJavaObjectArray;
LFace: JFaceDetector_Face;
LSurface: TBitmapSurface;
LBitmap: JBitmap;
LMidpoint: JPointF;
LFaceCount, I: Integer;
LRect: TRectF;
LHalfWidth: Single;

begin

LSurface := TBitmapSurface.Create;
try
LSurface.Assign(FaceImage.Bitmap);
LBitmap := TJBitmap.JavaClass.createBitmap(LSurface.Width, LSurface.Height,
TJBitmap_Config.JavaClass.ARGB_8888);
SurfaceToJBitmap(LSurface, LBitmap);
LMidpoint := TJPointF.Create;
LFaces := TJavaObjectArray.Create(10);
LDetector := TJFaceDetector.JavaClass.init(LBitmap.getWidth,
LBitmap.getHeight, 10);
LFaceCount := LDetector.findFaces
(LBitmap.copy(TJBitmap_Config.JavaClass.RGB_565, False), LFaces);
Label1.Text := LFaceCount.ToString + 'caras';
for I := 0 to LFaceCount - 1 do
begin
LFace := LFaces.Items[I];
LFace.getMidPoint(LMidpoint);
LHalfWidth := LFace.eyesDistance * 2;
LRect := RectF(LMidpoint.x - LHalfWidth, LMidpoint.y - LHalfWidth,
LMidpoint.x + LHalfWidth, LMidpoint.y + LHalfWidth);
FaceImage.Bitmap.Canvas.BeginScene;
try
FaceImage.Bitmap.Canvas.Stroke.Color := TAlphaColorRec.Red;
FaceImage.Bitmap.Canvas.Stroke.Thickness := 2;
FaceImage.Bitmap.Canvas.DrawRect(LRect,0,0,allcorners, 100);
finally
FaceImage.Bitmap.Canvas.EndScene;
end;
end;
finally
LSurface.Free;
end;
end;





y a continuación ejecutamos el código y veremos cómo nos ha creado un rectángulo rodeando los rostros que ha detectado:
















En un próximo post publicaré cómo utilizar redes neuronales para la identificación de imágenes.


Además me gustaría recordarles que si quieren iniciarse en la programación con Delphi pueden utilizar una versión gratuita para siempre llamada Delphi Starter Edition que la pueden descargar desde aquí o también pueden descargar la edición de prueba por 30 días totalmente funcional desde aquí.


Si les ha gustado y quieren compartir el post, pueden pulsar los iconos de twitter, facebook, google+ que tienen un poco más abajo




Reconocimiento de caras con Delphi





Software de reconocimiento de caras ( face recognition ) en imágenes con formato bmp.



Lo que hace es enmarcar cada rostro detectado dentro de un rectángulo utilizando funciones de una dll llamada VCOpenCV.


VCOpenCV se basa en OpenCV (Open Computer Vision) que es una biblioteca de funciones relacionadas con visión artificial  y que como curiosidad se ha utilizado en el sistema de visión del vehículo no tripulado del "Gran desafío DARPA"

Actualmente es un área de investigación muy compleja que necesita la participación de investigadores de diferentes ámbitos, ya que involucra no sólo o programadores e ingenieros de software, sino que también necesita la colaboración de neurocientíficos y psicólogos.




Debido a que estos sistemas son poco intrusivos, aún permanecen en primera línea de investigación por encima de otros como pueden ser los sistemas biométricos, de detección de huellas o reconocimiento del iris.






Descargar codigo fuente




En caso de que nos interese detectar zonas más específicas como ojos y boca, 

tendremos que hacerlo como indica el programa del que abajo os adjunto el link




Descargar codigo fuente




Descargar OpenCV.pas




Descargar OpenCV.pas (Es la traducción de las cabeceras de Opencv en Delphi realizada por Vladimir Vasilyev)





Además me gustaría recordarles que si quieren iniciarse en la programación con Delphi pueden utilizar una versión totalmente gratuita llamada Delphi Starter Edition que la pueden descargar desde aquí.
 




Libros



Face-Detection and Gesture Recognition for Human-computer interaction

Intelligent Biometric Techniques in Fingerprint and Face Recognition (International Series on Computational Intelligence)

Handbook of Face Recognition






















Reconocimiento facial con los componentes MITOV en Delphi




He estado probando los componentes MITOV y he quedado asombrado con lo que pueden hacer, tienen un nivel de abstracción muy alto, con pocas instrucciones se pueden realizar programas complejos (algo parecido al Livebinding de Delphi) lo que a los programadores seguro nos facilitará mucho el desarrollo de software.

En palabras de Boian Mitov, propietario y CEO de Mitov. Software. "Estos componentes ofrecen una combinación única de compilación multiplataforma nativa y características avanzadas de lenguaje moderno como RTTI avanzado por esto Delphi ha permitido implementar componentes de inteligencia artificial multiplataforma potentes y de alto rendimiento".

Jim McKeeth, jefe de desarrollo e ingeniero de Embarcadero dijo "Me encanta que IntelligenceLab de Mitov Software tome algo tan complejo como las redes neuronales y la inteligencia artificial y lo haga accesible a través de componentes reutilizables, ahora todos nuestros desarrolladores pueden agregar redes neuronales avanzadas y otros clasificadores de IA a sus aplicaciones multiplataforma". 




La licencia es gratuita para uso educativo y no comercial.






Seguidamente les mostraré cómo se hace un programa de reconocimiento facial utilizando los componentes basados en inteligencia artificial de Mitov.

Primero tenemos que descargarnos el paquete "Intelligence lab" desde aquí  (IntelligenceLab_VCL_7.8.2.288.zip)

Lo guardamos en una carpeta, lo descomprimimos y ejecutamos el setup.exe, aquí hay que tener paciencia ya que es un archivo de casi 2 Gb.

Nos pedirá que tipo de licencia tenemos: free, comercial, with source code, etc...

Pulsamos aceptar y si no hay ningún problema en la instalación tendremos en el IDE los componentes de este pack.









 

Creamos un nuevo proyecto y añadimos el componente

ILRadialBasisFunctionNetwork

Del cual sólo tenemos que modificar la propiedad MaxInfluencefield = 300

En función de este valor tendremos una mayor o menor precisión en el reconocimiento de caras.

Las imágenes de prueba las guardamos en la carpeta "faces" y las dividimos en 2 grupos uno para hacer el entrenamiento de la red y otro para hacer un test en el que verificaremos la precisión del reconocimiento facial.


En total hay 40 personas distintas y de cada una de ellas se han hecho 9 fotos, como ven en la siguiente imagen las fotos destinadas a entrenar la red se llaman "Train_(1..9)_(1..40)" y las destinadas a test se llaman "Reco_(1..40)"





 



El código que entrena la red y que se pone en el evento Onclick es:



procedure TForm1.TrainButtonClick(Sender: TObject);
var
I : Integer;
J : Integer;
K : Integer;
ABitmap : TBitmap;
AFeaturesBuffer : ISLRealBuffer;
AInPtr : PByte;
AOutPtr : PReal;
AItem : TListItem;

begin
ABitmap := TBitmap.Create();
ProgressBar1.Max := 40;
AFeaturesBuffer := TSLRealBuffer.CreateSize( 32 * 32 );

ListView1.Items.BeginUpdate();
for I := 1 to 40 do
begin
for J := 1 to 9 do
begin
ABitmap.LoadFromFile( '.\Faces\Train_' + IntToStr( I ) + '_' + IntToStr( J ) + '.bmp' );
ImageList1.Add( ABitmap, NIL );
AItem := ListView1.Items.Add();
AItem.ImageIndex := ImageList1.Count - 1;
AItem.Caption := IntToStr( I );
AInPtr := ABitmap.ScanLine[ ABitmap.Height - 1 ];
AOutPtr := AFeaturesBuffer.Write();
for K := 0 to AFeaturesBuffer.Size - 1 do
begin
AOutPtr^ := AInPtr^ / 256;
Inc( AOutPtr );
Inc( AInPtr );
end;

ILRadialBasisFunctionNetwork1.Train( AFeaturesBuffer, I );
end;

ProgressBar1.Position := I;
end;

ListView1.Items.EndUpdate();
ABitmap.Free();
RecognizeButton.Enabled := True;
TrainButton.Enabled := False;
TrainLabel.Caption := IntToStr( ILRadialBasisFunctionNetwork1.Neurons.Count ) + ' Neurons used.';
ILRadialBasisFunctionNetwork1.SaveToFile('redneuronal1');
end;





Al final del entrenamiento se crea el fichero "redneuronal1" que contiene todas las características y pesos de la red.



ILRadialBasisFunctionNetwork1.SaveToFile('redneuronal1');



El siguiente paso es probar su fiabilidad, para ello colocamos otro botón en nuestro proyecto y en el evento OnClick lo primero que hacemos es cargar la red almacenada antes:



ILRadialBasisFunctionNetwork1.LoadFromFile('redneuronal1');

 

 

El código que reconoce las imágenes de test es el siguiente:


procedure TForm1.RecognizeButtonClick(Sender: TObject);
var
I : Integer;
K : Integer;
ABitmap : TBitmap;
AFeaturesBuffer : ISLRealBuffer;
AInPtr : PByte;
AOutPtr : PReal;
AItem : TListItem;

begin

ILRadialBasisFunctionNetwork1.LoadFromFile('redneuronal1');


FTotalCount := 0;
FErrorCount := 0;

ABitmap := TBitmap.Create();
ProgressBar1.Max := 40;
AFeaturesBuffer := TSLRealBuffer.CreateSize( 32 * 32 );

ListView2.Items.BeginUpdate();
for I := 1 to 40 do
begin
FExpectedID := I;
ABitmap.LoadFromFile( '.\Faces\Reco_' + IntToStr( I ) + '.bmp' );
ImageList1.Add( ABitmap, NIL );
AItem := ListView2.Items.Add();
AItem.ImageIndex := ImageList1.Count - 1;
AInPtr := ABitmap.ScanLine[ ABitmap.Height - 1 ];
AOutPtr := AFeaturesBuffer.Write();
for K := 0 to AFeaturesBuffer.Size - 1 do
begin
AOutPtr^ := AInPtr^ / 256;
Inc( AOutPtr );
Inc( AInPtr );
end;

ILRadialBasisFunctionNetwork1.Predict( AFeaturesBuffer );

if( FResultCathegory <> I ) then
begin
if( FResultCathegory = 0 ) then
AItem.Caption := 'Error - Can''t recognize'

else
AItem.Caption := 'Error - Expected:' + IntToStr( I ) +
' recognized as: ' + IntToStr( FResultCathegory ) + ' Distance: ' + FloatToStr( FDistance );

end

else
AItem.Caption := 'Correct: ' + IntToStr( I ) + ' Distance: ' + FloatToStr( FDistance );

ProgressBar1.Position := I;
end;

ListView2.Items.EndUpdate();
ABitmap.Free();

RecognizeLabel.Caption := IntToStr( FErrorCount ) + ' errors of ' + IntToStr( FTotalCount ) + ' faces - ' + FloatToStr( ( FTotalCount - FErrorCount ) * 100 / FTotalCount ) + '% correct';
end;







Al ejecutar el código anterior comprobamos que ha reconocido 35 caras de 40 lo que representa un 87,5% de fiabilidad, ¡no está nada mal!








Hay que saber que lo primero que hay que hacer es un preprocesamiento de las imágenes, ya que todas tienen que tener las mismas medidas, hay que convertirlas a b/n, tener el mismo formato, etc.. y que cuanto más imágenes se tengan de cada persona mejor...siempre dentro de un límite para no llegar al sobreentrenamiento de la red, ya que en ese caso se produciría una mayor tasa de error.

Como ven es sencillo hacer un reconocimiento facial con los componentes MITOV.

Espero que les haya gustado el post.



Código fuente y fotos de prueba
























Redes neuronales con Delphi


Os presento una página donde muestra cómo se implementa en delphi una red neuronal utilizando backpropagación como algoritmo de aprendizaje.





Una red neuronal la forman varias capas, una de ellas es la capa de entrada, otra la capa de salida y una o varias capas ocultas. Cada capa se interconecta con la previa desde sus nodos (neuronas) simulando de alguna manera los sistemas neuronales biológicos.





La salida viene dada por tres funciones:



-función de propagación: Sumatorio de cada entrada multiplicado por el peso de su interconexión.

-función de activación: Suele ser la salida de la función de propagación

-función de transferencia: Acota la salida entre [-1,1] (en este caso utiliza la tangente hiperbólica - tanh-, aunque en otros casos se utiliza la función sigmoidea)





Link:

http://www.ibrtses.com/delphi/neuralnets.html











OCR con Delphi

Aquí tenéis un OCR (Optical Character Recognition) en Delphi, que traduce lo que se ha tecleado o escrito en formato de imagen (como un bitmap) dentro de un fichero editable (texto), viene con código fuente (freeware y licencia open source)





Tiene la capacidad de aprender patrones desde un tipo y tamaño de font determinado utilizando una red neural con el algoritmo de backpropagación.




Hay que tener encuenta que el OCR no ha sido entrenado, por lo que lo primero que hay que hacer es entrenarlo para que pueda reconocer el texto.




Para ello hay que abrir la ventana "Process->Training...", seleccionar los patrones desde los fonts disponibles y el tamaño de letra (Manteniendo pulsado shift o Ctrl se seleccionan varios items), o también se puede dibujar con el ratón un patrón, y para finalizar pulsar el botón "Add Training Pairs".




Cuando estén todos items definidos (podemos probar p.ej. con los números "1,2,3,4")


pulsamos el botón "Train".




El botón "Test" prueba la red. (Es conveniente pulsarlo para ver el tanto por ciento de coincidencia del patrón con el dato de prueba)






Ventana de entrenamiento:


Seleccionar el Font, Char y Size y después pulsar "Add Training Pairs"










Ventana para teclear los datos:


Escribir con el ratón en la parte superior alguno de los números seleccionado en la pantalla anterior (con cuidado de imitar el font y su tamaño) y después activar el menú "Process->Recognize"


En la parte inferior de la ventana aparecen los caracteres reconocidos por el programa.








En este caso la coincidencia ha sido del 100 por ciento.







Descargar el programa con su código fuente:





Pruebas realizadas con Delphi 7



El programa utiliza el componente TBackProp



Autor:        Theo Zacharias (theo_yz@yahoo.com)

Descripción : TBackProp es una clase que encapsula un objeto de red neuronal backpropagation


Eventos: OnTraining, OnTrainingFinish


Propiedades: ErrorThreshold (r/w), InputLayer (r/w),
                  InputPatternHeight (r/o), InputPatternWidth (r/o),
                  KnownSymbol (r/o), LearningRate (r/w), MaxEpoch (r/w),
                  Modified (r/o), NHiddenNeuron (r/o), NInputNeuron (r/o),
                  NNeuronError (r/o), NOutputNeuron (r/o), NTrainingEpoch (r/o),
                  NTrainingNeuron (r/o), NTrainingPair (r/o), OutputLayer (r/o),
                  StopTraining (r/w), TargetClassificationError (r/w),
                  TargetPatternHeight (r/o), TargetPatternWidth (r/0),
                  TargetSquaredError (r/o), TrainingError (r/o),
                  WeightsInitFactor (r/w)



Métodos: : AddTrainingPairs, Apply, GetResult, NewKnowledge,
                  OpenKnowledge, Retrain, SaveKnowledge, Train




Descargar el componente tBackProp



Redes Neuronales y Bolsa - Neural Networks and financial markets


Ahora que en todos los medios de comunicación se habla de la Bolsa, creo que podría ser interesante utilizar el componente TFFNN del que os hablé hace unos días para que veáis cómo se puede utilizar para predecir un valor de una serie temporal basándose en datos anteriores.


Supongamos que tenemos las cotizaciones de cierre de Telefónica, S.A. (p.ej. 1000 valores) y queremos saber cual será el valor de cierre del día N sabiendo la cotización del día N-1, N-2, N-3, N-4 y N-5



Lo primero que hay que hacer es:

Asignar los parámetros de la red neuronal


FFNN1.InputCount:=6 //Son 5 valores + el valor a predecir
FFNN1.OutputCount:=1
FFNN1.InputMax := MAX; //Valor máximo de la serie de cotizaciones
FFNN1.InputMin := MIN; //Valor mínimo de la serie de cotizaciones
FFNN1.OutputMax := MAX; //Valor máximo de la serie de cotizaciones
FFNN1.OutputMin := MIN; ;//Valor mínimo de la serie de cotizaciones






El "Valor máximo" y el "Valor mínimo" es el valor máximo y mínimo de los 1000 valores que componen la serie ( No de los 5 valores )


CÓDIGO PARA ENTRENAR LA RED






VecesQueSeRepite := 1; NumsALeer := 6;
//Este bucle se repetirá 5000 veces o
//hasta que el error sea menor que 0.001
REPEAT

//Bucle que sirve para leer las cotizaciones y
//entrenar la red
REPEAT

//Puntero: Es un apuntador a la serie de valores que salta de 6 en 6
//FicheroEntrada: tStringlist que almacena las 1000 cotizaciones de Telefónica
//NumsLeidos:VAR Array de 6 valores de tipo real
//NoSePuedenLeerMasNumeros:Variable Booleana que se pone a TRUE
//al llegar al final del Fichero de Entrada
//Lee las cotizaciones de Telefónica de 6 en 6
LeeNNums(Puntero, ficheroEntrada, NumsLeidos,
NoSePuedenLeerMasNumeros);

//Almacena en la red 5 cotizaciones procedentes del array "NumsLeidos"
FOR i := 1 TO NumsALeer - 1 DO
FFNN1.Input[i] := NumsLeidos[i];
FFNN1.DesiredOutput[1] := NumsLeidos[NumsALeer];
FFNN1.BackProp; //Entrena la red con el par (In, Out).

UNTIL NoSePuedenLeerMasNumeros;


//Vuelve a tomar los datos de entrada de la red ya entrenada y
//calcula el valor de salida
Puntero := Numvalores DIV 2;
NoSePuedenLeerMasNumeros := false;
REPEAT

//coge las cotizaciones de Telefónica de 6 en 6
LeeNNums(Puntero, FicheroEntrada, NumsLeidos,
NoSePuedenLeerMasNumeros);
FOR i := 1 TO NumsALeer - 1 DO
FFNN1.Input[i] := NumsLeidos[i];
FFNN1.calcOut;
rdo := FFNN1.output[1];
FFNN1.DesiredOutput[1] := NumsLeidos[NumsALeer];
Error := FFNN1.GetMaxError;

UNTIL NOT NoSePuedenLeerMasNumeros;


Inc(VecesQueSeRepite);
UNTIL (VecesQueSeRepite > 5000) OR (Error<0 .001="">



MOSTRAR RESULTADOS




Ahora una vez que hemos terminado de entrenar la red podemos crear un form con 6 cajas de texto.
En 5 de ellas teclearemos cotizaciones diarias de Telefónica y en la sexta caja tendremos el valor predicho por la red neuronal.

El código sería este:



VAR


ValorPredichoPorLaRedNeuronal:Real;

begin

FFNN1.Input[1] := strtofloat(edit1.text);

FFNN1.Input[2] := strtofloat(edit2.text);

FFNN1.Input[3] := strtofloat(edit3.text);

FFNN1.Input[4] := strtofloat(edit4.text);

FFNN1.Input[5] := strtofloat(edit5.text);

ffnn1.calcOut;

ValorPredichoPorLaRedNeuronal := ffnn1.output[1];

Edit6.text:= FloatToStr( ValorPredichoPorLaRedNeuronal )

end;






MEJORAS
- Se puede entrenar el sistema con las cotizaciones de más empresas para mejorar la predicción,


-Es conveniente normalizar los valores antes de introducirlos en la red neuronal.


-Se puede aumentar el número de capas (FFNN1.NLayers) y el número de neuronas de cada capa para ver en qué momento tenemos la mejor estimación.

-Si utilizáis un tchart para ir visualizando los valores calculados en cada iteración se puede ver gráficamente cómo poco a poco se va ajustando la curva de valores calculados respecto a la curva de valores reales (es impresionante)





Redes neuronales con Delphi - Neural net with Delphi

En este post os presento el componente TFFNN que os ayudará a realizar redes neuronales.

Utiliza el algoritmo de retropropagación o propagación hacia atrás de los errores (en inglés backpropagation), método usado habitualmente para el entrenamiento de redes.



Se puede descargar desde aquí



www.datalandsoftware.com/files/ffnn.zip



Descomprimimos el componente sobre una carpeta llamada (p.ej) "redes neuronales" y desde nuestro Delphi accedemos a

File->Open



Seleccionamos FFNNPackage.dpk de la carpeta "redes neuronales" y pulsamos "Abrir"



En el ProjectGroup1 hacemos clic con el botón derecho del ratón sobre FNNPackage.bpl y activamos el menú "Install"









Con lo que se instalará el componente TFFNN en la pestaña "Dataland" de la paleta de componentes.

Guardamos y cerramos el ProjectGroup1 con File->Save All, y después File->Close.

Ahora vamos a crear una nueva aplicación de prueba:

File->New-> VCL Forms Application - Delphi for Win32





Arrastramos de la paleta de componentes (pestaña "dataland") "TFFNN" a nuestro Form, creamos un TMemo, y 4 botones (Entrenar, Mostrar, Cargar patrón de entrenamiento, Guardar patrón de entrenamiento)











Después tendremos que indicar los parámetros de nuestra red neuronal:

InputCount (Nº de entradas)=1

InputMax (Máximo número de entradas)=8

InputMin (Mínimo número de entradas)=-1

OutputCount (Nº de salidas)=1

OutputMax (Máximo número de salidas)=10

OutputMin (Mínimo número de salidas)=9

En NLayers indicaremos el número de capas de nuestra red (En este caso tendrá sólo una capa) y el número de neuronas de cada capa=2

Hay que indicar que cuanto mayor sea el número de capas y de neuronas más tiempo tardará la red en conseguir un entrenamiento óptimo.





OBJETIVO DE LA RED

Es la simulación de la función: y= 10 + x





DEFINICIÓN DE BOTONES:

Botón "Cargar patrón de entrenamiento":

FFNN1.LoadFromFile('redneural1.txt');



Botón "Guardar patrón de entrenamiento":

FFNN1.SaveToFile('redneural1.txt');



RedNeural1.txt es un fichero de texto con los parámetros y variables de nuestra red neuronal, que no hay que modificar bajo ningún concepto.



Botón "Entrenar":



procedure TForm1.EntrenarClick(Sender: TObject);
var
i: Integer;
begin
for i:=1 to 10000 do begin

FFNN1.Input[1]:=i mod 7; //Pone la entrada
FFNN1.DesiredOutput[1]:=func( i mod 7 ); //Pone lo que queremos que salga
FFNN1.BackProp; //Entrena la red con este par de valores(In, Out).
{ Cuando se usan vectores: Input, Output y DesiredOutput usan índices entre 1 y Count (Input[1], Input[2], Output[1]...
Los índices: Input[0], Output[0] y DesiredOutput[0] son reservados por la aplicación }
end;
end;



Quizás en este caso no sea necesario llegar a que el índice del bucle "i" llegue a 10000 ya que lo que se hace es que cuando el valor del error cuadrático medio sea menor que 0,01 (P.ej) se detenga el cálculo.

El Error cuadrático medio se calcula desde FFNN1.GetAvgError







Botón "Mostrar":



procedure TForm1.MostrarClick(Sender: TObject);
var
r, t: Real;
i: Integer;
begin
for i:=0 to 6 do begin
r:=i;
FFNN1.Input[1]:=r; //Pone un valor a la neurona de entrada nº 1
FFNN1.CalcOut; //Calcula la salida de la red neuronal. Después de esta linea podremos leer la salida
t:=FFNN1.Output[1];
FFNN1.DesiredOutput[1]:=func( i ); //Calculamos el valor que deseamos tenga en la salida
Memo1.Lines.Add(Format('%f %f %f %f', [r, t, FFNN1.GetAvgError, FFNN1.GetMaxError]));
//Ambos errores son los mismos ya que tenemos 1 output (Avg = Max)
end;
end;



function TForm1.func(x: Real): Real;
begin
//Entrenamos a la red para reproducir esta función
Result:=10 + x;
end;





Abajo os muestro los resultados después de entrenar a la red, como véis los resultados obtenidos se parecen bastante a los esperados con lo que podemos afirmar que la red ha sido entrenada correctamente.

Ahora debemos guardar los parámetros de la red con FFNN1.SaveToFile('redneural1.txt'), de tal forma que la próxima vez que queramos simular la función y=10+x no sea necesario entrenarla ya que bastaría con cargar el patrón de red previamente guardado con FFNN1.LoadFromFile('redneural1.txt').


Simulación del movimiento de los electrones en un campo electrico

Espectacular simulación realizada con OpenGL del movimiento de los electrones cuando atraviesan un campo eléctrico. Como muestra la image...