示例#1
0
    public IList<RecoResult> Recognize(TraceGroup testTraceGroup)
    {
      var testPreProcTraceGroup = _preProc.PreProcess(testTraceGroup);
      var testFeature = _featureExtractor.ExtractFeature(testPreProcTraceGroup);

      var distanceList = new List<KeyValuePair<int, float>>();
      foreach(var train in _trainList)
      {
        var d = _featureExtractor.ComputeEuclideanDistance(train.ShapeFeatures, testFeature);
        distanceList.Add(new KeyValuePair<int, float>(train.ClassId, d));
      }

      distanceList.Sort((f1, f2) => f1.Value.CompareTo(f2.Value));

      var tempRecoResult = new List<RecoResult>();
      var sumSimiliarity = 0f;
      for (var i = 0; i < distanceList.Count; i++ )
      {
        var foundDuplicated = tempRecoResult.Find(c => c.ShapeId == distanceList[i].Key);
        if(foundDuplicated==null)
        {
          sumSimiliarity += distanceList[i].Value;
          tempRecoResult.Add(new RecoResult{ShapeId = distanceList[i].Key, ConfidenceLevel = distanceList[i].Value});

          if (tempRecoResult.Count == _numOfChoice) break;
        }
      }

      for (var i = 0; i < _numOfChoice; i++ )
      {
        tempRecoResult[i].ConfidenceLevel = (sumSimiliarity - tempRecoResult[i].ConfidenceLevel)/sumSimiliarity;
      }

      return tempRecoResult;
    }
示例#2
0
    public TraceGroup ReadFromInkFile(string path)
    {
      var outTraceGroup = new TraceGroup();
      var input = new FileStream(path, FileMode.Open, FileAccess.Read);
      var fileReader = new StreamReader(input);
      var strLine = "";
      char[] splitter = { ' ' };

      var captureDevice = new CaptureDevice { SamplingRate = 100, Latency = 0f };
      while(!fileReader.EndOfStream)
      {
        strLine = fileReader.ReadLine();
        if (strLine == null) continue;
        
        //Read header info
        if (strLine.Contains(".X_POINTS_PER_INCH"))
        {
          var strToken = strLine.Split(splitter, StringSplitOptions.None);
          captureDevice.XDpi = Convert.ToInt32(strToken[1]);
        }

        if (strLine.Contains(".Y_POINTS_PER_INCH"))
        {
          var strToken = strLine.Split(splitter, StringSplitOptions.None);
          captureDevice.YDpi = Convert.ToInt32(strToken[1]);
        }

        if (strLine.Contains(".POINTS_PER_SECOND"))
        {
          var strToken = strLine.Split(splitter, StringSplitOptions.None);
          //use later
        }

        if (!strLine.Trim().Equals(".PEN_DOWN")) continue;
        
        var strCoord = "";

        var trace = new Trace();
        while(!(strCoord = fileReader.ReadLine()?? "").Trim().Equals(".PEN_UP") && !fileReader.EndOfStream)
        {
          
          var strToken = strCoord.Split(splitter, StringSplitOptions.None);

          var x = Convert.ToInt32(strToken[0]);
          var y = Convert.ToInt32(strToken[1]);

          trace.Points.Add(new PenPoint{X=x, Y=y});
        }
        outTraceGroup.Traces.Add(trace);
      }

      fileReader.Close();
      input.Close();

      outTraceGroup.CaptureDevice = captureDevice;

      return outTraceGroup;
    }
示例#3
0
    public static TraceGroup ToTraceGroup(this Ink ink)
    {
      var traceGroup = new TraceGroup();
      foreach(var stroke in ink.Strokes)
      {
        var trace = new Trace();
        foreach(var point in stroke.GetPoints())
        {
          var penPoint = new PenPoint {X = point.X, Y = point.Y};
          trace.Points.Add(penPoint);
        }
        traceGroup.Traces.Add(trace);
      }

      return traceGroup;
    }
示例#4
0
    public TraceGroup SmoothenTraceGroup(TraceGroup traceGroup)
    {
      var filterLength = 5;
      var newTraceGroup = new TraceGroup();
      var sumX = 0f;
      var sumY = 0f;
      var actualIndex = 0;
      foreach (var trace in traceGroup.Traces)
      {
        var newTrace = new Trace();
        var numPoints = trace.Points.Count;
        var channelX = trace.ChannelX;
        var channelY = trace.ChannelY;
        for(var pointIndex=0; pointIndex<numPoints; pointIndex++)
        {
          sumX = sumY = 0f;

          for(var loopIdex=0;loopIdex<filterLength;loopIdex++)
          {
            actualIndex = (pointIndex - loopIdex);
            if(actualIndex<0)
            {
              actualIndex = 0;
            }else if(actualIndex>=numPoints)
            {
              actualIndex = numPoints - 1;
            }

            //accumulate sum
            sumX += channelX[actualIndex];
            sumY += channelY[actualIndex];
          }

          sumX /= filterLength;
          sumY /= filterLength;

          
          newTrace.Points.Add(new PenPoint{X=sumX, Y=sumY});
        }
        newTraceGroup.Traces.Add(newTrace);
      }

      return newTraceGroup;
    }
示例#5
0
        public void AffineTransform(float xScaleFactor, float yScaleFactor, float translateToX, float translateToY, TraceGroupCornerEnum referenceCorner)
        {
            var   outTraceGroup = new TraceGroup();
            float xReference = 0f, yReference = 0f;
            float x, y;

            if (xScaleFactor <= 0) //invalid
            {
            }

            if (yScaleFactor <= 0)
            {
                //invalid
            }

            var box = GetBoundingBox();

            switch (referenceCorner)
            {
            case TraceGroupCornerEnum.XMin_YMin:
                xReference = box.XMin;
                yReference = box.YMin;
                break;

            case TraceGroupCornerEnum.XMin_YMax:
                xReference = box.XMin;
                yReference = box.YMax;
                break;

            case TraceGroupCornerEnum.XMax_YMin:
                xReference = box.XMax;
                yReference = box.YMin;
                break;

            case TraceGroupCornerEnum.XMax_YMax:
                xReference = box.XMax;
                yReference = box.YMax;
                break;

            default:
                break;
            }

            foreach (var trace in Traces)
            {
                var xVec = trace.ChannelX;
                var yVec = trace.ChannelY;

                var scaleTrace = new Trace();
                foreach (var point in trace.Points)
                {
                    //the additive term is to translate back the scaled tracegroup
                    //so that the corner asked for is preserved at the destination
                    //(translateToX,translateToY)
                    x = (point.X * xScaleFactor) / XScaleFactor + (translateToX - (xReference * (xScaleFactor / XScaleFactor)));

                    //the additive term is to translate back the scaled tracegroup
                    //so that the corner asked for is preserved at the destination
                    //(translateToX,translateToY)
                    y = (point.Y * yScaleFactor) / YScaleFactor + (translateToY - (yReference * (yScaleFactor / YScaleFactor)));

                    scaleTrace.Points.Add(new PenPoint {
                        X = x, Y = y
                    });
                }
                outTraceGroup.Traces.Add(scaleTrace);
            }

            Traces = outTraceGroup.Traces;

            XScaleFactor = xScaleFactor;
            YScaleFactor = yScaleFactor;

            //return outTraceGroup;
        }
示例#6
0
    public void AffineTransform(float xScaleFactor, float yScaleFactor, float translateToX, float translateToY, TraceGroupCornerEnum referenceCorner)
    {
      var outTraceGroup = new TraceGroup();
      float xReference = 0f, yReference = 0f;
      float x, y;

      if (xScaleFactor <= 0) //invalid
      {
      }

      if (yScaleFactor <= 0)
      {
        //invalid
      }

      var box = GetBoundingBox();

      switch (referenceCorner)
      {
        case TraceGroupCornerEnum.XMin_YMin:
          xReference = box.XMin;
          yReference = box.YMin;
          break;
        case TraceGroupCornerEnum.XMin_YMax:
          xReference = box.XMin;
          yReference = box.YMax;
          break;
        case TraceGroupCornerEnum.XMax_YMin:
          xReference = box.XMax;
          yReference = box.YMin;
          break;
        case TraceGroupCornerEnum.XMax_YMax:
          xReference = box.XMax;
          yReference = box.YMax;
          break;
        default:
          break;
      }

      foreach(var trace in Traces)
      {
        var xVec = trace.ChannelX;
        var yVec = trace.ChannelY;

        var scaleTrace = new Trace();
        foreach (var point in trace.Points)
        {
          //the additive term is to translate back the scaled tracegroup
          //so that the corner asked for is preserved at the destination
          //(translateToX,translateToY)
          x = (point.X*xScaleFactor)/XScaleFactor + (translateToX - (xReference*(xScaleFactor/XScaleFactor)));

          //the additive term is to translate back the scaled tracegroup
          //so that the corner asked for is preserved at the destination
          //(translateToX,translateToY)
          y = (point.Y*yScaleFactor)/YScaleFactor + (translateToY - (yReference*(yScaleFactor/YScaleFactor)));

          scaleTrace.Points.Add(new PenPoint{X=x, Y=y});
        }
        outTraceGroup.Traces.Add(scaleTrace);
      }

      Traces = outTraceGroup.Traces;

      XScaleFactor = xScaleFactor;
      YScaleFactor = yScaleFactor;

      //return outTraceGroup;
    }
示例#7
0
        public TraceGroup ReadFromInkFile(string path)
        {
            var outTraceGroup = new TraceGroup();
            var input         = new FileStream(path, FileMode.Open, FileAccess.Read);
            var fileReader    = new StreamReader(input);
            var strLine       = "";

            char[] splitter = { ' ' };

            var captureDevice = new CaptureDevice {
                SamplingRate = 100, Latency = 0f
            };

            while (!fileReader.EndOfStream)
            {
                strLine = fileReader.ReadLine();
                if (strLine == null)
                {
                    continue;
                }

                //Read header info
                if (strLine.Contains(".X_POINTS_PER_INCH"))
                {
                    var strToken = strLine.Split(splitter, StringSplitOptions.None);
                    captureDevice.XDpi = Convert.ToInt32(strToken[1]);
                }

                if (strLine.Contains(".Y_POINTS_PER_INCH"))
                {
                    var strToken = strLine.Split(splitter, StringSplitOptions.None);
                    captureDevice.YDpi = Convert.ToInt32(strToken[1]);
                }

                if (strLine.Contains(".POINTS_PER_SECOND"))
                {
                    var strToken = strLine.Split(splitter, StringSplitOptions.None);
                    //use later
                }

                if (!strLine.Trim().Equals(".PEN_DOWN"))
                {
                    continue;
                }

                var strCoord = "";

                var trace = new Trace();
                while (!(strCoord = fileReader.ReadLine() ?? "").Trim().Equals(".PEN_UP") && !fileReader.EndOfStream)
                {
                    var strToken = strCoord.Split(splitter, StringSplitOptions.None);

                    var x = Convert.ToInt32(strToken[0]);
                    var y = Convert.ToInt32(strToken[1]);

                    trace.Points.Add(new PenPoint {
                        X = x, Y = y
                    });
                }
                outTraceGroup.Traces.Add(trace);
            }

            fileReader.Close();
            input.Close();

            outTraceGroup.CaptureDevice = captureDevice;

            return(outTraceGroup);
        }
示例#8
0
    public TraceGroup PreProcess(TraceGroup inTraceGroup)
    {
      var norm = NormalizeSize(inTraceGroup);
      var sampling = ResampleTraceGroup(norm);

      return sampling;
    }
示例#9
0
    public TraceGroup NormalizeSize(TraceGroup inTraceGroup)
    {
      var outTraceGroup = new TraceGroup();
      var xScale = 0f;
      var yScale = 0f;
      var aspectRatio = 0f;
      float scaleX, scaleY, offsetX, offsetY;

      var box = inTraceGroup.GetBoundingBox();

      outTraceGroup = inTraceGroup;

      xScale = Math.Abs(box.XMax - box.XMin)/outTraceGroup.XScaleFactor;
      yScale = Math.Abs(box.YMax - box.YMin)/outTraceGroup.YScaleFactor;

      if(_preserveAspectRatio)
      {
        if(yScale>xScale)
        {
          aspectRatio = (xScale > _eps) ? (yScale/xScale): _aspectRatioThreshold+_eps;
        }else
        {
          aspectRatio = (yScale > _eps) ? (xScale/yScale) : _aspectRatioThreshold + _eps;
        }

        if(aspectRatio>_aspectRatioThreshold)
        {
          if (yScale > xScale) xScale = yScale;
          else yScale = xScale;
        }
      }

      offsetY = 0.0f;
      if (_preserveRelativeYPosition) offsetY = (box.YMin + box.YMax)/2.0f;

      if(xScale <= (_dotThreshold*_captureDevice.XDpi) && yScale<=(_dotThreshold*_captureDevice.YDpi))
      {
        offsetX = _preprocNormalizeSize/2;
        offsetY += _preprocNormalizeSize/2;

        outTraceGroup.Traces.Clear();

        foreach(var trace in inTraceGroup.Traces)
        {
          var normalizedTrace = new Trace();
          foreach(var point in trace.Points)
          {
            normalizedTrace.Points.Add(new PenPoint{X=offsetX, Y=offsetY});
          }
          outTraceGroup.Traces.Add(normalizedTrace);
        }
      }

      //finding the final scale and offset values for the x channel
      if((!_preserveAspectRatio) && (xScale<(_sizeThreshold*_captureDevice.XDpi)))
      {
        scaleX = 1.0f;
        offsetX = (float)(_preprocNormalizeSize/2.0);
      }else
      {
        scaleX = (float)(_preprocNormalizeSize / xScale);
        offsetX = 0.0f;
      }

      // finding the final scale and offset values for the y channel
      if((!_preserveAspectRatio) && (yScale<_sizeThreshold*_captureDevice.YDpi))
      {
        offsetY += _preprocNormalizeSize/2;
        scaleY = 1.0f;
      }else
      {
        scaleY = (float)(_preprocNormalizeSize/yScale);
      }

      outTraceGroup.AffineTransform(scaleX, scaleY, offsetX, offsetY, TraceGroupCornerEnum.XMin_YMin);

      return outTraceGroup;
    }
示例#10
0
    //public TraceGroup ResampleTraceGroup(TraceGroup inTraceGroup)
    //{
    //  var outTraceGroup = new TraceGroup();
    //  foreach(var trace in inTraceGroup.Traces)
    //  {
    //    var outTrace = ResampleTrace(trace, 60);
    //    outTraceGroup.Traces.Add(outTrace);
    //  }
    //  return outTraceGroup;
    //}

    public TraceGroup ResampleTraceGroup(TraceGroup inTraceGroup)
    {
      var total = 0;
      var totalLength = 0f;
      var totalPoints = 0;

      var numOfTraces = inTraceGroup.Traces.Count;

      //Implement length base scheme
      var maxIndex = 0;
      float maxLength = 0f;
      var lengthsVec = new List<float>();

      for(var j=0; j<numOfTraces; j++)
      {
        var trace = inTraceGroup.Traces[j];
        var length = ComputeTraceLength(trace, 0, trace.Points.Count-1);

        lengthsVec.Add(length);
        if (Math.Abs(lengthsVec[j]) < _eps) lengthsVec[j] = _eps;

        totalLength += lengthsVec[j];
        if(lengthsVec[j] > maxLength)
        {
          maxLength = lengthsVec[j];
          maxIndex = j;
        }
      }

      var pointsPerTrace = new List<int>();
      
      for(int i=0; i<numOfTraces; i++)
      {
        pointsPerTrace.Add(0);
        if(i!=maxIndex)
        {
          var tempPoints = _quantizationStep*
                              (int) (Math.Floor(_traceDimension*lengthsVec[i]/(_quantizationStep*totalLength)) + 0.5f);

          pointsPerTrace[i] = tempPoints;
          if (pointsPerTrace[i] <= 0) pointsPerTrace[i] = 1;

          total += pointsPerTrace[i];

        }
      }
      pointsPerTrace[maxIndex] = _traceDimension - total;

      int sum = 0;
      for(int temp = 0; temp<pointsPerTrace.Count; temp++)
      {
        sum += pointsPerTrace[temp];
      }

      var outTraceGroup = new TraceGroup();
      for(int i=0;i<numOfTraces;i++)
      {
        var trace = inTraceGroup.Traces[i];
        var newTrace = ResampleTrace(trace, pointsPerTrace[i]);
        outTraceGroup.Traces.Add(newTrace);
      }
      outTraceGroup.XScaleFactor = inTraceGroup.XScaleFactor;
      outTraceGroup.YScaleFactor = inTraceGroup.YScaleFactor;

      return outTraceGroup;
    }
示例#11
0
    private string ReadTraceGroupInUnipenFormat(TraceGroup traceGroup)
    {
      var str = new StringBuilder();
      foreach (var trace in traceGroup.Traces)
      {
        str.AppendLine(".PEN_DOWN");

        foreach (var point in trace.Points)
        {
          str.AppendLine("X=" + point.X + "   Y=" + point.Y);
        }
        str.AppendLine(".PEN_UP");
        str.AppendLine("----- Total Points = " + trace.Points.Count);
      }

      return str.ToString();
    }
     public IList<PointFloatShapeFeature> ExtractFeature(TraceGroup inTraceGroup)
     {
       var outVector = new List<PointFloatShapeFeature>();
       float x, y, deltaX;
       float sinTheta, cosTheta, sqSum;
       var numPoints = 0;

       foreach(var trace in inTraceGroup.Traces)
       {
         numPoints += trace.ChannelX.Count;
       }

       var xVec = new List<float>(numPoints);
       var yVec = new List<float>(numPoints);
       var penUpVec = new List<bool>();

       foreach(var trace in inTraceGroup.Traces)
       {
         var tempxVec = trace.ChannelX;
         var tempyVec = trace.ChannelY;
         var currentStrokeSize = tempxVec.Count;

         for(var point=0; point<currentStrokeSize;point++)
         {
           xVec.Add(tempxVec[point]);
           yVec.Add(tempyVec[point]);

           if(point == currentStrokeSize-1)
           {
             penUpVec.Add(true);
           }else
           {
             penUpVec.Add(false);
           }
         }
       }

       //Concatenating the strokes
       var theta = new List<float>(numPoints);
       var delta_x = new List<float>(numPoints);
       var delta_y = new List<float>(numPoints);

       for (var i = 0; i < numPoints - 1;i++ )
       {
         delta_x.Add( xVec[i + 1] - xVec[i]);
         delta_y.Add( yVec[i + 1] - yVec[i]);
       }

       //Add the control info here
       sqSum = (float)Math.Sqrt(Math.Pow(xVec[0], 2) + Math.Pow(yVec[0], 2)) + _eps;
       sinTheta = (1 + yVec[0]/sqSum)*_preprocNormalizeSize/2;
       cosTheta = (1 + xVec[0]/sqSum)*_preprocNormalizeSize/2;

       var feature = new PointFloatShapeFeature
                       {X = xVec[0], Y = yVec[0], SinTheta = sinTheta, CosTheta = cosTheta, IsPenUp = penUpVec[0]};

       outVector.Add(feature);

       for (var i = 1; i < numPoints; i++ )
       {
         sqSum = (float)Math.Sqrt(Math.Pow(delta_x[i-1], 2) + Math.Pow(delta_y[i-1], 2)) + _eps;
         sinTheta = (1 + delta_y[i-1] / sqSum) * _preprocNormalizeSize / 2;
         cosTheta = (1 + delta_x[i-1] / sqSum) * _preprocNormalizeSize / 2;

         feature = new PointFloatShapeFeature { X = xVec[i], Y = yVec[i], SinTheta = sinTheta, CosTheta = cosTheta, IsPenUp = penUpVec[i] };
         outVector.Add(feature);
       }

       return outVector;
     }