This commit is contained in:
2025-09-04 14:09:11 +08:00
parent 5741100181
commit aabe919de1

View File

@@ -0,0 +1,356 @@
package org.dromara.easyai.entity;
import org.dromara.easyai.matrixTools.Matrix;
import org.dromara.easyai.matrixTools.MatrixOperation;
public class ThreeChannelMatrix {
private Matrix matrixR;
private Matrix matrixG;
private Matrix matrixB;
private Matrix H;
private int x;
private int y;
private final MatrixOperation matrixOperation = new MatrixOperation();
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public float getDist(ThreeChannelMatrix th) throws Exception {
if (th.getX() == x && th.getY() == y) {
float subR = matrixOperation.getEDistByMatrix(matrixR, th.getMatrixR());
float subG = matrixOperation.getEDistByMatrix(matrixG, th.getMatrixG());
float subB = matrixOperation.getEDistByMatrix(matrixB, th.getMatrixB());
return (subR + subB + subG) / 3;
} else {
throw new Exception("图像尺寸大小不匹配本图像尺寸x是" + x + ",y:" + y + "。待匹配尺寸图像 x:" + th.getX() +
",y:" + th.getY());
}
}
public void grayscaleScale(float toR, float toG, float toB) throws Exception {//灰度缩放
MatrixOperation matrixOperation = new MatrixOperation();
float avgR = matrixR.getAVG();
float avgG = matrixG.getAVG();
float avgB = matrixB.getAVG();
float rk = toR / avgR;
float gk = toG / avgG;
float bk = toB / avgB;
matrixOperation.mathMul(matrixR, rk);
matrixOperation.mathMul(matrixG, gk);
matrixOperation.mathMul(matrixB, bk);
}
//生成一个高斯核
private Matrix createGaussianKern(float sd, int kerSize) throws Exception {
float a = (float) (1 / (2 * (float) Math.PI * (float) Math.pow(sd, 2)));
Matrix matrix = new Matrix(kerSize, kerSize);
int half = kerSize / 2;
for (int i = 0; i < kerSize; i++) {
for (int j = 0; j < kerSize; j++) {
int xIndex = i - half;
int yIndex = j - half;
float b = (float) Math.exp(-((float) Math.pow(xIndex, 2) + (float) Math.pow(yIndex, 2)) / (2 * (float) Math.pow(sd, 2)));
matrix.setNub(i, j, a * b);
}
}
float sigma = matrix.getSigma();
matrixOperation.mathDiv(matrix, sigma);
return matrix;
}
public ThreeChannelMatrix rotate(double rotateSize) throws Exception {//旋转
ThreeChannelMatrix outPic = new ThreeChannelMatrix();
Matrix matrixRR = new Matrix(x, y);
Matrix matrixGG = new Matrix(x, y);
Matrix matrixBB = new Matrix(x, y);
outPic.setX(x);
outPic.setY(y);
outPic.setMatrixR(matrixRR);
outPic.setMatrixG(matrixGG);
outPic.setMatrixB(matrixBB);
double centerX = x / 2d;//中心点坐标
double centerY = y / 2d;//中心点坐标
for (int i = 0; i < x; i++) {
for (int j = 0; j < y; j++) {
double nj = (j - centerY) * Math.cos(rotateSize) - (i - centerX) * Math.sin(rotateSize) + centerY;
double ni = (j - centerY) * Math.sin(rotateSize) + (i - centerX) * Math.cos(rotateSize) + centerX;
int tj = (int) nj;
int ti = (int) ni;
float r = matrixR.getNumber(i, j);
float g = matrixG.getNumber(i, j);
float b = matrixB.getNumber(i, j);
if (ti > 0 && ti < x && tj > 0 && tj < y) {
matrixRR.setNub(ti, tj, r);
matrixGG.setNub(ti, tj, g);
matrixBB.setNub(ti, tj, b);
}
}
}
return outPic;
}
public Matrix calculateAvgGrayscale() throws Exception {//计算均值灰度
Matrix matrix = new Matrix(x, y);
for (int i = 0; i < x; i++) {
for (int j = 0; j < y; j++) {
float value = (matrixR.getNumber(i, j) + matrixG.getNumber(i, j) + matrixB.getNumber(i, j)) / 3F;
matrix.setNub(i, j, value);
}
}
return matrix;
}
public ThreeChannelMatrix gaussianVague(float sd, int kerSize, boolean scaleWidth, float scaleSize) throws Exception {//高斯模糊
if (kerSize % 2 != 1) {
throw new Exception("高斯核大小必须为奇数");
}
ThreeChannelMatrix threeChannelMatrix = scale(scaleWidth, scaleSize);
Matrix matrixR = threeChannelMatrix.getMatrixR();
Matrix matrixG = threeChannelMatrix.getMatrixG();
Matrix matrixB = threeChannelMatrix.getMatrixB();
Matrix gaussianMatrix = createGaussianKern(sd, kerSize);
Matrix gr = conv(matrixR, gaussianMatrix, kerSize);
Matrix gg = conv(matrixG, gaussianMatrix, kerSize);
Matrix gb = conv(matrixB, gaussianMatrix, kerSize);
ThreeChannelMatrix vague = new ThreeChannelMatrix();
vague.setX(gr.getX());
vague.setY(gr.getY());
vague.setMatrixR(gr);
vague.setMatrixG(gg);
vague.setMatrixB(gb);
return vague;
}
private float getConv(Matrix conv, Matrix gaussianMatrix) throws Exception {
int x = gaussianMatrix.getX();
int y = gaussianMatrix.getY();
float sigma = 0;
for (int i = 0; i < x; i++) {
for (int j = 0; j < y; j++) {
float value = conv.getNumber(i, j) * gaussianMatrix.getNumber(i, j);
sigma = sigma + value;
}
}
return sigma;
}
private Matrix conv(Matrix matrix, Matrix gaussianMatrix, int kerSize) throws Exception {
int x = matrix.getX();
int y = matrix.getY();
int half = kerSize / 2;
Matrix convMatrix = new Matrix(x - half * 2, y - half * 2);
for (int i = half; i < x - half; i++) {
for (int j = half; j < y - half; j++) {
Matrix conv = matrix.getSonOfMatrix(i - half, j - half, kerSize, kerSize);
float value = getConv(conv, gaussianMatrix);
convMatrix.setNub(i - half, j - half, value);
}
}
return convMatrix;
}
public Matrix getLBPMatrix() throws Exception {
Matrix addMatrix = new Matrix(x, y);
for (int i = 0; i < x; i++) {
for (int j = 0; j < y; j++) {
float value = matrixR.getNumber(i, j) + matrixG.getNumber(i, j) + matrixB.getNumber(i, j);
addMatrix.setNub(i, j, value);
}
}
return matrixOperation.lbpMatrix(addMatrix);
}
public void standardization() throws Exception {//标准化
standardizationMatrix(matrixR);
standardizationMatrix(matrixG);
standardizationMatrix(matrixB);
}
private void standardizationMatrix(Matrix matrix) throws Exception {
float avg = matrix.getAVG();
float sigma = 0;
float size = x * y;
for (int i = 0; i < x; i++) {
for (int j = 0; j < y; j++) {
sigma = sigma + (float) Math.pow(matrix.getNumber(i, j) - avg, 2);
}
}
sigma = sigma / size;//方差
float b = (float) Math.sqrt(sigma);//标准差
for (int i = 0; i < x; i++) {
for (int j = 0; j < y; j++) {
float value = (matrix.getNumber(i, j) - avg) / b;
matrix.setNub(i, j, value);
}
}
}
public ThreeChannelMatrix scale(boolean scaleWidth, float size) throws Exception {//缩放图像
float value;
if (scaleWidth) {//将宽度等比缩放至指定尺寸
value = y / size;
} else {//将高度等比缩放至指定尺寸
value = x / size;
}
int narrowX = (int) (x / value);
int narrowY = (int) (y / value);
if (scaleWidth) {
narrowY = (int) size;
} else {
narrowX = (int) size;
}
ThreeChannelMatrix scaleMatrix = new ThreeChannelMatrix();
scaleMatrix.setX(narrowX);
scaleMatrix.setY(narrowY);
Matrix matrixCR = new Matrix(narrowX, narrowY);
Matrix matrixCG = new Matrix(narrowX, narrowY);
Matrix matrixCB = new Matrix(narrowX, narrowY);
Matrix matrixCH = new Matrix(narrowX, narrowY);
scaleMatrix.setMatrixR(matrixCR);
scaleMatrix.setMatrixG(matrixCG);
scaleMatrix.setMatrixB(matrixCB);
scaleMatrix.setH(matrixCH);
for (int i = 0; i < narrowX; i++) {
for (int j = 0; j < narrowY; j++) {
int indexX = (int) (i * value);
int indexY = (int) (j * value);
matrixCR.setNub(i, j, matrixR.getNumber(indexX, indexY));
matrixCG.setNub(i, j, matrixG.getNumber(indexX, indexY));
matrixCB.setNub(i, j, matrixB.getNumber(indexX, indexY));
}
}
return scaleMatrix;
}
public void add(float nub, boolean add) throws Exception {//对rgb矩阵曝光进行处理
if (add) {//加数值
matrixOperation.mathAdd(matrixR, nub);
matrixOperation.mathAdd(matrixG, nub);
matrixOperation.mathAdd(matrixB, nub);
} else {//减数值
matrixOperation.mathSub(matrixR, nub);
matrixOperation.mathSub(matrixG, nub);
matrixOperation.mathSub(matrixB, nub);
}
}
public void center() throws Exception {
center(matrixR);
center(matrixG);
center(matrixB);
}
private void center(Matrix matrix) throws Exception {
float avg = matrix.getAVG();
matrixOperation.mathSub(matrix, avg);
}
public ThreeChannelMatrix copy() throws Exception {//复制当前的三通道矩阵并返回
ThreeChannelMatrix copyThreeChannelMatrix = new ThreeChannelMatrix();
copyThreeChannelMatrix.setX(this.x);
copyThreeChannelMatrix.setY(this.y);
Matrix matrixCR = new Matrix(this.x, this.y);
Matrix matrixCG = new Matrix(this.x, this.y);
Matrix matrixCB = new Matrix(this.x, this.y);
for (int i = 0; i < x; i++) {
for (int j = 0; j < y; j++) {
matrixCR.setNub(i, j, matrixR.getNumber(i, j));
matrixCG.setNub(i, j, matrixG.getNumber(i, j));
matrixCB.setNub(i, j, matrixB.getNumber(i, j));
}
}
copyThreeChannelMatrix.setMatrixR(matrixCR);
copyThreeChannelMatrix.setMatrixG(matrixCG);
copyThreeChannelMatrix.setMatrixB(matrixCB);
return copyThreeChannelMatrix;
}
//将一个图像填充到本图像的指定位置
public void fill(int x, int y, ThreeChannelMatrix fillThreeChannelMatrix) throws Exception {
int xIndex = x + fillThreeChannelMatrix.getX();
int yIndex = y + fillThreeChannelMatrix.getY();
Matrix matrixFR = fillThreeChannelMatrix.getMatrixR();
Matrix matrixFG = fillThreeChannelMatrix.getMatrixG();
Matrix matrixFB = fillThreeChannelMatrix.getMatrixB();
if (xIndex <= this.x && yIndex <= this.y) {
for (int i = x; i < xIndex; i++) {
for (int j = y; j < yIndex; j++) {
matrixR.setNub(i, j, matrixFR.getNumber(i - x, j - y));
matrixG.setNub(i, j, matrixFG.getNumber(i - x, j - y));
matrixB.setNub(i, j, matrixFB.getNumber(i - x, j - y));
}
}
} else {
throw new Exception("The filled image goes beyond the boundary !");
}
}
public ThreeChannelMatrix cutChannel(int x, int y, int XSize, int YSize) throws Exception {
ThreeChannelMatrix threeChannelMatrix = new ThreeChannelMatrix();
threeChannelMatrix.setX(XSize);
threeChannelMatrix.setY(YSize);
int xLen = this.matrixR.getX();
int yLen = this.matrixR.getY();
if (x < 0 || y < 0 || x + XSize > xLen || y + YSize > yLen) {
throw new Exception("size out,xLen:" + xLen + ",yLen:" + yLen + "," +
"x:" + x + ",y:" + y + ",xSize:" + (x + XSize) + ",ySize:" + (y + YSize));
}
Matrix matrixR = this.matrixR.getSonOfMatrix(x, y, XSize, YSize);
Matrix matrixG = this.matrixG.getSonOfMatrix(x, y, XSize, YSize);
Matrix matrixB = this.matrixB.getSonOfMatrix(x, y, XSize, YSize);
Matrix matrixH = H.getSonOfMatrix(x, y, XSize, YSize);
threeChannelMatrix.setX(XSize);
threeChannelMatrix.setY(YSize);
threeChannelMatrix.setMatrixR(matrixR);
threeChannelMatrix.setMatrixG(matrixG);
threeChannelMatrix.setMatrixB(matrixB);
threeChannelMatrix.setH(matrixH);
return threeChannelMatrix;
}
public Matrix getH() {
return H;
}
public void setH(Matrix h) {
H = h;
}
public Matrix getMatrixR() {
return matrixR;
}
public void setMatrixR(Matrix matrixR) {
this.matrixR = matrixR;
}
public Matrix getMatrixG() {
return matrixG;
}
public void setMatrixG(Matrix matrixG) {
this.matrixG = matrixG;
}
public Matrix getMatrixB() {
return matrixB;
}
public void setMatrixB(Matrix matrixB) {
this.matrixB = matrixB;
}
}