百度飛槳OCR(PP-OCRv4_server_det|PP-OCRv4_server_rec_doc)文本識別-Java項目實踐

什么是OCR?

OCR(Optical Character Recognition,光學字符識別)是一種通過技術手段將圖像或掃描件中的文字內容轉換為可編輯、可搜索的文本格式(如TXT、Word、PDF等)的技術。它廣泛應用于文檔數字化、信息提取、自動化處理等領域。


OCR的核心功能

  1. 圖像轉文本
    將紙質文檔、照片、PDF掃描件等圖像中的文字提取為計算機可識別的字符。

    • 例如:從一張發票中提取金額、日期等信息。
  2. 多語言支持
    支持多種語言的字符識別(如中文、英文、日文、阿拉伯語等),甚至能處理手寫體、特殊符號。

  3. 格式保留
    部分高級OCR工具可保留原文檔的排版、表格結構、字體樣式等。


OCR的工作原理

  1. 圖像預處理

    • 去噪、二值化、傾斜校正等,優化圖像質量以提高識別準確率。
  2. 字符檢測與分割

    • 定位圖像中的文字區域,并將單個字符或單詞分割出來。
  3. 特征提取與匹配

    • 通過算法(如深度學習模型)分析字符形狀,與已知字符庫比對,確定最可能的字符。
  4. 后處理與優化

    • 結合上下文語義修正識別結果(如將“0”修正為字母“O”),提升文本準確性。

常見應用場景

  1. 文檔數字化

    • 將紙質書籍、合同、檔案掃描為電子文本,便于存儲和檢索。
  2. 自動化辦公

    • 提取發票、收據、表單中的數據,自動導入數據庫或財務系統。
  3. 移動應用

    • 手機APP(如Google Keep、掃描全能王)通過拍照提取文字,支持翻譯、復制粘貼。
  4. 車牌識別與安防

    • 監控攝像頭捕捉車牌信息,用于交通管理或停車場系統。
  5. 殘障人士輔助

    • 幫助視障用戶通過圖像識別文字,再轉為語音朗讀。

技術挑戰與局限性

  • 復雜背景干擾:如花紋背景、低對比度文字可能導致識別失敗。
  • 特殊字體或手寫體:藝術字體、潦草手寫體可能降低準確率。
  • 多語言混合:不同語言字符的混合場景需要更復雜的模型支持。
  • 圖像質量依賴:模糊、傾斜、光照不均的圖像會影響識別效果。

主流OCR工具/服務

  1. 商業工具

    • Adobe Acrobat(PDF文字提取)、Google Drive(在線OCR)、ABBYY FineReader。
  2. 開源項目

    • Tesseract OCR(Google開源,支持多種語言)。
    • PaddleOCR(基于深度學習的高精度識別)。
  3. 云服務API

    • Google Cloud Vision API、Amazon Textract、百度AI開放平臺OCR。

未來趨勢

  • 深度學習優化:通過Transformer、CNN等模型提升復雜場景的識別準確率。
  • 端側部署:輕量化模型(如移動端OCR)實現實時處理。
  • 多模態融合:結合語音、圖像、上下文信息提升語義理解能力。
    來源于qwen3

百度飛槳OCR(python)

開源地址:

https://github.com/PaddlePaddle/PaddleOCR
文檔:
https://paddlepaddle.github.io/PaddleOCR/latest/index.html

文本檢測+方向分類+文本識別

以cpu為例:
conda create -n py310 python=3.10 -y
conda activate py310
python -m pip install paddlepaddle==3.0.0rc1 -i https://www.paddlepaddle.org.cn/packages/stable/cpu/
pip install paddleocrfrom paddleocr import PaddleOCR, draw_ocr# Paddleocr supports Chinese, English, French, German, Korean and Japanese
# You can set the parameter `lang` as `ch`, `en`, `french`, `german`, `korean`, `japan`
# to switch the language model in order
ocr = PaddleOCR(use_angle_cls=True, lang='en') # need to run only once to download and load model into memory
img_path = 'PaddleOCR/doc/imgs_en/img_12.jpg'
result = ocr.ocr(img_path, cls=True)
for idx in range(len(result)):res = result[idx]for line in res:print(line)# draw result
from PIL import Image
result = result[0]
image = Image.open(img_path).convert('RGB')
boxes = [line[0] for line in result]
txts = [line[1][0] for line in result]
scores = [line[1][1] for line in result]
im_show = draw_ocr(image, boxes, txts, scores, font_path='/path/to/PaddleOCR/doc/fonts/simfang.ttf')
im_show = Image.fromarray(im_show)
im_show.save('result.jpg')

低代碼平臺:
https://github.com/PaddlePaddle/PaddleX
文檔:
https://paddlepaddle.github.io/PaddleX/latest/module_usage/tutorials/ocr_modules/text_detection.html
開箱即用:

PaddleX:

conda create -n py310 python=3.10 -y
conda activate py310from paddlex import create_model
## 文本檢測 PP-OCRv4_server_det
## 文本識別 PP-OCRv4_server_rec_doc# 車牌檢測 :    PP-YOLOE-L_vehicle
# 車輛屬性檢測:  PP-LCNet_x1_0_vehicle_attribute
model = create_model(model_name="PP-LCNet_x1_0_vehicle_attribute")
output = model.predict(input="img/cc.jpg", batch_size=1)
# print("----",str(output))for res in output:res.print()res.save_to_img(save_path="./output/")res.save_to_json(save_path="./output/res.json")

cnocr 開源項目(python)

https://github.com/breezedeus/cnocr

開箱即用:

conda create -n py310 python=3.10 -y
conda activate py310
## cpu版本
pip install cnocr[ort-cpu] -i https://mirrors.aliyun.com/pypi/simple## gpu版本
pip install cnocr[ort-gpu] -i https://mirrors.aliyun.com/pypi/simple# 簡單使用
from cnocr import CnOcr
img_fp = './docs/examples/huochepiao.jpeg'
ocr = CnOcr()  # 所有參數都使用默認值
out = ocr.ocr(img_fp)
print(out)## 使用百度飛槳的版本
from cnocr import CnOcr
img_fp = './docs/examples/shupai.png'
ocr = CnOcr(rec_model_name='ch_PP-OCRv4')
out = ocr.ocr(img_fp)
print(out)

RapidOCR

用于PaddleOCR onnx的跨平臺 (python|java|C++|C#)
在這里插入圖片描述
開源地址:
https://github.com/RapidAI/RapidOCR
文檔:
https://rapidai.github.io/RapidOCRDocs/main/

jvm:jni 方式調用 onnx
https://github.com/RapidAI/RapidOcrOnnxJvm
https://github.com/RapidAI/RapidOcrOnnx

開箱即用

conda create -n py310 python=3.10 -y
conda activate py310pip install onnxruntime
pip install rapidocrfrom rapidocr import RapidOCR
engine = RapidOCR(params={"Global.with_torch": True})
img_url = "https://img1.baidu.com/it/u=3619974146,1266987475&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=516"
result = engine(img_url)
print(result)
result.vis("vis_result.jpg")

RapidOCRJava

在這里插入圖片描述

開源地址:
https://gitee.com/lc_monster/rapid-ocr-java

開箱即用:

<dependency><groupId>io.github.mymonstercat</groupId><artifactId>rapidocr-onnx-platform</artifactId><version>0.0.7</version>
</dependency><dependency><groupId>io.github.mymonstercat</groupId><artifactId>rapidocr-ncnn-platform</artifactId><version>0.0.7</version>
</dependency>public static void main(String[] args) {InferenceEngine engine = InferenceEngine.getInstance(Model.ONNX_PPOCR_V4);OcrResult ocrResult = engine.runOcr("/images/test.png");System.out.println(ocrResult.getStrRes().trim());}

場景

(標準的印刷體電子文檔識別和數據抽取)

一般地OCR識別底層處理

1, 文字區域識別 (det)
2,方向分類(cls)
3,文字光學識別 (rec)

PaddleOCR to onnx

## det
paddle2onnx  --model_dir C:/Users/linpx/.paddlex/official_models/PP-OCRv4_server_det  --model_filename inference.pdmodel   --params_filename inference.pdiparams  --save_file ./ppocrv4_det.onnx  --opset_version 11# rec
paddle2onnx  --model_dir C:/Users/linpx/.paddlex/official_models/PP-OCRv4_server_rec_doc  --model_filename inference.pdmodel   --params_filename inference.pdiparams  --save_file ./ppocrv4_rec_doc.onnx  --opset_version 11

項目使用

  • 底層使用 PP-OCRv4_server_det + PP-OCRv4_server_rec_doc
  • onnxruntime(2onnx): ppocrv4_det.onnx + ppocrv4_rec_doc.onnx
  • 使用rapidOCR的跨平臺的jni
  • rapidOCRJava pom依賴 快速的項目集成簡單ocr能力

代碼部分

主要有:pdf文件轉圖片》圖片OCR》結果重畫

package app;import com.alibaba.fastjson.JSON;
import com.benjaminwan.ocrlibrary.OcrResult;
import com.benjaminwan.ocrlibrary.Point;
import com.benjaminwan.ocrlibrary.TextBlock;
import com.visual.open.anpr.core.domain.DrawImage;
import io.github.mymonstercat.Model;
import io.github.mymonstercat.ocr.InferenceEngine;
import io.github.mymonstercat.ocr.config.ParamConfig;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import nu.pattern.OpenCV;
import org.apache.commons.collections4.list.TreeList;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;
import java.util.List;public class RapidOCRJavaDemo {static {OpenCV.loadShared();System.out.println("Loaded OpenCV version: " + Core.VERSION);}public static void main(String[] args) throws IOException {System.out.println("----------start-----------------");String parentPath = "D:\\work\\ocr-img\\pdf";pdfToPng(parentPath);File parent = new File(parentPath,"pdf2img");File[] files = parent.listFiles();for (File file : files){runOcr(file.getAbsolutePath());}System.out.println("----------end-----------------");}private static void runOcr(String filePath) {File file = new File(filePath);File parent = file.getParentFile();new File(parent.getAbsolutePath()+"/ocr").mkdirs();ParamConfig paramConfig = ParamConfig.getDefaultConfig();// 圖像外接白框,用于提升識別率,文字框沒有正確框住所有文字時,增加此值。默認50。paramConfig.setPadding(50);// 按圖像長邊進行總體縮放,放大增加識別耗時但精度更高,縮小減小耗時但精度降低,maxSideLen為0表示不縮放paramConfig.setMaxSideLen(0);// 文字框置信度門限,文字框沒有正確框住所有文字時,減小此值paramConfig.setBoxScoreThresh(0.5f);// 同上,自行試驗paramConfig.setBoxThresh(0.3f);// 單個文字框大小倍率,越大時單個文字框越大paramConfig.setUnClipRatio(1.6f);// 啟用(true)/禁用(false) 文字方向檢測,只有圖片倒置的情況下(旋轉90~270度的圖片),才需要啟用文字方向檢測,默認關閉paramConfig.setDoAngle(false);// 啟用(1)/禁用(0) 角度投票(整張圖片以最大可能文字方向來識別),當禁用文字方向檢測時,此項也不起作用,默認關閉paramConfig.setMostAngle(false);InferenceEngine engine = InferenceEngine.getInstance(Model.ONNX_PPOCR_V4);String outFileBox = parent.getAbsolutePath()+"/ocr/result_box_"+file.getName();String outFileFill = parent.getAbsolutePath()+"/ocr/result_fill_"+file.getName();OcrResult ocrResult = engine.runOcr(filePath, paramConfig);System.out.println(JSON.toJSONString(ocrResult));
//        System.out.println(ocrResult.getStrRes().trim());// 畫框版本DrawImage drawBox = DrawImage.build(filePath);drawTextToImg(ocrResult.getTextBlocks(), drawBox);saveFileToDir(drawBox, outFileBox);createGrayBackgroundImage(filePath, outFileFill);// 填充文本版本DrawImage drawFill = DrawImage.build(outFileFill);drawFilledTextToImg(ocrResult.getTextBlocks(), drawFill);saveFileToDir(drawFill, outFileFill);}private static void pdfToPng(String parentPath) throws IOException {File parent = new File(parentPath);File[] files = parent.listFiles();new File(parent.getAbsolutePath()+"/pdf2img").mkdirs();for (int i = 0; i < files.length; i++) {File file = files[i];PDDocument document = PDDocument.load(file);PDFRenderer renderer = new PDFRenderer(document);String newFileName = UUID.randomUUID().toString().replace("-","");for (int j = 0; j < document.getNumberOfPages(); j++) {BufferedImage image = renderer.renderImageWithDPI(j, 300); // 300 DPIImageIO.write(image, "PNG", new File(parent.getAbsolutePath()+"/pdf2img",newFileName+"_page_" + (j + 1) + ".png"));}document.close();}}/*** 根據源圖片生成一個灰色背景的新空白圖片** @param sourceImagePath 源圖片路徑* @param outputImagePath 輸出圖片路徑* @param grayValue       灰色值(0~255),推薦 128*/public static void createGrayBackgroundImage(String sourceImagePath, String outputImagePath) {int grayValue = 100;// 讀取源圖片Mat src = Imgcodecs.imread(sourceImagePath);if (src.empty()) {throw new RuntimeException("無法讀取源圖片: " + sourceImagePath);}// 獲取源圖尺寸int width = src.cols();int height = src.rows();// 創建一個與源圖尺寸相同的新 Mat 對象,3 通道,8 位無符號整型Mat grayImage = new Mat(height, width, CvType.CV_8UC3, new Scalar(grayValue, grayValue, grayValue));// 釋放源圖資源(如果不需要后續使用)src.release();// 保存新圖片boolean success = Imgcodecs.imwrite(outputImagePath, grayImage);if (!success) {throw new RuntimeException("無法保存新圖片到: " + outputImagePath);}System.out.println("灰色背景圖片已保存至: " + outputImagePath);// 釋放新圖片資源(如果不需要后續使用)grayImage.release();}private static void drawTextToImg(List<TextBlock> textBlocks, DrawImage drawImage) {for (TextBlock block : textBlocks) {List<Point> points = block.getBoxPoint();if (points == null || points.size() != 4) {continue; // 忽略無效數據}// 依次繪制四條線,形成閉合四邊形for (int i = 0; i < 4; i++) {Point p1 = points.get(i);Point p2 = points.get((i + 1) % 4);drawImage.drawLine(new DrawImage.Point(p1.getX(), p1.getY()),new DrawImage.Point(p2.getX(), p2.getY()),2, Color.RED);}// 可選:繪制文本內容和置信度String displayText = String.format("%s", block.getText());// 文本位置設置在框的上方Point topLeft = points.get(0);int textX = topLeft.getX();int textY = topLeft.getY() - 25;drawImage.drawText(displayText,new DrawImage.Point(textX, textY),13,Color.GREEN);}}private static void saveFileToDir( DrawImage drawImage, String outputFilePath) {Mat outputMat = drawImage.toMat();Imgcodecs.imwrite(outputFilePath, outputMat);ByteArrayOutputStream plateStream = convertMatToStream(outputMat);saveStreamToFile(plateStream, outputFilePath);System.out.println("Saved to: " + outputFilePath);outputMat.release();}public static ByteArrayOutputStream convertMatToStream(Mat image) {MatOfByte matOfByte = new MatOfByte();Imgcodecs.imencode(".jpg", image, matOfByte); // 將 Mat 編碼成 JPG 格式ByteArrayOutputStream outputStream = new ByteArrayOutputStream();try {outputStream.write(matOfByte.toArray()); // 寫入字節流} catch (IOException e) {throw new RuntimeException("Error converting Mat to stream", e);}image.release();return outputStream;}public static void saveStreamToFile(ByteArrayOutputStream stream, String filePath) {try (FileOutputStream fileOutputStream = new FileOutputStream(filePath)) {stream.writeTo(fileOutputStream); // 將流寫入文件} catch (IOException e) {throw new RuntimeException("Error writing stream to file", e);}}@Data@AllArgsConstructor@NoArgsConstructor@Builderstatic class  OcrTextDTO{private String text;private int x1;private int x2;private int y1;private int y2;}private static void drawFilledTextToImg(List<TextBlock> textBlocks, DrawImage drawImage) {//        System.out.println("textBlocks sort pre:"+JSON.toJSONString(textBlocks));Map<String,List<OcrTextDTO>> tableGroup = new LinkedHashMap<>();int currentY = 0;textBlocks.sort(Comparator.comparingInt(o ->o.getBoxPoint().stream().mapToInt(Point::getY).min().orElse(Integer.MAX_VALUE)));
//        System.out.println("textBlocks sort end:"+JSON.toJSONString(textBlocks));for (TextBlock block : textBlocks) {List<Point> points = block.getBoxPoint();if (points == null || points.size() != 4) {continue; // 忽略無效數據}int minY = Integer.MAX_VALUE;int maxY = Integer.MIN_VALUE;int minX = Integer.MAX_VALUE;int maxX = Integer.MIN_VALUE;System.out.println("points:"+JSON.toJSONString(points));// [{"x":1022,"y":971},{"x":1116,"y":971},{"x":1116,"y":1000},{"x":1022,"y":1000}]// 依次繪制四條線,形成閉合四邊形for (int i = 0; i < 4; i++) {Point p1 = points.get(i);Point p2 = points.get((i + 1) % 4);drawImage.drawLine(new DrawImage.Point(p1.getX(), p1.getY()),new DrawImage.Point(p2.getX(), p2.getY()),2, Color.RED);minY = Math.min(minY, p1.getY());maxY = Math.max(maxY, p1.getY());minX = Math.min(minX, p1.getX());maxX = Math.max(maxX, p1.getX());}int height = maxY - minY;// 可選:繪制文本內容和置信度String displayText = String.format("%s", block.getText());// 文本位置設置在框的上方Point topLeft = points.get(0);int textX = topLeft.getX();int textY = topLeft.getY();
//            System.out.println("maxY:"+maxY+",minY:"+minY+",height:"+height);
//            System.out.println("currentY:"+currentY+",minY-currentY:"+(minY-currentY)+",minY:"+minY);if(currentY == 0){currentY = minY;}else {if(minY-currentY  > 18){currentY = minY;}}
//            System.out.println("----currentY:"+currentY+",minY:"+minY+",height:"+height);List<OcrTextDTO> orDefault = tableGroup.getOrDefault(currentY+"", new TreeList<>());orDefault.add(OcrTextDTO.builder().text(displayText).x1(minX).y1(minY).x2(maxX).y2(maxY).build());orDefault.sort(Comparator.comparingInt(OcrTextDTO::getX1));tableGroup.put(currentY+"",orDefault);
//            System.out.println("textY:"+textY+",height:"+height+",text:"+displayText);int fontSize;if (height > 40) {fontSize = (int) (height * 0.6);} else if (height > 25) {fontSize = (int) (height * 0.7);} else if (height > 15) {fontSize = (int) (height * 0.8);}else {fontSize = height;}drawImage.drawText(displayText,new DrawImage.Point(textX, textY),fontSize,Color.GREEN);}System.out.println(JSON.toJSONString(tableGroup));}
}

擴展

在java平臺可以直接使用 onnxrunntime來進行解析,不使用 jni的方式

免責聲明:樣例僅供參考,如有錯誤還請糾正!謝謝

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/81778.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/81778.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/81778.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Pytorch實現常用代碼筆記

Pytorch實現常用代碼筆記 基礎實現代碼其他代碼示例Networks or ProjectsNetwork ModulesLossUtils 基礎實現代碼 參考 深度學習手寫代碼 其他代碼示例 Networks or Projects SENet學習筆記 SKNet——SENet孿生兄弟篇 GCNet&#xff1a;當Non-local遇見SENet YOLOv1到YOLO…

word通配符表

目錄 一、word查找欄代碼&通配符一覽表二、word替換欄代碼&通配符一覽表三、參考文獻 一、word查找欄代碼&通配符一覽表 序號清除使用通配符復選框勾選使用通配符復選框特殊字符代碼特殊字符代碼or通配符1任意單個字符^?一個任意字符?2任意數字^#任意數字&#…

TYUT-企業級開發教程-第6章

這一章 考點不多 什么是緩存&#xff1f;為什么要設計出緩存&#xff1f; 企業級應用為了避免讀取數據時受限于數據庫的訪問效率而導致整體系統性能偏低&#xff0c;通 常會在應用程序與數據庫之間建立一種臨時的數據存儲機制&#xff0c;該臨時存儲數據的區域稱 為緩存。緩存…

雙檢鎖(Double-Checked Locking)單例模式

在項目中使用雙檢鎖&#xff08;Double-Checked Locking&#xff09;單例模式來管理 JSON 格式化處理對象&#xff08;如 ObjectMapper 在 Jackson 庫中&#xff0c;或 JsonParser 在 Gson 庫中&#xff09;是一種常見的做法。這種模式確保了對象只被創建一次&#xff0c;同時在…

華為網路設備學習-22(路由器OSPF-LSA及特殊詳解)

一、基本概念 OSPF協議的基本概念 OSPF是一種內部網關協議&#xff08;IGP&#xff09;&#xff0c;主要用于在自治系統&#xff08;AS&#xff09;內部使路由器獲得遠端網絡的路由信息。OSPF是一種鏈路狀態路由協議&#xff0c;不直接傳遞路由表&#xff0c;而是通過交換鏈路…

數獨求解器3.0 增加latex格式讀取

首先說明兩種讀入格式 latex輸入格式說明 \documentclass{article} \begin{document}This is some text before oku.\begin{array}{|l|l|l|l|l|l|l|l|l|} \hline & & & & 5 & & 2 & 9 \\ \hline& & 5 & 1 & & 7…

20250520在全志H3平臺的Nano Pi NEO CORE開發板上運行Ubuntu Core16.04.3時跑通4G模塊EC20

1、h3-sd-friendlycore-xenial-4.14-armhf-20210618.img.gz 在WIN10下使用7-ZIP解壓縮/ubuntu20.04下使用tar 2、Win32DiskImager.exe 寫如32GB的TF卡。【以管理員身份運行】 3、TF卡如果已經做過會有3個磁盤分區&#xff0c;可以使用SD Card Formatter/SDCardFormatterv5_WinE…

精益數據分析(74/126):從愿景到落地的精益開發路徑——Rally的全流程管理實踐

精益數據分析&#xff08;74/126&#xff09;&#xff1a;從愿景到落地的精益開發路徑——Rally的全流程管理實踐 在創業的黏性階段&#xff0c;如何將抽象的愿景轉化為可落地的產品功能&#xff1f;如何在快速迭代中保持戰略聚焦&#xff1f;今天&#xff0c;我們通過Rally軟…

Javascript 編程基礎(4)函數 | 4.3、apply() 與 call() 方法

文章目錄 一、apply() 與 call() 方法1、核心概念1.1、call() 方法1.2、apply() 方法 2、使用示例2.1、基本用法2.2、處理 this 指向問題 3、call() 與 apply() 的區別 一、apply() 與 call() 方法 apply() 和 call() 都是 JavaScript 函數對象的方法&#xff0c;用于顯式設置函…

讀一本書第一遍是快讀還是細讀?

在時間充足且計劃對重要書籍進行多遍閱讀的前提下&#xff0c;第一遍閱讀的策略可以結合**「快讀搭建框架」與「標記重點」**&#xff0c;為后續細讀奠定基礎。以下是具體建議及操作邏輯&#xff1a; 一、第一遍&#xff1a;快讀為主&#xff0c;目標是「建立全局認知」 1. 快…

基于大模型的全面驚厥性癲癇持續狀態技術方案

目錄 一、數據收集與預處理系統1.1 多模態數據集成模塊1.2 數據預處理流程二、大模型構建與訓練系統2.1 模型架構設計2.2 訓練流程三、術前評估系統3.1 癲癇發作風險預測3.2 手術可行性評估流程四、術中決策支持系統4.1 實時監測數據處理4.2 麻醉方案優化流程五、術后護理系統5…

React 19 中的useRef得到了進一步加強。

文章目錄 前言一 useRef 的核心原理1.1 為什么需要 useRef&#xff1f;1.2 基本語法 二、React 19 中 useRef 的常見用法2.1 訪問 DOM 元素2.2 保存跨渲染的數據 三、React 19 中的改進ref 作為一個屬性案例演示(觸發子組件焦點事件) 注意 總結 前言 在 React 的世界里&#x…

idea查看class文件源碼

1、在idea中查看.class文件源碼 在idea的一個工程里面將.class文件復制進去&#xff0c;會提示如下&#xff1a; 這時候&#xff0c;打開一個其他類&#xff0c;右鍵-》"show in explorer"&#xff0c;打開資源文件夾&#xff0c;這時候將class文件粘貼在此處&#…

基于 Vue + CEF3 的瀏覽器批量管理系統(附功能詳解)

&#x1f310; 基于 Vue CEF3 的瀏覽器批量管理系統&#xff08;附功能詳解&#xff09; 在當前多任務操作需求日益增長的背景下&#xff0c;如何高效管理多個瀏覽器實例成為了一個值得探討的問題。今天給大家介紹一款基于 Vue 和 CEF3 構建的瀏覽器批量管理系統&#xff0c;…

JS實現古詩豎排從右至左

一個老題目&#xff0c;將下面古詩文由橫排&#xff0c;變成古文豎排模式&#xff1a; 靜夜思 李白 床前明月光&#xff0c; 疑似地上霜。 舉頭望明月&#xff0c; 低頭思故鄉。變成&#xff1a; 低|舉|疑|床|靜 頭|頭|似|前|夜 思|望|地|明|思 故|明|上|月| 鄉|月|霜|光|李…

在 Android 中實現支持多手勢交互的自定義 View(Kotlin 完整指南)

本文將手把手教你創建一個支持拖動、縮放、旋轉等多種手勢交互的自定義 View&#xff0c;并提供完整的代碼實現和優化建議。 一、基礎實現 1.1 創建自定義 View 骨架 import android.content.Context import android.graphics.* import android.util.AttributeSet import an…

Kotlin 協程 (一)

1. Kotlin 協程的核心概念 1.1 協程&#xff08;Coroutine&#xff09; 定義&#xff1a;協程是一種輕量級的執行上下文&#xff0c;可以在任何時候掛起和恢復&#xff0c;而不需要阻塞線程。特點&#xff1a; 比傳統線程更輕量&#xff0c;開銷更小。支持掛起和恢復&#xf…

機器學習 集成學習方法之隨機森林

集成學習方法之隨機森林 1 集成學習2 隨機森林的算法原理2.1 Sklearn API2.2 示例 1 集成學習 機器學習中有一種大類叫集成學習&#xff08;Ensemble Learning&#xff09;&#xff0c;集成學習的基本思想就是將多個分類器組合&#xff0c;從而實現一個預測效果更好的集成分類…

thinkphp6實現統一監聽并記錄所有執行的sql語句除查詢外

創建文件app/middleware/SqlLogger.php <?php namespace app\middleware;use think\facade\Db; use think\facade\Session;class SqlLogger {public function handle($request, \Closure $next){// 監聽所有SQL $request->ip()Db::listen(function($sql, $time) {if (p…

pytorch訓練可視化工具---TensorBoard

一、目的&#xff1a;為什么使用 TensorBoard 調控模型 使用 TensorBoard 可以幫我們&#xff1a; 實時查看 loss / acc 曲線 → 判斷是否過擬合、欠擬合&#xff1b; 對比不同模型或超參數的效果&#xff1b; 可視化模型結構 → 幫助調試模型設計&#xff1b; 查看權重/梯…