You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
911 lines
40 KiB
911 lines
40 KiB
package org.wlld.imageRecognition;
|
|
|
|
|
|
import org.wlld.MatrixTools.Matrix;
|
|
import org.wlld.MatrixTools.MatrixOperation;
|
|
import org.wlld.config.Classifier;
|
|
import org.wlld.config.StudyPattern;
|
|
import org.wlld.i.OutBack;
|
|
import org.wlld.imageRecognition.border.*;
|
|
import org.wlld.imageRecognition.segmentation.RegionBody;
|
|
import org.wlld.imageRecognition.segmentation.Specifications;
|
|
import org.wlld.imageRecognition.segmentation.Watershed;
|
|
import org.wlld.nerveCenter.NerveManager;
|
|
import org.wlld.nerveCenter.Normalization;
|
|
import org.wlld.nerveEntity.SensoryNerve;
|
|
import org.wlld.tools.ArithUtil;
|
|
import org.wlld.tools.IdCreator;
|
|
|
|
import java.util.*;
|
|
|
|
public class Operation {//进行计算
|
|
private TempleConfig templeConfig;//配置初始化参数模板
|
|
private Convolution convolution = new Convolution();
|
|
private MatrixBack matrixBack = new MatrixBack();
|
|
private ImageBack imageBack = new ImageBack();
|
|
private OutBack outBack;
|
|
private int dif;
|
|
|
|
public Operation(TempleConfig templeConfig) {
|
|
this.templeConfig = templeConfig;
|
|
dif = templeConfig.getFood().getShrink();
|
|
}
|
|
|
|
public Operation(TempleConfig templeConfig, OutBack outBack) {
|
|
this.templeConfig = templeConfig;
|
|
this.outBack = outBack;
|
|
dif = templeConfig.getFood().getShrink();
|
|
}
|
|
|
|
public List<Double> convolution(Matrix matrix, Map<Integer, Double> tagging) throws Exception {
|
|
//进行卷积
|
|
int maxNub;
|
|
if (templeConfig.getRow() >= templeConfig.getColumn()) {
|
|
maxNub = templeConfig.getRow();
|
|
} else {
|
|
maxNub = templeConfig.getColumn();
|
|
}
|
|
int id = -1;
|
|
if (tagging != null && templeConfig.isHavePosition()) {
|
|
for (Map.Entry<Integer, Double> entry : tagging.entrySet()) {
|
|
if (entry.getValue() == 1) {
|
|
id = entry.getKey();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
Matrix matrix1 = convolution.getFeatures(matrix, maxNub, templeConfig, id);
|
|
return sub(matrix1);
|
|
}
|
|
|
|
public void colorStudy(ThreeChannelMatrix threeChannelMatrix, int tag, List<Specifications> specificationsList) throws Exception {
|
|
Watershed watershed = new Watershed(threeChannelMatrix.getMatrixRGB(), specificationsList, templeConfig);
|
|
List<RegionBody> regionBodies = watershed.rainfall();
|
|
if (regionBodies.size() == 1) {
|
|
RegionBody regionBody = regionBodies.get(0);
|
|
int minX = regionBody.getMinX() + dif;
|
|
int minY = regionBody.getMinY() + dif;
|
|
int maxX = regionBody.getMaxX() - dif;
|
|
int maxY = regionBody.getMaxY() - dif;
|
|
int xSize = maxX - minX;
|
|
int ySize = maxY - minY;
|
|
ThreeChannelMatrix threeChannelMatrix1 = convolution.getRegionMatrix(threeChannelMatrix, minX, minY, xSize, ySize);
|
|
//convolution.filtering(threeChannelMatrix1);//光照过滤
|
|
int times = templeConfig.getFood().getTimes();
|
|
for (int i = 0; i < times; i++) {
|
|
List<Double> feature = convolution.getCenterColor(threeChannelMatrix1, templeConfig.getPoolSize(),
|
|
templeConfig.getFeatureNub());
|
|
if (templeConfig.isShowLog()) {
|
|
System.out.println(tag + ":" + feature);
|
|
}
|
|
//System.out.println("=====================================");
|
|
int classifier = templeConfig.getClassifier();
|
|
switch (classifier) {
|
|
case Classifier.DNN:
|
|
Map<Integer, Double> map = new HashMap<>();
|
|
map.put(tag, 1.0);
|
|
if (templeConfig.getSensoryNerves().size() == templeConfig.getFeatureNub() * 3) {
|
|
intoDnnNetwork(1, feature, templeConfig.getSensoryNerves(), true, map, null);
|
|
} else {
|
|
throw new Exception("nerves number is not equal featureNub");
|
|
}
|
|
break;
|
|
case Classifier.LVQ:
|
|
Matrix vector = MatrixOperation.listToRowVector(feature);
|
|
lvqStudy(tag, vector);
|
|
break;
|
|
case Classifier.VAvg:
|
|
Matrix vec = MatrixOperation.listToRowVector(feature);
|
|
avgStudy(tag, vec);
|
|
break;
|
|
case Classifier.KNN:
|
|
Matrix veck = MatrixOperation.listToRowVector(feature);
|
|
knnStudy(tag, veck);
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
throw new Exception("Parameter exception region size==" + regionBodies.size());
|
|
}
|
|
}
|
|
|
|
private void knnStudy(int tagging, Matrix vector) throws Exception {
|
|
Knn knn = templeConfig.getKnn();
|
|
knn.insertMatrix(vector, tagging);
|
|
}
|
|
|
|
private void avgStudy(int tagging, Matrix myMatrix) throws Exception {//特征矩阵均值学习
|
|
VectorK vectorK = templeConfig.getVectorK();
|
|
vectorK.insertMatrix(tagging, myMatrix);
|
|
}
|
|
|
|
private void lvqStudy(int tagging, Matrix myMatrix) throws Exception {//LVQ学习
|
|
LVQ lvq = templeConfig.getLvq();
|
|
MatrixBody matrixBody = new MatrixBody();
|
|
matrixBody.setMatrix(myMatrix);
|
|
matrixBody.setId(tagging);
|
|
lvq.insertMatrixBody(matrixBody);
|
|
}
|
|
|
|
public List<RegionBody> colorLook(ThreeChannelMatrix threeChannelMatrix, List<Specifications> specificationsList) throws Exception {
|
|
Watershed watershed = new Watershed(threeChannelMatrix.getMatrixRGB(), specificationsList, templeConfig);
|
|
List<RegionBody> regionList = watershed.rainfall();
|
|
for (RegionBody regionBody : regionList) {
|
|
MaxPoint maxPoint = new MaxPoint();
|
|
int minX = regionBody.getMinX() + dif;
|
|
int minY = regionBody.getMinY() + dif;
|
|
int maxX = regionBody.getMaxX() - dif;
|
|
int maxY = regionBody.getMaxY() - dif;
|
|
int xSize = maxX - minX;
|
|
int ySize = maxY - minY;
|
|
ThreeChannelMatrix threeChannelMatrix1 = convolution.getRegionMatrix(threeChannelMatrix, minX, minY, xSize, ySize);
|
|
//convolution.filtering(threeChannelMatrix1);//光照过滤
|
|
List<Double> feature = convolution.getCenterColor(threeChannelMatrix1, templeConfig.getPoolSize(),
|
|
templeConfig.getFeatureNub());
|
|
if (templeConfig.isShowLog()) {
|
|
System.out.println(feature);
|
|
}
|
|
int classifier = templeConfig.getClassifier();
|
|
int id = 0;
|
|
switch (classifier) {
|
|
case Classifier.LVQ:
|
|
Matrix myMatrix = MatrixOperation.listToRowVector(feature);
|
|
id = getIdByLVQ(myMatrix);
|
|
break;
|
|
case Classifier.DNN:
|
|
if (templeConfig.getSensoryNerves().size() == templeConfig.getFeatureNub() * 3) {
|
|
intoDnnNetwork(IdCreator.get().nextId(), feature, templeConfig.getSensoryNerves(), false, null, maxPoint);
|
|
id = maxPoint.getId();
|
|
} else {
|
|
throw new Exception("nerves number is not equal featureNub");
|
|
}
|
|
break;
|
|
case Classifier.VAvg:
|
|
Matrix myMatrix1 = MatrixOperation.listToRowVector(feature);
|
|
id = getIdByVag(myMatrix1);
|
|
break;
|
|
case Classifier.KNN:
|
|
Matrix myMatrix2 = MatrixOperation.listToRowVector(feature);
|
|
Knn knn = templeConfig.getKnn();
|
|
id = knn.getType(myMatrix2);
|
|
break;
|
|
}
|
|
regionBody.setType(id);
|
|
//System.out.println("类别" + id);
|
|
}
|
|
return regionList;
|
|
}
|
|
|
|
private int getIdByCos(Matrix myVector) throws Exception {//VAG获取分类
|
|
Map<Integer, Matrix> matrixK = templeConfig.getVectorK().getMatrixK();
|
|
double maxCos = 0;
|
|
int id = 0;
|
|
for (Map.Entry<Integer, Matrix> entry : matrixK.entrySet()) {
|
|
Matrix matrix = entry.getValue();
|
|
double cos = MatrixOperation.getNormCos(matrix, myVector);
|
|
//System.out.println("距离===" + dist + ",类别==" + entry.getKey()+",核心:"+matrix.getString());
|
|
if (cos > maxCos) {
|
|
maxCos = cos;
|
|
id = entry.getKey();
|
|
}
|
|
}
|
|
return id;
|
|
}
|
|
|
|
private int getIdByVag(Matrix myVector) throws Exception {//VAG获取分类
|
|
Map<Integer, Matrix> matrixK = templeConfig.getVectorK().getMatrixK();
|
|
double minDist = 0;
|
|
int id = 0;
|
|
for (Map.Entry<Integer, Matrix> entry : matrixK.entrySet()) {
|
|
Matrix matrix = entry.getValue();
|
|
double dist = MatrixOperation.getEDist(matrix, myVector);
|
|
//System.out.println("距离===" + dist + ",类别==" + entry.getKey()+",核心:"+matrix.getString());
|
|
if (minDist == 0 || dist < minDist) {
|
|
minDist = dist;
|
|
id = entry.getKey();
|
|
}
|
|
}
|
|
//System.out.println("=======================");
|
|
return id;
|
|
}
|
|
|
|
private int getIdByLVQ(Matrix myVector) throws Exception {//LVQ获取分类
|
|
int id = 0;
|
|
double distEnd = 0;
|
|
LVQ lvq = templeConfig.getLvq();
|
|
MatrixBody[] matrixBodies = lvq.getModel();
|
|
for (int i = 0; i < matrixBodies.length; i++) {
|
|
MatrixBody matrixBody = matrixBodies[i];
|
|
Matrix vector = matrixBody.getMatrix();
|
|
double dist = lvq.vectorEqual(myVector, vector);
|
|
if (distEnd == 0 || dist < distEnd) {
|
|
id = matrixBody.getId();
|
|
distEnd = dist;
|
|
}
|
|
}
|
|
return id;
|
|
}
|
|
|
|
public void coverStudy(Map<Integer, ThreeChannelMatrix> matrixMap, int poolSize, int sqNub, int regionSize,
|
|
int times) throws Exception {
|
|
if (templeConfig.getStudyPattern() == StudyPattern.Cover_Pattern) {
|
|
int size = 0;
|
|
List<CoverBody> coverBodies = new ArrayList<>();
|
|
for (Map.Entry<Integer, ThreeChannelMatrix> entry : matrixMap.entrySet()) {
|
|
CoverBody coverBody = new CoverBody();
|
|
Map<Integer, Double> tag = new HashMap<>();
|
|
tag.put(entry.getKey(), 1.0);
|
|
List<List<Double>> lists = convolution.kAvg(entry.getValue(), poolSize, sqNub, regionSize);
|
|
size = lists.size();
|
|
coverBody.setFeature(lists);
|
|
coverBody.setTag(tag);
|
|
coverBodies.add(coverBody);
|
|
}
|
|
//特征塞入容器完毕
|
|
for (int j = 0; j < times; j++) {
|
|
for (int i = 0; i < size; i++) {
|
|
for (CoverBody coverBody : coverBodies) {
|
|
List<Double> list = coverBody.getFeature().get(i);
|
|
if (templeConfig.isShowLog()) {
|
|
System.out.println("feature:" + list);
|
|
}
|
|
intoDnnNetwork(1, list, templeConfig.getSensoryNerves(), true, coverBody.getTag(), null);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public Map<Integer, Double> coverPoint(ThreeChannelMatrix matrix, int poolSize, int sqNub, int regionSize) throws Exception {
|
|
if (templeConfig.getStudyPattern() == StudyPattern.Cover_Pattern) {
|
|
Map<Integer, Double> coverMap = new HashMap<>();
|
|
Map<Integer, Integer> typeNub = new HashMap<>();
|
|
List<List<Double>> lists = convolution.kAvg(matrix, poolSize, sqNub, regionSize);
|
|
//特征塞入容器完毕
|
|
int size = lists.size();
|
|
int all = 0;
|
|
for (int i = 0; i < size; i++) {
|
|
List<Double> list = lists.get(i);
|
|
MaxPoint maxPoint = new MaxPoint();
|
|
long pid = IdCreator.get().nextId();
|
|
intoDnnNetwork(pid, list, templeConfig.getSensoryNerves(), false, null, maxPoint);
|
|
int id = maxPoint.getId();
|
|
if (typeNub.containsKey(id)) {
|
|
typeNub.put(id, typeNub.get(id) + 1);
|
|
} else {
|
|
typeNub.put(id, 1);
|
|
}
|
|
all++;
|
|
}
|
|
for (Map.Entry<Integer, Integer> entry : typeNub.entrySet()) {
|
|
int nub = entry.getValue();
|
|
coverMap.put(entry.getKey(), ArithUtil.div(nub, all));
|
|
}
|
|
return coverMap;
|
|
} else {
|
|
throw new Exception("PATTERN IS NOT COVER");
|
|
}
|
|
}
|
|
|
|
//模板学习
|
|
public void study(Matrix matrix, Map<Integer, Double> tagging) throws Exception {
|
|
if (templeConfig.getStudyPattern() == StudyPattern.Speed_Pattern) {
|
|
List<Double> list = convolution(matrix, tagging);
|
|
intoDnnNetwork(1, list, templeConfig.getSensoryNerves(), true, tagging, null);
|
|
} else {
|
|
throw new Exception("pattern is wrong");
|
|
}
|
|
}
|
|
|
|
public int toThreeSee(ThreeChannelMatrix threeChannelMatrix) throws Exception {//三通道
|
|
NerveManager convolutionNerveManagerR = templeConfig.getConvolutionNerveManagerR();
|
|
NerveManager convolutionNerveManagerB = templeConfig.getConvolutionNerveManagerB();
|
|
NerveManager convolutionNerveManagerG = templeConfig.getConvolutionNerveManagerG();
|
|
Matrix matrixR = threeChannelMatrix.getMatrixR();
|
|
Matrix matrixG = threeChannelMatrix.getMatrixG();
|
|
Matrix matrixB = threeChannelMatrix.getMatrixB();
|
|
//进卷积网络
|
|
MatrixBack matrixBackR = new MatrixBack();
|
|
MatrixBack matrixBackG = new MatrixBack();
|
|
MatrixBack matrixBackB = new MatrixBack();
|
|
intoConvolutionNetwork(1, matrixR, convolutionNerveManagerR.getSensoryNerves(),
|
|
false, 0, matrixBackR);
|
|
intoConvolutionNetwork(1, matrixG, convolutionNerveManagerG.getSensoryNerves(),
|
|
false, 0, matrixBackG);
|
|
intoConvolutionNetwork(1, matrixB, convolutionNerveManagerB.getSensoryNerves(),
|
|
false, 0, matrixBackB);
|
|
Matrix myMatrixR = matrixBackR.getMatrix();
|
|
Matrix myMatrixG = matrixBackG.getMatrix();
|
|
Matrix myMatrixB = matrixBackB.getMatrix();
|
|
List<Double> featureALL = new ArrayList<>();
|
|
List<Double> featureR = getFeature(myMatrixR);
|
|
List<Double> featureG = getFeature(myMatrixG);
|
|
List<Double> featureB = getFeature(myMatrixB);
|
|
featureALL.addAll(featureR);
|
|
featureALL.addAll(featureG);
|
|
featureALL.addAll(featureB);
|
|
MaxPoint maxPoint = new MaxPoint();
|
|
long id = IdCreator.get().nextId();
|
|
intoDnnNetwork(id, featureALL, templeConfig.getSensoryNerves(), false, null, maxPoint);
|
|
return maxPoint.getId();
|
|
}
|
|
|
|
public void threeLearning(ThreeChannelMatrix threeChannelMatrix, int tagging, boolean isNerveStudy) throws Exception {
|
|
boolean isKernelStudy = true;
|
|
if (isNerveStudy) {
|
|
isKernelStudy = false;
|
|
}
|
|
NerveManager convolutionNerveManagerR = templeConfig.getConvolutionNerveManagerR();
|
|
NerveManager convolutionNerveManagerB = templeConfig.getConvolutionNerveManagerB();
|
|
NerveManager convolutionNerveManagerG = templeConfig.getConvolutionNerveManagerG();
|
|
Matrix matrixR = threeChannelMatrix.getMatrixR();
|
|
Matrix matrixG = threeChannelMatrix.getMatrixG();
|
|
Matrix matrixB = threeChannelMatrix.getMatrixB();
|
|
//进卷积网络
|
|
MatrixBack matrixBackR = new MatrixBack();
|
|
MatrixBack matrixBackG = new MatrixBack();
|
|
MatrixBack matrixBackB = new MatrixBack();
|
|
intoConvolutionNetwork(1, matrixR, convolutionNerveManagerR.getSensoryNerves(),
|
|
isKernelStudy, tagging, matrixBackR);
|
|
intoConvolutionNetwork(1, matrixG, convolutionNerveManagerG.getSensoryNerves(),
|
|
isKernelStudy, tagging, matrixBackG);
|
|
intoConvolutionNetwork(1, matrixB, convolutionNerveManagerB.getSensoryNerves(),
|
|
isKernelStudy, tagging, matrixBackB);
|
|
if (isNerveStudy) {
|
|
Matrix myMatrixR = matrixBackR.getMatrix();
|
|
Matrix myMatrixG = matrixBackG.getMatrix();
|
|
Matrix myMatrixB = matrixBackB.getMatrix();
|
|
List<Double> featureALL = new ArrayList<>();
|
|
List<Double> featureR = getFeature(myMatrixR);
|
|
List<Double> featureG = getFeature(myMatrixG);
|
|
List<Double> featureB = getFeature(myMatrixB);
|
|
featureALL.addAll(featureR);
|
|
featureALL.addAll(featureG);
|
|
featureALL.addAll(featureB);
|
|
Map<Integer, Double> map = new HashMap<>();
|
|
map.put(tagging, 1.0);
|
|
intoDnnNetwork(1, featureALL, templeConfig.getSensoryNerves(), true, map, null);
|
|
}
|
|
|
|
}
|
|
|
|
public void threeNormalization(ThreeChannelMatrix threeChannelMatrix) throws Exception {
|
|
normalization(threeChannelMatrix.getMatrixR(), templeConfig.getConvolutionNerveManagerR());
|
|
normalization(threeChannelMatrix.getMatrixG(), templeConfig.getConvolutionNerveManagerG());
|
|
normalization(threeChannelMatrix.getMatrixB(), templeConfig.getConvolutionNerveManagerB());
|
|
|
|
}
|
|
|
|
public void normalization(Matrix matrix, NerveManager nerveManager) throws Exception {
|
|
Normalization normalization = templeConfig.getNormalization();
|
|
intoConvolutionNetwork(1, matrix, nerveManager.getSensoryNerves(),
|
|
false, 0, matrixBack);
|
|
Matrix myMatrix = matrixBack.getMatrix();
|
|
for (int i = 0; i < myMatrix.getX(); i++) {
|
|
for (int j = 0; j < myMatrix.getY(); j++) {
|
|
normalization.putFeature(myMatrix.getNumber(i, j));
|
|
}
|
|
}
|
|
}
|
|
|
|
//卷积核学习
|
|
public void learning(Matrix matrix, int tagging, boolean isNerveStudy) throws Exception {
|
|
if (templeConfig.getStudyPattern() == StudyPattern.Accuracy_Pattern) {
|
|
Border border = null;
|
|
if (templeConfig.isHavePosition() && isNerveStudy && tagging > 0) {
|
|
outBack = imageBack;
|
|
border = convolution.borderOnce(matrix, templeConfig);
|
|
}
|
|
boolean isKernelStudy = true;
|
|
if (isNerveStudy) {
|
|
isKernelStudy = false;
|
|
}
|
|
//进卷积网络
|
|
intoConvolutionNetwork(1, matrix, templeConfig.getConvolutionNerveManager().getSensoryNerves(),
|
|
isKernelStudy, tagging, matrixBack);
|
|
if (isNerveStudy) {
|
|
//卷积后的结果
|
|
Matrix myMatrix = matrixBack.getMatrix();
|
|
if (templeConfig.isHavePosition() && tagging > 0) {
|
|
border.end(myMatrix, tagging);
|
|
}
|
|
int classifier = templeConfig.getClassifier();
|
|
switch (classifier) {
|
|
case Classifier.DNN:
|
|
dnn(tagging, myMatrix);
|
|
break;
|
|
case Classifier.LVQ:
|
|
lvq(tagging, myMatrix);
|
|
break;
|
|
case Classifier.VAvg:
|
|
vectorAvg(tagging, myMatrix);
|
|
break;
|
|
}
|
|
}
|
|
} else {
|
|
throw new Exception("pattern is wrong");
|
|
}
|
|
}
|
|
|
|
private void dnn(int tagging, Matrix myMatrix) throws Exception {//DNN网络学习
|
|
Map<Integer, Double> map = new HashMap<>();
|
|
map.put(tagging, 1.0);
|
|
List<Double> feature = getFeature(myMatrix);
|
|
if (templeConfig.isShowLog()) {
|
|
System.out.println(feature);
|
|
}
|
|
intoDnnNetwork(1, feature, templeConfig.getSensoryNerves(), true, map, null);
|
|
}
|
|
|
|
private void vectorAvg(int tagging, Matrix myMatrix) throws Exception {//特征矩阵均值学习
|
|
Matrix vector = MatrixOperation.matrixToVector(myMatrix, true);
|
|
VectorK vectorK = templeConfig.getVectorK();
|
|
vectorK.insertMatrix(tagging, vector);
|
|
}
|
|
|
|
private void lvq(int tagging, Matrix myMatrix) throws Exception {//LVQ学习
|
|
LVQ lvq = templeConfig.getLvq();
|
|
Matrix vector = MatrixOperation.matrixToVector(myMatrix, true);
|
|
if (templeConfig.isShowLog()) {
|
|
System.out.println(vector.getString());
|
|
}
|
|
MatrixBody matrixBody = new MatrixBody();
|
|
matrixBody.setMatrix(vector);
|
|
matrixBody.setId(tagging);
|
|
lvq.insertMatrixBody(matrixBody);
|
|
}
|
|
|
|
private List<Double> getFeatures(Matrix matrix) throws Exception {
|
|
List<Double> list = new ArrayList<>();
|
|
for (int i = 0; i < matrix.getX(); i++) {
|
|
for (int j = 0; j < matrix.getY(); j++) {
|
|
double nub = matrix.getNumber(i, j);
|
|
list.add(nub);
|
|
}
|
|
}
|
|
return list;
|
|
}
|
|
|
|
private List<Double> getFeature(Matrix matrix) throws Exception {//将特征矩阵转化为集合并除10
|
|
List<Double> list = new ArrayList<>();
|
|
Normalization normalization = templeConfig.getNormalization();
|
|
double middle = normalization.getAvg();
|
|
for (int i = 0; i < matrix.getX(); i++) {
|
|
for (int j = 0; j < matrix.getY(); j++) {
|
|
double nub = matrix.getNumber(i, j);
|
|
if (nub != 0) {
|
|
nub = ArithUtil.sub(nub, middle);
|
|
list.add(nub);
|
|
} else {
|
|
list.add(0.0);
|
|
}
|
|
}
|
|
}
|
|
return list;
|
|
}
|
|
|
|
private List<List<Double>> getFeatures(Matrix matrix, int size) throws Exception {
|
|
List<List<Double>> lists = new ArrayList<>();
|
|
int x = matrix.getX() - size;//求导后矩阵的行数
|
|
int y = matrix.getY() - size;//求导后矩阵的列数
|
|
for (int i = 0; i < x; i += size) {//遍历行
|
|
for (int j = 0; j < y; j += size) {//遍历每行的列
|
|
Matrix myMatrix = matrix.getSonOfMatrix(i, j, size, size);
|
|
lists.add(getListFeature(myMatrix));
|
|
}
|
|
}
|
|
return lists;
|
|
}
|
|
|
|
private List<Double> getListFeature(Matrix matrix) throws Exception {
|
|
List<Double> list = new ArrayList<>();
|
|
int x = matrix.getX();
|
|
int y = matrix.getY();
|
|
for (int i = 0; i < x; i++) {
|
|
for (int j = 0; j < y; j++) {
|
|
double nub = matrix.getNumber(i, j) / 255;
|
|
list.add(nub);
|
|
}
|
|
}
|
|
return list;
|
|
}
|
|
|
|
//图像视觉 speed 模式
|
|
public void look(Matrix matrix, long eventId) throws Exception {
|
|
if (templeConfig.getStudyPattern() == StudyPattern.Speed_Pattern) {
|
|
List<Double> list = convolution(matrix, null);
|
|
intoDnnNetwork(eventId, list, templeConfig.getSensoryNerves(), false, null, outBack);
|
|
} else if (templeConfig.getStudyPattern() == StudyPattern.Accuracy_Pattern) {
|
|
throw new Exception("studyPattern not right");
|
|
}
|
|
}
|
|
|
|
public List<Integer> manyLook(Matrix matrix, long eventId) throws Exception {//无定位多物体识别
|
|
if (templeConfig.getStudyPattern() == StudyPattern.Accuracy_Pattern) {
|
|
List<Integer> list = new ArrayList<>();
|
|
Frame frame = templeConfig.getFrame();
|
|
List<FrameBody> frameBodies = convolution.getRegion(matrix, frame);
|
|
MatrixBack matrixBack = new MatrixBack();
|
|
for (FrameBody frameBody : frameBodies) {
|
|
intoConvolutionNetwork(eventId, frameBody.getMatrix(), templeConfig.getConvolutionNerveManager().getSensoryNerves(),
|
|
false, -1, matrixBack);
|
|
Matrix myMatrix = matrixBack.getMatrix();
|
|
int classifier = templeConfig.getClassifier();
|
|
int id = 0;
|
|
switch (classifier) {
|
|
case Classifier.LVQ:
|
|
id = getClassificationIdByLVQ(myMatrix);
|
|
break;
|
|
case Classifier.DNN:
|
|
id = getClassificationIdByDnn(myMatrix);
|
|
break;
|
|
case Classifier.VAvg:
|
|
id = getClassificationIdByVag(myMatrix);
|
|
break;
|
|
}
|
|
list.add(id);
|
|
}
|
|
return list;
|
|
} else {
|
|
throw new Exception("wrong model");
|
|
}
|
|
}
|
|
|
|
//边框检测+识别分类
|
|
public Map<Integer, List<FrameBody>> lookWithPosition(Matrix matrix, long eventId) throws Exception {
|
|
Frame frame = templeConfig.getFrame();
|
|
if (templeConfig.isHavePosition() && frame != null && frame.isReady()) {
|
|
//区域分割
|
|
List<FrameBody> frameBodies = convolution.getRegion(matrix, frame);
|
|
if (templeConfig.getStudyPattern() == StudyPattern.Speed_Pattern) {
|
|
int maxNub = 0;
|
|
if (templeConfig.getRow() >= templeConfig.getColumn()) {
|
|
maxNub = templeConfig.getRow();
|
|
} else {
|
|
maxNub = templeConfig.getColumn();
|
|
}
|
|
//坐标回调类
|
|
for (FrameBody frameBody : frameBodies) {
|
|
//Speed 模式下的最后卷积结果
|
|
Matrix matrix1 = convolution.getFeatures(frameBody.getMatrix(), maxNub, templeConfig, -1);
|
|
//卷积层输出即边框回归的输入的特征向量
|
|
frameBody.setEndMatrix(matrix1);
|
|
List<Double> list = sub(matrix1);
|
|
imageBack.setFrameBody(frameBody);
|
|
//进入神经网络判断
|
|
intoDnnNetwork(eventId, list, templeConfig.getSensoryNerves(), false, null, imageBack);
|
|
}
|
|
return toPosition(frameBodies, frame.getWidth(), frame.getHeight());
|
|
} else if (templeConfig.getStudyPattern() == StudyPattern.Accuracy_Pattern) {
|
|
MatrixBack matrixBack = new MatrixBack();
|
|
for (FrameBody frameBody : frameBodies) {
|
|
intoConvolutionNetwork(eventId, frameBody.getMatrix(), templeConfig.getConvolutionNerveManager().getSensoryNerves(),
|
|
false, -1, matrixBack);
|
|
Matrix myMatrix = matrixBack.getMatrix();
|
|
//卷积层输出即边框回归的输入的特征向量
|
|
frameBody.setEndMatrix(myMatrix);
|
|
int classifier = templeConfig.getClassifier();
|
|
int id = 0;
|
|
switch (classifier) {
|
|
case Classifier.LVQ:
|
|
id = getClassificationIdByLVQ(myMatrix);
|
|
break;
|
|
case Classifier.DNN:
|
|
id = getClassificationIdByDnn(myMatrix);
|
|
break;
|
|
case Classifier.VAvg:
|
|
id = getClassificationIdByVag(myMatrix);
|
|
break;
|
|
}
|
|
frameBody.setId(id);
|
|
}
|
|
return toPosition(frameBodies, frame.getWidth(), frame.getHeight());
|
|
} else {
|
|
throw new Exception("wrong model");
|
|
}
|
|
} else {
|
|
throw new Exception("position not study or frame is not ready");
|
|
}
|
|
}
|
|
|
|
private Map<Integer, List<FrameBody>> toPosition(List<FrameBody> frameBodies, int width, int height) throws Exception {//把分类都拿出来
|
|
for (FrameBody frameBody : frameBodies) {
|
|
if (frameBody.getPoint() > templeConfig.getTh()) {//存在一个识别分类
|
|
getBox(frameBody, width, height);
|
|
}
|
|
}
|
|
return result(frameBodies);
|
|
}
|
|
|
|
private Map<Integer, List<FrameBody>> result(List<FrameBody> frameBodies) {
|
|
Map<Integer, List<FrameBody>> map = new HashMap<>();
|
|
for (FrameBody frameBody : frameBodies) {
|
|
if (frameBody.getPoint() > templeConfig.getTh()) {//存在一个识别分类
|
|
int id = frameBody.getId();
|
|
if (map.containsKey(id)) {
|
|
List<FrameBody> frameBodies1 = map.get(id);
|
|
boolean isHere = false;
|
|
for (FrameBody frameBody1 : frameBodies1) {
|
|
double iou = getIou(frameBody1, frameBody);
|
|
if (iou > templeConfig.getIouTh()) {
|
|
isHere = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!isHere) {
|
|
frameBodies1.add(frameBody);
|
|
}
|
|
} else {
|
|
List<FrameBody> frameBodyList = new ArrayList<>();
|
|
frameBodyList.add(frameBody);
|
|
map.put(id, frameBodyList);
|
|
}
|
|
}
|
|
}
|
|
return map;
|
|
}
|
|
|
|
private Matrix getBoxMatrix(Matrix matrix, Map<Integer, Box> boxMap) throws Exception {
|
|
Matrix positionMatrix = null;
|
|
double endDist = -1;
|
|
for (Map.Entry<Integer, Box> entry : boxMap.entrySet()) {
|
|
Box box = entry.getValue();
|
|
Matrix boxMatrix = box.getMatrix();
|
|
double dist = MatrixOperation.getEDist(matrix, boxMatrix);
|
|
if (endDist == -1 || dist < endDist) {
|
|
endDist = dist;
|
|
positionMatrix = box.getMatrixPosition();
|
|
}
|
|
}
|
|
return positionMatrix;
|
|
}
|
|
|
|
//获得预测边框
|
|
private void getBox(FrameBody frameBody, int width, int height) throws Exception {
|
|
if (templeConfig.isBoxReady()) {
|
|
Matrix matrix = frameBody.getEndMatrix();
|
|
int id = frameBody.getId();
|
|
int x = frameBody.getX();
|
|
int y = frameBody.getY();
|
|
KClustering kClustering = templeConfig.getKClusteringMap().get(id);
|
|
Map<Integer, Box> boxMap = kClustering.getPositionMap();
|
|
//将矩阵化为向量
|
|
matrix = MatrixOperation.matrixToVector(matrix, true);
|
|
Matrix positionMatrix = getBoxMatrix(matrix, boxMap);
|
|
//锚点坐标及长宽预测值
|
|
double tx = positionMatrix.getNumber(0, 0);
|
|
double ty = positionMatrix.getNumber(0, 1);
|
|
double th = positionMatrix.getNumber(0, 3);
|
|
double tw = positionMatrix.getNumber(0, 2);
|
|
//修正相对位置
|
|
double realX = ArithUtil.add(ArithUtil.mul(tx, height), x);
|
|
double realY = ArithUtil.add(ArithUtil.mul(ty, width), y);
|
|
double realWidth = ArithUtil.mul(Math.exp(tw), width);
|
|
double realHeight = ArithUtil.mul(Math.exp(th), height);
|
|
frameBody.setRealX(realX);
|
|
frameBody.setRealY(realY);
|
|
frameBody.setRealWidth(realWidth);
|
|
frameBody.setRealHeight(realHeight);
|
|
} else {
|
|
throw new Exception("box is not study");
|
|
}
|
|
}
|
|
|
|
//计算两个边框的IOU
|
|
private double getIou(FrameBody frameBody1, FrameBody frameBody2) {
|
|
double iou = 1;
|
|
double s1 = ArithUtil.mul(frameBody1.getRealHeight(), frameBody1.getRealWidth());
|
|
double s2 = ArithUtil.mul(frameBody2.getRealHeight(), frameBody2.getRealWidth());
|
|
double s = ArithUtil.add(s1, s2);
|
|
double minX1 = frameBody1.getRealX();
|
|
double minY1 = frameBody1.getRealY();
|
|
double maxX1 = ArithUtil.add(minX1, frameBody1.getRealHeight());
|
|
double maxY1 = ArithUtil.add(minY1, frameBody1.getRealWidth());
|
|
double minX2 = frameBody2.getRealX();
|
|
double minY2 = frameBody2.getRealY();
|
|
double maxX2 = ArithUtil.add(minX2, frameBody2.getRealHeight());
|
|
double maxY2 = ArithUtil.add(minY2, frameBody2.getRealWidth());
|
|
double maxMinX, minMaxX, maxMinY, minMaxY;
|
|
if (maxX2 > maxX1) {
|
|
maxMinX = maxX1;
|
|
} else {
|
|
maxMinX = maxX2;
|
|
}
|
|
if (minX2 > minX1) {
|
|
minMaxX = minX2;
|
|
} else {
|
|
minMaxX = minX1;
|
|
}
|
|
if (maxY2 > maxY1) {
|
|
maxMinY = maxY1;
|
|
} else {
|
|
maxMinY = maxY2;
|
|
}
|
|
if (minY2 > minY1) {
|
|
minMaxY = minY2;
|
|
} else {
|
|
minMaxY = minY1;
|
|
}
|
|
double intersectX = ArithUtil.sub(maxMinX, minMaxX);//相交X
|
|
double intersectY = ArithUtil.sub(maxMinY, minMaxY);//相交Y
|
|
if (intersectX < 0) {
|
|
intersectX = 0;
|
|
}
|
|
if (intersectY < 0) {
|
|
intersectY = 0;
|
|
}
|
|
double intersectS = ArithUtil.mul(intersectX, intersectY);//相交面积
|
|
double mergeS = ArithUtil.sub(s, intersectS);//相并面积
|
|
iou = ArithUtil.div(intersectS, mergeS);
|
|
return iou;
|
|
}
|
|
|
|
public double toSeeById(Matrix matrix, int id) throws Exception {//返回某一个分类的概率
|
|
intoConvolutionNetwork(2, matrix, templeConfig.getConvolutionNerveManager().getSensoryNerves(),
|
|
false, 0, matrixBack);
|
|
List<Double> list = getFeature(matrixBack.getMatrix());
|
|
MaxPoint maxPoint = new MaxPoint();
|
|
maxPoint.setPid(id);
|
|
long t = IdCreator.get().nextId();
|
|
intoDnnNetwork(t, list, templeConfig.getSensoryNerves(), false, null, maxPoint);
|
|
return maxPoint.getpPoint();
|
|
}
|
|
|
|
//图像视觉 Accuracy 模式
|
|
public int toSee(Matrix matrix) throws Exception {
|
|
if (templeConfig.getStudyPattern() == StudyPattern.Accuracy_Pattern) {
|
|
intoConvolutionNetwork(2, matrix, templeConfig.getConvolutionNerveManager().getSensoryNerves(),
|
|
false, 0, matrixBack);
|
|
Matrix myMatrix = matrixBack.getMatrix();
|
|
int classifier = templeConfig.getClassifier();
|
|
int id = -1;
|
|
switch (classifier) {
|
|
case Classifier.LVQ:
|
|
id = getClassificationIdByLVQ(myMatrix);
|
|
break;
|
|
case Classifier.DNN:
|
|
id = getClassificationIdByDnn(myMatrix);
|
|
break;
|
|
case Classifier.VAvg:
|
|
id = getClassificationIdByVag(myMatrix);
|
|
break;
|
|
}
|
|
return id;
|
|
} else {
|
|
throw new Exception("pattern is wrong");
|
|
}
|
|
}
|
|
|
|
private int getClassificationIdByDnn(Matrix myMatrix) throws Exception {
|
|
List<Double> list = getFeature(myMatrix);
|
|
MaxPoint maxPoint = new MaxPoint();
|
|
maxPoint.setTh(templeConfig.getTh());
|
|
long id = IdCreator.get().nextId();
|
|
intoDnnNetwork(id, list, templeConfig.getSensoryNerves(), false, null, maxPoint);
|
|
return maxPoint.getId();
|
|
}
|
|
|
|
private int getClassificationIdByVag(Matrix myMatrix) throws Exception {//VAG获取分类
|
|
Matrix myVector = MatrixOperation.matrixToVector(myMatrix, true);
|
|
Map<Integer, Matrix> matrixK = templeConfig.getVectorK().getMatrixK();
|
|
double minDist = 0;
|
|
int id = 0;
|
|
for (Map.Entry<Integer, Matrix> entry : matrixK.entrySet()) {
|
|
Matrix matrix = entry.getValue();
|
|
double dist = MatrixOperation.getEDist(matrix, myVector);
|
|
//System.out.println("距离===" + dist + ",类别==" + entry.getKey());
|
|
if (minDist == 0 || dist < minDist) {
|
|
minDist = dist;
|
|
id = entry.getKey();
|
|
}
|
|
}
|
|
return id;
|
|
}
|
|
|
|
private int getClassificationIdByLVQ(Matrix myMatrix) throws Exception {//LVQ获取分类
|
|
Matrix myVector = MatrixOperation.matrixToVector(myMatrix, true);
|
|
int id = 0;
|
|
double distEnd = 0;
|
|
LVQ lvq = templeConfig.getLvq();
|
|
MatrixBody[] matrixBodies = lvq.getModel();
|
|
for (int i = 0; i < matrixBodies.length; i++) {
|
|
MatrixBody matrixBody = matrixBodies[i];
|
|
Matrix vector = matrixBody.getMatrix();
|
|
double dist = lvq.vectorEqual(myVector, vector);
|
|
if (distEnd == 0 || dist < distEnd) {
|
|
id = matrixBody.getId();
|
|
distEnd = dist;
|
|
}
|
|
}
|
|
return id;
|
|
}
|
|
|
|
public double isCover(ThreeChannelMatrix threeChannelMatrix) throws Exception {//固定背景覆盖率计算
|
|
ThreeChannelMatrix backGround = templeConfig.getBackGround();
|
|
double errorBack = templeConfig.getBackGroundError();
|
|
if (backGround != null && errorBack >= 0 && errorBack <= 255) {
|
|
Matrix matrixR = threeChannelMatrix.getMatrixR();
|
|
Matrix matrixG = threeChannelMatrix.getMatrixG();
|
|
Matrix matrixB = threeChannelMatrix.getMatrixB();
|
|
Matrix matrixRBg = backGround.getMatrixR();
|
|
Matrix matrixGBg = backGround.getMatrixG();
|
|
Matrix matrixBBg = backGround.getMatrixB();
|
|
int x = matrixR.getX();
|
|
int y = matrixR.getY();
|
|
double size = x * y;
|
|
double cover = 0;
|
|
if (x == matrixRBg.getX() && y == matrixRBg.getY()) {
|
|
for (int i = 0; i < x; i++) {
|
|
for (int j = 0; j < y; j++) {
|
|
double rB = matrixRBg.getNumber(i, j);
|
|
double gB = matrixGBg.getNumber(i, j);
|
|
double bB = matrixBBg.getNumber(i, j);
|
|
double r = matrixR.getNumber(i, j);
|
|
double g = matrixG.getNumber(i, j);
|
|
double b = matrixB.getNumber(i, j);
|
|
double subR = Math.abs(r - rB);
|
|
double subG = Math.abs(g - gB);
|
|
double subB = Math.abs(b - bB);
|
|
double error = (subR + subB + subG) / 3;
|
|
if (error > errorBack) {
|
|
cover++;
|
|
}
|
|
}
|
|
}
|
|
return cover / size;
|
|
} else {
|
|
throw new Exception("Temple matrix is different");
|
|
}
|
|
} else {
|
|
throw new Exception("value is null");
|
|
}
|
|
}
|
|
|
|
private List<Double> sub(Matrix matrix) throws Exception {//
|
|
List<Double> list = new ArrayList<>();
|
|
int x = matrix.getX() - 1;
|
|
int y = matrix.getY() - 1;
|
|
for (int i = 0; i < templeConfig.getRow(); i++) {
|
|
for (int j = 0; j < templeConfig.getColumn(); j++) {
|
|
if (i > x || j > y) {
|
|
list.add(0.0);
|
|
} else {
|
|
list.add(matrix.getNumber(i, j));
|
|
}
|
|
}
|
|
}
|
|
return list;
|
|
}
|
|
|
|
/**
|
|
* @param eventId 事件ID
|
|
* @param featureList 特征集合
|
|
* @param sensoryNerveList 感知神经元集合
|
|
* @param isStudy 是否学习
|
|
* @param map 标注
|
|
* @param outBack 输出结果回调类
|
|
*/
|
|
|
|
private void intoDnnNetwork(long eventId, List<Double> featureList, List<SensoryNerve> sensoryNerveList
|
|
, boolean isStudy, Map<Integer, Double> map, OutBack outBack) throws Exception {//进入DNN 神经网络
|
|
for (int i = 0; i < sensoryNerveList.size(); i++) {
|
|
sensoryNerveList.get(i).postMessage(eventId, featureList.get(i), isStudy, map
|
|
, outBack);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param eventId 事件ID
|
|
* @param feature 特征矩阵
|
|
* @param sensoryNerveList 感知神经元集合
|
|
* @param isKernelStudy 是否进行核学习
|
|
* @param E 期望矩阵
|
|
* @param outBack 输出结果回调类
|
|
*/
|
|
private void intoConvolutionNetwork(long eventId, Matrix feature, List<SensoryNerve> sensoryNerveList
|
|
, boolean isKernelStudy, int E, OutBack outBack) throws Exception {//进入卷积神经网络
|
|
for (int i = 0; i < sensoryNerveList.size(); i++) {
|
|
sensoryNerveList.get(i).postMatrixMessage(eventId, feature, isKernelStudy, E, outBack);
|
|
}
|
|
}
|
|
} |