Friday, 19 February 2010

Electric motor bike and bicycles

Are you interested in the latest changes as far as electric motor bikes and bicycles are concerned.

Go have a look at http://thekneeslider.com

Many of the major manufacturers such as Peugeot are getting on-board as far as electric scooters are concerned. Soon you will be able to get a electric scooter from your local dealer.

First try with fibre glass and epoxy

Monday, 15 February 2010

Fibra de vidrio



Fibra de Vidrio kit

Se utiliza para embarcaciones, tablas de windsurf, patines, accesorios de moto y la pared de reparación

5m * 1m of fibra de vidrio (Twill 2*2, 0.15 ancho)
1L de epoxy y 333ml de epoxy endurecedor (mesclar 3 to 1 ratio)

Fibre Glass



Fibre Glass kit

Used for boats, wind surf boards, skateboards, motor bike accessories.

5m * 1m of fibre glass (Twill 2*2, 0.15 thickness)
1L of epoxy and 333ml of epoxy hardener (mix in a 3 to 1 ratio)

Friday, 12 February 2010

Bicycle build kits



Ever wanted to just do things on your own. Do you like engineering? Ever thought of building your own bicycle frame because what you want is just not out there.

This bicycles construction kits contains

Epoxy hardener,Epoxy Softener (Mix in 3(Hardener) to 1(Softener) ratio)
3 meters squared of carbon fibre - Twill 2*2.
1 Bracket shell
1 Clamp (For the seat)

Rent a bicycle in Madrid, Spain



Riding around Madrid, Spain on bicycle is a great way to see the city. There are plenty of bicycle paths and the Spanish drivers are not as crazy as you think they are. There are lots of out of the way places to see like the "Anillo Verde" i.e. ("The green road").

You will need to collect the bike from Embajadores and leave a deposit of €300 and pay €20 per day. You will also need to state how many bicycles are needed. Call +346548696 to arrange a time to pick the bikes ups. You will have to phone first.

Map
www.ecokits.eu

Thursday, 11 February 2010

CFingerPrint C# (Biometric SDK)

/*
Biometric SDK
Version 1.3

This file contains functions that manipulate , extract features and match
fingerprint images.

Copyright (C) 2005 Scott Johnston
Email : moleisking@googlemail.com

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; either version 2
of the License, or (at your option) any later version.

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.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

using System;
using System.Drawing;
using System.Drawing.Drawing2D;

namespace BiometricsSDK.FingerPrint
{
///
/// Summary description for CFinger.
///

public class CFingerPrint
{
//used for image
//for digital persona with kit
//public int FP_IMAGE_WIDTH = 500;
//public int FP_IMAGE_HEIGHT = 500;
//for verifinger with kit
public int FP_IMAGE_WIDTH = 323;
public int FP_IMAGE_HEIGHT = 352;
//Used by template
//be carefull the size of the array must always be 1 larger than a number divisable by 4
public int FP_TEMPLATE_MAX_SIZE = 601;
//used for matching
//the max distance between to points when comparing two points to count as a match
public int FP_MATCH_POINT_DISTANCE_MOVEMENT = 10;
//the max rotation to use when comparint two points to count as a match
public int FP_MATCH_POINT_ROTATION_MOVEMENT = 10;//10;
//a percentage
public int FP_MATCH_THRESHOLD = 55;
//finger print classifications
//Wirbel class
public const int FP_CLASS_WHORL = 1 ;
//lasso class
public const int FP_CLASS_LEFT_LOOP = 2;
public const int FP_CLASS_RIGHT_LOOP = 3;
public const int FP_CLASS_ARCH = 4;
public const int FP_CLASS_ARCH_TENTED = 5;
//fingerprint template values
private const int FP_TEMPLATE_SIZE = 0;
private const int FP_TEMPLATE_ORIGIN_X = 1;
private const int FP_TEMPLATE_ORIGIN_Y = 2;
private const int FP_TEMPLATE_FEATURE_SIZE = 6;
private const int FP_TEMPLATE_SEARCH_RADIUS = 1;
//fingerprint origin values
//private int FP_ORIGIN_SEARCH_RADIUS = 5;
//holds skeletinized image
public byte [,] P = new byte[500,500];

public CFingerPrint()
{
}

public CFingerPrint(int width , int height )
{
FP_IMAGE_WIDTH = width;
FP_IMAGE_HEIGHT = height;
P = new byte[width,height];
}

public CFingerPrint(int width , int height ,int MatchPointDistanceMovement , int MatchPointRotationMovment , int MatchThreshold )
{

FP_IMAGE_WIDTH = width;
FP_IMAGE_HEIGHT = height;
FP_MATCH_POINT_DISTANCE_MOVEMENT = MatchPointDistanceMovement;
FP_MATCH_POINT_ROTATION_MOVEMENT = MatchPointRotationMovment;
FP_MATCH_THRESHOLD = MatchThreshold;
}

public void setFingerPrintImage(Bitmap m_image)
{
try
{
for (int i = 0; i <= FP_IMAGE_WIDTH - 1; i++) { for (int j = 0; j <= FP_IMAGE_HEIGHT - 1; j++) { if ((m_image.GetPixel(i, j).B <= 127) && (m_image.GetPixel(i, j).R <= 127) && (m_image.GetPixel(i, j).G <= 127)) { P[i, j] = 1; } else { P[i, j] = 0; } } } //set edges to 0 for (int i = 0; i <= FP_IMAGE_WIDTH - 1; i++) { P[i, 0] = 0; P[i, FP_IMAGE_HEIGHT - 1] = 0; } for (int j = 0; j <= FP_IMAGE_HEIGHT - 1; j++) { P[0, j] = 0; P[FP_IMAGE_WIDTH - 1, j] = 0; } } catch (Exception ex) { throw ex; } } public Bitmap getFingerPrintImage() { Bitmap imageBuffer = new Bitmap(FP_IMAGE_WIDTH,FP_IMAGE_HEIGHT ); for (int i = 0; i<= FP_IMAGE_WIDTH - 1;i++) { for (int j = 0;j<= FP_IMAGE_HEIGHT - 1;j++) { if (P[i, j] == 1) { imageBuffer.SetPixel(i, j, Color.Blue); } else { imageBuffer.SetPixel(i, j, Color.White); } } } return imageBuffer; } public Bitmap getFingerPrintImageDetail() { //set finger print image Bitmap imageBuffer = new Bitmap(FP_IMAGE_WIDTH,FP_IMAGE_HEIGHT ); for (int i = 0; i<= FP_IMAGE_WIDTH - 1;i++) { for (int j = 0;j<= FP_IMAGE_HEIGHT - 1;j++) { if (P[i,j] == 1) imageBuffer.SetPixel(i,j,Color.Blue); else imageBuffer.SetPixel(i,j,Color.White ); } } //get features double[] m_arr = this.getFingerPrintTemplate(); // int linelength = 5; //draw points Pen penBlue = new Pen(Color.Blue, 1); Pen penRed = new Pen(Color.Red, 1); Pen penGreen = new Pen(Color.Green, 1); Pen penGray = new Pen(Color.Gray, 1); //Graphics gf = Graphics.FromImage(Image.FromHbitmap(m_ImageBuffer.GetHbitmap() )); Graphics gf = Graphics.FromImage(imageBuffer); gf.CompositingMode = CompositingMode.SourceOver; for(int i=7 ; i<=m_arr[0]-1;i=i+6) { if(m_arr[i+4]>1)
{
gf.DrawRectangle(penRed,(int)m_arr[i]+(int)m_arr[1]-3,(int)m_arr[i+1]+(int)m_arr[2]-2,5,5);
}
else if(m_arr[i+4]==1)
{
gf.DrawEllipse(penGreen,(int)m_arr[i]+(int)m_arr[1]-3,(int)m_arr[i+1]+(int)m_arr[2]-2,5,5);
}


}//end for
//draws the origin
gf.DrawLine(penGray,(int)m_arr[1]-5,(int)m_arr[2],(int)m_arr[1]+5,(int)m_arr[2]);
gf.DrawLine(penGray,(int)m_arr[1],(int)m_arr[2]-5,(int)m_arr[1],(int)m_arr[2]+5);
return imageBuffer;
}//end getFingerPrintImageDetail()

public void ThinningHilditch()
{
int change = 1;
bool mbool = true;
while (change != 0)
{
change = 0;
for(int i = 2; i <= FP_IMAGE_WIDTH - 2;i++) { for(int j = 2; j <= FP_IMAGE_HEIGHT - 2;j++) { if (P[i,j] == 1) { short c = 0; //count surrounding 1 //a) Make sure pixel 1, has 2 to 6 (inclusive) neighbors if (P[i,j+1] == 1) { c++;} if (P[i+1,j+1] == 1) { c++;} if (P[i+1,j] == 1) { c++;} if (P[i+1,j-1] == 1) { c++;} if (P[i,j-1] == 1) { c++;} if (P[i-1,j-1] == 1) { c++;} if (P[i-1,j] == 1) { c++;} if (P[i-1,j+1] == 1) { c++;} if ((c >= 2) && (c <= 6 )) { c = 0; //b) starting from 2, go clockwise until 9, and count the //' number of 0 to 1 transitions. This should be equal to 1. if ((P[i-1,j+1] == 0) && (P[i,j+1] == 1)) { c++;} if ((P[i,j+1] == 0) && (P[i+1,j+1] == 1)) { c++;} if ((P[i+1,j+1] == 0) && (P[i+1,j] == 1)) { c++;} if ((P[i+1,j] == 0) && (P[i+1,j-1] == 1)) { c++;} if ((P[i + 1,j-1] == 0) && (P[i,j-1] == 1)) { c++;} if ((P[i,j-1] == 0) && (P[i-1,j-1] == 1)) { c++;} if ((P[i-1,j-1] == 0) && (P[i-1,j] == 1)) { c++;} if ((P[i - 1,j] == 0) && (P[i-1,j+1] == 1)) { c++;} if (c == 1 ) { c = 0; if (mbool == true) { //c) 2*4*6=0 (ie either 2,4 ,or 6 is off) if ((P[i,j+1] * P[i+1,j] * P[i+1,j-1]) == 0 ) { //d) 4*6*8=0 if ((P[i+1,j] * P[i+1,j-1] * P[i-1,j]) == 0 ) { P[i,j] = 0; change++; } } mbool = false; } else { //c) 2*6*8=0 if ((P[i,j+1] * P[i+1,j-1] * P[i-1,j]) == 0) { //d) 2*4*8=0 if ((P[i,j+1] * P[i+1,j] * P[i-1,j]) == 0) { P[i,j] = 0; change++; } } mbool = true; } } } } } } }//End While }//end ThinningHilditchAlgorithim public void ThinningHitAndMiss() { /* * basicly you take all patterns * 111 X1X * X1X or x11 so on * 000 xxX * if these conditions are true then set the middle 1 to 0 */ int c = 1; while (c != 0) { c = 0; for(int i = 1;i<=FP_IMAGE_WIDTH - 1;i++) { for(int j = 1;j<=FP_IMAGE_HEIGHT - 1;j++) { if ((P[i,j] == 1) && (i != 0) && (j != FP_IMAGE_HEIGHT - 1) && (j != 0) && (i != FP_IMAGE_WIDTH - 1)) { if ((P[i-1,j-1] == 1) &&( P[i,j-1] == 1) && (P[i+1,j-1] == 1) && (P[i-1,j+1] == 0) && (P[i,j+1] == 0) && (P[i+1,j+1] == 0)) { P[i,j] = 0; //'1 on bottom c++; } else if ((P[i-1,j+1] == 1) && (P[i,j+1] == 1) && (P[i+1,j+1] == 1) && (P[i-1,j-1] == 0) && (P[i,j-1] == 0) && (P[i+1,j-1] == 0)) { P[i,j] = 0; //'1 on top c++; } else if ((P[i-1,j] == 1) && (P[i-1,j - 1] == 1) && (P[i-1,j+1] == 1) && (P[i+1,j] == 0) && (P[i+1,j+1] == 0) && (P[i+1,j-1] == 0)) { P[i,j] = 0; //'1 on left c++; } else if ((P[i+1,j] == 1) && (P[i+1,j-1] == 1) && (P[i+1,j+1] == 1) && (P[i-1,j] == 0) && (P[i-1,j+1] == 0) && (P[i-1,j-1] == 0) ) { P[i,j] = 0; //'1 on right c++; } else if ((P[i-1,j] == 1) && (P[i,j-1] == 1) && (P[i,j+1] == 0) && (P[i+1,j+1] == 0) && (P[i + 1,j] == 0)) { //x00 //110 //x1x P[i,j] = 0; //'1 on Bottem Left c++; } else if ((P[i-1,j] == 1) && (P[i,j+1] == 1) && (P[i,j-1] == 0) && (P[i+1,j-1] == 0) && (P[i+1,j] == 0)) { //x1x //110 //x00 P[i,j] = 0; //'1 on Top Left c++; } else if ((P[i,j+1]== 1) && (P[i+1,j] == 1) && (P[i-1,j] == 0) && (P[i-1,j-1] == 0) && (P[i,j-1] == 0)) { //x1x //011 //00x P[i,j] = 0; //'1 on Top Right c++; } else if ((P[i,j-1] == 1) && (P[i+1,j] == 1) && (P[i-1,j] == 0) && (P[i-1,j+1] == 0) && (P[i,j+1] == 0) ) { //00x //011 //x1x P[i,j] = 0; //'1 on Bottom Right c++; } } }//Next }//Next }//End While }//end ThinningHitAndMiss public void ChaneLinkAlgorithm(int ChainLinkDistance) { //short count1; for(int i = 1;i<= FP_IMAGE_WIDTH - 1;i++) { for (int j = 1 ; j <= FP_IMAGE_HEIGHT - 1;j++) { //change second condition when changeing direction //Horizontal if ((P[i,j] == 1) && (i != FP_IMAGE_WIDTH - 1) && (i != 0) && (j != FP_IMAGE_HEIGHT - 1) && (j != 0)) { if (P[i + 1,j] == 0) { short countX = 0; //count Horizontal Hole while (((i + countX) <= FP_IMAGE_WIDTH - 1) && (countX <= ChainLinkDistance)) { if (((i + countX + 1) <= FP_IMAGE_WIDTH - 1) && ((countX + 1) <= ChainLinkDistance)) { if (P[i + countX + 1,j] == 0) { countX++; } else { break; } } else { break; } } //Fill hole if it is wide enough if ((countX != 0) && ((countX + 1) <= ChainLinkDistance)) { for (int temp = 0; temp<= countX;temp++) { P[i+temp,j] = 1; } } } } //change second condition when changeing direction //Vertical if ((P[i,j] == 1) && (i != FP_IMAGE_WIDTH - 1) && (i != 0) && (j != FP_IMAGE_HEIGHT - 1) && (j != 0)) { if (P[i,j+1] == 0 ) { short countY = 0; //count Horizontal Hole while (((j + countY) <= FP_IMAGE_HEIGHT-1) && (countY <= ChainLinkDistance)) { if (((j + countY + 1) <= FP_IMAGE_HEIGHT-1) && ((countY + 1) <= ChainLinkDistance) ) { //i pu this here bacause it kept on crashing if (P[i,j + countY + 1] == 0) { countY++; } else { break; } } else { break; } } //Fill hole if it is wide enough if ((countY != 0) && (countY + 1 <= ChainLinkDistance)) { for(int temp = 0;temp<= countY;temp++) { P[i,j + temp] = 1; } } } } //change second condition when changeing direction //Vertical Horizontal if ((P[i,j] == 1) && (i != FP_IMAGE_WIDTH - 1) && (i != 0) && (j != FP_IMAGE_HEIGHT - 1) && (j != 0)) { if (P[i + 1,j + 1] == 0) { short countYX = 0; //1 //count Horizontal Hole while ((j + countYX <= FP_IMAGE_HEIGHT-1) && (i + countYX <= FP_IMAGE_WIDTH-1) && (countYX <= ChainLinkDistance)) { if (((j + countYX + 1) <= FP_IMAGE_HEIGHT-1) && ((i + countYX + 1) <= FP_IMAGE_WIDTH-1) && ((countYX + 1) <= ChainLinkDistance)) if (P[i+countYX+1,j + countYX + 1] == 0) { countYX++; } else { break; } else { break; } } //Fill hole if it is wide enough if ((countYX != 0) && (countYX + 1 <= ChainLinkDistance)) { for(int temp = 0 ; temp <= countYX ; temp++) { P[i+temp,j+temp] = 1; } } } } } } } /// /// /// ################################ /// # Extract Origin # /// ################################ /// /// In future i want to use the gradients to classifie the finger print into the 5 different /// catagories which are marked in the FP_CLASS. /// /// This function still needs to improved and somtimes dosen't find the center of the finger print. /// /// The principle in finding the centre is simple , just find the greatest change in the gradient /// bettween two lines and you have your centre. /// /// To find the classification you have to find the average changes in gradients in the different /// sectors (if you divided your picture in 4 using the fingerprint centre as the centre).You should /// then classifie the fingerprint according to this. /// /// private Point getFingerPrintOrigin() { Point m_Point = new Point(); double gradcur=0; double gradprev=0; double gradchangebig=0; double gradchange=0; double graddistancebig=0; double graddistance=0; double prevx=0; double prevy=0; for(int j =50;j<=FP_IMAGE_HEIGHT-50;j++) { for(int i =50;i<=FP_IMAGE_WIDTH-50;i++) { if(P[i,j]==1) { //count surrounding pixels int tc=0; int x1=0; int y1=0; int x2=0; int y2=0; //find surrounding 1s for (int m = -1*FP_TEMPLATE_SEARCH_RADIUS;m<=FP_TEMPLATE_SEARCH_RADIUS;m++) { for (int n = -1*FP_TEMPLATE_SEARCH_RADIUS;n<=FP_TEMPLATE_SEARCH_RADIUS;n++) { if ((m==FP_TEMPLATE_SEARCH_RADIUS)||(m==(-1)*FP_TEMPLATE_SEARCH_RADIUS)||(n==FP_TEMPLATE_SEARCH_RADIUS)||(n==(-1)*FP_TEMPLATE_SEARCH_RADIUS)) { if(P[i+m,j+n] == 1 ) { tc++; if (tc==1) { x1=i+m; y1=j+n; } if (tc==2) { x2=i+m; y2=j+n; } }//end if }//end if }//end for n } //end for m //does all the hard work of finding the greatest change in gradient if(tc==2) { if ((x2-x1)>0)
{
gradcur = (y2-y1)/(x2-x1);
//check to see gradient change by at least 270 degrees

{
gradchange = Math.Abs(gradcur) + Math.Abs(gradprev) ;
graddistance = Math.Abs(i) - Math.Abs(prevx);
if(gradchangebig
{
if (graddistancebig
{
gradchangebig=gradchange;
graddistancebig=graddistance;
m_Point.X=i;//FP_ORIGIN_X =i;
m_Point.Y=j;//FP_ORIGIN_Y =j;
}
}
break;
}
//reset varibles for new checks
gradprev=gradcur;
gradcur=0;
prevx=i;
prevy=j;
}//(x2-x1)>0
}//end if tc==2
}//end if P[x,y]==1
}//end for i
}//end for j
// JOptionPane.showMessageDialog (null,Integer.toString(FP_ORIGIN_X)+";"+Integer.toString(FP_ORIGIN_Y),"getFingerPrintOrigin",JOptionPane.PLAIN_MESSAGE);
return m_Point;
}

private int getFingerPrintClassification()
{
Point m_Point = this.getFingerPrintOrigin();
double gradcur=0;

//stores total gradient of corners
double gradlt=0;
double gradrt=0;
double gradlb=0;
double gradrb=0;

//counts total of each corner gradient
double cgradlt=0;
double cgradrt=0;
double cgradlb=0;
double cgradrb=0;

for(int j =50;j<=FP_IMAGE_HEIGHT-50;j++) { for(int i =50;i<=FP_IMAGE_WIDTH-50;i++) { if(P[i,j]==1) { //count surrounding pixels int tc=0; int x1=0; int y1=0; int x2=0; int y2=0; //find surrounding 1s for (int m = -1*FP_TEMPLATE_SEARCH_RADIUS;m<=FP_TEMPLATE_SEARCH_RADIUS;m++) { for (int n = -1*FP_TEMPLATE_SEARCH_RADIUS;n<=FP_TEMPLATE_SEARCH_RADIUS;n++) { if ((m==FP_TEMPLATE_SEARCH_RADIUS)||(m==(-1)*FP_TEMPLATE_SEARCH_RADIUS)||(n==FP_TEMPLATE_SEARCH_RADIUS)||(n==(-1)*FP_TEMPLATE_SEARCH_RADIUS)) { if(P[i+m,j+n] == 1 ) { tc++; if (tc==1) { x1=i+m; y1=j+n; } if (tc==2) { x2=i+m; y2=j+n; } }//end if }//end if }//end for n } //end for m //does all the hard work of finding the greatest change in gradient if(tc==2) { if ((x2-x1)>0)
{
gradcur = (y2-y1)/(x2-x1);
//check to see gradient change by at least 270 degrees
if ((x2m_Point.Y))
{
gradlt=gradlt+gradcur;
gradlt++;
}
else if ((x2>m_Point.X)&&(y2>m_Point.Y))
{
gradrt=gradrt+gradcur;
gradrt++;
}
else if ((x2
{
gradlb=gradlb+gradcur;
gradlb++;
}
else if ((x2>m_Point.X)&&(y2
{
gradrb=gradrb+gradcur;
gradrb++;
}

}//(x2-x1)>0
}//end if tc==2
}//end if P[x,y]==1
}//end for i
}//end for j
//get average gradient for 4 corners
gradlb=gradlb/cgradlb;
gradrb=gradrb/cgradrb;
gradlt=gradlt/cgradlt;
gradrt=gradrt/cgradrt;
//determin classification according to gradient
//needs work
if ((gradlt>0)&&(gradrt>0)&&(gradlb>0)&&(gradrb>0))
{
return FP_CLASS_WHORL;
}
else if ((gradlt>0)&&(gradrt>0)&&(gradlb>0)&&(gradrb>0))
{
return FP_CLASS_LEFT_LOOP;
}
else if ((gradlt>0)&&(gradrt>0)&&(gradlb>0)&&(gradrb>0))
{
return FP_CLASS_RIGHT_LOOP;
}
else if ((gradlt>0)&&(gradrt>0)&&(gradlb>0)&&(gradrb>0))
{
return FP_CLASS_ARCH;
}
else if ((gradlt>0)&&(gradrt>0)&&(gradlb>0)&&(gradrb>0))
{
return FP_CLASS_ARCH_TENTED;
}
else
{
return 1;
}
// JOptionPane.showMessageDialog (null,Integer.toString(FP_ORIGIN_X)+";"+Integer.toString(FP_ORIGIN_Y),"getFingerPrintOrigin",JOptionPane.PLAIN_MESSAGE);
}


///
///
/// ################################
/// # Extract Template #
/// ################################
///
/// The template will have to be formated according to the ISO standards as set out buy
/// NIST , NIST also has a set of binary pictures to use for examples. This database is used for
/// determaning the FAR(False Acceptance Rate) and FRR (False Rejection Rate)
///
/// First 7 are (elements in array , originx , originy , null , null , null ,null) after that
/// the format is (x,y,r,degree ,number of ends,resultant degree).The size of the array
/// is always pre set.
///
/// There is also future work that needs to be done on genralization , basicly what this means is
/// that you take 3 finger templates , then take the features that are common to all three templeate
/// and you will then come out with a generalized template.This will improve quality of the template.
///
///


public double[] getFingerPrintTemplate()
{
// final int SEARCH_RADIUS = 1;
double x=0;
double y=0;
double r=0;
double d=0;
double[] m_arr = new double[FP_TEMPLATE_MAX_SIZE];

this.ThinningHilditch();
this.ThinningHitAndMiss();
this.ThinningHilditch();
this.ThinningHitAndMiss();

Point origin = this.getFingerPrintOrigin();
m_arr[1]=origin.X;
m_arr[2]=origin.Y;

int c = 7 ;
int previ=0;
int prevj=0;

bool first = true;

//start from 5 units in to avoid detection of edges of finger print and out of bound exceptions
for(int j = 5 ;j<= FP_IMAGE_HEIGHT - 6;j++) { first = true; for( int i =5 ;i<= FP_IMAGE_WIDTH - 6;i++) { if ((c { /* * Must not capture first and last feature because those are the edges of the finger print * and will provide no value to the template. */ if(first == true) { first = false; //cheak to see if previos item in array was aslo end if( (c>7)&&((m_arr[c-6]+origin.X)==previ)&&((m_arr[c-5]+origin.Y)==prevj) )
{
//delete previos featue
m_arr[c--]=0;
m_arr[c--]=0;
m_arr[c--]=0;
m_arr[c--]=0;
m_arr[c--]=0;
m_arr[c--]=0;
}
}
else
{
int tc = 0;
for (int m = -1*FP_TEMPLATE_SEARCH_RADIUS;m<=FP_TEMPLATE_SEARCH_RADIUS;m++) { for (int n = -1*FP_TEMPLATE_SEARCH_RADIUS;n<=FP_TEMPLATE_SEARCH_RADIUS;n++) { if ((m==FP_TEMPLATE_SEARCH_RADIUS)||(m==(-1)*FP_TEMPLATE_SEARCH_RADIUS)||(n==FP_TEMPLATE_SEARCH_RADIUS)||(n==(-1)*FP_TEMPLATE_SEARCH_RADIUS)) { if(P[i+m,j+n] == 1 ) { tc++; }//end if }//end if }//end for n } //end for m //calculate parameters necesary for template if ((tc==1)||(tc==3)) { x = i- origin.X; y = j- origin.Y; r = Math.Sqrt(x*x + y*y); if ((x>0)&&(y>0))
{
d =Math.Atan(y/x);
}

{
d =Math.Atan(y/x) - Math.PI ;
}

{
d =Math.PI + Math.Atan(y/x);
}

{
d =2*Math.PI + Math.Atan(y/x);
}
}

//check to see if point already been captured
bool foundx = false;
bool foundy = false;
for (int m=7;m<=c;m=m+6) { if(m_arr[m+4]==3) { { foundx=true; } { foundy=true; } }//end if }//end for m //1 surrounding 1s if ((tc==1) && (c <= FP_TEMPLATE_MAX_SIZE-6) && (x!=0) && (y!=0) && ((foundx==false)||(foundy==false)) ) { if (P[i-1,j+1] == 1) { m_arr[c++] = x; m_arr[c++] = y; m_arr[c++] = r; m_arr[c++] = d; m_arr[c++] = 1 ; m_arr[c++] = 135 ; } else if (P[i,j+1] == 1) { m_arr[c++] = x; m_arr[c++] = y; m_arr[c++] = r; m_arr[c++] = d; m_arr[c++] = 1 ; m_arr[c++] =90 ; } else if (P[i+1,j+1] == 1) { m_arr[c++] = x; m_arr[c++] = y; m_arr[c++] = r; m_arr[c++] = d; m_arr[c++] = 1 ; m_arr[c++] =45 ; } else if (P[i+1,j] == 1) { m_arr[c++] = x; m_arr[c++] = y; m_arr[c++] = r; m_arr[c++] = d; m_arr[c++] = 1 ; m_arr[c++] = 0 ; } else if (P[i+1,j-1] == 1) { m_arr[c++] = x; m_arr[c++] = y; m_arr[c++] = r; m_arr[c++] = d; m_arr[c++] = 1 ; m_arr[c++] =315 ; } else if (P[i,j-1] == 1) { m_arr[c++] = x; m_arr[c++] = y; m_arr[c++] = r; m_arr[c++] = d; m_arr[c++] = 1 ; m_arr[c++] = 270 ; } else if (P[i-1,j-1] == 1) { m_arr[c++] = x; m_arr[c++] = y; m_arr[c++] = r; m_arr[c++] = d; m_arr[c++] = 1 ; m_arr[c++] = 225 ; } else if (P[i-1, j] == 1 ) { m_arr[c++] = x; m_arr[c++] = y; m_arr[c++] = r; m_arr[c++] = d; m_arr[c++] = 1 ; m_arr[c++] = 180 ; } } else if ((tc>=3)&&(c <= FP_TEMPLATE_MAX_SIZE - 6)&&(x!=0)&&(y!=0)&&((foundx==false)||(foundy==false)) ) { //3 surrounding 1s m_arr[c++] = x; m_arr[c++] = y; m_arr[c++] = r; m_arr[c++] = d; m_arr[c++] = 3; m_arr[c++] = 0; }//if tc>=3
}//end if first
previ=i;
prevj=j;

//306;269
if (((i- origin.X)>=(306 - 4))&&((i- origin.Y)>=(269-4)))
{
if (((i- origin.X)<=(306+4))&&((i- origin.Y)<=(269+4))) { //JOptionPane.showMessageDialog (null,Double.toString(c)+";"+Integer.toString(i)+";"+Integer.toString(j),"My Point",JOptionPane.PLAIN_MESSAGE); } } }//end if that checks for p[x,y]=1 }//end for }//end for //put total size of points collected at 0 in array m_arr[0]=c; return m_arr; }//end getFingerPrintTemplate() public String ConvertFingerPrintTemplateDoubleToString(double[] finger) { String temp=""; for (int i=0;i<=finger.Length-1 ; i++) { temp = temp + finger[i].ToString() +";"; } return temp; } public double [] ConvertFingerPrintTemplateStringToDouble(String finger) { double[] m_finger = new double[FP_TEMPLATE_MAX_SIZE]; int c=-1; String m_double = ""; String temp =""; for (int i=0;i<=finger.Length-1 ; i++) { char[] tempch = finger.ToCharArray(); temp = temp[i].ToString(); if (temp==";") { m_finger[c++] =Double.Parse(m_double); } else { m_double = m_double + temp; } } return m_finger; } /// /// ################################ /// # Matching # /// ################################ /// /// Something to possably look at are /// /// Distance = (X1 -X2)^2 + (Y1 - Y2)^2. The Error_Rating , if a image is is to the left or /// right or even at a angle the distance betwwen matched points will always be the same. /// /// The matching dose account for rotation , thats what the cos and sin are for. /// /// In matching you will never get a 100% match uunless they are exactly the same /// image. 60% is quite good in general ,anything above 55% is considered a match , even /// in other commercial versions. Remember you comparing twod DIFFERENT images then drawing a conclusion of a match. /// /// //cross-corelation algorithm public int Match(double[] finger1,double[] finger2 , int threshold , bool fastmatch) { //compare matrix with all shifted matrixes //must do later. must get the size of the array // JOptionPane.showMessageDialog (null,Double.toString(finger1[0])+";"+Double.toString(finger1[1])+";"+Double.toString(finger2[3]),"Match",JOptionPane.PLAIN_MESSAGE); double matchcount = 0; double matchcounttotal = (finger1[0]-6)/6; double bestmatch =0; double radian = Math.PI/180; bool foundpoint; for (int k = -1*FP_MATCH_POINT_ROTATION_MOVEMENT; k <= FP_MATCH_POINT_ROTATION_MOVEMENT; k++) { for (int i =7; i <= finger1[0]-5; i=i+6) { foundpoint = false; for (int j =7; j <= finger2[0]-5; j=j+6) { if(foundpoint==false) { //compare two points account for rotational , verticle and horizontal shift int resx=0; int resy=0; double x1=0 ; double y1=0; double x2=0; double y2=0; double r=0; double d=0; //find nessasary parameters r =finger2[j+2]; d = finger2[j+3]; x2=finger1[i]; y2=finger1[i+1]; //do angle shift for x x1 = r*Math.Cos(d+(k*radian)); resx = Math.Abs((int)x2 + (int)(-1*x1)); //do angle shift for y y1 = r*Math.Sin(d+(k*radian)); resy = Math.Abs((int)y2 + (int)(-1*y1)); //cheak shift matchs count as match if((FP_MATCH_POINT_DISTANCE_MOVEMENT > resx) && (FP_MATCH_POINT_DISTANCE_MOVEMENT > resy))
{

//cheak if same kind of feature
if(finger1[i+4] == finger2[j+4])
{
//cheak if feature in same direction
// if(((finger1[i+5]-finger2[j+5])<=46)||((finger1[i+5]==0)&&(finger2[j+5]==315))||((finger1[i+5]==0)&&(finger2[j+5]==45))) // { matchcount++; foundpoint = true; //break; // }//cheak if feature in same direction } //cheak if same kind of feature }//end if }//if found }//end for j }//end for i //see if we have a match if ((((matchcount/matchcounttotal)*100)>=threshold)&& (fastmatch == true))
{
//found match
return (int)((matchcount/matchcounttotal)*100);
}
else
{
//not found match
if(matchcount>bestmatch)
{
bestmatch = matchcount;
}
//reset match counter to 0
matchcount=0;
} //end if

}//end for k
return (int)((bestmatch/matchcounttotal)*100);
}//end Match



}//end class
}//end namespace