当前位置: 首页 > news >正文

Linux C++ JNI封装、打包成jar包供Java调用详细介绍

在前面 Android专栏 中详细介绍了如何在Android Studio中调用通过jni封装的c++库。

在Android使用 opencv c++代码,需要准备opencv4android,也就是c++的任何代码,是使用Android NDK编译的,相当于在windows/mac上使用Android stdido交叉编译。

本文再介绍服务端的使用方式,c++通过jni封装的库,直接被java后端服务代码调用。 这里c++依赖库都是linux主机上,jni有关库也都是linux上的,因此就不存在交叉编译。

最后,还将项目打包成 jar包。

实际项目参考 GitCode FLowMeasurem。

文章目录

  • 1、环境准备
    • 1.1、java sdk安装
    • 1.2、opencv
    • 1.3、gcc/g++ 和 cmake
  • 2、项目实现
    • 2.1、java端代码
    • 2.2、生成头文件
    • 2.4、C++实现
    • 2.5、编译共享库
      • 2.5.1、命令行编译
      • 2.5.2、cmake编译
  • 2.6、测试运行
  • 3、导出Jar包给后端直接使用
    • 3.1、项目结构
    • 3.2、项目准备
      • 3.2.1、创建Java类
      • 3.2.2、生成JNI头文件
      • 3.2.3、实现c++代码
      • 3.2.4、编写CMake构建文件
      • 3.2.5、构建动态库
    • 3.3、 打包jar
      • 3.3.1、编译java代码
      • 3.3.2、创建MANIFEST.MF
      • 3.3.3 打包JAR
      • 3.3.4、jar包中添加so动态库
    • 3.4、测试jar包
    • 3.5、包声明问题
  • 4、优化 Jar 包代码和结构

1、环境准备

1.1、java sdk安装

这里直接使用apt安装(可能还需要配置环境变量),

sudo apt install openjdk-8-jdk

之后使用 javacjavah 工具,能正常使用即可。

1.2、opencv

简单起见,直接

sudo apt install libopencv-dev

1.3、gcc/g++ 和 cmake

不赘述。

2、项目实现

2.1、java端代码

我们定义一个 OpenCVJNI.java 类,里面包含native函数,以及测试代码main函数。

public class OpenCVJNI {// 加载本地库static {System.loadLibrary("OpenCVJNI");}// 声明本地方法public native int detectFaces(String imagePath, String outputPath);// 测试main函数public static void main(String[] args) {if (args.length < 2) {System.out.println("Usage: java OpenCVJNI <inputImage> <outputImage>");return;}OpenCVJNI ocv = new OpenCVJNI();int faceCount = ocv.detectFaces(args[0], args[1]);System.out.println("Detected " + faceCount + " faces.");}
}

2.2、生成头文件

编译Java类的命令 javac OpenCVJNI.java 此时,会在当前目录生成 OpenCVJNI.class 文件;
继续执行 javah -jni OpenCVJNI 会继续在当前目录生成 OpenCVJNI.h 文件。

我们可以使用 javac OpenCVJNI.java -h ./ 直接在当前目录生成class文件 ( -s 指定class保存目录), 和 -h 指定目录下保存生的 h 文件。

内容如下

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class OpenCVJNI */#ifndef _Included_OpenCVJNI
#define _Included_OpenCVJNI
#ifdef __cplusplus
extern "C" {
#endif
/** Class:     OpenCVJNI* Method:    detectFaces* Signature: (Ljava/lang/String;Ljava/lang/String;)I*/
JNIEXPORT jint JNICALL Java_OpenCVJNI_detectFaces(JNIEnv *, jobject, jstring, jstring);#ifdef __cplusplus
}
#endif
#endif

2.4、C++实现

#include <jni.h>
#include <opencv2/opencv.hpp>
#include "OpenCVJNI.h"using namespace cv;JNIEXPORT jint JNICALL Java_OpenCVJNI_detectFaces(JNIEnv *env, jobject obj, jstring imagePath, jstring outputPath) {// 将Java字符串转换为C字符串const char* inputPath = env->GetStringUTFChars(imagePath, 0);const char* outPath = env->GetStringUTFChars(outputPath, 0);// 加载图像Mat image = imread(inputPath);if(image.empty()) {env->ReleaseStringUTFChars(imagePath, inputPath);env->ReleaseStringUTFChars(outputPath, outPath);return -1;}// 转换为灰度图像Mat gray;cvtColor(image, gray, COLOR_BGR2GRAY);// 加载预训练的人脸检测器CascadeClassifier faceDetector;String faceCascadePath = "/usr/share/opencv4/haarcascades/haarcascade_frontalface_default.xml";if(!faceDetector.load(faceCascadePath)) {env->ReleaseStringUTFChars(imagePath, inputPath);env->ReleaseStringUTFChars(outputPath, outPath);return -2;}// 检测人脸std::vector<Rect> faces;faceDetector.detectMultiScale(gray, faces, 1.1, 3, 0, Size(30, 30));// 在检测到的人脸周围绘制矩形for(size_t i = 0; i < faces.size(); i++) {rectangle(image, faces[i], Scalar(0, 255, 0), 2);}// 保存结果图像imwrite(outPath, image);// 释放资源env->ReleaseStringUTFChars(imagePath, inputPath);env->ReleaseStringUTFChars(outputPath, outPath);return faces.size();
}

2.5、编译共享库

2.5.1、命令行编译

使用g++命令行编译

g++ -I"$JAVA_HOME/include" -I"$JAVA_HOME/include/linux" -I/usr/include/opencv4 \-shared -fPIC -o libOpenCVJNI.so OpenCVJNI.cpp \-lopencv_core -lopencv_imgproc -lopencv_objdetect -lopencv_highgui

若提示错误找不到jni有关头文件,请配置环境变量 JAVA_HOME, 例如这里的为 /usr/lib/jvm/java-8-openjdk-amd64

编译之后,会在当前目录下生成 libOpenCVJNI.so 文件。

2.5.2、cmake编译

在当前目录创建 CMakeLists.txt:

cmake_minimum_required(VERSION 3.5)
project(OpenCVJNI)find_package(Java REQUIRED)
find_package(JNI REQUIRED)
find_package(OpenCV REQUIRED)include_directories(${JNI_INCLUDE_DIRS})
include_directories(${OpenCV_INCLUDE_DIRS})add_library(OpenCVJNI SHARED OpenCVJNI.cpp)
target_link_libraries(OpenCVJNI ${OpenCV_LIBS})

执行以下命令,在当build目录下生成 libOpenCVJNI.so 文件。

mkdir build
cd build
cmake ..
make

2.6、测试运行

以cmake方式为例,给出当前项目目录结构

OpenCVJNIProject/
├── CMakeLists.txt
├── lena.png
├── OpenCVJNI.java
├── OpenCVJNI.cpp
├── OpenCVJNI.h
└── build/└── libOpenCVJNI.so

我们运行时,需要将编译生成的 libOpenCVJNI.so ,复制到Java库路径或者指定路径,之后在OpenCVJNI.class的目录下执行。

  • 方式1
cd build
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
cd ..
java -Djava.library.path=. OpenCVJNI ../lena.png output.jpg
  • 方式2

在项目目录下指定so目录path

java -Djava.library.path=./build OpenCVJNI ../lena.png output.jpg
  • 方式3

将 OpenCVJNI.class 和 libOpenCVJNI.so 放在同一目录(当前命令也包含图片),直接运行

java OpenCVJNI ../lena.png output.jpg

在这里插入图片描述

3、导出Jar包给后端直接使用

前面OpenCVJNI.java 就包含了接口,也包含了测试代码。 这里,我们将前面人脸识别的接口进行封装成一个jar包,供其他java项目直接调用。

3.1、项目结构

我们按照java调用的格式创建一个目录结构

MyOpenCVProject/
├── native/                  # 本地代码(C/C++)目录
│   ├── CMakeLists.txt       # C++构建配置
│   ├── src/                 # C++源代码
│   └── lib/                 # 生成的动态库
├── java/                    # Java代码目录
│   ├── src/                 # Java源代码
│   └── target/              # 构建输出
└── dist/                    # 最终分发目录

3.2、项目准备

3.2.1、创建Java类

在创建目录 java/src/com/magicsky/OpenCVWrapper,在当前包下创建OpenCVWrapper.java 文件.

package com.magicsky.OpenCVWrapper;public class OpenCVWrapper {static {System.loadLibrary("opencv_jni"); // 加载动态库}// 声明本地方法public native int detectFaces(String inputPath, String outputPath);// 辅助方法:获取当前平台对应的库名称private static String getLibraryName() {String osName = System.getProperty("os.name").toLowerCase();if (osName.contains("linux")) {return "opencv_jni";} else if (osName.contains("win")) {return "opencv_jni";} else if (osName.contains("mac")) {return "opencv_jni";}return "opencv_jni";}
}

3.2.2、生成JNI头文件

首先编译生成class文件,并导出头文件,这里一步到位

cd java/src
javac -h ../../native/src com/magicsky/OpenCVWrapper/OpenCVWrapper.java

运行之后,会在 OpenCVWrapper.java 同级目录下生成 OpenCVWrapper.class文件。

类似Android中,在 native/src下创建了一个文件 com_magicsky_OpenCVWrapper_OpenCVWrapper.h

3.2.3、实现c++代码

native/src/下创建opencv_jni.cpp 代码,除了引用目录和函数命名,其他内容和前述 OpenCVJNI.java 内容一致。

#include <jni.h>
#include <opencv2/opencv.hpp>
#include "com_magicsky_OpenCVWrapper_OpenCVWrapper.h"using namespace cv;JNIEXPORT jint JNICALL Java_com_magicsky_OpenCVWrapper_OpenCVWrapper_detectFaces(JNIEnv *env, jobject obj, jstring imagePath, jstring outputPath) {// 实现代码与之前示例相同// ...
}

3.2.4、编写CMake构建文件

cmake_minimum_required(VERSION 3.5)
project(OpenCVJNI)find_package(Java REQUIRED)
find_package(JNI REQUIRED)
find_package(OpenCV REQUIRED)include_directories(${JNI_INCLUDE_DIRS})
include_directories(${OpenCV_INCLUDE_DIRS})
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src)set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/lib)add_library(opencv_jni SHARED src/opencv_jni.cpp)
target_link_libraries(opencv_jni ${OpenCV_LIBS})

3.2.5、构建动态库

cd native
mkdir -p build
cd build
cmake …
make
生成的动态库会在native/lib/目录下,名为libopencv_jni.so

查看项目目录结构主要文件如下
在这里插入图片描述

3.3、 打包jar

有了以上so文件,按照jar包规则将需要的数据组织起来。

3.3.1、编译java代码

其实就是生成class文件。可以之前复制之前生成的。这里使用命令 javac -d 生成并存入指定位置。

cd java/src
javac -d ../target com/magicsky/OpenCVWrapper/OpenCVWrapper.java

运行后在 java/target 目录下户集成一个多级目录,并创建文件 java/target/com/magicsky/OpenCVWrapper/OpenCVWrapper.class

-s 的结果为 java/target/OpenCVWrapper.class

3.3.2、创建MANIFEST.MF

创建 java/target/META-INF/ 目录,并添加 `MANIFEST.MF文件 ,内容如下

Manifest-Version: 1.0
Class-Path: .

3.3.3 打包JAR

先试用 jar 工具 打包 MANIFEST.MF 和 OpenCVWrapper.class ,命令如下

mkdir dist
cd java/target
jar cvfm ../../dist/OpenCVWrapper.jar META-INF/MAINFEST.MF com/

运行结果如下

$ mkdir dist
$ cd java/target/
$ jar cvfm ../../dist/OpenCVWrapper.jar META-INF/MAINFEST.MF com/
added manifest
adding: com/(in = 0) (out= 0)(stored 0%)
adding: com/magicsky/(in = 0) (out= 0)(stored 0%)
adding: com/magicsky/OpenCVWrapper/(in = 0) (out= 0)(stored 0%)
adding: com/magicsky/OpenCVWrapper/OpenCVWrapper.class(in = 829) (out= 507)(deflated 38%)

3.3.4、jar包中添加so动态库

将动态库打包到JAR中特定目录(如native/linux-x86_64):

cd dist
mkdir -p native/linux-x86_64
cp ../native/lib/libopencv_jni.so native/linux-x86_64/jar uf OpenCVWrapper.jar native/linux-x86_64/libopencv_jni.so

打包好后下载到本地,解压查看jar文件结构和内容
在这里插入图片描述
至此,jar打包完成。

还可以使用更高级的 Maven/Gradle 构建

3.4、测试jar包

准备目录结构,并拷贝对应文件

$ tree
.
├── dist
│   ├── native
│   │   └── linux-x86_64
│   │       └── libopencv_jni.so
│   └── OpenCVWrapper.jar
├── lena.png
├── Main.java

在项目根目录中添加 Main.java 文件,内容为

import com.magicsky.OpenCVWrapper.OpenCVWrapper;public class Main {public static void main(String[] args) {OpenCVWrapper wrapper = new OpenCVWrapper();int faceCount = wrapper.detectFaces("lena.png", "output.jpg");System.out.println("Detected " + faceCount + " faces.");}
}

使用 javac -cp dist/OpenCVWrapper.jar Main.java 编译生成 Main.class 文件。

之后执行命令,需要指定so目录, jar 目录等 (根目录下执行)
java -Djava.library.path=dist/native/linux-x86_64 -cp dist/OpenCVWrapper.jar:. Main

运行成功,截图如下
在这里插入图片描述

3.5、包声明问题

前面的测试代码,Main.java在根目录,不存在包声明。下面结构中,存在一个test包。那么在Main.java文件第一行为 "package test;"

$ tree
.
├── dist
│   ├── native
│   │   └── linux-x86_64
│   │       └── libopencv_jni.so
│   └── OpenCVWrapper.jar
├── lena.png
├── test
│   ├── Main.class
│   └── Main.java

有包声明时,命令需要修改 (根目录下执行,包声明中最上一层)
java -Djava.library.path=./dist/native/linux-x86_64 -cp ./dist/OpenCVWrapper.jar:. test.Main

4、优化 Jar 包代码和结构

前面jar包在使用时,没有使用jar包中的 native/lib/libopencv_jni.so 文件,而是拷贝了一份运行时再指定路径。

我们应该在用户使用该jar时,解压jar中的so并使用。
修改 java 文件如下 :

package com.magicsky.OpenCVWrapper;import java.io.*;
import java.nio.file.*;public class OpenCVWrapper {// static {//     System.loadLibrary("opencv_jni"); // 加载动态库// }static {loadLibrary();}private static void loadLibrary() {try {String libName = getLibraryName();String libPath = "/native/" + getPlatform() + "/lib" + libName + ".so";// 从JAR中提取库到临时目录InputStream in = OpenCVWrapper.class.getResourceAsStream(libPath);if (in == null) {throw new RuntimeException("Native library not found in JAR: " + libPath);}Path tempDir = Files.createTempDirectory("native-lib");tempDir.toFile().deleteOnExit();Path tempLib = tempDir.resolve("lib" + libName + ".so");Files.copy(in, tempLib, StandardCopyOption.REPLACE_EXISTING);in.close();// 加载库System.load(tempLib.toAbsolutePath().toString());} catch (IOException e) {throw new RuntimeException("Failed to load native library", e);}}// 声明本地方法public native int detectFaces(String inputPath, String outputPath);// 辅助方法:获取当前平台对应的库名称private static String getLibraryName() {String osName = System.getProperty("os.name").toLowerCase();if (osName.contains("linux")) {return "opencv_jni";} else if (osName.contains("win")) {return "opencv_jni";} else if (osName.contains("mac")) {return "opencv_jni";}return "opencv_jni";}private static String getPlatform() {String osName = System.getProperty("os.name").toLowerCase();String osArch = System.getProperty("os.arch").toLowerCase();if (osName.contains("linux")) {return "linux-" + osArch;} else if (osName.contains("win")) {return "win-" + osArch;} else if (osName.contains("mac")) {return "mac-" + osArch;}throw new UnsupportedOperationException("Unsupported platform: " + osName + "/" + osArch);}
}

重新编译并打包

cd java/src
javac -d ../target/ com/magicsky/OpenCVWrapper/OpenCVWrapper.java
cd ../target
jar cvfm ../../dist/OpenCVWrapper.jar META-INF/MAINFEST.MF com/
cd ../../dist
jar uf opencv-wrapper.jar native/linux-x86_64/libopencv_jni.so

相关文章:

Linux C++ JNI封装、打包成jar包供Java调用详细介绍

在前面 Android专栏 中详细介绍了如何在Android Studio中调用通过jni封装的c库。 在Android使用 opencv c代码&#xff0c;需要准备opencv4android&#xff0c;也就是c的任何代码&#xff0c;是使用Android NDK编译的&#xff0c;相当于在windows/mac上使用Android stdido交叉…...

CPO-BP+NSGA,豪冠猪优化BP神经网络+多目标遗传算法!(Matlab完整源码和数据)

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.CPO-BPNSGA&#xff0c;豪冠猪优化BP神经网络多目标遗传算法&#xff01;&#xff08;Matlab完整源码和数据&#xff09;&#xff0c;豪冠猪算法优化BP神经网络的权值和阈值&#xff0c;运行环境Matlab2020b及以上…...

组件通信-v-model

概述&#xff1a;实现 父↔子 之间相互通信。 前序知识 —— v-model的本质 <!-- 使用v-model指令 --> <input type"text" v-model"userName"><!-- v-model的本质是下面这行代码 --> <input type"text" :value"use…...

使用PyMongo连接MongoDB的基本操作

MongoDB是由C语言编写的非关系型数据库&#xff0c;是一个基于分布式文件存储的开源数据库系统&#xff0c;其内容存储形式类似JSON对象&#xff0c;它的字段值可以包含其他文档、数组及文档数组。在这一节中&#xff0c;我们就来回顾Python 3下MongoDB的存储操作。 常用命令:…...

010302-oss_反向代理_负载均衡-web扩展2-基础入门-网络安全

文章目录 1 OSS1.1 什么是 OSS 存储&#xff1f;1.2 OSS 核心功能1.3 OSS 的优势1.4 典型使用场景1.5 如何接入 OSS&#xff1f;1.6 注意事项1.7 cloudreve实战演示1.7.1 配置cloudreve连接阿里云oss1.7.2 常见错误1.7.3 安全测试影响 2 反向代理2.1 正向代理和反向代理2.2 演示…...

PyQt 或 PySide6 进行 GUI 开发文档与教程

一、官网文档 Qt 官方文档&#xff1a;Porting to Qt 6 | Qt 6.9Qt 维基&#xff1a;​​​​​​​Qt WikiQt for Python (PySide6) &#xff1a;​​​​​​​Qt for Python - Qt WikiPySide6 快速上手指南&#xff1a;​​​​​​​Getting Started - Qt for Python PyS…...

【东枫科技】AMD / Xilinx Alveo™ V80计算加速器卡

AMD / Xilinx Alveo™ V80计算加速器卡 AMD/Xilinx Alveo ™ V80计算加速器卡是一款功能强大的计算加速器&#xff0c;基于7nm Versal™ 自适应SoC架构而打造。 AMD/Xilinx Alveo V80卡设计用于内存密集型任务。 这些任务包括HPC、数据分析、网络安全、传感器处理、计算存储和…...

C++ 动态内存管理

operator new和operator delete函数是两个全局函数&#xff0c;编译器在编译new和delete时会调用这两个函数&#xff0c;其底层分别是封装malloc和free 1.new new 内置类型 内置类型没有构造函数&#xff0c;所以使用new就是调operator new函数开空间&#xff0c;如果要初始化…...

(11)Vue-Router路由的详细使用

本系列教程目录&#xff1a;Vue3Element Plus全套学习笔记-目录大纲 文章目录 第2章 路由 Vue-Router2.1 Vue路由快速入门2.1.1 创建项目2.1.2 路由运行流程 2.2 传递参数-useRoute2.2.1 路径参数-params1&#xff09;普通传参2&#xff09;传递多个参数3&#xff09;对象方式传…...

RISCV的smstateen-ssstateen扩展

RISC-V 的 Smstateen / Ssstateen 扩展是为了解决安全性和资源隔离性问题而设计的&#xff0c;尤其是针对在多个上下文&#xff08;如用户线程、多个虚拟机&#xff09;之间 潜在的隐蔽信道(covert channel) 风险。 &#x1f310; 背景&#xff1a;隐蔽信道与上下文切换问题 当…...

C++ 与 Lua 联合编程

在软件开发的广阔天地里&#xff0c;不同编程语言各有所长。C 以其卓越的性能、强大的功能和对硬件的直接操控能力&#xff0c;在系统开发、游戏引擎、服务器等底层领域占据重要地位&#xff0c;但c编写的程序需要编译&#xff0c;这往往是一个耗时操作&#xff0c;特别对于大型…...

瑞萨 EZ-CUBE2 调试器

瑞萨 EZ-CUBE2 调试器 本文介绍了瑞萨 EZ-CUBE2 调试器的基本信息、调试方式、环境搭建、硬件连接、软件测试等。 包装展示 调试器展示 开关选项 详见&#xff1a;EZ-CUBE2 | Renesas 瑞萨电子 . 环境搭建 使用 Renesas 公司的 e2 studio 开发工具&#xff0c;下载 并安装该…...

MATLAB滤波工具箱演示——自定义维度、滤波方法的例程演示与绘图、数据输出

使用 M A T L A B MATLAB MATLAB的界面做了一个 M A T L A B MATLAB MATLAB滤波工具箱 d e m o demo demo&#xff0c;本文章给出演示&#xff1a;自定义维度、滤波方法的例程演示与绘图、数据输出 文章目录 编辑界面使用方法优势待改进点部分代码 编辑界面 使用 M A T L A B …...

数据库索引优化实战: 如何设计高效的数据库索引

数据库索引优化实战: 如何设计高效的数据库索引 一、理解数据库索引的核心原理 1.1 B树索引的结构特性 数据库索引&#xff08;Database Index&#xff09;的本质是通过特定数据结构加速数据检索。现代关系型数据库普遍采用B树&#xff08;B Tree&#xff09;作为默认索引结构&…...

TS 安装

TS较JS优势 1 TS静态类型编程语言。编译时发现错误 2 类型系统 强化变量类型概念 3 支持新语法 4 类型推断机制 可以和React框架中的各种hook配合 5 任何地方都有代码提示 tsc 命令 将TS转为JS 1 tsc 文件.ts 生成 js文件 2 执行JS代码...

CMake separate_arguments用法详解

separate_arguments 是 CMake 中用于将字符串分割成参数列表的命令&#xff0c;适用于处理包含空格的参数或复杂命令行参数。以下是其用法详解&#xff1a; 基本语法 separate_arguments(<variable> [UNIX|WINDOWS_COMMAND] [PROGRAM <program>] [ARGS <args&…...

【AI科技】AMD ROCm 6.4 新功能:突破性推理、即插即用容器和模块化部署,可在 AMD Instinct GPU 上实现可扩展 AI

AMD ROCm 6.4 新功能&#xff1a;突破性推理、即插即用容器和模块化部署&#xff0c;可在 AMD Instinct GPU 上实现可扩展 AI 现代 AI 工作负载的规模和复杂性不断增长&#xff0c;而人们对性能和部署便捷性的期望也日益提升。对于在 AMD Instinct™ GPU 上构建 AI 和 HPC 未来…...

2025年- H20-Lc128-240. 搜索二维矩阵 II(矩阵)---java版

1.题目描述 2.思路 遍历矩阵&#xff0c;然后如果遇到矩阵中的值正好等于target&#xff0c;输出true。否则&#xff0c;输出false。 3.代码 public class H240 {public boolean searchMatrix(int[][] matrix, int target) {//1.计算出总的行值&#xff0c;总的列值。int mm…...

LearningFlow:大语言模型城市驾驶的自动化策略学习工作流程

《LearningFlow: Automated Policy Learning Workflow for Urban Driving with Large Language Models》2025年1月发表&#xff0c;来自香港科技大学广州分校的论文。 强化学习&#xff08;RL&#xff09;的最新进展表明了自动驾驶的巨大潜力。尽管有这一前景&#xff0c;但奖励…...

C语言数据类型与内存布局

C语言数据类型内存占用 类型32位系统64位系统格式说明符char1字节1字节%cint4字节4字节%dfloat4字节4字节%fdouble8字节8字节%lflong long8字节8字节%lld...

从原理到实战讲解回归算法!!!

哈喽&#xff0c;大家好&#xff0c;我是我不是小upper, 今天系统梳理了线性回归的核心知识&#xff0c;从模型的基本原理、参数估计方法&#xff0c;到模型评估指标与实际应用场景&#xff0c;帮助大家深入理解这一经典的机器学习算法&#xff0c;助力数据分析与预测工作。 …...

linux指令中的竖线(“|”)是干啥的?【含实例展示】

文章目录 一、管道符的基本概念二、管道符的核心作用三、常用实例展示四、进阶技巧五、注意事项总结 实操展示**案例1&#xff1a;统计日志中特定错误的数量****案例2&#xff1a;查找当前运行的进程****案例3&#xff1a;合并排序并去重****案例4&#xff1a;实时监控CPU占用前…...

[HOT 100] 0124. 二叉树中的最大路径和

文章目录 1. 题目链接2. 题目描述3. 题目示例4. 解题思路5. 题解代码6. 复杂度分析 1. 题目链接 124. 二叉树中的最大路径和 - 力扣&#xff08;LeetCode&#xff09; 2. 题目描述 二叉树中的 路径 被定义为一条节点序列&#xff0c;序列中每对相邻节点之间都存在一条边。同一…...

[SoC]AXI总线Performance验证方案

AXI总线Performance验证方案 测试 AXI (Advanced eXtensible Interface) 的性能是 SoC 验证中的重要任务,旨在评估其在不同负载和配置下的表现是否满足设计要求。以下详细说明如何测试 AXI 的性能、需要统计的变量、计算方法、在验证环境中动态计算性能的方法,以及如何…...

EMC PowerStore存储学习之一NVMe磁盘的命名规则

PowerStore的日志中经常会看到类似于/dev/nvme1n1的磁盘&#xff0c;在svc_diag list --show_drives中也可以看到类似这样的输出&#xff0c;如下图&#xff1a; 这里的Drives的显示都是 /dev/nvmeXnY的形式&#xff0c;那么这个磁盘命名规则怎么解读呢&#xff1f; 在Linux系…...

apt-mirror搭建ubuntu本地离线源

参考资料 4 Steps to Setup Local Repository in Ubuntu using APT-mirror 使用 APT-mirror 四步配置 Ubuntu 本地软件仓库 ubuntu下的apt-get内网本地源的搭建...

【记录】新Ubuntu20配置voxelmap的环境安装

因为系统总出问题&#xff0c;仅用于个人纪录。 1. 升级CMake到3.28及以上版本&#xff08;Sophus依赖&#xff09; wget https://github.com/Kitware/CMake/releases/download/v3.28.3/cmake-3.28.3-linux-x86_64.sh chmod x cmake-3.28.3-linux-x86_64.sh sudo ./cmake-3.2…...

Python全流程开发实战:基于IMAP协议安全下载个人Gmail邮箱内所有PDF附件

在日常办公场景中&#xff0c;面对成百上千封携带PDF附件的邮件&#xff0c;手动逐一下载往往耗时耗力&#xff0c;成为效率瓶颈。如何通过代码实现“一键批量下载”&#xff1f;本文将以**“Gmail全量PDF附件下载工具”**开发为例&#xff0c;完整拆解从需求分析到落地交付的P…...

CPU:AMD的线程撕裂者(Threadripper)和霄龙(EPYC)的区别

AMD的**线程撕裂者&#xff08;Threadripper&#xff09;和霄龙&#xff08;EPYC&#xff09;**虽然都是面向高性能市场的处理器&#xff0c;但它们在定位、功能和技术规格上有显著区别。以下是两者的主要差异&#xff1a; 1. 目标市场 线程撕裂者&#xff08;Threadripper&…...

【五一培训】Day 2

注&#xff1a; 1. 本次培训内容的记录将以“Topic”的方式来呈现&#xff0c;用于记录个人对知识点的理解。 2. 由于培训期间&#xff0c;作者受限于一些现实条件&#xff0c;本文的排版及图片等相关优化&#xff0c;需要过一段时间才能完成。 3. 关于老板点评的一些思考 你…...

shell_plus

python manage.py shell_plus 是由 django-extensions 提供的一个增强版的 Django shell&#xff0c;它自动导入你的所有模型和其他一些便捷功能&#xff0c;使得交互式开发更加方便。 如果你遇到配置或运行问题&#xff0c;特别是与 RQ_SHOW_ADMIN_LINK 相关的 ImproperlyCon…...

基于C++、JsonCpp、Muduo库实现的分布式RPC通信框架

⭐️个人主页&#xff1a;小羊 ⭐️所属专栏&#xff1a;RPC框架 很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~ 目录 项目介绍JsonCpp库简单介绍Muduo库简单介绍C11异步操作——std::future1. 使用 std::async 关联异步任务2. std::packaged_task…...

Redis TLS 加密对性能的影响分析

Redis TLS 加密对性能的影响分析 是的&#xff0c;Redis 启用 TLS 加密确实会对性能产生一定影响&#xff0c;但影响程度取决于多种因素。以下是详细分析&#xff1a; 一、性能影响的主要来源 加密/解密开销‌&#xff1a; TLS 握手过程中的非对称加密&#xff08;如 RSA、…...

树与二叉树完全解析:从基础到应用

目录 一、树形结构的基础认知 1.1 树的定义与特点 1.2 核心术语解析 二、二叉树的深度解析 2.1 二叉树定义 2.2 特殊二叉树类型 2.3 重要性质总结 三、二叉树的存储与遍历 3.1 存储方式对比 3.2 遍历算法精讲 四、经典题型训练 4.1 相同树判断&#xff08;LeetCode…...

PostgreSQL:pgJDBC 下载和安装

PostgreSQL 的 pgJDBC 是用于 Java 程序连接和操作 PostgreSQL 数据库的 JDBC 驱动程序。 PostgreSQL&#xff1a;pgJDBC v42.7 下载和安装 点击【Application Stack Builder】 安装目录&#xff1a; 运行 cmd cd D:\PostgreSQL\pgJDBC copy postgresql-42.7.2.jar D:\groovy-…...

正则表达式与文本三剑客grep、sed、awk

目录 一、正则表达式 1.1、字符匹配 1.2、次数匹配 1.3、位置锚定 1.4、分组或其他 二、扩展正则表达式 三、grep 四、awk 4.1、常用命令选项 4.2、工作原理 4.3、基础用法 4.4、内置变量 4.5、模式 4.6、条件判断 4.7、awk中的循环语句 4.8、数组 4.9、脚本 …...

(35)VTK C++开发示例 ---将图片映射到平面2

文章目录 1. 概述2. CMake链接VTK3. main.cpp文件4. 演示效果 更多精彩内容&#x1f449;内容导航 &#x1f448;&#x1f449;VTK开发 &#x1f448; 1. 概述 与上一个示例不同的是&#xff0c;使用vtkImageReader2Factory根据文件扩展名或内容自动创建对应的图像文件读取器&a…...

每日一题洛谷P8635 [蓝桥杯 2016 省 AB] 四平方和c++

P8635 [蓝桥杯 2016 省 AB] 四平方和 - 洛谷 (luogu.com.cn) 直接暴力枚举&#xff0c;不做任何优化的话最后会TLE一个&#xff0c;稍微优化一下就过了&#xff08;数据给的还是太良心了&#xff09; 优化&#xff1a;每层循环用if判断一下&#xff0c;如果大于n就直接跳 当然…...

【python】【UV】一篇文章学完新一代 Python 环境与包管理器使用指南

&#x1f40d; UV&#xff1a;新一代 Python 环境与包管理器使用指南 一、UV 是什么&#xff1f; UV 是由 Astral 团队开发的高性能 Python 环境管理器&#xff0c;旨在统一替代 pyenv、pip、venv、pip-tools、pipenv 等工具。 1.1 UV 的主要功能 &#x1f680; 极速包安装&…...

6.10.单源最短路径问题-Dijkstra算法

一.BFS算法的局限性&#xff1a; 如上图&#xff0c;BFS算法可以解决无权图的单源最短路径问题&#xff0c; 如果是解决带权图的单源最短路径问题&#xff0c;BFS算法就不适用了&#xff0c;如下图&#xff1a; 如上图&#xff0c;比如求G港到其他顶点的最短路径&#xff0c; …...

Python基于深度学习的网络舆情分析系统(附源码,部署)

大家好&#xff0c;我是Python徐师兄&#xff0c;一个有着7年大厂经验的程序员&#xff0c;也是一名热衷于分享干货的技术爱好者。平时我在 CSDN、掘金、华为云、阿里云和 InfoQ 等平台分享我的心得体会。 &#x1f345;文末获取源码联系&#x1f345; 2025年最全的计算机软件毕…...

mysql--索引

索引作为一种数据结构&#xff0c;其用途是用于提升检索数据的效率。 分类 普通索引&#xff08;INDEX&#xff09;&#xff1a;索引列值可重复 唯一索引&#xff08;UNIQUE&#xff09;&#xff1a;索引列值必须唯一&#xff0c;可以为NULL 主键索引&#xff08;PRIMARY KEY&a…...

【算法题】荷兰国旗问题[力扣75题颜色分类] - JAVA

一、题目 二、文字解释 1.1 前言 本题是经典的「荷兰国旗问题」&#xff0c;由计算机科学家 Edsger W. Dijkstra 首先提出。如同图中所示的荷兰国旗&#xff0c;其由红、白、蓝三色水平排列组成。在算法领域&#xff0c;该问题可类比为将一个由特定的三种元素&#xff08;可…...

【数据结构】堆的完整实现

堆的完整实现 堆的完整实现GitHub地址前言堆的核心功能实现重温堆的定义堆结构定义1. 堆初始化与销毁2. 元素交换函数3. 堆化操作向上调整&#xff08;子→父&#xff09;向下调整&#xff08;父→子&#xff09; 4. 堆元素插入5. 堆元素删除6. 辅助功能函数堆的判空获取堆顶元…...

软考 系统架构设计师系列知识点之杂项集萃(51)

接前一篇文章&#xff1a;软考 系统架构设计师系列知识点之杂项集萃&#xff08;50&#xff09; 第80题 设三个煤场A1、A2、A3分别能供应煤7、12、11万吨&#xff0c;三个工厂B1、B2、B3分别需要10、10、10万吨&#xff0c;从各煤场到各工厂运煤的单价&#xff08;百元/吨&…...

patch命令在代码管理中的应用

patch 是一个用于将差异文件&#xff08;补丁&#xff09;应用到源代码的工具&#xff0c;常用于修复 bug、添加功能或调整代码结构。在您提供的代码中&#xff0c;patch 命令通过一系列补丁文件&#xff08;.patch&#xff09;修改了 open-amp 库的源代码。 patch 命令的核心作…...

Qt结构体运算符重载指南

在 Qt 中&#xff0c;结构体&#xff08;struct&#xff09;或类&#xff08;class&#xff09;中重载运算符是一种常见的做法&#xff0c;用于实现自定义类型的逻辑操作&#xff08;如比较、算术运算等&#xff09;。以下是一些常见的运算符重载示例和注意事项&#xff1a; 1.…...

基于bert预训练模型的垃圾短信分类系统

文章目录 任务介绍数据说明注意事项数据处理数据准备数据集划分数据集类构建模型构建与训练模型构建模型训练模型推理附录任务介绍 随着移动通信技术的飞速发展,短信(Short Message Service, SMS)已成为人们日常生活中不可或缺的沟通方式之一。然而,垃圾短信(Spam SMS)的…...

[Android] 网易爆米花TV 2.0.0.0429(原网易Filmly,支持多网盘的TV版、电脑版带海报墙播放器)

[Android] 网易爆米花 链接&#xff1a;https://pan.xunlei.com/s/VOPDuQS9D7qixvAnoy7-he2PA1?pwdhzvh# [Android] 网易爆米花TV 2.0.0.0429&#xff08;原网易Filmly&#xff0c;支持多网盘的TV版、电脑版带海报墙播放器&#xff09; 详细介绍直接上主页截图&#xff0c;…...

# 前后端分离象棋对战项目开发记录

1. **结构清晰**&#xff1a;使用更直观的标题、分段和列表&#xff0c;增强可读性。 2. **视觉美观**&#xff1a;添加Markdown格式化&#xff08;如代码块、加粗、斜体&#xff09;&#xff0c;并建议配色和排版风格。 3. **内容精炼**&#xff1a;精简冗余表述&#xff0c;突…...