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; }
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; }
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; }
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; }
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; }
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; }
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); }
public TraceGroup PreProcess(TraceGroup inTraceGroup) { var norm = NormalizeSize(inTraceGroup); var sampling = ResampleTraceGroup(norm); return sampling; }
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; }
//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; }
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; }