diff --git a/easyAi.iml b/easyAi.iml deleted file mode 100644 index 389499f..0000000 --- a/easyAi.iml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/main/java/org/wlld/imageRecognition/Convolution.java b/src/main/java/org/wlld/imageRecognition/Convolution.java index 8e9d8c9..c424b11 100644 --- a/src/main/java/org/wlld/imageRecognition/Convolution.java +++ b/src/main/java/org/wlld/imageRecognition/Convolution.java @@ -10,8 +10,7 @@ import org.wlld.imageRecognition.modelEntity.RegressionBody; import org.wlld.tools.ArithUtil; import org.wlld.tools.Frequency; -import java.util.ArrayList; -import java.util.List; +import java.util.*; /** * @author lidapeng @@ -19,6 +18,8 @@ import java.util.List; * @date 9:23 上午 2020/1/2 */ public class Convolution extends Frequency { + private MeanClustering meanClustering; + protected Matrix getFeatures(Matrix matrix, int maxNub, TempleConfig templeConfig , int id) throws Exception { boolean isFirst = true; @@ -39,6 +40,88 @@ public class Convolution extends Frequency { return matrix; } + public void kc(ThreeChannelMatrix threeChannelMatrix, int size, int sqNub) throws Exception { + Matrix matrixR = threeChannelMatrix.getMatrixR(); + Matrix matrixG = threeChannelMatrix.getMatrixG(); + Matrix matrixB = threeChannelMatrix.getMatrixB(); + matrixR = late(matrixR, size); + matrixG = late(matrixG, size); + matrixB = late(matrixB, size); + int x = matrixR.getX(); + int y = matrixR.getY(); + meanClustering = new MeanClustering(sqNub); + for (int i = 0; i < x; i++) { + for (int j = 0; j < y; j++) { + double[] color = new double[]{matrixR.getNumber(i, j) / 255, matrixG.getNumber(i, j) / 255, matrixB.getNumber(i, j) / 255}; + meanClustering.setColor(color); + } + } + meanClustering.start(); + List rgbNorms = meanClustering.getMatrices(); + double minNorm = 0; + int normSize = rgbNorms.size(); + for (int i = 0; i < normSize; i++) { + RGBNorm rgbNorm = rgbNorms.get(i); + double[] rgb = rgbNorm.getRgb(); + for (int j = 0; j < normSize; j++) { + if (j != i) { + double normSub = getEDist(rgb, rgbNorms.get(j).getRgb()); + if (minNorm == 0 || normSub < minNorm) { + minNorm = normSub; + } + } + } + } + minNorm = ArithUtil.div(minNorm, 2); + System.out.println("min==" + minNorm); + } + + private void checkImage(Matrix matrixR, Matrix matrixG, Matrix matrixB, double minNorm, int size) { + List> lists = new ArrayList<>(); + int x = matrixR.getX() - size;//求导后矩阵的行数 + int y = matrixR.getY() - size;//求导后矩阵的列数 + for (int i = 0; i < x; i += size) {//遍历行 + for (int j = 0; j < y; j += size) {//遍历每行的列 + Matrix myMatrixR = matrixR.getSonOfMatrix(i, j, size, size); + Matrix myMatrixG = matrixG.getSonOfMatrix(i, j, size, size); + Matrix myMatrixB = matrixB.getSonOfMatrix(i, j, size, size); + + } + } + } + + private void getListFeature(Matrix matrixR, Matrix matrixG, Matrix matrixB, double minNorm) throws Exception { + int x = matrixR.getX(); + int y = matrixR.getY(); + Map map = new HashMap<>(); + List rgbNormList = meanClustering.getMatrices(); + for (int i = 0; i < x; i++) { + for (int j = 0; j < y; j++) { + double[] color = new double[]{matrixR.getNumber(i, j) / 255, matrixG.getNumber(i, j) / 255, matrixB.getNumber(i, j) / 255}; + int id = -1; + double feature = 0; + double minDist = 0; + for (int t = 0; t < rgbNormList.size(); t++) { + RGBNorm rgbNorm = rgbNormList.get(t); + double dist = getEDist(color, rgbNorm.getRgb()); + if (minDist == 0 || dist < minDist) { + minDist = dist; + id = t; + } + } + if (minDist >= minNorm) { + id = -1; + } + if (id > -1) { + feature = rgbNormList.get(id).getNorm(); + } + if (!map.containsKey(feature)) { + map.put(feature, 1); + } + } + } + } + public List> imageTrance(Matrix matrix, int size, int featureNub) throws Exception {//矩阵和卷积核大小 int xn = matrix.getX(); int yn = matrix.getY(); @@ -160,14 +243,18 @@ public class Convolution extends Frequency { for (int j = 0; j < yn - size; j += size) { Matrix matrix1 = matrix.getSonOfMatrix(i, j, size, size); double maxNub = 0; + int n = size * size; + double sigma = 0; for (int t = 0; t < matrix1.getX(); t++) { for (int k = 0; k < matrix1.getY(); k++) { double nub = matrix1.getNumber(t, k); + sigma = sigma + nub; if (nub > maxNub) { maxNub = nub; } } } + maxNub = ArithUtil.div(sigma, n); //迟化的最大值是 MAXNUB myMatrix.setNub(i / size, j / size, maxNub); } diff --git a/src/main/java/org/wlld/imageRecognition/MeanClustering.java b/src/main/java/org/wlld/imageRecognition/MeanClustering.java new file mode 100644 index 0000000..26c9177 --- /dev/null +++ b/src/main/java/org/wlld/imageRecognition/MeanClustering.java @@ -0,0 +1,96 @@ +package org.wlld.imageRecognition; + +import java.util.*; + +//K均值聚类 +public class MeanClustering { + private List matrixList = new ArrayList<>();//聚类集合 + private int length;//向量长度(模型需要返回) + private int speciesQuantity;//种类数量(模型需要返回) + private List matrices = new ArrayList<>();//均值K模型(模型需要返回) + + public List getMatrices() { + return matrices; + } + + public MeanClustering(int speciesQuantity) { + this.speciesQuantity = speciesQuantity;//聚类的数量 + } + + public void setColor(double[] color) throws Exception { + if (matrixList.size() == 0) { + matrixList.add(color); + length = color.length; + } else { + if (length == color.length) { + matrixList.add(color); + } else { + throw new Exception("vector length is different"); + } + } + } + + private void averageMatrix() { + for (double[] rgb : matrixList) {//遍历当前集合 + double min = -1; + int id = 0; + for (int i = 0; i < speciesQuantity; i++) { + RGBNorm rgbNorm = matrices.get(i); + double dist = rgbNorm.getEDist(rgb); + if (min == -1 || dist < min) { + min = dist; + id = i; + } + } + //进簇 + RGBNorm rgbNorm = matrices.get(id); + rgbNorm.setColor(rgb); + } + //重新计算均值 + for (RGBNorm rgbNorm : matrices) { + rgbNorm.norm(); + } + } + + private boolean isNext() { + boolean isNext = false; + for (RGBNorm rgbNorm : matrices) { + isNext = rgbNorm.compare(); + if (isNext) { + break; + } + } + return isNext; + } + + private void clear() { + for (RGBNorm rgbNorm : matrices) { + rgbNorm.clear(); + } + } + + public void start() throws Exception {//开始聚类 + if (matrixList.size() > 1) { + Random random = new Random(); + for (int i = 0; i < speciesQuantity; i++) {//初始化均值向量 + int index = random.nextInt(matrixList.size()); + double[] rgb = matrixList.get(index); + RGBNorm rgbNorm = new RGBNorm(rgb); + //要进行深度克隆 + matrices.add(rgbNorm); + } + //进行两者的比较 + boolean isNext; + do { + averageMatrix(); + isNext = isNext(); + if (isNext) { + clear(); + } + } + while (isNext); + } else { + throw new Exception("matrixList number less than 2"); + } + } +} diff --git a/src/main/java/org/wlld/imageRecognition/RGBNorm.java b/src/main/java/org/wlld/imageRecognition/RGBNorm.java new file mode 100644 index 0000000..19b5c04 --- /dev/null +++ b/src/main/java/org/wlld/imageRecognition/RGBNorm.java @@ -0,0 +1,84 @@ +package org.wlld.imageRecognition; + +import org.wlld.tools.ArithUtil; + +import java.util.Arrays; + +public class RGBNorm { + private double[] rgbAll = new double[3]; + private double norm; + private int nub; + private double[] rgb = new double[3]; + private double[] rgbUp; + + RGBNorm(double[] rgb) { + this.rgbUp = rgb; + } + + public void syn() { + rgbUp = rgb; + } + + public void clear() { + rgbAll = new double[3]; + nub = 0; + for (int i = 0; i < rgb.length; i++) { + rgbUp[i] = rgb[i]; + } + //System.out.println("clear==" + Arrays.toString(rgbUp)); + } + + public int getNub() { + return nub; + } + + public boolean compare() { + boolean isNext = false; + for (int i = 0; i < rgb.length; i++) { + if (rgb[i] != rgbUp[i]) { + isNext = true; + break; + } + } + return isNext; + } + + public double getEDist(double[] x) { + double[] y = new double[x.length]; + for (int i = 0; i < y.length; i++) { + y[i] = x[i] - rgbUp[i]; + } + double sigma = 0; + for (int i = 0; i < y.length; i++) { + sigma = sigma + Math.pow(y[i], 2); + } + return Math.sqrt(sigma); + } + + public void setColor(double[] rgb) { + for (int i = 0; i < rgb.length; i++) { + rgbAll[i] = rgbAll[i] + rgb[i]; + } + nub++; + } + + public void norm() {//范长计算 + double sigma = 0; + if (nub > 0) { + for (int i = 0; i < rgb.length; i++) { + double rgbc = ArithUtil.div(rgbAll[i], nub); + rgb[i] = rgbc; + sigma = sigma + Math.pow(rgbc, 2); + } + norm = Math.sqrt(sigma); + } + } + + public double getNorm() { + return norm; + } + + public double[] getRgb() { + return rgb; + } +} diff --git a/src/main/java/org/wlld/imageRecognition/border/KClustering.java b/src/main/java/org/wlld/imageRecognition/border/KClustering.java index 69ad9f8..e73f4a4 100644 --- a/src/main/java/org/wlld/imageRecognition/border/KClustering.java +++ b/src/main/java/org/wlld/imageRecognition/border/KClustering.java @@ -60,7 +60,7 @@ public class KClustering { } public KClustering(int speciesQuantity) { - this.speciesQuantity = speciesQuantity; + this.speciesQuantity = speciesQuantity;//聚类的数量 matrices = new Matrix[speciesQuantity]; for (int i = 0; i < speciesQuantity; i++) { clusterMap.put(i, new ArrayList<>()); @@ -163,8 +163,7 @@ public class KClustering { matrices[i] = matrixList.get(index).getMatrix(); } //进行两者的比较 - boolean isEqual = false; - int nub = 0; + boolean isEqual; do { Matrix[] matrices2 = averageMatrix(); isEqual = equals(matrices, matrices2); @@ -172,7 +171,6 @@ public class KClustering { matrices = matrices2; clear(); } - nub++; } while (!isEqual); //聚类结束,进行坐标均值矩阵计算 diff --git a/src/main/java/org/wlld/imageRecognition/segmentation/ImageSegmentation.java b/src/main/java/org/wlld/imageRecognition/segmentation/ImageSegmentation.java index eddc4df..44d85a0 100644 --- a/src/main/java/org/wlld/imageRecognition/segmentation/ImageSegmentation.java +++ b/src/main/java/org/wlld/imageRecognition/segmentation/ImageSegmentation.java @@ -1,6 +1,7 @@ package org.wlld.imageRecognition.segmentation; import org.wlld.MatrixTools.Matrix; +import org.wlld.imageRecognition.ThreeChannelMatrix; import java.util.HashMap; import java.util.Map; @@ -11,14 +12,26 @@ import java.util.Map; * @date 10:25 上午 2020/1/13 */ public class ImageSegmentation { - private Matrix regionMap; - private Matrix matrix; + private Matrix matrixR; + private Matrix matrixG; + private Matrix matrixB; private Map regionBodyList = new HashMap<>(); private int id = 1; - public ImageSegmentation(Matrix matrix) { - this.matrix = matrix; - regionMap = new Matrix(matrix.getX(), matrix.getY()); + public ImageSegmentation(ThreeChannelMatrix threeChannelMatrix) throws Exception { + matrixR = threeChannelMatrix.getMatrixR(); + matrixG = threeChannelMatrix.getMatrixG(); + matrixB = threeChannelMatrix.getMatrixB(); + int x = matrixR.getX(); + int y = matrixR.getY(); + for (int i = 0; i < x; i++) { + for (int j = 0; j < y; j++) { + double r = matrixR.getNumber(i, j); + double g = matrixG.getNumber(i, j); + double b = matrixB.getNumber(i, j); + + } + } } public int getMin(double[] array) { @@ -33,106 +46,4 @@ public class ImageSegmentation { return minIdx; } - private void connect(int x, int y) throws Exception { - double self = matrix.getNumber(x, y); - double rightPixel = matrix.getNumber(x, y + 1); - double leftPixel = matrix.getNumber(x, y - 1); - double bottomPixel = matrix.getNumber(x + 1, y); - double topPixel = matrix.getNumber(x - 1, y); - - double right = Math.abs(rightPixel - self); - double left = Math.abs(leftPixel - self); - double bottom = Math.abs(bottomPixel - self); - double top = Math.abs(topPixel - self); - double[] array = new double[]{left, right, top, bottom}; - double[] pixelArray = new double[]{leftPixel, rightPixel, topPixel, bottomPixel}; - int minIndex = getMin(array); - int i, j; - switch (minIndex) { - case 0: - i = x; - j = y - 1; - break; - case 1: - i = x; - j = y + 1; - break; - case 2: - i = x - 1; - j = y; - break; - case 3: - i = x + 1; - j = y; - break; - default: - throw new IllegalStateException("Unexpected value: " + minIndex); - } - int type = (int) regionMap.getNumber(i, j); - if (type > 0) {//有选区了 - RegionBody regionBody = regionBodyList.get(type); - regionBody.insertPosition(x, y, regionMap); - regionBody.setPixel(self); - } else {//链接最小方向的节点没有属于任何区域 - RegionBody regionBody = new RegionBody(id); - regionBody.insertPosition(x, y, regionMap); - regionBody.insertPosition(i, j, regionMap); - regionBody.setPixel(pixelArray[minIndex]); - regionBody.setPixel(self); - regionBodyList.put(id, regionBody); - id++; - } - } - - public void createMST() throws Exception { - int x = matrix.getX() - 1; - int y = matrix.getY() - 1; - for (int i = 1; i < x; i++) { - for (int j = 1; j < y; j++) { - if (regionMap.getNumber(i, j) == 0.0) { - connect(i, j); - } - } - } - for (int i = 0; i < 3; i++) { - mergeMSTX(); - } - } - - - private void mergeMSTX() throws Exception {//合并选区 - int x = matrix.getX() - 1; - int y = matrix.getY() - 1; - int now = (int) regionMap.getNumber(1, 1); - int nowX = 1; - int nowY = 1; - for (int i = 1; i < x; i++) { - for (int j = 1; j < y; j++) { - int self = (int) regionMap.getNumber(i, j); - if (now != self) {//遇到不同选区 区域NOW尝试与区域self合并 - double nowPoint = matrix.getNumber(nowX, nowY); - double selfPoint = matrix.getNumber(i, j); - RegionBody nowMST = regionBodyList.get(now); - RegionBody selfMST = regionBodyList.get(self); - double nowDiff = nowMST.getMaxDiff(); - double selfDiff = selfMST.getMaxDiff(); - double diff = Math.abs(nowPoint - selfPoint);//当前边的差异性 - double minDiff; - if (nowDiff > selfDiff) {//差异性最小的是SELF - minDiff = selfDiff; - } else {//差异性最小的是NOW - minDiff = nowDiff; - } - if (diff <= minDiff) {//进行合并 - nowMST.merge(selfMST, regionMap); - regionBodyList.remove(self); - } else {//不进行合并 - now = self; - } - } - nowX = i; - nowY = j; - } - } - } } diff --git a/src/main/java/org/wlld/imageRecognition/segmentation/RegionBody.java b/src/main/java/org/wlld/imageRecognition/segmentation/RegionBody.java index 5eb8ee4..1d14e2f 100644 --- a/src/main/java/org/wlld/imageRecognition/segmentation/RegionBody.java +++ b/src/main/java/org/wlld/imageRecognition/segmentation/RegionBody.java @@ -10,99 +10,5 @@ import java.util.List; * @description 分区实体 */ public class RegionBody { - private int minX = -1; - private int maxX = -1; - private int minY = -1; - private int maxY = -1; - private int point = 0xFFF; - private int bit = 4 * 3; - private int id;//本区域主键 - private double minPixel = -1;//最小像素值 - private double maxPixel = 0;//最大像素值 - private List pixels = new ArrayList<>(); - public int getMinX() { - return minX; - } - - public int getMaxX() { - return maxX; - } - - public int getMinY() { - return minY; - } - - public int getMaxY() { - return maxY; - } - - RegionBody(int id) { - this.id = id; - } - - public double getMaxDiff() { - return maxPixel - minPixel; - } - - public int getHeight() { - return maxX - minX; - } - - public int getWidth() { - return maxY - minY; - } - - public void merge(RegionBody body, Matrix regionMap) throws Exception {//合并区域 - List myPixels = body.getPixels(); - setPixel(body.getMaxPixel()); - setPixel(body.getMinPixel()); - for (int pixel : myPixels) { - int x = pixel >> bit; - int y = pixel & point; - insertPosition(x, y, regionMap); - } - - } - - public void setPixel(double pixel) { - if (pixel < minPixel || minPixel == -1) { - minPixel = pixel; - } - if (pixel > maxPixel) { - maxPixel = pixel; - } - } - - public void insertPosition(int x, int y, Matrix regionMap) throws Exception { - if (x < minX || minX == -1) { - minX = x; - } - if (y < minY || minY == -1) { - minY = y; - } - if (x > maxX) { - maxX = x; - } - if (y > maxY) { - maxY = y; - } - //行在前,列在后 - int pixel = x << bit | y; - pixels.add(pixel); - //给区域地图中的像素分配区域ID - regionMap.setNub(x, y, id); - } - - public double getMinPixel() { - return minPixel; - } - - public double getMaxPixel() { - return maxPixel; - } - - public List getPixels() { - return pixels; - } } diff --git a/src/main/java/org/wlld/tools/Frequency.java b/src/main/java/org/wlld/tools/Frequency.java index 938b3fe..aa4fa69 100644 --- a/src/main/java/org/wlld/tools/Frequency.java +++ b/src/main/java/org/wlld/tools/Frequency.java @@ -14,6 +14,18 @@ public abstract class Frequency {//统计频数 return allNub; } + public double getEDist(double[] x1, double[] x2) {//返回两个等长数组之间的欧式距离 + double[] y = new double[x1.length]; + for (int i = 0; i < y.length; i++) { + y[i] = x1[i] - x2[i]; + } + double sigma = 0; + for (int i = 0; i < y.length; i++) { + sigma = sigma + Math.pow(y[i], 2); + } + return Math.sqrt(sigma); + } + public double averageByList(List m) {//计算平均值 int len = m.size(); double allNub = 0; diff --git a/src/test/java/coverTest/CoverTest.java b/src/test/java/coverTest/CoverTest.java index ba0bc5c..761ddbd 100644 --- a/src/test/java/coverTest/CoverTest.java +++ b/src/test/java/coverTest/CoverTest.java @@ -7,12 +7,11 @@ import org.wlld.ModelData; import org.wlld.config.RZ; import org.wlld.config.StudyPattern; import org.wlld.function.Sigmod; -import org.wlld.imageRecognition.Operation; -import org.wlld.imageRecognition.Picture; -import org.wlld.imageRecognition.TempleConfig; +import org.wlld.imageRecognition.*; import org.wlld.nerveEntity.ModelParameter; import org.wlld.tools.ArithUtil; +import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -23,7 +22,7 @@ import java.util.Map; */ public class CoverTest { public static void main(String[] args) throws Exception { - cover(); + cover2(); //test(null, 25, 3); } @@ -107,6 +106,14 @@ public class CoverTest { System.out.println("wrongPoint==" + wrongPoint + "%"); } + public static void cover2() throws Exception { + Convolution convolution = new Convolution(); + Picture picture = new Picture(); + ThreeChannelMatrix threeChannelMatrix = picture.getThreeMatrix("D:\\docment/a.jpg"); + convolution.kc(threeChannelMatrix, 5, 5); + + } + //覆盖率学习 有学习才能有识别 public static void cover() throws Exception { //创建图片解析类 桔梗覆盖,桔梗焚烧,土壤扰动