Project1

标题: 传说中的BP手势识别 [打印本页]

作者: yangff    时间: 2010-12-31 21:55
标题: 传说中的BP手势识别
根据一个C#代码和一本书里面的翻译过来的
识别率不高……
另外为了提高效率,神经网络是事先Dump出来的
还有只能识别0~9
原始代吗是这个http://blog.linjian.org/articles/bp-mouse-gesture-recognition/
就是这样~
至于怎么用……
复制所有代码
DrawBox.new(x,y,width,height)
然后这只是个简易的版本,不解释……一般使用是够了……更多的功能……自己看着办吧……
NetworkFunctions.initData是构建网络
NetworkFunctions.save是保存网络
NetworkFunctions.load是读取网络
其他的什么常量啊7788的自己看着办被……
  1. module Useful
  2.   NUM_PATTERNS=10
  3.   NUM_VECTORS=12
  4.   MATCH_TOLERANCE=0.96
  5.   ACTIVATION_RESPONSE=1.0
  6.   BIAS=-1.0
  7.   ERROR_THRESHOLD = 0.003
  8.   LEARNING_RATE = 0.5
  9.   NUM_HIDDEN_NEURONS = 6
  10.   WITH_MOMENTUM = false
  11.   MOMENTUM = 0.9
  12.   WITH_NOISE = false
  13.   MAX_NOISE_TO_ADD = 0.1
  14.   InitNames=["0","1","2","3","4","5","6","7","8","9"]
  15.   InitPatterns=
  16.   [
  17.     [ -0.96, 0.29, -0.71, 0.71, -0.29, 0.96, 0.29, 0.96, 0.71, 0.71, 0.96, 0.29, 0.96, -0.29, 0.71, -0.71, 0.29, -0.96, -0.29, -0.96, -0.71, -0.71, -0.96, -0.29 ],
  18.     [ 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 ],
  19.     [ 1, 0, 1, 0, 1, 0, 1, 0, -0.71, 0.71, -0.71, 0.71, -0.71, 0.71, -0.71, 0.71, 1, 0, 1, 0, 1, 0, 1, 0 ],
  20.     [ 1, 0, 1, 0, 0.91, 0.41, 0.41, 0.91, -0.41, 0.91, -0.91, 0.41, 0.91, 0.41, 0.41, 0.91, -0.41, 0.91, -0.91, 0.41, -1, 0, -1, 0 ],
  21.     [ -0.32, 0.95, -0.32, 0.95, -0.32, 0.95, -0.32, 0.95, -0.32, 0.95, -0.32, 0.95, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0 ],
  22.     [ -1, 0, -1, 0, -1, 0, 0, 1, 0, 1, 1, 0, 0.91, 0.41, 0.41, 0.91, -0.41, 0.91, -0.91, 0.41, -1, 0, -0.91, -0.41 ],
  23.     [ -0.95, 0.32, -0.71, 0.71, -0.35, 0.94, 0, 1, 0.35, 0.94, 0.71, 0.71, 0.95, 0.32, 0.91, -0.41, 0.41, -0.91, -0.41, -0.91, -0.91, -0.41, -0.91, 0.41 ],
  24.     [ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 ],
  25.     [ -0.89, -0.45, -0.89, 0.45, 0, 1, 0.89, 0.45, 0.89, 0.45, 0, 1, -0.89, 0.45, -0.89, -0.45, 0, -1, 0.89, -0.45, 0.89, -0.45, 0, -1 ],
  26.     [ -1, 0, -1, 0, -1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1 ]
  27.   ]
  28.   def self.randomClamped
  29.     a=rand(11)/10.0
  30.     b=rand(11)/10.0
  31.     return a-b
  32.   end
  33.   module RUN_MODE
  34.     LEARNING=1
  35.     ACTIVE=2
  36.     UNREADY=3
  37.     TRAINING=4
  38.   end
  39. end
  40. class Neuron
  41.   attr_accessor:numInputs
  42.   attr_accessor:weights
  43.   attr_accessor:prevUpdate
  44.   attr_accessor:activation
  45.   attr_accessor:error
  46.   @numInputs=1
  47. =begin
  48.         public Neuron(int _NumInputs)
  49.         {
  50.             NumInputs = _NumInputs + 1;
  51.             Activation = 0;
  52.             Error = 0;
  53.             Weights = new List<double>();
  54.             PrevUpdate = new List<double>();

  55.             //生成随机权重
  56.             for (int i = 0; i < NumInputs; i++)
  57.             {
  58.                 Weights.Add(Useful.RandomClamped());
  59.                 PrevUpdate.Add(0.0);
  60.             }
  61.         }
  62. =end
  63.   def initialize(numInputs)
  64.     @numInputs=numInputs+1
  65.     @activation=0
  66.     @error=0
  67.     @weights=[]
  68.     @prevUpdate=[]
  69.     for i in 0...numInputs
  70.       @weights.push(Useful.randomClamped)
  71.       @prevUpdate.push(0.0)
  72.     end
  73.   end
  74.   
  75. end
  76. class NeuronLayer
  77.   attr_accessor:numNeurons
  78.   attr_accessor:neurons
  79. =begin
  80.         public NeuronLayer(int _NumNeurons, int _NumInputsPerNeuron)
  81.         {
  82.             NumNeurons = _NumNeurons;
  83.             Neurons = new List<Neuron>();

  84.             for (int i = 0; i < NumNeurons; i++)
  85.             {
  86.                 Neurons.Add(new Neuron(_NumInputsPerNeuron));
  87.             }
  88.         }
  89. =end
  90.   def initialize(numNeurons,numInputsPerNeuron)
  91.     @numNeurons=numNeurons
  92.     @neurons=[]
  93.     #p @numNeurons
  94.     for i in 0...@numNeurons
  95.       @neurons.push(Neuron.new(numInputsPerNeuron))
  96.     end
  97.   end
  98. end
  99. class NeuralNet
  100.   attr_accessor:numInputs
  101.   attr_accessor:numOutputs
  102.   attr_accessor:numHiddenLayers
  103.   attr_accessor:neuronsPerHiddenLyr
  104.   attr_accessor:learningRate
  105.   attr_accessor:errorSum
  106.   attr_accessor:trained
  107.   attr_accessor:numEpochs
  108.   attr_accessor:layers
  109. =begin
  110.         private bool NetworkTrainingEpoch(List<List<double>> SetIn, List<List<double>> SetOut)
  111.         {
  112.             if (Useful.WITH_MOMENTUM)
  113.             {
  114.                 return NetworkTrainingEpochWithMomentum(SetIn, SetOut);
  115.             }
  116.             else
  117.             {
  118.                 return NetworkTrainingEpochNonMomentum(SetIn, SetOut);
  119.             }
  120.         }
  121. =end
  122.   def networkTrainingEpoch(setIn,setOut)
  123.     #if Useful::WITH_MOMENTUM
  124.       return networkTrainingEpochWithMomentum(setIn, setOut)
  125.     #else
  126.     #  return networkTrainingEpochNonMomentum(SetIn, SetOut)
  127.   #  end
  128.   end
  129.   def networkTrainingEpochWithMomentum(setIn,setOut)
  130.     @errorSum=0.0000000
  131.     for vec in 0...setIn.size
  132.       outputs=update(setIn[vec])
  133.       if outputs.size==0
  134.         p "Bad inputs"
  135.         return false
  136.       end
  137.       for op in 0...@numOutputs
  138.         err=0.000000000
  139.         err=(setOut[vec][op]-outputs[op])*outputs[op]*(1.0000000-outputs[op])
  140.         @layers[1].neurons[op].error=err
  141.         @errorSum+=(setOut[vec][op] - outputs[op]) * (setOut[vec][op] - outputs[op])
  142.         curWeight=0
  143.         curNrnHid=0
  144.         while (curWeight < @layers[1].neurons[op].weights.size - 1)
  145.           @layers[1].neurons[op].weights[curWeight] += err * @learningRate * @layers[0].neurons[curNrnHid].activation
  146.          
  147.           curWeight+=1
  148.           curNrnHid+=1
  149.          
  150.         end
  151.         @layers[1].neurons[op].weights[curWeight] += err * @learningRate * Useful::BIAS
  152.         
  153.       end
  154.       curNrnHid=0
  155.       n=0
  156.       while (curNrnHid < @layers[0].neurons.size)
  157.         err=0.00000000
  158.         curNrnOut=0.00000000
  159.         while (curNrnOut < @layers[1].neurons.size)
  160.           err+=@layers[1].neurons[curNrnOut].error * @layers[1].neurons[curNrnOut].weights[n]
  161.           curNrnOut+=1
  162.         end
  163.         err*=@layers[0].neurons[curNrnHid].activation * (1.000000 - @layers[0].neurons[curNrnHid].activation)
  164.         for w in 0...@numInputs
  165.           @layers[0].neurons[curNrnHid].weights[w] += err * @learningRate * setIn[vec][w]
  166.         end
  167.         @layers[0].neurons[curNrnHid].weights[@numInputs] += err * @learningRate * Useful::BIAS
  168.         curNrnHid+=1
  169.         n+=1
  170.       end
  171.     end
  172.     return true
  173.   end
  174. =begin
  175.         private void CreateNet()
  176.         {
  177.             if (NumHiddenLayers > 0)
  178.             {
  179.                 //隐含层
  180.                 Layers.Add(new NeuronLayer(NeuronsPerHiddenLyr, NumInputs));
  181.                 for (int i = 0; i < NumHiddenLayers - 1; i++)
  182.                 {
  183.                     Layers.Add(new NeuronLayer(NeuronsPerHiddenLyr, NeuronsPerHiddenLyr));
  184.                 }

  185.                 //输出层
  186.                 Layers.Add(new NeuronLayer(NumOutputs, NeuronsPerHiddenLyr));
  187.             }
  188.             else
  189.             {
  190.                 //输出层
  191.                 Layers.Add(new NeuronLayer(NumOutputs, NumInputs));
  192.             }
  193.         }
  194. =end
  195.   def createNet
  196.     if @numHiddenLayers>0
  197.       #p @neuronsPerHiddenLyr
  198.       @layers.push(NeuronLayer.new(@neuronsPerHiddenLyr, @numInputs))
  199.       for i in 0...@numHiddenLayers -1
  200.         @layers.push(NeuronLayer.new(@neuronsPerHiddenLyr, @neuronsPerHiddenLyr))
  201.       end
  202.       @layers.push(NeuronLayer.new(@numOutputs, @neuronsPerHiddenLyr))
  203.     else
  204.       @layers.push(NeuronLayer.new(@numOutputs, @numInputs))
  205.     end
  206.   end
  207. =begin

  208.         private void InitializeNetwork()
  209.         {
  210.             //对于每一层执行
  211.             for (int i = 0; i < NumHiddenLayers + 1; i++)
  212.             {
  213.                 //对于每个神经元执行
  214.                 for (int n = 0; n < Layers[i].NumNeurons; n++)
  215.                 {
  216.                     //对于每个权重执行
  217.                     for (int k = 0; k < Layers[i].Neurons[n].NumInputs; k++)
  218.                     {
  219.                         Layers[i].Neurons[n].Weights[k] = Useful.RandomClamped();
  220.                     }
  221.                 }
  222.             }

  223.             ErrorSum = 9999;
  224.             NumEpochs = 0;
  225.         }
  226.         
  227. =end
  228.   def initializeNetwork
  229.     for i in 0...@numHiddenLayers+1
  230.       for n in 0...@layers[i].numNeurons #?
  231.         for k in 0...@layers[i].neurons[n].numInputs
  232.           @layers[i].neurons[n].weights[k] = Useful.randomClamped
  233.         end
  234.       end
  235.     end
  236.     @errorSum=9999
  237.     @numEpochs=0
  238.   end
  239. =begin
  240.         private double Sigmoid(double activation, double response)
  241.         {
  242.             return (1.0 / (1.0 + Math.Exp(- activation / response)));
  243.         }
  244. =end
  245.   def sigmoid(activation,response)
  246.     return (1.0000000/(1.0000000 + Math.exp(- activation / response)))
  247.   end
  248. =begin
  249.         public NeuralNet(int _NumInputs, int _NumOutputs, int _HiddenNeurons, double _LearningRate)
  250.         {
  251.             NumInputs = _NumInputs;
  252.             NumOutputs = _NumOutputs;
  253.             NumHiddenLayers = 1;
  254.             NeuronsPerHiddenLyr = _HiddenNeurons;
  255.             LearningRate = _LearningRate;
  256.             ErrorSum = 9999;
  257.             Trained = false;
  258.             NumEpochs = 0;
  259.             Layers = new List<NeuronLayer>();
  260.             CreateNet();
  261.         }
  262. =end
  263.   def initialize(numInputs,numOutputs,hiddenNeurons,learningRate)
  264.     @numInputs=numInputs
  265.     @numOutputs=numOutputs
  266.     @neuronsPerHiddenLyr=hiddenNeurons
  267.     @learningRate=learningRate
  268.     @numHiddenLayers=1
  269.     @errorSum=9999
  270.     @trained=false
  271.     @numEpochs=0
  272.     @layers=[]
  273.     createNet
  274.   end
  275. =begin
  276.        public List<double> Update(List<double> _inputs)
  277.         {
  278.             List<double> inputs = new List<double>(_inputs);
  279.             List<double> outputs = new List<double>();
  280.             int cWeight = 0;

  281.             //验证输入长度
  282.             if (inputs.Count != NumInputs)
  283.             {
  284.                 return outputs;
  285.             }

  286.             //对于每一层执行
  287.             for (int i = 0; i < NumHiddenLayers + 1; i++)
  288.             {
  289.                 if (i > 0)
  290.                 {
  291.                     inputs = new List<double>(outputs);
  292.                 }
  293.                 outputs.Clear();

  294.                 cWeight = 0;
  295. =end
  296.   def update(inputs1)
  297.     inputs=inputs1.clone
  298.     outputs=[]
  299.     cWeight=0
  300.     if inputs.size!=@numInputs
  301.       return outputs
  302.     end
  303.     for i in 0...@numHiddenLayers+1
  304.       if (i>0)
  305.         inputs = outputs.clone
  306.       end
  307.       outputs.clear
  308.       cWeight=0
  309.       
  310. =begin
  311.                 //对于每个神经元执行
  312.                 for (int n = 0; n < Layers[i].NumNeurons; n++)
  313.                 {
  314.                     double netinput = 0;

  315.                     int num = Layers[i].Neurons[n].NumInputs;

  316.                     //对于每个权重执行
  317.                     for (int k = 0; k < num - 1; k++)
  318.                     {
  319.                         netinput += Layers[i].Neurons[n].Weights[k] * inputs[cWeight++];
  320.                     }

  321.                     netinput += Layers[i].Neurons[n].Weights[num - 1] * Useful.BIAS;

  322.                     Layers[i].Neurons[n].Activation = Sigmoid(netinput, Useful.ACTIVATION_RESPONSE);

  323.                     outputs.Add(Layers[i].Neurons[n].Activation);

  324.                     cWeight = 0;
  325.                 }
  326.             }
  327.             return outputs;
  328.         }
  329. =end
  330.       for n in 0...@layers[i].numNeurons
  331.         netinput=0.000000000
  332.         num=@layers[i].neurons[n].numInputs
  333.         for k in 0...num-1
  334.           netinput+=@layers[i].neurons[n].weights[k] * inputs[cWeight]
  335.           cWeight+=1
  336.         end
  337.         netinput += @layers[i].neurons[n].weights[num - 1] * Useful::BIAS
  338.         @layers[i].neurons[n].activation = sigmoid(netinput, Useful::ACTIVATION_RESPONSE)
  339.         outputs.push(layers[i].neurons[n].activation)
  340.         cWeight=0
  341.       end
  342.     end
  343.     return outputs

  344.   end
  345. =begin
  346.             if ((SetIn.Count != SetOut.Count) || (SetIn[0].Count != NumInputs) || (SetOut[0].Count != NumOutputs))
  347.             {
  348.                 throw new Exception("训练集输入输出不符!");
  349.             }

  350.             InitializeNetwork();

  351.             //训练直至错误小于阈值
  352.             while (ErrorSum > Useful.ERROR_THRESHOLD)
  353.             {
  354.                 //迭代训练
  355.                 if (!NetworkTrainingEpoch(SetIn, SetOut))
  356.                 {
  357.                     return false;
  358.                 }

  359.                 NumEpochs++;

  360.                 //窗体刷新
  361.                 SendMessage(NumEpochs, ErrorSum);
  362.             }

  363.             Trained = true;
  364.             return true;

  365. =end
  366.   def train(data)
  367.     @v=Viewport.new(0,0,$原宽度,$原高度)
  368.     @v.z=99999999
  369.     @ss=Sprite.new
  370.     @ss.z=99999999
  371.     @ss.bitmap=Bitmap.new($原宽度,16)
  372.     @ss.bitmap.fill_rect(0,0,$原宽度,16,Color.new(255,255,255))
  373.     setIn=data.setIn.clone
  374.     setOut=data.setOut.clone
  375.     if ((setIn.size != setOut.size) or (setIn[0].size != @numInputs) or (setOut[0].size != @numOutputs))
  376.       print "训练集输入输出不符!"
  377.       exit(250)
  378.     end
  379.     initializeNetwork
  380.     t=0
  381.     while (@errorSum>Useful::ERROR_THRESHOLD)
  382.       if (!networkTrainingEpoch(setIn, setOut))
  383.         p "Bad Runnning"
  384.         return false
  385.       end
  386.       @numEpochs+=1
  387.       val=Useful::ERROR_THRESHOLD / @errorSum * $原宽度
  388.       @ss.bitmap.fill_rect(0,0,[[val,$原宽度].min,0].max.to_i,32,Color.new(0,0,255))
  389.       Graphics.update if (t % 100)==0
  390.       t+=1
  391.     end
  392.     @v.dispose
  393.     @ss.bitmap.dispose
  394.     @ss.dispose
  395.     @v=nil
  396.     @ss=nil
  397.     Graphics.update
  398.     Graphics.update
  399.   end
  400. end

  401. class GestureData
  402.   
  403.   attr_accessor:names
  404.   attr_accessor:patterns
  405.   attr_accessor:patternNumber
  406.   attr_accessor:patternSize
  407.   attr_accessor:setIn
  408.   attr_accessor:setOut
  409.   def init
  410.    
  411. =begin
  412.             for (int j = 0; j < PatternNumber; j++)
  413.             {
  414.                 List<double> temp = new List<double>();
  415.                 for (int v = 0; v < PatternSize * 2; v++)
  416.                 {
  417.                     temp.Add(Useful.InitPatterns[j][v]);
  418.                 }
  419.                 Patterns.Add(temp);
  420.                 Names.Add(Useful.InitNames[j]);
  421.             }
  422.             
  423. =end
  424.     for j in 0...@patternNumber
  425.       temp=[]
  426.       for v in 0...@patternSize*2
  427.         temp.push(Useful::InitPatterns[j][v])
  428.       end
  429.       @patterns.push(temp)
  430.       @names.push(Useful::InitNames[j])
  431.     end
  432.    
  433.   end
  434. =begin
  435.         public GestureData(int _PatternNumber, int _PatternSize)
  436.         {
  437.             Names = new List<string>();
  438.             Patterns = new List<List<double>>();
  439.             SetIn = new List<List<double>>();
  440.             SetOut = new List<List<double>>();
  441.             PatternNumber = _PatternNumber;
  442.             PatternSize = _PatternSize;

  443.             Init();
  444.             CreateTrainingSet();
  445.         }

  446. =end
  447.   def initialize(patternNumber, patternSize)
  448.     @names=[]
  449.     @patterns=[]
  450.     @setIn=[]
  451.     @setOut=[]
  452.     @patternNumber=patternNumber
  453.     @patternSize=patternSize
  454.     init
  455.     createTrainingSet
  456.   end
  457. =begin
  458.           public string PatternName(int index)
  459.         {
  460.             if (Names[index] != null)
  461.             {
  462.                 return Names[index];
  463.             }
  464.             else
  465.             {
  466.                 return "";
  467.             }
  468.         }
  469. =end
  470.   def patternName(index)
  471.     if @names[index]!=nil
  472.       return @names[index]
  473.     else
  474.       return ""
  475.     end
  476.   end
  477. =begin

  478.         public bool AddPattern(List<double> _Pattern, string _Name)
  479.         {
  480.             //检查手势向量长度
  481.             if (_Pattern.Count != PatternSize * 2)
  482.             {
  483.                 throw new Exception("手势向量长度错误!");
  484.             }

  485.             Names.Add(_Name);
  486.             Patterns.Add(new List<double>(_Pattern));
  487.             PatternNumber++;

  488.             CreateTrainingSet();
  489.             return true;
  490.         }
  491.         
  492. =end
  493.   def addPattern(pattern, name)
  494.     if pattern.size!=@patternSize*2
  495.       print "手势向量长度错误!"
  496.       exit
  497.     end
  498.     @names.push(name)
  499.     @pattern.push(pattern.clone)
  500.     @patternNumber+=1
  501.     createTrainingSet
  502.     return true
  503.   end
  504. =begin
  505.         public void CreateTrainingSet()
  506.         {
  507.             //清空训练集
  508.             SetIn.Clear();
  509.             SetOut.Clear();

  510.             //对每个手势操作
  511.             for (int j = 0; j < PatternNumber; j++)
  512.             {
  513.                 SetIn.Add(Patterns[j]);

  514.                 //相关的输出为1,不相关的输出为0
  515.                 List<double> outputs = new List<double>();
  516.                 for (int i = 0; i < PatternNumber; i++)
  517.                 {
  518.                     outputs.Add(0);
  519.                 }
  520.                 outputs[j] = 1;

  521.                 SetOut.Add(outputs);
  522.             }
  523.         }
  524. =end
  525.   def createTrainingSet
  526.     setIn.clear
  527.     setOut.clear
  528.     for j in 0...@patternNumber
  529.       setIn.push(@patterns[j])
  530.       outputs=[]
  531.       for i in 0...@patternNumber
  532.         outputs.push(0)
  533.       end
  534.       outputs[j]=1
  535.       setOut.push(outputs)
  536.     end
  537.   end
  538. end
  539. =begin
  540.         private void RenewNetwork()
  541.         {
  542.             Useful.LEARNING_RATE = (double)(txtLearning.Value);
  543.             Useful.ERROR_THRESHOLD = (double)(txtThreshold.Value);
  544.             Useful.NUM_HIDDEN_NEURONS = (int)(txtHidden.Value);
  545.             Useful.WITH_MOMENTUM = chkMomentum.Checked;
  546.             Useful.MOMENTUM = (double)(txtMomentum.Value);
  547.             Useful.WITH_NOISE = chkNoise.Checked;
  548.             Useful.MAX_NOISE_TO_ADD = (double)(txtNoise.Value);

  549.             net = new NeuralNet(Useful.NUM_VECTORS * 2, NumValidPatterns, Useful.NUM_HIDDEN_NEURONS, Useful.LEARNING_RATE);
  550.             net.SendMessage += new NeuralNet.DelegateOfSendMessage(ShowMessage);

  551.             txtState.Text = "Training";
  552.             TrainNetwork();
  553.             txtState.Text = "Ready";
  554.         }
  555.         private bool TrainNetwork()
  556.         {
  557.             Mode = RUN_MODE.TRAINING;
  558.             if (!(net.Train(data)))
  559.             {
  560.                 return false;
  561.             }

  562.             Mode = RUN_MODE.ACTIVE;
  563.             return true;
  564.         }
  565. =end
  566. module NetworkFunctions
  567. =begin


  568.         //手势相关数据对象
  569.         private GestureData data;

  570.         //神经网络对象
  571.         private NeuralNet net;

  572.         //手势数目
  573.         private int NumValidPatterns;

  574.         //需要记录的鼠标点数
  575.         private int NumSmoothPoints;

  576.         //用户鼠标输入的手势向量
  577.         private List<Point> RawPath;

  578.         //光滑化之后的手势向量
  579.         private List<Point> SmoothPath;

  580.         //待匹配的向量
  581.         private List<double> Vectors;

  582.         //网络最大的输出(最像的匹配)
  583.         private double HighestOutput;

  584.         //网络最大的输出对应的手势
  585.         private int BestMatch;

  586.         //匹配的手势
  587.         private int Match;

  588.         //程序的运行状态
  589.         private RUN_MODE Mode;
  590. =end
  591.   attr_accessor:net
  592.   attr_accessor:data
  593.   attr_accessor:mode
  594.   attr_accessor:numValidPatterns
  595.   attr_accessor:numSmoothPoints
  596.   attr_accessor:rawPath
  597.   attr_accessor:smoothPath
  598.   attr_accessor:vectors
  599.   attr_accessor:highestOutput
  600.   attr_accessor:bestMatch
  601.   attr_accessor:match
  602.   def self.net
  603.     return @net
  604.   end
  605.   def self.data
  606.     return @data
  607.   end
  608.   def self.numValidPatterns
  609.     return @numValidPatterns
  610.   end
  611.   def self.numSmoothPoints
  612.     return @numSmoothPoints
  613.   end
  614.   def self.rawPath
  615.     return @rawPath
  616.   end
  617.   def self.smoothPath
  618.     return @smoothPath
  619.   end
  620.   def self.vectors
  621.     return @vectors
  622.   end
  623.   def self.highestOutput
  624.     return @highestOutput
  625.   end
  626.   def self.bestMatch
  627.     return @bestMatch
  628.   end
  629.   def self.match
  630.     return @match
  631.   end
  632.   
  633.   def self.net=(v)
  634.     return @net=v  
  635.   end
  636.   def self.data=(v)
  637.     return @data=v  
  638.   end         
  639.   def self.numValidPatterns=(v)
  640.     return @numValidPatterns=v  
  641.   end                     
  642.   def self.numSmoothPoints=(v)
  643.     return @numSmoothPoints=v  
  644.   end                    
  645.   def self.rawPath=(v)
  646.     return @rawPath=v  
  647.   end            
  648.   def self.smoothPath=(v)
  649.     return @smoothPath=v  
  650.   end               
  651.   def self.vectors=(v)
  652.     return @vectors=v  
  653.   end            
  654.   def self.highestOutput=(v)
  655.     return @highestOutput=v  
  656.   end                  
  657.   def self.bestMatch=(v)
  658.     return @bestMatch=v  
  659.   end              
  660.   def self.match=(v)
  661.     return @match=v  
  662.   end           
  663.   
  664.   def self.renewNetwork
  665.     @net=NeuralNet.new(Useful::NUM_VECTORS * 2, @numValidPatterns, Useful::NUM_HIDDEN_NEURONS, Useful::LEARNING_RATE)
  666.     trainNetwork
  667.     return true
  668.   end
  669.   def self.trainNetwork
  670.     @mode=Useful::RUN_MODE::TRAINING
  671.     if !(@net.train(@data))
  672.       return false
  673.     end
  674.     @mode=Useful::RUN_MODE::ACTIVE
  675.   end
  676.   def self.mode
  677.     return @mode
  678.   end
  679.   def self.mode=(v)
  680.     return @mode=v
  681.   end
  682.   def self.initData
  683.     @mode=Useful::RUN_MODE::UNREADY
  684.     @numValidPatterns=Useful::NUM_PATTERNS
  685.     @numSmoothPoints=Useful::NUM_VECTORS + 1
  686.     @highestOutput=0.00000000
  687.     @bastMatch=-1
  688.     @match=-1
  689.     @rawPath=[]
  690.     @smoothPath=[]
  691.     @vectors=[]
  692.     @data=GestureData.new(@numValidPatterns, Useful::NUM_VECTORS)
  693.     @net=NeuralNet.new(Useful::NUM_VECTORS * 2, @numValidPatterns, Useful::NUM_HIDDEN_NEURONS, Useful::LEARNING_RATE)
  694.     trainNetwork
  695.   end
  696.   def self.save
  697.     save_data(@net,"BPNet.rvdata")
  698.     save_data(@data,"BPNetD.rvdata")
  699.   end
  700.   def self.load
  701.     @net = load_data("BPNet.rvdata")
  702.     @data= load_data("BPNetD.rvdata")
  703.     @mode=Useful::RUN_MODE::ACTIVE
  704.     @numValidPatterns=Useful::NUM_PATTERNS
  705.     @numSmoothPoints=Useful::NUM_VECTORS + 1
  706.     @highestOutput=0.00000000
  707.     @bastMatch=-1
  708.     @match=-1
  709.     @rawPath=[]
  710.     @smoothPath=[]
  711.     @vectors=[]
  712.   end

  713. end
  714. =begin
  715.         private void InitData()
  716.         {
  717.             Mode = RUN_MODE.UNREADY;
  718.             NumValidPatterns = Useful.NUM_PATTERNS;
  719.             NumSmoothPoints = Useful.NUM_VECTORS + 1;
  720.             HighestOutput = 0.0;
  721.             BestMatch = -1;
  722.             Match = -1;
  723.             RawPath = new List<Point>();
  724.             SmoothPath = new List<Point>();
  725.             Vectors = new List<double>();
  726.             data = new GestureData(NumValidPatterns, Useful.NUM_VECTORS);
  727.             net = new NeuralNet(Useful.NUM_VECTORS * 2, NumValidPatterns, Useful.NUM_HIDDEN_NEURONS, Useful.LEARNING_RATE);
  728.             net.SendMessage += new NeuralNet.DelegateOfSendMessage(ShowMessage);
  729.         }
  730. =end
  731. #NetworkFunctions.initData
  732. NetworkFunctions.load
  733. #NetworkFunctions.load
复制代码
  1. class Bitmap
  2.   #--------------------------------------------------------------------------
  3.   # ● 描绘直线   
  4.   #     x1,y1,x2,y2:  直线两端的坐标
  5.   #     width:    宽度  
  6.   #     color:    颜色
  7.   #--------------------------------------------------------------------------
  8.   def drawline(x1, y1, x2, y2, width, color)
  9.     x1 = x1.to_f
  10.     y1 = y1.to_f
  11.     x2 = x2.to_f
  12.     y2 = y2.to_f
  13.     width = width.to_f
  14.     k = (y2 - y1) / (x2 - x1)
  15.     if k.abs > 1
  16.       drawline_x(x1, y1, x2, y2, width, color)
  17.     else
  18.       drawline_y(x1, y1, x2, y2, width, color)
  19.     end
  20.   end
  21.   def drawline_x(x1, y1, x2, y2, width, color)
  22.     l = ((x1 - x2) ** 2 + (y1 - y2) ** 2) ** 0.5 * width / (y1 - y2)
  23.     length = l.abs * 2
  24.     k = (x2 - x1) / (y2 - y1) #x=ky+b
  25.     b = x1 - k * y1
  26.     if l > 0
  27.       for ty in y2.to_i..y1.to_i
  28.         tx = ty * k + b
  29.         fill_rect(tx - l, ty, length, 1, color)
  30.       end
  31.     else
  32.       for ty in y1.to_i..y2.to_i
  33.         tx = ty * k + b
  34.         fill_rect(tx + l, ty, length, 1, color)
  35.       end
  36.     end
  37.   end
  38.   def drawline_y(x1, y1, x2, y2, width, color)
  39.     l = ((x1 - x2) ** 2 + (y1 - y2) ** 2) ** 0.5 * width / (x1 - x2)
  40.     height = l.abs * 2
  41.     k = (y2 - y1) / (x2 - x1) #y=kx+b
  42.     b = y1 - k * x1
  43.     if l > 0
  44.       for tx in x2.to_i..x1.to_i
  45.         ty = tx * k + b
  46.         fill_rect(tx, ty - l, 1, height, color)
  47.       end
  48.     else
  49.       for tx in x1.to_i..x2.to_i
  50.         ty = tx * k + b
  51.         fill_rect(tx, ty + l, 1, height, color)
  52.       end
  53.     end
  54.   end
  55. end
  56. class DrawBox
  57.   include NetworkFunctions
  58.   def initialize(x,y,width,height)
  59.     @draw_sprite=Sprite.new
  60.     @draw_sprite.x=x
  61.     @draw_sprite.y=y
  62.     @draw_sprite.z=999999999
  63.     @draw_sprite.bitmap=Bitmap.new(width,height)
  64.     NetworkFunctions.rawPath=[]
  65.     @draw_area=Rect.new(x,y,width,height)
  66.     @in_drawing=false

  67.   end
  68.   def update
  69.     return if not Mouse.rect?(@draw_area)
  70.     if Mouse.up?(1)
  71.   #    mouse_up
  72.       @in_drawing=false
  73.       @draw_sprite.bitmap.clear
  74.       startMatch
  75.       
  76.     end
  77.     if Mouse.click?(1)
  78.   #    mouse_down
  79.       @draw_sprite.bitmap.clear
  80.       @in_drawing=true
  81.       @ox,@oy=Mouse.pos
  82.       NetworkFunctions.rawPath.clear
  83.       NetworkFunctions.smoothPath.clear
  84.       NetworkFunctions.vectors.clear
  85.       NetworkFunctions.rawPath.push(Mouse.pos)
  86.     end
  87.     if Mouse.pos!=[@ox,@oy] and @in_drawing
  88.       @draw_sprite.bitmap.drawline(@ox,@oy, Mouse.pos[0],Mouse.pos[1],3,Color.new(255,255,255,88))
  89.       NetworkFunctions.rawPath.push(Mouse.pos)
  90.       @ox,@oy=Mouse.pos
  91.     end
  92.   end
  93.   def startMatch
  94.     if smooth
  95.       createVectors
  96.       if (NetworkFunctions.mode == Useful::RUN_MODE::ACTIVE)
  97.         if not testForMatch
  98.          
  99.           return false
  100.         else
  101.           return showResult
  102.         end
  103.       else
  104.         #p "bye"
  105.       end
  106.     end
  107.   end
  108.   def showResult
  109.     p NetworkFunctions.data.patternName(NetworkFunctions.bestMatch)
  110.   end
  111. =begin
  112. private bool TestForMatch()
  113.         {
  114.             List<double> outputs = net.Update(Vectors);
  115.             if (outputs.Count == 0)
  116.             {
  117.                 return false;
  118.             }

  119.             HighestOutput = 0;
  120.             BestMatch = 0;
  121.             Match = -1;

  122.             for (int i = 0; i < outputs.Count; i++)
  123.             {
  124.                 if (outputs[i] > HighestOutput)
  125.                 {
  126.                     //记录最像的匹配
  127.                     HighestOutput = outputs[i];
  128.                     BestMatch = i;

  129.                     //确定是这个手势
  130.                     if (HighestOutput > Useful.MATCH_TOLERANCE)
  131.                     {
  132.                         Match = BestMatch;
  133.                     }
  134.                 }
  135.             }
  136.             return true;
  137.         }
  138. =end
  139.   def testForMatch
  140.     outputs=NetworkFunctions.net.update(NetworkFunctions.vectors)
  141.     if outputs.size==0
  142.       return false
  143.     end
  144.     NetworkFunctions.highestOutput=0
  145.     NetworkFunctions.bestMatch=0
  146.     NetworkFunctions.match=-1
  147.     for i in 0...outputs.size
  148.       if outputs[i]>NetworkFunctions.highestOutput
  149.         NetworkFunctions.highestOutput=outputs[i]
  150.         NetworkFunctions.bestMatch=i
  151.         if (NetworkFunctions.highestOutput>Useful::MATCH_TOLERANCE)
  152.           NetworkFunctions.match=NetworkFunctions.bestMatch
  153.         end
  154.       end
  155.     end
  156.     return true
  157.   end
  158. =begin
  159.         private bool Smooth()
  160.         {
  161.             //确保包含计算所需的足够的点
  162.             if (RawPath.Count < NumSmoothPoints)
  163.             {
  164.                 return false;
  165.             }

  166.             SmoothPath = new List<Point>(RawPath);

  167.             //对所有的最小跨度点对取中点,删除原来的点,循环执行
  168.             while (SmoothPath.Count > NumSmoothPoints)
  169.             {
  170.                 double ShortestSoFar = double.MaxValue;
  171.                 int PointMarker = 0;

  172.                 //计算最小跨度
  173.                 for (int SpanFront = 2; SpanFront < SmoothPath.Count - 1; SpanFront++)
  174.                 {
  175.                     //计算点对距离
  176.                     double length = Math.Sqrt((double)
  177.                         ((SmoothPath[SpanFront - 1].X - SmoothPath[SpanFront].X) *
  178.                           (SmoothPath[SpanFront - 1].X - SmoothPath[SpanFront].X) +
  179.                           (SmoothPath[SpanFront - 1].Y - SmoothPath[SpanFront].Y) *
  180.                           (SmoothPath[SpanFront - 1].Y - SmoothPath[SpanFront].Y)));

  181.                     if (length < ShortestSoFar)
  182.                     {
  183.                         ShortestSoFar = length;
  184.                         PointMarker = SpanFront;
  185.                     }
  186.                 }

  187.                 //插入中点,删除原来的点
  188.                 Point newPoint = new Point();
  189.                 newPoint.X = (SmoothPath[PointMarker - 1].X + SmoothPath[PointMarker].X) / 2;
  190.                 newPoint.Y = (SmoothPath[PointMarker - 1].Y + SmoothPath[PointMarker].Y) / 2;
  191.                 SmoothPath[PointMarker - 1] = newPoint;
  192.                 SmoothPath.RemoveAt(PointMarker);
  193.             }

  194.             return true;
  195.         }
  196. =end
  197.   def smooth
  198.     if NetworkFunctions.rawPath.size<NetworkFunctions.numSmoothPoints
  199.       return false
  200.     end
  201.     NetworkFunctions.smoothPath=NetworkFunctions.rawPath.clone
  202.     while (NetworkFunctions.smoothPath.size>NetworkFunctions.numSmoothPoints)
  203.       shortestSoFar=1.79769313486232E+308
  204.       pointMarker=0
  205.       for spanFront in 2...NetworkFunctions.smoothPath.size-1
  206.         length=Math.sqrt(((NetworkFunctions.smoothPath[spanFront - 1][0] - NetworkFunctions.smoothPath[spanFront][0]) *
  207.                           (NetworkFunctions.smoothPath[spanFront - 1][0] - NetworkFunctions.smoothPath[spanFront][0]) +
  208.                           (NetworkFunctions.smoothPath[spanFront - 1][1] - NetworkFunctions.smoothPath[spanFront][1]) *
  209.                           (NetworkFunctions.smoothPath[spanFront - 1][1] - NetworkFunctions.smoothPath[spanFront][1])))
  210.         if length<shortestSoFar
  211.           shortestSoFar=length
  212.           pointMarker=spanFront
  213.         end
  214.       end
  215.       newPoint=[]
  216.       newPoint[0]=(NetworkFunctions.smoothPath[pointMarker - 1][0] + NetworkFunctions.smoothPath[pointMarker][0]) / 2.0000000000
  217.       newPoint[1]=(NetworkFunctions.smoothPath[pointMarker - 1][1] + NetworkFunctions.smoothPath[pointMarker][1]) / 2.0000000000
  218.       NetworkFunctions.smoothPath[pointMarker-1]=newPoint
  219.       NetworkFunctions.smoothPath.delete_at(pointMarker)
  220.     end
  221.     return true
  222.   end
  223. =begin
  224.             for (int p = 1; p < SmoothPath.Count; ++p)
  225.             {
  226.                 double x = (double)(SmoothPath[p].X - SmoothPath[p - 1].X);
  227.                 double y = (double)(SmoothPath[p].Y - SmoothPath[p - 1].Y);
  228.                 double len = Math.Sqrt((double)(x * x + y * y));
  229.                 Vectors.Add(x / len);
  230.                 Vectors.Add(y / len);
  231.             }
  232. =end
  233.   def createVectors
  234.     for p in 1...NetworkFunctions.smoothPath.size
  235.       x=(NetworkFunctions.smoothPath[p][0] - NetworkFunctions.smoothPath[p - 1][0]).to_f
  236.       y=(NetworkFunctions.smoothPath[p][1] - NetworkFunctions.smoothPath[p - 1][1]).to_f
  237.       len=Math.sqrt(x*x+y*y).to_f
  238.       NetworkFunctions.vectors.push(x/len)
  239.       NetworkFunctions.vectors.push(y/len)
  240.     end
  241.   end
  242. end

  243.       
复制代码
手势文件放到根目录(可调)
Net.rar (4.52 KB, 下载次数: 248)
作者: 光的圆周率    时间: 2010-12-31 22:02
强大啊                        
作者: 1049079876    时间: 2011-1-3 06:47
提示: 作者被禁止或删除 内容自动屏蔽
作者: 沉影不器    时间: 2011-1-4 21:51
提示: 作者被禁止或删除 内容自动屏蔽
作者: yangff    时间: 2011-1-11 21:21
沉影不器 发表于 2011-1-4 21:51
这篇C++正好看过...
当时的感想是:如果只做到像很多IE浏览器那样鼠标手势的话,倒是容易得多,就不需要神经了 ...

识别率和效果问题。
只是要上下左右就不用神经了必须的……




欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1