diff --git a/README.md b/README.md index 08090d4..c0a7673 100644 --- a/README.md +++ b/README.md @@ -45,34 +45,34 @@ ``` java //创建图片解析类 Picture picture = new Picture(); - //创建一个静态单例配置模板 + //创建一个静态单例配置模板 static TempleConfig templeConfig = new TempleConfig(); //第三个参数和第四个参数分别是训练图片的宽和高,为保证训练的稳定性请保证训练图片大小的一致性 templeConfig.init(StudyPattern.Accuracy_Pattern, true, 640, 640, 2); //将配置模板类作为构造塞入计算类 Operation operation = new Operation(templeConfig); -//一阶段 循环读取不同的图片 + //一阶段 循环读取不同的图片 for (int i = 1; i < 1900; i++) { - //读取本地URL地址图片,并转化成矩阵 - Matrix a = picture.getImageMatrixByLocal("/Users/lidapeng/Desktop/myDocment/picture/a" + i + ".jpg"); - Matrix c = picture.getImageMatrixByLocal("/Users/lidapeng/Desktop/myDocment/picture/c" + i + ".jpg"); - //矩阵塞入运算类进行学习,第一个参数是图片矩阵,第二个参数是图片分类标注ID,第三个参数是第一次学习固定false - operation.learning(a, 1, false); - operation.learning(c, 2, false); - } + //读取本地URL地址图片,并转化成矩阵 + Matrix a = picture.getImageMatrixByLocal("/Users/lidapeng/Desktop/myDocment/picture/a" + i + ".jpg"); + Matrix c = picture.getImageMatrixByLocal("/Users/lidapeng/Desktop/myDocment/picture/c" + i + ".jpg"); + //矩阵塞入运算类进行学习,第一个参数是图片矩阵,第二个参数是图片分类标注ID,第三个参数是第一次学习固定false + operation.learning(a, 1, false); + operation.learning(c, 2, false); + } for (int i = 1; i < 1900; i++) { - //读取本地URL地址图片,并转化成矩阵 - Matrix a = picture.getImageMatrixByLocal("D:\\share\\picture/a" + i + ".jpg"); - Matrix c = picture.getImageMatrixByLocal("D:\\share\\picture/c" + i + ".jpg"); - //将图像矩阵和标注加入进行学习,Accuracy_Pattern 模式 进行第二次学习 - //第二次学习的时候,第三个参数必须是 true - operation.learning(a, 1, true); - operation.learning(c, 2, true); - } + //读取本地URL地址图片,并转化成矩阵 + Matrix a = picture.getImageMatrixByLocal("D:\\share\\picture/a" + i + ".jpg"); + Matrix c = picture.getImageMatrixByLocal("D:\\share\\picture/c" + i + ".jpg"); + //将图像矩阵和标注加入进行学习,Accuracy_Pattern 模式 进行第二次学习 + //第二次学习的时候,第三个参数必须是 true + operation.learning(a, 1, true); + operation.learning(c, 2, true); + } templeConfig.finishStudy();//结束学习 - //获取学习结束的模型参数,并将model保存数据库 - ModelParameter modelParameter = templeConfig.getModel(); - String model = JSON.toJSONString(modelParameter); + //获取学习结束的模型参数,并将model保存数据库 + ModelParameter modelParameter = templeConfig.getModel(); + String model = JSON.toJSONString(modelParameter); ``` ### 单物体图像识别部分最简API 说明: ``` java @@ -81,7 +81,7 @@ //返回此图片的分类ID int an = operation.toSee(a); ``` -### 单物体图像识别服务启动初始化API 说明: +### 物体图像识别服务启动初始化API 说明: ``` java //创建一个静态单例配置模板类 static TempleConfig templeConfig = new TempleConfig(); @@ -98,9 +98,9 @@ ``` java //创建模板读取类 TemplateReader templateReader = new TemplateReader(); - //读取语言模版,第一个参数是模版地址,第二个参数是编码方式,第三个参数是是否是WIN系统 + //读取语言模版,第一个参数是模版地址,第二个参数是文本编码方式 //同时也是学习过程 - templateReader.read("/Users/lidapeng/Desktop/myDocment/a1.txt", "UTF-8", IOConst.NOT_WIN); + templateReader.read("/Users/lidapeng/Desktop/myDocment/a1.txt", "UTF-8"); //学习结束获取模型参数 //WordModel wordModel = WordTemple.get().getModel(); //不用学习注入模型参数 @@ -155,10 +155,100 @@ //插入特征数据,森林对该数据的最终分类结果进行判断 randomForest.forest(Object objcet); ``` +### 如何提升精准度 +* 将模板类设置为不忽略精度 +``` java + TempleConfig templeConfig = new TempleConfig(false, true); +``` +>使用TempleConfig()有参构造,第一个参数目前依然固定传false(因为有功能还没完成),第二个参数是一个布尔值是否忽略精度。 +众所周知JAVA计算浮点是有精度损失的,如果选择true则使用大数计算类即无精度损失(默认为FALSE),但是这是以速度变慢十倍以上为代价的。 +忽略精度和使用精度准确度上差距,平均在5-6个百分点之间,所以用户按照自己的需求来判断是否使用精度计算。 +>>优点:准确度提升5-6个百分点,配合DNN分类器可达99%以上的准确率 +>>>缺点:运算速度变慢十倍以上,从百毫秒变为一至两秒 +* 根据业务情景选择使用分类器 +``` java + TempleConfig templeConfig = new TempleConfig(false, true); + templeConfig.setClassifier(Classifier.DNN); +``` +>在TempleConfig类调用init()方法前选择使用的分类器setClassifier() +``` java +public class Classifier {//分类器 + public static final int LVQ = 1;//LVQ分类 + public static final int DNN = 2; //使用DNN分类 + public static final int VAvg = 3;//使用特征向量均值分类 +} +``` +>目前easyAi提供三种分类器,即用户选择一种参数设置进配置模板类 +>> 这三种分类器的特点 +>> 1. LVQ:若用户训练图片量较少,比如一个种类只有一两百张图片,则使用此分类器达到当前条件下最大识别成功率 +>> 2. VAvg:若用户训练图片较少,同时分类数量也很少,比如只训练两三种物体识别,则VAvg达到当前最大识别成功率 +>> 3. DNN:若用户训练图片较多,每种分类1500张训练图片,则使用此分类器,准确率98%+。 +>> 4. 若不设置分类器,则框架默认使用VAvg分类器 +>>>使用DNN的话,API略有区别 +``` java + //创建图片解析类 + Picture picture = new Picture(); + //创建一个静态单例配置模板 + static TempleConfig templeConfig = new TempleConfig(); + //第三个参数和第四个参数分别是训练图片的宽和高,为保证训练的稳定性请保证训练图片大小的一致性 + templeConfig.init(StudyPattern.Accuracy_Pattern, true, 640, 640, 2); + //将配置模板类作为构造塞入计算类 + Operation operation = new Operation(templeConfig); + //一阶段 循环读取不同的图片 + for (int i = 1; i < 1900; i++) { + //读取本地URL地址图片,并转化成矩阵 + Matrix a = picture.getImageMatrixByLocal("/Users/lidapeng/Desktop/myDocment/picture/a" + i + ".jpg"); + Matrix c = picture.getImageMatrixByLocal("/Users/lidapeng/Desktop/myDocment/picture/c" + i + ".jpg"); + //矩阵塞入运算类进行学习,第一个参数是图片矩阵,第二个参数是图片分类标注ID,第三个参数是第一次学习固定false + operation.learning(a, 1, false); + operation.learning(c, 2, false); + } + for (int i = 1; i < 1900; i++) { + Matrix a = picture.getImageMatrixByLocal("D:\\share\\picture/a" + i + ".jpg"); + Matrix c = picture.getImageMatrixByLocal("D:\\share\\picture/c" + i + ".jpg"); + operation.normalization(a, templeConfig.getConvolutionNerveManager()); + operation.normalization(c, templeConfig.getConvolutionNerveManager()); + } + templeConfig.getNormalization().avg(); + for (int i = 1; i < 1900; i++) { + //读取本地URL地址图片,并转化成矩阵 + Matrix a = picture.getImageMatrixByLocal("D:\\share\\picture/a" + i + ".jpg"); + Matrix c = picture.getImageMatrixByLocal("D:\\share\\picture/c" + i + ".jpg"); + //将图像矩阵和标注加入进行学习,Accuracy_Pattern 模式 进行第二次学习 + //第二次学习的时候,第三个参数必须是 true + operation.learning(a, 1, true); + operation.learning(c, 2, true); + } +``` +>大家可以看到如果使用DNN,在一阶段学习和二阶段学习之间多了一段代码即: +``` java +for (int i = 1; i < 1900; i++) { + Matrix a = picture.getImageMatrixByLocal("D:\\share\\picture/a" + i + ".jpg"); + Matrix c = picture.getImageMatrixByLocal("D:\\share\\picture/c" + i + ".jpg"); + operation.normalization(a, templeConfig.getConvolutionNerveManager()); + operation.normalization(c, templeConfig.getConvolutionNerveManager()); + } + templeConfig.getNormalization().avg(); +``` +* 增加DNN神经网络深度 +``` java +templeConfig.setDeep(int deep); +``` +>若不设置默认深度为2,设置的深度越深则意味着准确率也越高,但同时也意味着你需要更多的训练图片去训练 +>增加一层深度,训练图片的数量至少乘以3,否则准确度不仅不会增加,反而会下降 +>>优点:更深的深度准确率可以无限接近100%,我们只要训练量足够大,我们就可以更深,越深越无敌 +>>>缺点:增加深度意味着成几何倍数提升的训练量,同时也意味着过拟合的风险 +### 什么样的图片会严重影响准确率 +* 训练图片或者识别图片有,比较大片的遮盖,暗光,阴影,或者使图片模糊的情况,识别和训练都会有严重的干扰 +* 训练图片要求会比较高,要求若物体无背景则扣干净,有背景的话使用统一背景不要变动,不要一个训练一个物体有很多种背景 +* 训练物体图片若有背景最好垫张白纸,纯白和纯色的背景干扰度最小,纯白最优 +* 识别图片的拍摄设备最好有补光灯,不要让拍摄物体有大片阴暗。除非你同时也训练阴暗图片,当然那样的话训练量太大不推荐,也没必要 +* 若使用定位与多物体识别功能,请将训练物体的图片背景扣干净,或保证RGB纯白色号背景即0XFFFFFF +* 某两种物体的图片太过相似即长的几乎一模一样,区别点特别小或者微弱,识别不出来,就好比同卵双胞胎你也很难做出区分 ### 常见抛错 * error:Wrong size setting of image in templateConfig * 原因是模版配置类图片宽高设置相差太大 -> templeConfig.init(StudyPattern.Accuracy_Pattern, true, width, height, 1); +` templeConfig.init(StudyPattern.Accuracy_Pattern, true, width, height, 1);` ##### 最终说明 * TempleConfig():配置模版类,一定要静态在内存中长期持有,检测的时候不要每次都NEW, 一直就使用一个配置类就可以了。 @@ -180,4 +270,4 @@ * 速度模式是使用固定的边缘算子进行多次卷积核,然后使用BP的多层神经网络进行强行拟合给出的结果(它之所以学习快,就是因为速度模式学习的是 全连接层的权重及阈值,而没有对卷积核进行学习) * 本包检测使用的是灰度单通道,即对RGB进行降纬变成灰度图像来进行检测(RGB三通道都算的话,CPU有些吃不住)。 -* 若使用本包还有疑问可自行看测试包内的HelloWorld测试案例类,或者联系作者Q:794757862 +* 若使用本包还有疑问可自行看测试包内的HelloWorld测试案例类,或者进群交流:561433236,提出问题 diff --git a/src/main/java/org/wlld/nerveEntity/OutNerve.java b/src/main/java/org/wlld/nerveEntity/OutNerve.java index 0bafaec..4b1e52c 100644 --- a/src/main/java/org/wlld/nerveEntity/OutNerve.java +++ b/src/main/java/org/wlld/nerveEntity/OutNerve.java @@ -71,10 +71,10 @@ public class OutNerve extends Nerve { Matrix myMatrix = dynamicNerve(matrix, eventId, isKernelStudy); if (isKernelStudy) {//回传 Matrix matrix1 = matrixMapE.get(E); - if (isShowLog) { - System.out.println("E================" + E); - System.out.println(myMatrix.getString()); - } +// if (isShowLog) { +// System.out.println("E================" + E); +// System.out.println(myMatrix.getString()); +// } if (matrix1.getX() <= myMatrix.getX() && matrix1.getY() <= myMatrix.getY()) { double g = getGradient(myMatrix, matrix1); backMatrix(g, eventId); diff --git a/src/test/java/org/wlld/HelloWorld.java b/src/test/java/org/wlld/HelloWorld.java index 9a8cb4c..348e4bf 100644 --- a/src/test/java/org/wlld/HelloWorld.java +++ b/src/test/java/org/wlld/HelloWorld.java @@ -125,8 +125,8 @@ public class HelloWorld { // frame.setLengthWidth(640); // templeConfig.setFrame(frame); templeConfig.setClassifier(Classifier.DNN); - //templeConfig.isShowLog(true); - templeConfig.init(StudyPattern.Accuracy_Pattern, true, 640, 640, 2); + templeConfig.isShowLog(true); + templeConfig.init(StudyPattern.Accuracy_Pattern, true, 640, 640, 4); // ModelParameter modelParameter2 = JSON.parseObject(ModelData.DATA2, ModelParameter.class); // templeConfig.insertModel(modelParameter2); Operation operation = new Operation(templeConfig); @@ -136,18 +136,16 @@ public class HelloWorld { for (int i = 1; i < 1900; i++) {//一阶段 System.out.println("study1===================" + i); //读取本地URL地址图片,并转化成矩阵 - Matrix a = picture.getImageMatrixByLocal("/Users/lidapeng/Desktop/myDocment/picture/a" + i + ".jpg"); - //Matrix b = picture.getImageMatrixByLocal("/Users/lidapeng/Desktop/myDocment/picture/b" + i + ".jpg"); - Matrix c = picture.getImageMatrixByLocal("/Users/lidapeng/Desktop/myDocment/picture/c" + i + ".jpg"); - //Matrix d = picture.getImageMatrixByLocal("/Users/lidapeng/Desktop/myDocment/picture/d" + i + ".jpg"); - //Matrix f = picture.getImageMatrixByLocal("D:\\share\\picture/f" + i + ".png"); + Matrix a = picture.getImageMatrixByLocal("D:\\share\\picture/a" + i + ".jpg"); + Matrix b = picture.getImageMatrixByLocal("D:\\share\\picture/b" + i + ".jpg"); + Matrix c = picture.getImageMatrixByLocal("D:\\share\\picture/c" + i + ".jpg"); + Matrix d = picture.getImageMatrixByLocal("D:\\share\\picture/d" + i + ".jpg"); //将图像矩阵和标注加入进行学习,Accuracy_Pattern 模式 进行第二次学习 //第二次学习的时候,第三个参数必须是 true - // operation.learning(f, 0, false); operation.learning(a, 1, false); - // operation.learning(b, 2, false); - operation.learning(c, 2, false); - //operation.learning(d, 4, false); + operation.learning(b, 2, false); + operation.learning(c, 3, false); + operation.learning(d, 4, false); } } @@ -155,14 +153,13 @@ public class HelloWorld { for (int i = 1; i < 1900; i++) { System.out.println("avg==" + i); Matrix a = picture.getImageMatrixByLocal("D:\\share\\picture/a" + i + ".jpg"); - //Matrix b = picture.getImageMatrixByLocal("/Users/lidapeng/Desktop/myDocment/picture/b" + i + ".jpg"); + Matrix b = picture.getImageMatrixByLocal("D:\\share\\picture/b" + i + ".jpg"); Matrix c = picture.getImageMatrixByLocal("D:\\share\\picture/c" + i + ".jpg"); - //Matrix d = picture.getImageMatrixByLocal("/Users/lidapeng/Desktop/myDocment/picture/d" + i + ".jpg"); - + Matrix d = picture.getImageMatrixByLocal("D:\\share\\picture/d" + i + ".jpg"); operation.normalization(a, templeConfig.getConvolutionNerveManager()); - //operation.normalization(b, templeConfig.getConvolutionNerveManager()); + operation.normalization(b, templeConfig.getConvolutionNerveManager()); operation.normalization(c, templeConfig.getConvolutionNerveManager()); - //operation.normalization(d, templeConfig.getConvolutionNerveManager()); + operation.normalization(d, templeConfig.getConvolutionNerveManager()); } templeConfig.getNormalization().avg(); for (int j = 0; j < 1; j++) { @@ -170,19 +167,15 @@ public class HelloWorld { System.out.println("study2==================" + i); //读取本地URL地址图片,并转化成矩阵 Matrix a = picture.getImageMatrixByLocal("D:\\share\\picture/a" + i + ".jpg"); - //Matrix b = picture.getImageMatrixByLocal("/Users/lidapeng/Desktop/myDocment/picture/b" + i + ".jpg"); + Matrix b = picture.getImageMatrixByLocal("D:\\share\\picture/b" + i + ".jpg"); Matrix c = picture.getImageMatrixByLocal("D:\\share\\picture/c" + i + ".jpg"); - //Matrix d = picture.getImageMatrixByLocal("/Users/lidapeng/Desktop/myDocment/picture/d" + i + ".jpg"); - //Matrix f = picture.getImageMatrixByLocal("D:\\share\\picture/f" + i + ".png"); + Matrix d = picture.getImageMatrixByLocal("D:\\share\\picture/d" + i + ".jpg"); //将图像矩阵和标注加入进行学习,Accuracy_Pattern 模式 进行第二次学习 //第二次学习的时候,第三个参数必须是 true - // operation.learning(f, 0, true); - //System.out.println("1==============="); operation.learning(a, 1, true); - //System.out.println("2==============="); - //operation.learning(b, 2, true); - operation.learning(c, 2, true); - //operation.learning(d, 4, true); + operation.learning(b, 2, true); + operation.learning(c, 3, true); + operation.learning(d, 4, true); } } @@ -198,22 +191,29 @@ public class HelloWorld { // Operation operation2 = new Operation(templeConfig2); int wrong = 0; int allNub = 0; - for (int i = 1900; i <= 2000; i++) { + for (int i = 1900; i <= 1998; i++) { //读取本地URL地址图片,并转化成矩阵 Matrix a = picture.getImageMatrixByLocal("D:\\share\\picture/a" + i + ".jpg"); - //Matrix b = picture.getImageMatrixByLocal("/Users/lidapeng/Desktop/myDocment/picture/b" + i + ".jpg"); + Matrix b = picture.getImageMatrixByLocal("D:\\share\\picture/b" + i + ".jpg"); Matrix c = picture.getImageMatrixByLocal("D:\\share\\picture/c" + i + ".jpg"); - //Matrix d = picture.getImageMatrixByLocal("/Users/lidapeng/Desktop/myDocment/picture/d" + i + ".jpg"); + Matrix d = picture.getImageMatrixByLocal("D:\\share\\picture/d" + i + ".jpg"); //将图像矩阵和标注加入进行学习,Accuracy_Pattern 模式 进行第二次学习 //第二次学习的时候,第三个参数必须是 true - allNub += 2; + allNub += 4; int an = operation.toSee(a); + int bn = operation.toSee(b); int cn = operation.toSee(c); + int dn = operation.toSee(d); if (an != 1) { wrong++; - } else { } - if (cn != 2) { + if (bn != 2) { + wrong++; + } + if (cn != 3) { + wrong++; + } + if (dn != 4) { wrong++; } }