Java 实现 YoloV7 人体姿态识别

news2024/11/24 17:03:45

1 OpenCV 环境的准备

这个项目中需要用到 opencv 进行图片的读取与处理操作,因此我们需要先配置一下 opencv 在 java 中运行的配置。

首先前往 opencv 官网下载 opencv-4.6 :点此下载;下载好后仅选择路径后即可完成安装。

此时将 opencv\build\java\x64 路径下的 opencv_java460.dll 复制到 C:\Windows\System32 中,再将 D:\Tools\opencv\opencv\build\java 下的 opencv-460.jar 放到我们 Springboot 项目 resources 文件夹下的 lib 文件夹下。

本文所需 ONNX 文件请 点此下载 。

JAVA使用YOLOV7进行 目标检测 请转至 Java使用OnnxRuntime及OpenCV实现YoloV7目标检测,
项目代码可前往 项目主页 查看。

2 Maven 配置

引入 onnxruntime 和 opencv 这两个依赖即可。值得注意的是,引 opencv 时systemPath记得与上文说的opencv-460.jar所在路径保持一致。

<dependency>
    <groupId>com.microsoft.onnxruntime</groupId>
    <artifactId>onnxruntime</artifactId>
    <version>1.12.1</version>
</dependency>

<dependency>
    <groupId>org.opencv</groupId>
    <artifactId>opencv</artifactId>
    <version>4.6.0</version>
    <scope>system</scope>
    <systemPath>${project.basedir}/src/main/resources/lib/opencv-460.jar</systemPath>
</dependency>

3 Config

3.1 PEPlotConfig.java

在此配置一些画图时用到的超参数

package cn.halashuo.config;

import org.opencv.core.Scalar;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public final class PEPlotConfig {

    public static final List<Scalar> palette= new ArrayList<>(Arrays.asList(
            new Scalar( 255, 128, 0 ),
            new Scalar( 255, 153, 51 ),
            new Scalar( 255, 178, 102 ),
            new Scalar( 230, 230, 0 ),
            new Scalar( 255, 153, 255 ),
            new Scalar( 153, 204, 255 ),
            new Scalar( 255, 102, 255 ),
            new Scalar( 255, 51, 255 ),
            new Scalar( 102, 178, 255 ),
            new Scalar( 51, 153, 255 ),
            new Scalar( 255, 153, 153 ),
            new Scalar( 255, 102, 102 ),
            new Scalar( 255, 51, 51 ),
            new Scalar( 153, 255, 153 ),
            new Scalar( 102, 255, 102 ),
            new Scalar( 51, 255, 51 ),
            new Scalar( 0, 255, 0 ),
            new Scalar( 0, 0, 255 ),
            new Scalar( 255, 0, 0 ),
            new Scalar( 255, 255, 255 )
    ));

    public static final int[][] skeleton = {
            {16, 14}, {14, 12}, {17, 15}, {15, 13}, {12, 13}, {6, 12},
            {7, 13}, {6, 7}, {6, 8}, {7, 9}, {8, 10}, {9, 11}, {2, 3},
            {1, 2}, {1, 3}, {2, 4}, {3, 5}, {4, 6}, {5, 7}
    };

    public static final List<Scalar> poseLimbColor = new ArrayList<>(Arrays.asList(
            palette.get(9), palette.get(9), palette.get(9), palette.get(9), palette.get(7),
            palette.get(7), palette.get(7), palette.get(0), palette.get(0), palette.get(0),
            palette.get(0), palette.get(0), palette.get(16), palette.get(16), palette.get(16),
            palette.get(16), palette.get(16), palette.get(16), palette.get(16)));

    public static final List<Scalar> poseKptColor = new ArrayList<>(Arrays.asList(
            palette.get(16), palette.get(16), palette.get(16), palette.get(16), palette.get(16),
            palette.get(0), palette.get(0), palette.get(0), palette.get(0), palette.get(0),
            palette.get(0), palette.get(9), palette.get(9), palette.get(9), palette.get(9),
            palette.get(9), palette.get(9)));

}

4 Utils

3.1 Letterbox.java

这个类负责调整图像大小和填充图像,使满足步长约束,并记录参数。

package cn.halashuo.utils;

import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;

public class Letterbox {

    private final Size newShape = new Size(1280, 1280);
    private final double[] color = new double[]{114,114,114};
    private final Boolean auto = false;
    private final Boolean scaleUp = true;
    private final Integer stride = 32;

    private double ratio;
    private double dw;
    private double dh;

    public double getRatio() {
        return ratio;
    }

    public double getDw() {
        return dw;
    }

    public Integer getWidth() {
        return (int) this.newShape.width;
    }

    public Integer getHeight() {
        return (int) this.newShape.height;
    }

    public double getDh() {
        return dh;
    }

    public Mat letterbox(Mat im) { // 调整图像大小和填充图像,使满足步长约束,并记录参数

        int[] shape = {im.rows(), im.cols()}; // 当前形状 [height, width]
        // Scale ratio (new / old)
        double r = Math.min(this.newShape.height / shape[0], this.newShape.width / shape[1]);
        if (!this.scaleUp) { // 仅缩小,不扩大(一起为了mAP)
            r = Math.min(r, 1.0);
        }
        // Compute padding
        Size newUnpad = new Size(Math.round(shape[1] * r), Math.round(shape[0] * r));
        double dw = this.newShape.width - newUnpad.width, dh = this.newShape.height - newUnpad.height; // wh 填充
        if (this.auto) { // 最小矩形
            dw = dw % this.stride;
            dh = dh % this.stride;
        }
        dw /= 2; // 填充的时候两边都填充一半,使图像居于中心
        dh /= 2;
        if (shape[1] != newUnpad.width || shape[0] != newUnpad.height) { // resize
            Imgproc.resize(im, im, newUnpad, 0, 0, Imgproc.INTER_LINEAR);
        }
        int top = (int) Math.round(dh - 0.1), bottom = (int) Math.round(dh + 0.1);
        int left = (int) Math.round(dw - 0.1), right = (int) Math.round(dw + 0.1);
        // 将图像填充为正方形
        Core.copyMakeBorder(im, im, top, bottom, left, right, Core.BORDER_CONSTANT, new org.opencv.core.Scalar(this.color));
        this.ratio = r;
        this.dh = dh;
        this.dw = dw;
        return im;
    }
}

3.2 NMS.java

这个类负责进行非极大值抑制,以筛选检测到的人。

package cn.halashuo.utils;

import cn.halashuo.domain.PEResult;

import java.util.ArrayList;
import java.util.List;

public class NMS {

    public static List<PEResult> nms(List<PEResult> boxes, float iouThreshold) {
        // 根据score从大到小对List进行排序
        boxes.sort((b1, b2) -> Float.compare(b2.getScore(), b1.getScore()));
        List<PEResult> resultList = new ArrayList<>();
        for (int i = 0; i < boxes.size(); i++) {
            PEResult box = boxes.get(i);
            boolean keep = true;
            // 从i+1开始,遍历之后的所有boxes,移除与box的IOU大于阈值的元素
            for (int j = i + 1; j < boxes.size(); j++) {
                PEResult otherBox = boxes.get(j);
                float iou = getIntersectionOverUnion(box, otherBox);
                if (iou > iouThreshold) {
                    keep = false;
                    break;
                }
            }
            if (keep) {
                resultList.add(box);
            }
        }
        return resultList;
    }
    private static float getIntersectionOverUnion(PEResult box1, PEResult box2) {
        float x1 = Math.max(box1.getX0(), box2.getX0());
        float y1 = Math.max(box1.getY0(), box2.getY0());
        float x2 = Math.min(box1.getX1(), box2.getX1());
        float y2 = Math.min(box1.getY1(), box2.getY1());
        float intersectionArea = Math.max(0, x2 - x1) * Math.max(0, y2 - y1);
        float box1Area = (box1.getX1() - box1.getX0()) * (box1.getY1() - box1.getY0());
        float box2Area = (box2.getX1() - box2.getX0()) * (box2.getY1() - box2.getY0());
        float unionArea = box1Area + box2Area - intersectionArea;
        return intersectionArea / unionArea;
    }
}

5 domain

5.1 KeyPoint.java

记录关键点信息的实体类。

package cn.halashuo.domain;

public class KeyPoint {
    private Integer id;
    private Float x;
    private Float y;
    private Float score;

    public KeyPoint(Integer id, Float x, Float y, Float score) {
        this.id = id;
        this.x = x;
        this.y = y;
        this.score = score;
    }

    public Integer getId() {
        return id;
    }

    public Float getX() {
        return x;
    }

    public Float getY() {
        return y;
    }

    public Float getScore() {
        return score;
    }

    @Override
    public String toString() {
        return "    第 " + (id+1) + " 个关键点: " +
                " x=" + x +
                " y=" + y +
                " c=" + score +
                "\n";
    }
}

5.2 PEResult.java

记录所有人物检测信息的实体类。

package cn.halashuo.domain;

import java.util.ArrayList;
import java.util.List;

public class PEResult {

    private Float x0;
    private Float y0;
    private Float x1;
    private Float y1;
    private Float score;
    private Integer clsId;
    private List<KeyPoint> keyPointList;

    public PEResult(float[] peResult) {
        float x = peResult[0];
        float y = peResult[1];
        float w = peResult[2]/2.0f;
        float h = peResult[3]/2.0f;
        this.x0 = x-w;
        this.y0 = y-h;
        this.x1 = x+w;
        this.y1 = y+h;
        this.score = peResult[4];
        this.clsId = (int) peResult[5];
        this.keyPointList = new ArrayList<>();
        int keyPointNum = (peResult.length-6)/3;
        for (int i=0;i<keyPointNum;i++) {
            this.keyPointList.add(new KeyPoint(i, peResult[6+3*i], peResult[6+3*i+1], peResult[6+3*i+2]));
        }
    }

    public Float getX0() {
        return x0;
    }

    public Float getY0() {
        return y0;
    }

    public Float getX1() {
        return x1;
    }

    public Float getY1() {
        return y1;
    }

    public Float getScore() {
        return score;
    }

    public Integer getClsId() {
        return clsId;
    }

    public List<KeyPoint> getKeyPointList() {
        return keyPointList;
    }

    @Override
    public String toString() {
        String result = "PEResult:" +
                "  x0=" + x0 +
                ", y0=" + y0 +
                ", x1=" + x1 +
                ", y1=" + y1 +
                ", score=" + score +
                ", clsId=" + clsId +
                "\n";
        for (KeyPoint x : keyPointList) {
            result = result + x.toString();
        }
        return result;
    }
}


6 PoseEstimation.java

设置好 ONNX 文件路径及需要识别的图片路径即可。如有需要也可设置 CUDA 作为运行环境,大幅提升 FPS。

package cn.halashuo;

import ai.onnxruntime.OnnxTensor;
import ai.onnxruntime.OrtEnvironment;
import ai.onnxruntime.OrtException;
import ai.onnxruntime.OrtSession;
import cn.halashuo.domain.KeyPoint;
import cn.halashuo.domain.PEResult;
import cn.halashuo.utils.Letterbox;
import cn.halashuo.utils.NMS;
import cn.halashuo.config.PEPlotConfig;
import org.opencv.core.*;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;

import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class PoseEstimation {
    static
    {
        //在使用OpenCV前必须加载Core.NATIVE_LIBRARY_NAME类,否则会报错
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
    }

    public static void main(String[] args) throws OrtException {

        // 加载ONNX模型
        OrtEnvironment environment = OrtEnvironment.getEnvironment();
        OrtSession.SessionOptions sessionOptions = new OrtSession.SessionOptions();
        OrtSession session = environment.createSession("src\\main\\resources\\model\\yolov7-w6-pose.onnx", sessionOptions);
        // 输出基本信息
        session.getInputInfo().keySet().forEach(x -> {
            try {
                System.out.println("input name = " + x);
                System.out.println(session.getInputInfo().get(x).getInfo().toString());
            } catch (OrtException e) {
                throw new RuntimeException(e);
            }
        });

        // 读取 image
        Mat img = Imgcodecs.imread("src\\main\\resources\\image\\bus.jpg");
        Imgproc.cvtColor(img, img, Imgproc.COLOR_BGR2RGB);
        Mat image = img.clone();

        // 在这里先定义下线的粗细、关键的半径(按比例设置大小粗细比较好一些)
        int minDwDh = Math.min(img.width(), img.height());
        int thickness = minDwDh / 333;
        int radius = minDwDh / 168;

        // 更改 image 尺寸
        Letterbox letterbox = new Letterbox();
        letterbox.setNewShape(new Size(960, 960));
        letterbox.setStride(64);
        image = letterbox.letterbox(image);
        double ratio = letterbox.getRatio();
        double dw = letterbox.getDw();
        double dh = letterbox.getDh();
        int rows = letterbox.getHeight();
        int cols = letterbox.getWidth();
        int channels = image.channels();

        // 将Mat对象的像素值赋值给Float[]对象
        float[] pixels = new float[channels * rows * cols];
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols; j++) {
                double[] pixel = image.get(j, i);
                for (int k = 0; k < channels; k++) {
                    // 这样设置相当于同时做了image.transpose((2, 0, 1))操作
                    pixels[rows * cols * k + j * cols + i] = (float) pixel[k] / 255.0f;
                }
            }
        }

        // 创建OnnxTensor对象
        long[] shape = {1L, (long) channels, (long) rows, (long) cols};
        OnnxTensor tensor = OnnxTensor.createTensor(environment, FloatBuffer.wrap(pixels), shape);
        HashMap<String, OnnxTensor> stringOnnxTensorHashMap = new HashMap<>();
        stringOnnxTensorHashMap.put(session.getInputInfo().keySet().iterator().next(), tensor);

        // 运行模型
        OrtSession.Result output = session.run(stringOnnxTensorHashMap);

        // 得到结果
        float[][] outputData = ((float[][][]) output.get(0).getValue())[0];

        List<PEResult> peResults = new ArrayList<>();
        for (int i=0;i<outputData.length;i++){
            PEResult result = new PEResult(outputData[i]);
            if (result.getScore()>0.25f) {
                peResults.add(result);
            }
        }

        // 对结果进行非极大值抑制
        peResults = NMS.nms(peResults, 0.65f);

        for (PEResult peResult: peResults) {
            System.out.println(peResult);
            // 画框
            Point topLeft = new Point((peResult.getX0()-dw)/ratio, (peResult.getY0()-dh)/ratio);
            Point bottomRight = new Point((peResult.getX1()-dw)/ratio, (peResult.getY1()-dh)/ratio);
            Imgproc.rectangle(img, topLeft, bottomRight, new Scalar(255,0,0), thickness);
            List<KeyPoint> keyPoints = peResult.getKeyPointList();
            // 画点
            keyPoints.forEach(keyPoint->{
                if (keyPoint.getScore()>0.50f) {
                    Point center = new Point((keyPoint.getX()-dw)/ratio, (keyPoint.getY()-dh)/ratio);
                    Scalar color = PEPlotConfig.poseKptColor.get(keyPoint.getId());
                    Imgproc.circle(img, center, radius, color, -1); //-1表示实心
                }
            });
            // 画线
            for (int i=0;i<PEPlotConfig.skeleton.length;i++){
                int indexPoint1 = PEPlotConfig.skeleton[i][0]-1;
                int indexPoint2 = PEPlotConfig.skeleton[i][1]-1;
                if ( keyPoints.get(indexPoint1).getScore()>0.5f && keyPoints.get(indexPoint2).getScore()>0.5f ) {
                    Scalar coler = PEPlotConfig.poseLimbColor.get(i);
                    Point point1 = new Point(
                            (keyPoints.get(indexPoint1).getX()-dw)/ratio,
                            (keyPoints.get(indexPoint1).getY()-dh)/ratio
                    );
                    Point point2 = new Point(
                            (keyPoints.get(indexPoint2).getX()-dw)/ratio,
                            (keyPoints.get(indexPoint2).getY()-dh)/ratio
                    );
                    Imgproc.line(img, point1, point2, coler, thickness);
                }
            }
        }
        Imgproc.cvtColor(img, img, Imgproc.COLOR_RGB2BGR);
        // 保存图像
        // Imgcodecs.imwrite("image.jpg", img);
        HighGui.imshow("Display Image", img);
        // 等待按下任意键继续执行程序
        HighGui.waitKey();

    }
}

运行结果:

input name = images
TensorInfo(javaType=FLOAT,onnxType=ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT,shape=[1, 3, 960, 960])
PEResult:  x0=164.1142, y0=357.69672, x1=341.0573, y1=800.42975, score=0.7534131, clsId=0
    第 1 个关键点:  x=246.95715 y=397.0772 c=0.9736327
    第 2 个关键点:  x=252.17633 y=389.2904 c=0.8335564
    第 3 个关键点:  x=238.11848 y=389.0014 c=0.96936846
    第 4 个关键点:  x=256.3179 y=395.70413 c=0.26490688
    第 5 个关键点:  x=217.58188 y=395.21817 c=0.9350542
    第 6 个关键点:  x=261.88034 y=443.02286 c=0.9898272
    第 7 个关键点:  x=197.16116 y=444.8831 c=0.9871879
    第 8 个关键点:  x=288.0304 y=506.67032 c=0.96026266
    第 9 个关键点:  x=232.06883 y=506.9636 c=0.97538215
    第 10 个关键点:  x=239.84201 y=521.9722 c=0.9516981
    第 11 个关键点:  x=277.70163 y=489.83765 c=0.970703
    第 12 个关键点:  x=257.0904 y=574.55255 c=0.9929459
    第 13 个关键点:  x=208.6877 y=576.3064 c=0.9918982
    第 14 个关键点:  x=271.411 y=667.6743 c=0.98325074
    第 15 个关键点:  x=203.27112 y=671.0604 c=0.98317075
    第 16 个关键点:  x=285.6367 y=760.895 c=0.91636044
    第 17 个关键点:  x=184.19543 y=757.7814 c=0.91179585

PEResult:  x0=316.40674, y0=360.82706, x1=426.57, y1=759.98706, score=0.2713838, clsId=0
    第 1 个关键点:  x=381.07776 y=401.219 c=0.97289705
    第 2 个关键点:  x=386.32465 y=393.87543 c=0.8813406
    第 3 个关键点:  x=372.7825 y=394.40253 c=0.9677005
    第 4 个关键点:  x=392.475 y=397.61212 c=0.38852227
    第 5 个关键点:  x=358.659 y=399.40833 c=0.90877795
    第 6 个关键点:  x=402.89664 y=442.8764 c=0.9850693
    第 7 个关键点:  x=344.9049 y=448.23697 c=0.98851293
    第 8 个关键点:  x=414.33658 y=491.29187 c=0.932391
    第 9 个关键点:  x=342.81982 y=514.2552 c=0.97218585
    第 10 个关键点:  x=372.42307 y=471.12778 c=0.9217508
    第 11 个关键点:  x=355.56168 y=568.59796 c=0.9616347
    第 12 个关键点:  x=395.88492 y=558.541 c=0.98994935
    第 13 个关键点:  x=356.53287 y=560.3552 c=0.99083
    第 14 个关键点:  x=402.41013 y=636.82916 c=0.97681665
    第 15 个关键点:  x=356.1795 y=645.22626 c=0.9832493
    第 16 个关键点:  x=363.65356 y=694.9054 c=0.92282534
    第 17 个关键点:  x=358.54623 y=727.66455 c=0.93670356

PEResult:  x0=120.30354, y0=488.97424, x1=189.55516, y1=765.24194, score=0.2625065, clsId=0
    第 1 个关键点:  x=128.37527 y=496.36432 c=0.039970636
    第 2 个关键点:  x=129.2826 y=488.29858 c=0.01759991
    第 3 个关键点:  x=129.88588 y=487.7059 c=0.023388624
    第 4 个关键点:  x=128.1956 y=486.87085 c=0.022539705
    第 5 个关键点:  x=129.61555 y=486.93362 c=0.026325405
    第 6 个关键点:  x=124.60656 y=506.1516 c=0.11605239
    第 7 个关键点:  x=124.11076 y=506.29758 c=0.1002911
    第 8 个关键点:  x=129.53989 y=577.0432 c=0.39045402
    第 9 个关键点:  x=129.05757 y=578.36163 c=0.4030531
    第 10 个关键点:  x=161.94182 y=651.2286 c=0.51389414
    第 11 个关键点:  x=162.66849 y=654.58966 c=0.54413426
    第 12 个关键点:  x=128.37022 y=633.2864 c=0.12599188
    第 13 个关键点:  x=128.395 y=635.9184 c=0.110325515
    第 14 个关键点:  x=128.9154 y=668.3744 c=0.098092705
    第 15 个关键点:  x=129.4807 y=669.07947 c=0.08956778
    第 16 个关键点:  x=128.86487 y=750.24927 c=0.09377599
    第 17 个关键点:  x=127.63382 y=751.3636 c=0.086484134

PEResult:  x0=710.87134, y0=352.32605, x1=839.29944, y1=781.6887, score=0.2580245, clsId=0
    第 1 个关键点:  x=815.21063 y=390.9094 c=0.37949353
    第 2 个关键点:  x=819.77454 y=382.87204 c=0.34996593
    第 3 个关键点:  x=816.6579 y=382.68045 c=0.0947094
    第 4 个关键点:  x=831.6544 y=386.69308 c=0.3775956
    第 5 个关键点:  x=830.4774 y=386.01678 c=0.044245332
    第 6 个关键点:  x=828.6047 y=435.97873 c=0.62260723
    第 7 个关键点:  x=838.1829 y=433.01996 c=0.32877648
    第 8 个关键点:  x=817.08154 y=511.3317 c=0.7232578
    第 9 个关键点:  x=824.0419 y=505.8941 c=0.21007198
    第 10 个关键点:  x=773.95953 y=496.15784 c=0.80840695
    第 11 个关键点:  x=790.11487 y=490.05597 c=0.33966026
    第 12 个关键点:  x=826.98004 y=571.4592 c=0.6694445
    第 13 个关键点:  x=830.14514 y=567.2725 c=0.508251
    第 14 个关键点:  x=796.26184 y=655.2373 c=0.81898046
    第 15 个关键点:  x=802.0529 y=650.5082 c=0.6584172
    第 16 个关键点:  x=762.1977 y=747.01917 c=0.6550461
    第 17 个关键点:  x=763.58057 y=741.5452 c=0.5072014


使用 yolov7-w6-pose 的官方模型训练并转化成 onnx 后,得到的结果维度为 n × 57 n\times 57 n×57。其中,前六个元素分别是 x、y、w、h、score、classId。关键点信息由x、y、score三个元素构成,共有17个关键点,因此每个人体监测信息共计 3 × 17 + 6 = 57 3\times 17 + 6 = 57 3×17+6=57 个元素。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/467354.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

30基于非对称纳什谈判的多微网电能共享运行优化策略MATLAB程序

资源地址&#xff1a; 30基于非对称纳什谈判的多微网电能共享运行优化策略MATLAB程序资源-CSDN文库 参考文献&#xff1a; 《基于非对称纳什谈判的多微网电能共享运行优化策略》——吴锦领 仿真平台&#xff1a;MATLAB CPLEXMOSEK/IPOPT 主要内容&#xff1a; 主要做的是…

优思学院|精益生产为企业带来革命性转变的效益

企业的成长和发展需要不断的变革和创新&#xff0c;而精益生产则成为了这个时代的代名词。精益生产不仅仅是一个生产方式&#xff0c;更是一种革命性的转变&#xff0c;为企业带来了无限的效益。 什么是精益生产&#xff1f; 精益生产是一种基于持续改进的生产方式&#xff0…

基于matlab的混合波束成形仿真

一、前言 本示例介绍了混合波束成形的基本概念&#xff0c;并展示了如何仿真此类系统。 二、介绍 现代无线通信系统使用空间复用来提高散射体丰富的环境中系统内的数据吞吐量。为了通过通道发送多个数据流&#xff0c;从通道矩阵中导出一组预编码和组合权重。然后&#xff0c;可…

lammps教程:聚合物压缩,避免“bond atoms missing”

本文介绍聚合物的压缩方法。 lammps模拟聚合物体系时&#xff0c;最常见的一个错误是“bond atoms missing”,其中一个原因是建模方法不对。 这个原理在之前的专栏文章中已经详细介绍。 如果使用ms建模&#xff0c;聚合物的链会伸出到盒子外面&#xff0c;在导出data文件后&…

MindFusion.Diagramming for WinForms 6.8.6

您现在可以指定在修改项目时要显示的视觉效果。 2023 年 4 月 26 日 - 15:55新版本 特征 您现在可以指定在修改项目时要显示的视觉效果。新的 Opacity 属性允许您创建半透明的 DiagramItem。添加了新的 CopySelection 重载&#xff0c;它允许您复制项目列表而无需选择它们。您现…

OrbStack

OrbStack 是一个可以在 macOS 上快速运行 Docker 容器&#xff0c;和 Linux 虚拟机的工具&#xff0c;资源占用率低&#xff0c;高效&#xff0c;快速。 macOS 上的 Parallels Desktop 和 Docker Desktop 一直是饱受诟病&#xff0c;慢、重、资源消耗巨大。OrbStack 的出现就是…

goroutine和channel

进程与线程 进程就是程序执行在操作系统中的一次在执行过程&#xff0c;是系统进行资源分配的基本单位。 线程就是进程的一个执行实例&#xff0c;是程序的最小执行单元&#xff0c;是比进程更小的独立运行的单位。 一个进程可以创建多个线程&#xff0c;同一一个进程中的多…

如何在C中动态分配二维数组

在C语言中如何动态申请连续的二维数组。可以采用多申请一些指针&#xff0c;然后这一些指针分别指向后面数据区中对应的位置&#xff0c;如一个3*4的int类型数组&#xff0c;我们先申请大小为sizeof(int*) * 3 3 * 4 * sizeof(int)的一维数组设为arr。然后arr[0]存放指向arr …

OpenAirInterface通过docker build方式构建images

本文主要讲解如何通过build方式构建各个网元的image&#xff0c;因为直接pull的image无法对其进行更改&#xff0c;而build的镜像可以对其源代码进行编辑更改后生成镜像。 参考链接&#xff1a;OAI build iamges 1.获取正确的网络功能分支 此存储库仅包含教程和持续集成脚本…

有假币与求正数数组的最小不可组成和

一、编程题 1.有假币 链接&#xff1a;有假币__牛客网 (nowcoder.com) 居然有假币&#xff01; 现在猪肉涨了&#xff0c;但是农民的工资却不见涨啊&#xff0c;没钱怎么买猪肉啊。nowcoder这就去买猪肉&#xff0c;结果找来的零钱中有假币&#xff01;&#xff01;&#xff…

爪哇项目maven项目的打包方式

大家好 ~ 前言 现在都是使用idea中maven插件来打包项目&#xff0c;出现了很多问题很多类或者方法、依赖没有打入到包中&#xff0c;发生了很多问题&#xff0c;因此此文章将基于idea中的maven插件打包。 概念 打包分为小包和大包两种概念&#xff1a; 小包&#xff1a;只打…

Conda虚拟环境的复制和迁移

Conda虚拟环境的复制和迁移 在本机复制Conda虚拟环境 conda create --name snapshot --clone myenv相同操作系统之间复制环境 方法一&#xff1a;requirements.txt 这个方法不推荐&#xff0c;因为只会导出你使用pip安装的依赖包&#xff0c;不会导出虚拟环境所依赖的包&am…

SQL应用题分析

SQL应用题的一般考点&#xff1a; 基本表的查询&#xff08;单表、多表、嵌入、分组、排序&#xff09;、向表中插入数据、更新数据、建立视图 关系代数替换sql&#xff0c;使用关系代数来进行查询 基本上就这几点 SQL基本表的插入、更新和建立视图都是死板的&#xff0c;只…

前端开发:CSS中@import指令详解

前言 在前端开发过程中&#xff0c;关于CSS的使用也是非常的&#xff0c;尤其是样式相关的设置等操作。作为前端开发者关于import指令都会有所了解&#xff0c;尤其是在导入CSS样式的时候会用到&#xff0c;但是刚入行不久的前端开发者对应import指令会有所陌生。那么本文就来分…

项目管理:我该怎么安排下属的工作

在刚开始做项目经理的时候&#xff0c;分配任务时会局限于这样的心理&#xff1a;以前我们都是平级的同事&#xff0c;现在我比他们高一个级别了&#xff0c;我说的话他们会不会听啊。 在这个阶段&#xff0c;大部分项目经理都缺乏自信&#xff0c;觉得在项目成员心中威望不足…

Linux shell编程 条件语句if case

条件测试 test命令 测试表达式是否成立&#xff0c;若成立返回0&#xff0c;否则返回其他数值 格式1: test 条件表达式 格式2: [ 条件表达式 ]文件测试 [ 操作符 文件或者目录 ][ -e 1.txt ]#查看1.txt是否存在&#xff0c;存在返回0 echo $? #查看是上一步命令执行结果 0成…

15天学习MySQL计划-存储过程变量判断循环游标函数触发器(进阶篇)-第九天

15天学习MySQL计划-存储过程/变量/判断/循环/游标/函数/触发器&#xff08;进阶篇&#xff09;-第九天 存储过程 1.介绍 ​ 存储过程是事先经过编译并存储是数据库中的一段SQL语句的集合&#xff0c;调用存储过程可以简化应用开发人员的很多工作&#xff0c;减少数据在数据库…

SR常用数据集介绍

1.Download Link&#xff1a; 1.DIV2K: DIV2K Dataset 2.Set5:【实践与问题解决28】最全超分辨率&#xff08;SR&#xff09;数据集介绍以及多方法下载链接_超分辨率数据集_呆呆象呆呆的博客-CSDN博客 3.Set14:【实践与问题解决28】最全超分辨率&#xff08;SR&#xff09;数…

Java --- springboot2的静态资源配置原理

目录 一、静态资源配置原理 1.1、配置类只有一个有参构造器 1.2、资源处理的默认规则 1.3、欢迎页的处理规则 一、静态资源配置原理 springboot启动默认加载xxxAutoConfiguration(自动配置) springmvc功能的自动配置类&#xff0c;生效 Configuration(proxyBeanMethods …

Find My资讯|苹果iOS 17将增强Health应用、引入情绪追踪器

彭博社的马克・古尔曼表示&#xff0c;苹果计划在 iOS / iPadOS 17 系统中&#xff0c;为 iPhone / iPad 用户引入几项和健康相关的新功能。其中最值得关注的一款新应用&#xff0c;可以追踪用户的情绪。 苹果计划进一步增强 Health 应用&#xff0c;引入视力状况相关的功能。…