java后端生成心电图-jfreechart
用jfreechart生成心电图
先上成功的图片
上代码
1.导入包
implementation 'org.jfree:jfreechart:1.5.4'implementation 'org.jfree:jcommon:1.0.24'
2.实现代码
对数据进行滤波
转换单位
package com.shinrun.infrastructure.util;import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;public class ECGDataConverter {/*** 将原始数据转换为mV单位的数据* @param rawData 原始数据数组* @param scaleFactor 比例因子(20000对应1mV)* @return 转换后的数据数组(单位mV)*/public static double[] convertToMillivolts(double[] rawData, double scaleFactor) {double[] convertedData = new double[rawData.length];for (int i = 0; i < rawData.length; i++) {convertedData[i] = rawData[i] / scaleFactor;}return convertedData;}/*** 将原始数据转换为微伏(uV)单位的数据* @param rawData 原始数据数组* @param scaleFactor 比例因子(20000对应1mV)* @return 转换后的数据数组(单位uV)*/public static double[] convertToMicrovolts(double[] rawData, double scaleFactor) {double[] convertedData = new double[rawData.length];for (int i = 0; i < rawData.length; i++) {convertedData[i] = (rawData[i] / scaleFactor) * 1000; // 转换为uV}return convertedData;}/*** 移动平均滤波器 - 平滑高频噪声* @param data 原始ECG数据(uV)* @param windowSize 窗口大小(建议3-7)* @return 滤波后的数据*/public static double[] movingAverageFilter(double[] data, int windowSize) {if (windowSize < 1 || windowSize > data.length) {throw new IllegalArgumentException("Invalid window size");}double[] filtered = new double[data.length];int halfWindow = windowSize / 2;for (int i = 0; i < data.length; i++) {int start = Math.max(0, i - halfWindow);int end = Math.min(data.length - 1, i + halfWindow);double sum = 0;int count = 0;for (int j = start; j <= end; j++) {sum += data[j];count++;}filtered[i] = sum / count;}return filtered;}/*** 中值滤波器 - 有效去除脉冲噪声* @param data 原始ECG数据(uV)* @param windowSize 窗口大小(建议3-5)* @return 滤波后的数据*/public static double[] medianFilter(double[] data, int windowSize) {if (windowSize < 1 || windowSize > data.length || windowSize % 2 == 0) {throw new IllegalArgumentException("Window size must be odd and positive");}double[] filtered = new double[data.length];int halfWindow = windowSize / 2;double[] window = new double[windowSize];for (int i = 0; i < data.length; i++) {int start = Math.max(0, i - halfWindow);int end = Math.min(data.length - 1, i + halfWindow);// 填充窗口int index = 0;for (int j = start; j <= end; j++) {window[index++] = data[j];}// 对窗口数据进行排序Arrays.sort(window, 0, index);// 取中值filtered[i] = window[index / 2];}return filtered;}/*** 基于阈值的异常值过滤* @param data 原始ECG数据(uV)* @param thresholdMultiplier 阈值乘数(建议2.5-3.5)* @return 过滤后的数据*/public static double[] thresholdFilter(double[] data, double thresholdMultiplier) {// 计算数据的均值和标准差double mean = 0;for (double v : data) {mean += v;}mean /= data.length;double stdDev = 0;for (double v : data) {stdDev += Math.pow(v - mean, 2);}stdDev = Math.sqrt(stdDev / data.length);double threshold = thresholdMultiplier * stdDev;double[] filtered = new double[data.length];for (int i = 0; i < data.length; i++) {if (Math.abs(data[i] - mean) > threshold) {// 如果是异常值,用前后值的平均值替代double prev = i > 0 ? filtered[i-1] : mean;double next = i < data.length-1 ? data[i+1] : mean;filtered[i] = (prev + next) / 2;} else {filtered[i] = data[i];}}return filtered;}/*** 组合滤波器 - 先中值滤波再移动平均* @param data 原始ECG数据(uV)* @param medianWindow 中值滤波窗口大小(建议3)* @param averageWindow 移动平均窗口大小(建议5)* @return 滤波后的数据*/public static double[] combinedFilter(double[] data, int medianWindow, int averageWindow) {double[] medianFiltered = medianFilter(data, medianWindow);return movingAverageFilter(medianFiltered, averageWindow);}/*** 原始数据强过滤(处理ADC值)* @param rawData 原始ADC数据* @param maxAllowed 允许的最大ADC绝对值* @return 过滤后的原始ADC数据*/public static double[] filterRawData(double[] rawData, double maxAllowed) {if (rawData == null) {return new double[0];}double[] filtered = Arrays.copyOf(rawData, rawData.length);int windowSize = 7; // 使用前后各3个点(共7点窗口)for (int i = 0; i < filtered.length; i++) {if (Math.abs(filtered[i]) > maxAllowed) {// 获取周围正常值的滑动窗口中值filtered[i] = getSlidingWindowReplacement(filtered, i, windowSize, maxAllowed);}}return filtered;}private static double getSlidingWindowReplacement(double[] data, int centerIdx,int windowSize, double maxAllowed) {int halfWindow = windowSize / 2;List<Double> validValues = new ArrayList<>();// 收集窗口内有效值for (int i = -halfWindow; i <= halfWindow; i++) {int actualIdx = centerIdx + i;if (actualIdx >= 0 && actualIdx < data.length &&Math.abs(data[actualIdx]) <= maxAllowed) {validValues.add(data[actualIdx]);}}// 处理策略(按优先级):if (!validValues.isEmpty()) {// 1. 有有效值则取中位数Collections.sort(validValues);return validValues.get(validValues.size() / 2);} else {// 2. 无有效值则取前一个正常值(向前搜索)for (int i = centerIdx - 1; i >= 0; i--) {if (Math.abs(data[i]) <= maxAllowed) {return data[i];}}// 3. 极端情况返回0return 0.0;}}}
图片生成 方法
package com.shinrun.infrastructure.util;import org.jfree.chart.ChartFactory;
import org.jfree.chart.ChartUtils;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.chart.ui.RectangleInsets;
import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection;import java.awt.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Base64;/*** 医疗级心电图生成工具类(10段垂直排列)* 实现了标准心电图纸网格和比例尺*/
public class ECGChartGenerator {// ============= 默认参数配置 =============private static final int DEFAULT_SAMPLE_RATE = 500; // 默认采样率500Hzprivate static final int SEGMENT_COUNT = 10; // 固定10段心电图private static final int DEFAULT_WIDTH = 800; // 图片默认宽度private static final int SEGMENT_HEIGHT = 150; // 每段心电图高度private static final int TOTAL_HEIGHT = SEGMENT_COUNT * SEGMENT_HEIGHT; // 总高度// 心电图纸网格参数(医疗标准)private static final int SMALL_GRID_MM = 1; // 小方格1mmprivate static final int LARGE_GRID_MM = 5; // 大方格5mm(5个小方格)private static final int GRID_SIZE_PX = 12; // 1mm对应的像素数(方法二)// 心电图显示参数private static final double DEFAULT_MM_PER_MV = 10.0; // 标准灵敏度:10mm/mVprivate static final double DEFAULT_PAPER_SPEED_MM_PER_SEC = 25.0; // 标准走纸速度:25mm/sprivate static final int DEFAULT_HEIGHT = 600; // 图片默认高度/*** 生成无标签的心电图纸网格*/public static String generateECGGrid() throws IOException {// 创建空数据集(不需要实际数据)XYSeriesCollection dataset = new XYSeriesCollection();// 创建图表JFreeChart chart = ChartFactory.createXYLineChart(null, "", "", dataset);// 自定义网格样式customizeGridChart(chart);return convertChartToBase64(chart, DEFAULT_WIDTH, DEFAULT_HEIGHT);}/*** 自定义网格图表样式*/private static void customizeGridChart(JFreeChart chart) {XYPlot plot = chart.getXYPlot();// 1. 背景设置plot.setBackgroundPaint(Color.WHITE);chart.setBackgroundPaint(Color.WHITE);// 2. 网格线设置(医疗标准)plot.setDomainGridlinePaint(new Color(255, 200, 200)); // 小网格线颜色plot.setRangeGridlinePaint(new Color(255, 200, 200));plot.setDomainGridlineStroke(new BasicStroke(0.5f)); // 小网格线宽度plot.setRangeGridlineStroke(new BasicStroke(0.5f));// 计算网格大小(像素)double smallGridPx = SMALL_GRID_MM * GRID_SIZE_PX;double largeGridPx = LARGE_GRID_MM * GRID_SIZE_PX;// 3. X轴(时间轴)设置 - 隐藏所有标签和刻度NumberAxis xAxis = (NumberAxis) plot.getDomainAxis();xAxis.setAxisLineVisible(false);xAxis.setTickMarksVisible(false);xAxis.setTickLabelsVisible(false);xAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());xAxis.setTickUnit(new org.jfree.chart.axis.NumberTickUnit(largeGridPx));// 4. Y轴(幅度轴)设置 - 隐藏所有标签和刻度NumberAxis yAxis = (NumberAxis) plot.getRangeAxis();yAxis.setAxisLineVisible(false);yAxis.setTickMarksVisible(false);yAxis.setTickLabelsVisible(false);yAxis.setTickUnit(new org.jfree.chart.axis.NumberTickUnit(largeGridPx));// 5. 移除所有渲染器(因为我们只需要网格)plot.setRenderer(null);// 6. 调整图表边距plot.setAxisOffset(new RectangleInsets(5, 5, 5, 5));// 7. 确保没有图例chart.removeLegend();// 8. 设置合适的范围以显示网格xAxis.setRange(0, DEFAULT_WIDTH / GRID_SIZE_PX);yAxis.setRange(0, DEFAULT_HEIGHT / GRID_SIZE_PX);}/*** 使用默认参数生成10段ECG Base64图片*/public static String generateSegmentedECGImage(double[] ecgData) throws IOException {return generateSegmentedECGImage(ecgData, DEFAULT_SAMPLE_RATE, DEFAULT_MM_PER_MV, DEFAULT_PAPER_SPEED_MM_PER_SEC);}/*** 自定义参数生成10段ECG Base64图片*/public static String generateSegmentedECGImage(double[] ecgData, int sampleRate, double mmPerMv, double paperSpeedMmPerSec) throws IOException {// 计算每段数据点数int pointsPerSegment = ecgData.length / SEGMENT_COUNT;XYSeriesCollection dataset = new XYSeriesCollection();// 创建10个数据段for (int seg = 0; seg < SEGMENT_COUNT; seg++) {int start = seg * pointsPerSegment;int end = (seg == SEGMENT_COUNT - 1) ? ecgData.length : start + pointsPerSegment;XYSeries series = new XYSeries("ECG Segment " + (seg + 1));// 垂直偏移量(使各段分开显示)double yOffset = -seg * 2.0; // 每段下移2mVfor (int i = start; i < end; i++) {// 计算时间并转换为毫米(基于走纸速度)double timeSec = (i - start) / (double) sampleRate;double xPosMm = timeSec * paperSpeedMmPerSec;// 转换为像素double xPixel = xPosMm * GRID_SIZE_PX;// 转换ECG值到mV(输入是uV)double valueMv = ecgData[i] / 1000.0;// 应用垂直比例尺(mm/mV)double yPosMm = valueMv * mmPerMv;// 转换为像素并加上偏移量double yPixel = yPosMm * GRID_SIZE_PX + (yOffset * mmPerMv * GRID_SIZE_PX);series.add(xPixel, yPixel);}dataset.addSeries(series);}// 创建图表JFreeChart chart = ChartFactory.createXYLineChart(null, "时间 (mm)", "幅度 (mm)", dataset);// 自定义心电图样式customizeMedicalECGChart(chart, mmPerMv, paperSpeedMmPerSec);return convertChartToBase64(chart, DEFAULT_WIDTH, TOTAL_HEIGHT);}/*** 自定义心电图图表样式(医疗标准)*/private static void customizeMedicalECGChart(JFreeChart chart, double mmPerMv, double paperSpeedMmPerSec) {XYPlot plot = chart.getXYPlot();// 1. 背景设置plot.setBackgroundPaint(Color.WHITE);chart.setBackgroundPaint(Color.WHITE);// 2. 网格线设置(医疗标准)plot.setDomainGridlinePaint(new Color(255, 200, 200)); // 小网格线颜色plot.setRangeGridlinePaint(new Color(255, 200, 200));plot.setDomainGridlineStroke(new BasicStroke(0.5f)); // 小网格线宽度plot.setRangeGridlineStroke(new BasicStroke(0.5f));// 计算网格大小(像素)double smallGridPx = SMALL_GRID_MM * GRID_SIZE_PX;double largeGridPx = LARGE_GRID_MM * GRID_SIZE_PX;// 3. X轴(时间轴)设置NumberAxis xAxis = (NumberAxis) plot.getDomainAxis();xAxis.setAxisLinePaint(Color.BLACK);xAxis.setTickMarkPaint(Color.BLACK);xAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());xAxis.setTickUnit(new org.jfree.chart.axis.NumberTickUnit(largeGridPx));// 新版JFreeChart不再支持setMinorTickMarkPaint,改用以下方式设置次刻度xAxis.setMinorTickCount(4);xAxis.setMinorTickMarksVisible(true);// 4. Y轴(幅度轴)设置NumberAxis yAxis = (NumberAxis) plot.getRangeAxis();yAxis.setAxisLinePaint(Color.BLACK);yAxis.setTickMarkPaint(Color.BLACK);yAxis.setTickUnit(new org.jfree.chart.axis.NumberTickUnit(largeGridPx));yAxis.setMinorTickCount(4);yAxis.setMinorTickMarksVisible(true);// 5. 心电图曲线渲染设置XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer();renderer.setSeriesPaint(0, Color.BLACK);renderer.setSeriesStroke(0, new BasicStroke(1.5f));// 为所有段应用相同的渲染器for (int i = 0; i < SEGMENT_COUNT; i++) {plot.setRenderer(i, renderer);renderer.setSeriesPaint(i, Color.BLACK);renderer.setSeriesStroke(i, new BasicStroke(1.5f));renderer.setSeriesShapesVisible(i, false);}// 6. 调整图表边距plot.setAxisOffset(new RectangleInsets(5, 5, 5, 5));// 7. 移除图例chart.removeLegend();// 8. 添加标题显示参数chart.setTitle("心电图 - " + mmPerMv + "mm/mV, 走纸速度 " + paperSpeedMmPerSec + "mm/s");}/*** 使用默认参数生成10段ECG Base64图片(无刻度值)*/public static String generateSegmentedECGImageNoLabels(double[] ecgData) throws IOException {return generateSegmentedECGImageNoLabels(ecgData, DEFAULT_SAMPLE_RATE,DEFAULT_MM_PER_MV, DEFAULT_PAPER_SPEED_MM_PER_SEC);}/*** 自定义参数生成10段ECG Base64图片(无刻度值)*/public static String generateSegmentedECGImageNoLabels(double[] ecgData, int sampleRate,double mmPerMv, double paperSpeedMmPerSec) throws IOException {// 计算每段数据点数int pointsPerSegment = ecgData.length / SEGMENT_COUNT;XYSeriesCollection dataset = new XYSeriesCollection();// 创建10个数据段for (int seg = 0; seg < SEGMENT_COUNT; seg++) {int start = seg * pointsPerSegment;int end = (seg == SEGMENT_COUNT - 1) ? ecgData.length : start + pointsPerSegment;XYSeries series = new XYSeries("ECG Segment " + (seg + 1));// 垂直偏移量(使各段分开显示)double yOffset = -seg * 2.0; // 每段下移2mVfor (int i = start; i < end; i++) {// 计算时间并转换为毫米(基于走纸速度)double timeSec = (i - start) / (double) sampleRate;double xPosMm = timeSec * paperSpeedMmPerSec;// 转换为像素double xPixel = xPosMm * GRID_SIZE_PX;// 转换ECG值到mV(输入是uV)double valueMv = ecgData[i] / 1000.0;// 应用垂直比例尺(mm/mV)double yPosMm = valueMv * mmPerMv;// 转换为像素并加上偏移量double yPixel = yPosMm * GRID_SIZE_PX + (yOffset * mmPerMv * GRID_SIZE_PX);series.add(xPixel, yPixel);}dataset.addSeries(series);}// 创建图表JFreeChart chart = ChartFactory.createXYLineChart(null, "", "", dataset); // 空标题和空轴标签// 自定义心电图样式(无刻度值)customizeMedicalECGChartNoLabels(chart, mmPerMv, paperSpeedMmPerSec);return convertChartToBase64(chart, DEFAULT_WIDTH, TOTAL_HEIGHT);}/*** 自定义心电图图表样式(医疗标准,无刻度值)*/private static void customizeMedicalECGChartNoLabels(JFreeChart chart, double mmPerMv, double paperSpeedMmPerSec) {XYPlot plot = chart.getXYPlot();// 1. 背景设置plot.setBackgroundPaint(Color.WHITE);chart.setBackgroundPaint(Color.WHITE);// 2. 网格线设置(医疗标准)plot.setDomainGridlinePaint(new Color(255, 200, 200)); // 小网格线颜色plot.setRangeGridlinePaint(new Color(255, 200, 200));plot.setDomainGridlineStroke(new BasicStroke(0.5f)); // 小网格线宽度plot.setRangeGridlineStroke(new BasicStroke(0.5f));// 计算网格大小(像素)double smallGridPx = SMALL_GRID_MM * GRID_SIZE_PX;double largeGridPx = LARGE_GRID_MM * GRID_SIZE_PX;// 3. X轴(时间轴)设置 - 隐藏刻度值NumberAxis xAxis = (NumberAxis) plot.getDomainAxis();xAxis.setAxisLineVisible(false); // 隐藏轴线xAxis.setTickMarksVisible(false); // 隐藏刻度线xAxis.setTickLabelsVisible(false); // 隐藏刻度标签xAxis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());xAxis.setTickUnit(new org.jfree.chart.axis.NumberTickUnit(largeGridPx));// 4. Y轴(幅度轴)设置 - 隐藏刻度值NumberAxis yAxis = (NumberAxis) plot.getRangeAxis();yAxis.setAxisLineVisible(false); // 隐藏轴线yAxis.setTickMarksVisible(false); // 隐藏刻度线yAxis.setTickLabelsVisible(false); // 隐藏刻度标签yAxis.setTickUnit(new org.jfree.chart.axis.NumberTickUnit(largeGridPx));// 5. 心电图曲线渲染设置XYLineAndShapeRenderer renderer = new XYLineAndShapeRenderer();renderer.setSeriesPaint(0, Color.BLACK);renderer.setSeriesStroke(0, new BasicStroke(0.8f));// 为所有段应用相同的渲染器for (int i = 0; i < SEGMENT_COUNT; i++) {plot.setRenderer(i, renderer);renderer.setSeriesPaint(i, Color.BLACK);renderer.setSeriesStroke(i, new BasicStroke(0.8f));renderer.setSeriesShapesVisible(i, false);}// 6. 调整图表边距plot.setAxisOffset(new RectangleInsets(5, 5, 5, 5));// 7. 移除图例chart.removeLegend();// 8. 移除标题chart.setTitle("心电图 - " + mmPerMv + "mm/mV, 走纸速度 " + paperSpeedMmPerSec + "mm/s");}/*** 将图表转换为Base64编码的PNG图片*/private static String convertChartToBase64(JFreeChart chart, int width, int height) throws IOException {try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {ChartUtils.writeChartAsPNG(outputStream, chart, width, height);return "data:image/png;base64," + Base64.getEncoder().encodeToString(outputStream.toByteArray());}}
}
讲解使用
我的心电图数据是来着于第三方平台的(是由机器将心电数据文件上传到第三方系统,第三方系统给我返回的double数组)
首先是进行 滤波,数据会有很大的外界因素影响,波动会很大,
再将数据转换成mv
再画图,进行调试
public String generateEcg(double[] rawData ) {// 转换参数double scaleFactor = 20.0;String oss="";// 方法1: 使用默认参数处理double[] processedECG = ECGDataConverter.filterRawData(rawData,4000);//转换成mvdouble[] doubles = ECGDataConverter.convertToMillivolts(processedECG, scaleFactor);// 生成时间轴try {String string = ECGChartGenerator.generateSegmentedECGImageNoLabels(doubles);oss= uploadFile(string, "image/ecg");} catch (IOException e) {throw new RuntimeException(e);}return oss;}
关键点
double[] processedECG = ECGDataConverter.filterRawData(rawData,4000);
这里 滤波参数我给的4000 其实就是 将超过4000的值给过滤掉,第三方给的数据 人的平均心跳峰值不超过4000,超过4000的那就不对需要过滤掉,这个根据你实际的数据进行修改
double scaleFactor = 20.0;//转换成mvdouble[] doubles = ECGDataConverter.convertToMillivolts(processedECG, scaleFactor);
这里传个参数scaleFactor ,其实就是对数据进行除一下,这里由于第三方给的数据不太规范,不除以一下的话画出来不太好看
一般数据除到是百位数就行了
如果上面两点没有做好的话效果可能如下
相关文章:

java后端生成心电图-jfreechart
用jfreechart生成心电图 先上成功的图片 上代码 1.导入包 implementation org.jfree:jfreechart:1.5.4implementation org.jfree:jcommon:1.0.242.实现代码 对数据进行滤波 转换单位 package com.shinrun.infrastructure.util;import java.util.ArrayList; import java.ut…...

算法/机理模型演示平台搭建(二)——算法接口部署(FastApi)
算法/机理模型演示平台搭建(二)—— 算法接口部署(FastApi) 1. 项目结构2. 构建 Docker 镜像3. 运行 Docker 容器4. 访问 API 文档5. 调用 API1. 项目结构 app app/algorithms app/models Dockerfile FROM python:3.9-slimWORKDIR /codeCOPY ./requirements.txt /code…...

动态规划-647.回文子串-力扣(LeetCode)
一、题目解析 这里的子字符串是连续的,与之前的子序列不同,这里需要我们统计回文子串的数目。 二、算法原理 这里也有其他算法可以解决该问题,如中心扩展算法 时间复杂度O(N^2)/空间复杂度O(1),马拉车算法(具有局限性) 时间复杂…...
es 的字段类型(text和keyword)
Text 当一个字段是要被全文检索时,比如 Email 内容、产品描述,这些字段应该使用 text 类型。设置 text 类型以后,字段内容会被分析,在生成倒排索引之前,字符串会被分析器分词。text类型的字段不用于排序,很…...
Kotlin 中companion object {} 什么时候触发
在 Kotlin 中,companion object 的初始化触发时机是一个重要但容易被忽视的细节。以下是详细的解释: 1. 基本触发时机 companion object 的初始化发生在: 首次访问该类时(无论是访问伴生对象成员、创建类实例,还是通过…...

仿真每日一练 | Workbench中接触种类及选择方法简介
Workbench中给我们提供的接触类型主要包括以下几种👇 ◆ 1、摩擦 ◆ 2、无摩擦 ◆ 3、绑定 ◆ 4、不分离 ◆ 5、粗糙 ◆ 6、强制滑移 下面通过最常用的摩擦和绑定给大家展示两者的区别,同时文末也给大家介绍了几种接触的选择方法。首先先给大家介绍一下…...

Go语言中的rune和byte类型详解
1. rune类型 1.1. 基本概念 1. rune是Go语言的内建类型,它是int32的别名,即32位有符号整数; 2. 用于表示一个Unicode码点,全拼Unicode code point; 3. 可以表示任何UTF-8编码的字符; 1.2. 特点 1. 每…...
superior哥AI系列第6期:Transformer注意力机制:AI界的“注意力革命“
🎭 superior哥AI系列第6期:Transformer注意力机制:AI界的"注意力革命" 嘿!小伙伴们!👋 今天superior哥要带你们探索AI界最火的技术——Transformer!这个家伙可了不得,它不…...

【java面试】redis篇
redis篇 一、适用场景(一)缓存1、缓存穿透1.1 解决方案1:缓存空数据,查询返回的数据为空,将空结果缓存1.2 解决方案2:布隆过滤器 2、缓存击穿1.1 解决方案1:互斥锁1.2 解决方案2:逻辑…...

高效易用的 MAC 版 SVN 客户端:macSvn 使用体验
高效易用的 MAC 版 SVN 客户端:macSvn 使用体验 下载安装使用总结 最近有个项目要使用svn, 但是mac缺乏一款像 Windows 平台 TortoiseSVN 那样全面、高效且便捷的 SVN 客户端工具, 直到博主找到了该工具本文将结合实际使用体验,详细介绍 macSvn工具的核心…...
【搭建 Transformer】
搭建 Transformer 的基本步骤 Transformer 是一种基于自注意力机制的深度学习模型,广泛应用于自然语言处理任务。以下为搭建 Transformer 的关键步骤和代码示例。 自注意力机制 自注意力机制是 Transformer 的核心,计算输入序列中每个元素与其他元素的…...
自然图像数据集
目录 CIFAR-10 数据集CIFAR-100 数据集AFHQ 数据集FFHQ 数据集 CIFAR-10 数据集 简介: CIFAR-10 是一个经典的图像分类数据集,广泛用于机器学习领域的计算机视觉算法基准测试。它包含60000幅32x32的彩色图像,分为10个类,每类6000…...
Linux下使用nmcli连接网络
Linux下使用nmcli连接网络 介绍 在使用ubuntu系统的时候,有时候不方便使用桌面,使用ssh远程连接,可能需要使用nmcli命令来连接网络。本文将介绍如何使用nmcli命令连接网络。nmcli 是 NetworkManager 的命令行工具,用于管理网络连…...

HCIP(BGP综合实验)
一、实验拓扑 AS 划分: AS1:R1(环回 L0:172.16.0.1/32,L1:192.168.1.0/24)AS2:R2、R3、R4、R5、R6、R7(内部运行 OSPF,AS 号为 64512 和 64513 的联盟)AS3:R…...

Attention Is All You Need (Transformer) 以及Transformer pytorch实现
参考https://zhuanlan.zhihu.com/p/569527564 Attention Is All You Need (Transformer) 是当今深度学习初学者必读的一篇论文。 一. Attention Is All You Need (Transformer) 论文精读 1. 知识准备 机器翻译,就是将某种语言的一段文字翻译成另一段文字。 由…...

uniapp+vue2+uView项目学习知识点记录
持续更新中... 1、发送给朋友,分享到朋友圈功能开启 利用onShareAppMessage和onShareTimeline生命周期函数,在script中与data同级去写 // 发送给朋友 onShareAppMessage() {return {title: 清清前端, // 分享标题path: /pages/index/index, // 分享路…...

精美的软件下载页面HTML源码:现代UI与动画效果的完美结合
精美的软件下载页面HTML源码:现代UI与动画效果的完美结合 在数字化产品推广中,一个设计精良的下载页面不仅能提升品牌专业度,还能显著提高用户转化率。本文介绍的精美软件下载页面HTML源码,通过现代化UI设计与丰富的动画效果&…...

车载诊断架构 --- DTC消抖参数(Trip Counter DTCConfirmLimit )
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…...

javaEE->IO:
文件: 操作系统中会把很多 硬件设备 和 软件资源 抽象成“文件”,统一进行管理。 大部分谈到的文件,都是指 硬盘的文件,文件就相当于是针对“硬盘”数据的一种抽象 硬盘: 1.机械硬盘:便宜 2.固态硬盘&…...

Oracle 用户/权限/角色管理
1. 用户 1.1. 用户的创建和删除 1.1.1. 创建用户 create user user identified {by password | externally} [ default tablespace tablespace ] [ temporary tablespace tablespace ] [ quota {integer [k | m ] | unlimited } on tablespace [ quota {integer [k | m ] | …...
使用免费wordpress成品网站模板需要注意点什么
在使用免费 WordPress 成品网站模板时,需要从版权、安全性、兼容性、功能限制等多个方面谨慎考量,避免后续出现问题。以下是具体需要注意的要点: 一、版权与授权问题 明确授权类型 免费模板可能分为「开源免费」「限个人使用」「禁止商业用…...
深入理解 JSX:React 的核心语法
1. 什么是 JSX? JSX(JavaScript And XML)是 React 中最核心的概念之一,也是区别于 Vue 的一个重要特征(尽管 Vue 现在也支持 JSX 语法)。JSX 是一种在 JavaScript 中编写 HTML 代码片段的语法协议…...

工厂方法模式深度解析:从原理到应用实战
作者简介 我是摘星,一名全栈开发者,专注 Java后端开发、AI工程化 与 云计算架构 领域,擅长Python技术栈。热衷于探索前沿技术,包括大模型应用、云原生解决方案及自动化工具开发。日常深耕技术实践,乐于分享实战经验与…...
TS 星际通信指南:从 TCP 到 UDP 的宇宙漫游
文章目录 一、计算机网络通信1、基本概念2、核心要素(一)终端设备(二)通信介质(三)网络协议 3、常用通信模型(一)OSI 七层模型(理论框架)(二&…...

python可视化:端午假期旅游火爆原因分析
python可视化:端午假期旅游火爆原因分析 2025年的旅游市场表现强劲: 2025年端午假期全社会跨区域人员流动量累计6.57亿人次,日均2.19亿人次,同比增长3.0%。入境游订单同比大涨近90%,门票交易额(GMV&#…...
Missashe考研日记—Day51-Day57
Missashe考研日记—Day51-Day57 写在面前 本系列博客用于记录博主一周的学习进度。线代题型总结 专业课408 这周简直是拼命学计网,花了两三天速通传输层和应用层内容,又臭又长的网课听不下去一点了,赶紧结束准备开二轮进行复习和刷题了。…...
electron-vite_18桌面共享
electron默认不支持桌面共享,需要添加desktopCapturer配置,这样在使用navigator.mediaDevices.getUserMedia API访问可用于从桌面捕获音频和视频的媒体源的信息。 electron版本 "electron": "^31.0.2",在main.js中添加desktopCaptu…...

SOC-ESP32S3部分:28-BLE低功耗蓝牙
飞书文档https://x509p6c8to.feishu.cn/wiki/CHcowZMLtiinuBkRhExcZN7Ynmc 蓝牙是一种短距的无线通讯技术,可实现固定设备、移动设备之间的数据交换,下图是一个蓝牙应用的分层架构,Application部分则是我们需要实现的内容,Protoc…...

Git-flow流
Git git是版本控制软件,一般用来做代码版本控制 github是一个免费版本控制仓库是国内外很多开源项目的集中地,其本体是一个git服务器 Git初始化操作 git init 初始化仓库 git status 查看当前仓库的状态 git add . 将改动的文件加到暂存区 gi…...

VirtualBox给Rock Linux9.x配置网络
写这篇文章之前,先说明一下,我参考的是我之前写的《VirtualBox Linux网络配置》 我从CentOS7转到了Rock9,和配置Centos7一样,主流程没有变化,变化的是Rock9.x中的配置文件和使用的命令。 我再说一次,因为主…...