/// <summary> /// /// </summary> /// <param name="matrix_size"></param> /// <param name="steps"></param> /// <returns></returns> private int[][,] ToMatrix(Size matrix_size, out List <int> steps) { var metrix = new List <int[, ]>(); steps = new List <int>(); for (int id_char = 0; id_char < Characters.Count; id_char++) { var character = Characters[id_char]; //每个图分成多个笔画,一笔一笔画到矩阵上 metrix.Add(new int[matrix_size.Width, matrix_size.Height]); int step = 1; foreach (var stroke in character.Strokes) { var side = stroke.Points.ToArray().FindSide(); //内容 与 矩阵 比例 这里是等比缩放,所以横竖轴线只取短轴的比例即可 double scale = 0; //字符区域的大小 var charzone_size = new Size(side.Right - side.Left, side.Bottom - side.Top); double scale_x = (double)(matrix_size.Width - 1) / (double)charzone_size.Width; double scale_y = (double)(matrix_size.Height - 1) / (double)charzone_size.Height; scale = scale_x < scale_y ? scale_x : scale_y; //每个笔画分成多个像素点 for (int p = 0; p < stroke.Points.Count(); p++) { stroke.Points[p].X = (int)((stroke.Points[p].X - side.Left) * scale); stroke.Points[p].Y = (int)((stroke.Points[p].Y - side.Top) * scale); if (p == 0) { continue; //第一笔属于起点,跳过 } var distance = Extends.Distance(stroke.Points[p - 1], stroke.Points[p]); if (distance <= 0) { continue; } var ratio = (double)(stroke.Points[p].X - stroke.Points[p - 1].X) / (double)distance; var angle = ratio.Acos(); for (int stepofstroke = 0; stepofstroke < distance; stepofstroke++) { int x = (int)(angle.Cos() * stepofstroke + stroke.Points[p - 1].X); int y = (int)(angle.Sin() * stepofstroke + stroke.Points[p - 1].Y); metrix[id_char][x, y] = step; step += 1; } } steps.Add(step); } } return(metrix.ToArray()); }
static void Main(string[] args) { //总训练次数 const int alltimes = 10000; Console.Title = ""; //单独读取笔画数据 var traindata = new TrainData[] { new TrainData("Res/Strokes/S00.json", 0), new TrainData("Res/Strokes/S01.json", 1), new TrainData("Res/Strokes/S02.json", 2), new TrainData("Res/Strokes/S03.json", 3), new TrainData("Res/Strokes/S04.json", 4), new TrainData("Res/Strokes/S05.json", 5), new TrainData("Res/Strokes/S06.json", 6) }; #region 合并数据到一起 var data_num = 0; foreach (var item in traindata) { data_num += item.MatrixData.GetLength(0); } var sumdata = new TrainData(); sumdata.MatrixData = new double[data_num, traindata[0].MatrixData.GetLength(1)]; sumdata.Anwser = new double[data_num, traindata[0].Anwser.GetLength(1)]; int startpoint = 0; for (int i = 0; i < traindata.Length; i++) { var item = traindata[i]; for (int k = 0; k < item.MatrixData.GetLength(0); k++) { for (int j = 0; j < item.MatrixData.GetLength(1); j++) { sumdata.MatrixData[startpoint, j] = item.MatrixData[k, j]; } for (int j = 0; j < item.Anwser.GetLength(1); j++) { sumdata.Anwser[startpoint, j] = item.Anwser[k, j]; } startpoint++; } } #endregion Console.WriteLine("加载数据完成,开始训练..."); //把"问题"和"答案"交给神经网络,让神经网络自己研究怎么把"问题"计算成"答案" var bp = new BpNet(sumdata.MatrixData, sumdata.Anwser); //循环进行多次训练 for (int i = 1; i < alltimes; i++) { bp.train(sumdata.MatrixData, sumdata.Anwser); if (i % (alltimes / 10) == 0) { Console.WriteLine($"总训练次数:{alltimes} 当前训练次数:{i}"); } } Console.WriteLine("训练完成,开始预测.."); //加载测试数据集 var test = Extends.GetDim1Matrix("Res/test.json"); //循环把测试数据集放进去识别: for (int i = 0; i < test.GetLength(0); i++) { var sim0 = bp.sim(test.GetColumn(i)); int like = 0; var distant = double.MaxValue; //排序.把最接近1的排到上面 for (int k = 0; k < sim0.Length; k++) { if (Math.Abs(sim0[k] - 1) > distant) { continue; } distant = Math.Abs(sim0[k] - 1); like = k; } Console.WriteLine($"测试数据{i}识别结果:{like}"); } var result = bp.ToString(); //把训练出来的权重数据保存到JSON File.WriteAllText("GData.json", result); Console.ReadKey(true); }