增加物体定位API即边框检测简略说明

pull/1/head
lidapeng 5 years ago
parent 932c4fa02d
commit f46c9247e5

@ -14,15 +14,18 @@
* 比如你要分辨当前图像 是 苹果或是香蕉或是桃子,对图像进行判断分类,精准度更高,对图像的切割,针对占比比较大的物体切割,定位。
* 下面API文档有不清楚的地方可联系作者询问QQ794757862
## 好的让我们从HELLO WORLD 开始:
public class HelloWorld {
public static void testPic() throws Exception {
//测试SPEED模式学习过程
//初始化图像转矩阵类:作用就是说将一个图片文件转化为矩阵类
Picture picture = new Picture();
//初始化配置模板类,设置模式为SPEED_PATTERN模式 即速度模式
TempleConfig templeConfig = getTemple(true, StudyPattern.Speed_Pattern);
//初始化计算类,并将配置模版载入计算类
Operation operation = new Operation(templeConfig);
//初始化计算类,并将配置模版和输出回调类载入计算类
//运算类有两个构造一个是配置回调类,一个是不配置回调类
//若使用定位功能,则无需配置回调类,若不启用,则要配置回调类
//回调类要实现OutBack接口中的方法
Ma ma = new Ma();
Operation operation = new Operation(templeConfig, ma);
//标注主键为 第几种分类,值为标注 1 是TRUE 0是FALSE
//给训练图像进行标注健是分类的ID,对应的就是输出结果的ID值值要么写0要么写1
// 1就是 是这种分类0就是不是这种分类
@ -34,8 +37,7 @@
for (int i = 1; i < 999; i++) {
System.out.println("开始学习1==" + i);
//读取本地URL地址图片(适用于电脑本地图片),并转化成矩阵
//注意学习图片至少要一千张+同物体的不同图片,推荐一万张
//学习的越多就越准,拿同样的图片反复循环学习是没用的
//注意学习图片至少要一千张+同物体的不同图片,学习的越多就越准,拿同样的图片反复循环学习是没用的
//picture.getImageMatrixByIo(InputStream) 另外一个api,是通过字节流读取图片矩阵,适用于网络传输的图片
Matrix right = picture.getImageMatrixByLocal("/Users/lidapeng/Desktop/myDocment/c/c" + i + ".png");
Matrix wrong = picture.getImageMatrixByLocal("/Users/lidapeng/Desktop/myDocment/b/b" + i + ".png");
@ -45,6 +47,9 @@
//wrong这个矩阵是错误的图片所以要配置上面错误的标注0.0 学习 告诉计算机这个图片是错误的
operation.study(wrong, wrongTagging);
}
//如果启用物体坐标定位则在学习结束的时候一定要执行boxStudy方法
//若不启用,则请不要使用,否则会报错
//templeConfig.boxStudy();
//获取训练结束的模型参数提取出来转化成JSON保存数据库下次服务启动时不用学习
//直接将模型参数注入
//获取模型MODLE 这个模型就是我们程序学习的目的,学习结束后我们要拿到这个模型
@ -52,6 +57,7 @@
//将模型MODEL转化成JSON 字符串 保存到数据库 留待下次服务启动的时候,识别提取用
String model = JSON.toJSONString(modelParameter);
//以上就是SPEED模式下的学习全过程识别的过程就是再次初始化将学习结果注入之后使用
//识别过程
//将从数据库取出的JSON字符串转化为模型MODEL
ModelParameter modelParameter1 = JSONObject.parseObject(model, ModelParameter.class);
@ -61,22 +67,21 @@
templeConfig1.insertModel(modelParameter1);
//将配置模板配置到运算类
Operation operation1 = new Operation(templeConfig1);
//获取本地图片字节码转化成降纬后的灰度矩阵</br>
//获取本地图片字节码转化成降纬后的灰度矩阵
Matrix right = picture.getImageMatrixByLocal("/Users/lidapeng/Desktop/myDocment/test/a101.png");
Matrix wrong = picture.getImageMatrixByLocal("/Users/lidapeng/Desktop/myDocment/b/b1000.png");
//进行图像识别 参数说明 eventId,事件id,因为输出结果是在回调类回调的,所以必须有个主键去判断事件
//说明你回调是响应的哪一次调用的ID,所以每一次识别调用请用不同的id
operation1.look(wrong, 3);
operation1.look(right, 2);
//若启用定位功能检测请使用lookWithPosition,若没有启用,使用检测会报错
//返回map,主键是分类id,值是该图片中此分类有多少个物体,每个物体的具体位置坐标的大小
//Map<Integer, List<FrameBody>> map = operation1.lookWithPosition(right, 4);
}
public static TempleConfig getTemple(boolean isFirst, int pattern) throws Exception {
//创建一个配置模板类,作用:主要是保存及载入一些配置参数用
TempleConfig templeConfig = new TempleConfig();
//创建一个回调类,图像识别最后输出结果,在这个类输出,这个类要实现 OutBack接口
Ma ma = new Ma();//创建一个回调类
//将这个回调类注册到配置模版里 必写
templeConfig.setOutBack(ma);
//全连接层深度,选填可不填 不填默认值为2
//这就像人类大脑的意识深度原理一样,深度学习越深,训练结果越准,但是训练量成几何倍数增加
//比如默认深度是2 需要 正负模板各一千+张照片进行训练。识别率70%(数值只是举个例子,不是具体数值)
@ -85,8 +90,14 @@
//但是有极限,即超过某个深度,即使再增加深度,识别率反而会下降。需要具体不断尝试找到 合适的深度
//注意:若深度提升,训练量没有成倍增长,则准确度反而更低!
templeConfig.setDeep(2);
//启用定位学习 注意启用在图片中对某个物体进行定位,要注意
//学习的图片必须除了学习的物体以外,其他位置都是白色或者空白(即用PS扣空)。
//即该图片除了这个物体,没有其他任何干扰杂色(一个像素的杂色都不可以有)
//templeConfig.setHavePosition(true);
//窗口类,就是用来扫描图片的窗口大小和移动距离的设定
//Frame frame = new Frame();
//初始化配置模版,参数说明(int studyPattern, boolean initPower, int width, int height
, int classificationNub)
//, int classificationNub)
//studyPattern 学习模式:常量值 StudyPattern.Accuracy_Pattern;StudyPattern.Speed_Pattern
//第一种模式精准模式,第二种模式是速度模式
//精准模式顾名思义准确相对高很多但是缺点也很明显学习速度慢不是一般的慢CPU学习1000张图片
@ -105,6 +116,7 @@
//要识别和学习的图片尺寸与这个宽高比 必要相差太大就好,而且宁长勿短
//classificationNub 要识别的有几个分类比如我就识别苹果就是1 有两种苹果橘子就是 2
templeConfig.init(pattern, isFirst, 3204, 4032, 1);
return templeConfig;
}
@ -120,6 +132,7 @@
ModelParameter modelParameter2 = templeConfig2.getModel();
String model2 = JSON.toJSONString(modelParameter2);
System.out.println(model2);
}
public static void testPic2() throws Exception {
@ -132,7 +145,7 @@
Map<Integer, Double> wrongTagging = new HashMap<>();//分类标注
rightTagging.put(1, 1.0);
wrongTagging.put(1, 0.0);
for (int i = 1; i < 5; i++) {
for (int i = 1; i < 2; i++) {
System.out.println("开始学习1==" + i);
//读取本地URL地址图片,并转化成矩阵
Matrix right = picture.getImageMatrixByLocal("/Users/lidapeng/Desktop/myDocment/c/c" + i + ".png");
@ -140,10 +153,11 @@
//将图像矩阵和标注加入进行学习 注意的是 Accuracy_Pattern 模式 要学习两次
//这里使用learning方法前两个参数与SPEED模式相同多了一个第三个参数
//第一次学习的时候 这个参数必须是 false
//最后一个参数id
operation.learning(right, rightTagging, false);
operation.learning(wrong, wrongTagging, false);
}
for (int i = 1; i < 5; i++) {//
for (int i = 1; i < 2; i++) {//
System.out.println("开始学习2==" + i);
//读取本地URL地址图片,并转化成矩阵
Matrix right = picture.getImageMatrixByLocal("/Users/lidapeng/Desktop/myDocment/c/c" + i + ".png");
@ -159,7 +173,7 @@
//若有疑问可以参考一下 testModel()方法
operation.look(right, 2);
operation.look(wrong, 3);
}}
}
回调输出类:
public class Ma implements OutBack {
private int nub;
@ -177,3 +191,8 @@
回调第一个参数是输出值 指的是 这个分类的概率 该数值是0-1之间的浮点
第二个参数是 分类的id 判断是训练的哪个分类的ID
第三个参数是 事件ID,一次判断事件 使用一个ID,让开发者知道是哪次事件的回调判断
#### 最终说明
* TempleConfig():配置模版类一定要静态,在内存中长期持有
* Operation():运算类除了学习可以使用一个以外用户每检测一次都要NEW一次。
因为学习是单线程无所谓,而检测是多线程,如果使用一个运算类,可能会造成线程安全问题

@ -65,9 +65,16 @@ public class Operation {//进行计算
}
//卷积核学习
public void learning(Matrix matrix, Map<Integer, Double> tagging, boolean isNerveStudy, int id) throws Exception {
public void learning(Matrix matrix, Map<Integer, Double> tagging, boolean isNerveStudy) throws Exception {
if (templeConfig.getStudyPattern() == StudyPattern.Accuracy_Pattern) {
Border border = null;
int id = 0;
for (Map.Entry<Integer, Double> entry : tagging.entrySet()) {
if (entry.getValue() > 0.5) {
id = entry.getKey();
break;
}
}
if (templeConfig.isHavePosition() && isNerveStudy && id > 0) {
outBack = imageBack;
border = convolution.borderOnce(matrix, templeConfig);

@ -7,9 +7,12 @@ import org.wlld.config.StudyPattern;
import org.wlld.imageRecognition.Operation;
import org.wlld.imageRecognition.Picture;
import org.wlld.imageRecognition.TempleConfig;
import org.wlld.imageRecognition.border.Frame;
import org.wlld.imageRecognition.border.FrameBody;
import org.wlld.nerveEntity.ModelParameter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
@ -19,22 +22,8 @@ import java.util.Map;
*/
public class HelloWorld {
public static void main(String[] args) throws Exception {
//testPic();
testPic();
//testModel();
test();
}
public static void test() throws Exception {
Picture picture = new Picture();
Matrix right = picture.getImageMatrixByLocal("/Users/lidapeng/Desktop/myDocment/test/a101.png");
TempleConfig templeConfig = getTemple(true, StudyPattern.Accuracy_Pattern);
Ma ma = new Ma();
Operation operation = new Operation(templeConfig, ma);
long a = System.currentTimeMillis();
operation.look(right, 2);
long b = System.currentTimeMillis();
System.out.println("耗时:" + (b - a));
}
public static void testPic() throws Exception {
@ -43,8 +32,12 @@ public class HelloWorld {
Picture picture = new Picture();
//初始化配置模板类,设置模式为SPEED_PATTERN模式 即速度模式
TempleConfig templeConfig = getTemple(true, StudyPattern.Speed_Pattern);
//初始化计算类,并将配置模版载入计算类
Operation operation = new Operation(templeConfig);
//初始化计算类,并将配置模版和输出回调类载入计算类
//运算类有两个构造一个是配置回调类,一个是不配置回调类
//若使用定位功能,则无需配置回调类,若不启用,则要配置回调类
//回调类要实现OutBack接口中的方法
Ma ma = new Ma();
Operation operation = new Operation(templeConfig, ma);
//标注主键为 第几种分类,值为标注 1 是TRUE 0是FALSE
//给训练图像进行标注健是分类的ID,对应的就是输出结果的ID值值要么写0要么写1
// 1就是 是这种分类0就是不是这种分类
@ -66,6 +59,9 @@ public class HelloWorld {
//wrong这个矩阵是错误的图片所以要配置上面错误的标注0.0 学习 告诉计算机这个图片是错误的
operation.study(wrong, wrongTagging);
}
//如果启用物体坐标定位则在学习结束的时候一定要执行boxStudy方法
//若不启用,则请不要使用,否则会报错
//templeConfig.boxStudy();
//获取训练结束的模型参数提取出来转化成JSON保存数据库下次服务启动时不用学习
//直接将模型参数注入
//获取模型MODLE 这个模型就是我们程序学习的目的,学习结束后我们要拿到这个模型
@ -90,6 +86,9 @@ public class HelloWorld {
//说明你回调是响应的哪一次调用的ID,所以每一次识别调用请用不同的id
operation1.look(wrong, 3);
operation1.look(right, 2);
//若启用定位功能检测请使用lookWithPosition,若没有启用,使用检测会报错
//返回map,主键是分类id,值是该图片中此分类有多少个物体,每个物体的具体位置坐标的大小
//Map<Integer, List<FrameBody>> map = operation1.lookWithPosition(right, 4);
}
public static TempleConfig getTemple(boolean isFirst, int pattern) throws Exception {
@ -103,6 +102,12 @@ public class HelloWorld {
//但是有极限,即超过某个深度,即使再增加深度,识别率反而会下降。需要具体不断尝试找到 合适的深度
//注意:若深度提升,训练量没有成倍增长,则准确度反而更低!
templeConfig.setDeep(2);
//启用定位学习 注意启用在图片中对某个物体进行定位,要注意
//学习的图片必须除了学习的物体以外,其他位置都是白色或者空白(即用PS扣空)。
//即该图片除了这个物体,没有其他任何干扰杂色(一个像素的杂色都不可以有)
//templeConfig.setHavePosition(true);
//窗口类,就是用来扫描图片的窗口大小和移动距离的设定
//Frame frame = new Frame();
//初始化配置模版,参数说明(int studyPattern, boolean initPower, int width, int height
//, int classificationNub)
//studyPattern 学习模式:常量值 StudyPattern.Accuracy_Pattern;StudyPattern.Speed_Pattern
@ -160,8 +165,9 @@ public class HelloWorld {
//将图像矩阵和标注加入进行学习 注意的是 Accuracy_Pattern 模式 要学习两次
//这里使用learning方法前两个参数与SPEED模式相同多了一个第三个参数
//第一次学习的时候 这个参数必须是 false
operation.learning(right, rightTagging, false, 1);
operation.learning(wrong, wrongTagging, false, 0);
//最后一个参数id
operation.learning(right, rightTagging, false);
operation.learning(wrong, wrongTagging, false);
}
for (int i = 1; i < 2; i++) {//神经网络学习
System.out.println("开始学习2==" + i);
@ -170,8 +176,8 @@ public class HelloWorld {
Matrix wrong = picture.getImageMatrixByLocal("/Users/lidapeng/Desktop/myDocment/b/b" + i + ".png");
//将图像矩阵和标注加入进行学习Accuracy_Pattern 模式 进行第二次学习
//第二次学习的时候,第三个参数必须是 true
operation.learning(right, rightTagging, true, 1);
operation.learning(wrong, wrongTagging, true, 0);
operation.learning(right, rightTagging, true);
operation.learning(wrong, wrongTagging, true);
}
Matrix right = picture.getImageMatrixByLocal("/Users/lidapeng/Desktop/myDocment/test/a101.png");
Matrix wrong = picture.getImageMatrixByLocal("/Users/lidapeng/Desktop/myDocment/b/b1000.png");

Loading…
Cancel
Save