主頁 > 後端開發 > JavaCV的攝像頭實戰之十二:性別檢測

JavaCV的攝像頭實戰之十二:性別檢測

2023-07-01 07:45:34 後端開發

歡迎訪問我的GitHub

這里分類和匯總了欣宸的全部原創(含配套原始碼):https://github.com/zq2599/blog_demos

本篇概覽

  • 本文是《JavaCV的攝像頭實戰》系列的第十二篇,咱們來開發一個實用功能:識別性別并顯示在預覽頁面,如下圖:
    在這里插入圖片描述

  • 今天的代碼,主要功能如下圖所示:
    在這里插入圖片描述

  • 如果您看過《JavaCV的攝像頭實戰》系列的其他文章,就會發現上圖中只有藍色部分是新增內容,其余的步驟都是固定套路,《JavaCV的攝像頭實戰》系列的每一個應用玩的都是相同套路:別看步驟挺多,其實都是同一個流程

關于性別和年齡檢測

  • 使用卷積神經網路推理性別和年齡的更多技術細節,這里有更詳細的說明:
    https://talhassner.github.io/home/publication/2015_CVPR
  • 本篇會使用已訓練好的Caffe 模型,訓練該模型的資料來自Flickr相冊,通過從 iPhone5(或更高版本)智能手機設備自動上傳組裝而成,并由其作者根據知識共享 (CC) 許可向公眾發布,共有26580張照片,涉及2284人,這些人的年齡一共被標識成八組:(0-2、4-6、8-13、15-20、25-32、38-43、48-53、60 -)
  • 關于資料源的更多詳細,請參考:https://talhassner.github.io/home/projects/Adience/Adience-data.html
  • 論文地址:https://talhassner.github.io/home/projects/cnn_agegender/CVPR2015_CNN_AgeGenderEstimation.pdf

原始碼下載

  • 《JavaCV人臉識別三部曲》的完整原始碼可在GitHub下載到,地址和鏈接資訊如下表所示(https://github.com/zq2599/blog_demos):
名稱 鏈接 備注
專案主頁 https://github.com/zq2599/blog_demos 該專案在GitHub上的主頁
git倉庫地址(https) https://github.com/zq2599/blog_demos.git 該專案原始碼的倉庫地址,https協議
git倉庫地址(ssh) [email protected]:zq2599/blog_demos.git 該專案原始碼的倉庫地址,ssh協議
  • 這個git專案中有多個檔案夾,本篇的原始碼在javacv-tutorials檔案夾下,如下圖紅框所示:
    在這里插入圖片描述
  • javacv-tutorials里面有多個子工程,《JavaCV的攝像頭實戰》系列的代碼在simple-grab-push工程下:
    在這里插入圖片描述

準備:檔案下載

  • 本次實戰需要三個檔案:
  1. 人臉檢測的模型檔案:https://raw.github.com/opencv/opencv/master/data/haarcascades/haarcascade_frontalface_alt.xml
  2. 性別識別的組態檔:https://raw.githubusercontent.com/GilLevi/AgeGenderDeepLearning/master/gender_net_definitions/deploy.prototxt
  3. 性別識別的模型檔案:https://raw.githubusercontent.com/GilLevi/AgeGenderDeepLearning/master/models/gender_net.caffemodel
  • 我已將上述檔案打包上傳到CSDN,您也可以在CSDN下載(無需積分):
    https://download.csdn.net/download/boling_cavalry/70730586

準備:代碼介面簡介

  • 編碼前,先把涉及到的所有java檔案說明一下:
  1. AbstractCameraApplication.java:主程式的抽象類,這里面定義了打開攝像頭、抓取每一幀、處理每一幀的基本框架,避免每個應用都把這些事情重復做一遍
  2. PreviewCameraWithGenderAge.java:主程式,是AbstractCameraApplication的實作類,本次實戰的核心功能人臉檢測和性別檢測,都委托給它的成員變數detectService去完成
  3. DetectService.java:檢測服務的介面,里面定義了幾個重要的api,例如初始化、處理每一幀、釋放資源等
  4. GenderDetectService.java:是DetectService介面的實作類,本次實戰的核心功能都寫在這個類中
  • 介紹完畢,可以開始編碼了,先從最簡單的主程式開始

編碼:主程式

  • 《JavaCV的攝像頭實戰之一:基礎》創建的simple-grab-push工程中已經準備好了父類AbstractCameraApplication,所以本篇繼續使用該工程,創建子類實作那些抽象方法即可
  • 編碼前先回顧父類的基礎結構,如下圖,粗體是父類定義的各個方法,紅色塊都是需要子類來實作抽象方法,所以接下來,咱們以本地視窗預覽為目標實作這三個紅色方法即可:
    在這里插入圖片描述
  • 新建檔案PreviewCameraWithGenderAge.java,這是AbstractCameraApplication的子類,其代碼很簡單,接下來按上圖順序依次說明
  • 先定義CanvasFrame型別的成員變數previewCanvas,這是展示視頻幀的本地視窗:
protected CanvasFrame previewCanvas
  • 把前面創建的DetectService作為成員變數,后面檢測的時候會用到:
    /**
     * 檢測工具介面
     */
    private DetectService detectService;
  • PreviewCameraWithGenderAge的構造方法,接受DetectService的實體:
    /**
     * 不同的檢測工具,可以通過構造方法傳入
     * @param detectService
     */
    public PreviewCameraWithGenderAge(DetectService detectService) {
        this.detectService = detectService;
    }
  • 然后是初始化操作,可見是previewCanvas的實體化和引數設定,還有檢測、識別的初始化操作:
    @Override
    protected void initOutput() throws Exception {
        previewCanvas = new CanvasFrame("攝像頭預覽", CanvasFrame.getDefaultGamma() / grabber.getGamma());
        previewCanvas.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        previewCanvas.setAlwaysOnTop(true);

        // 檢測服務的初始化操作
        detectService.init();
    }
  • 接下來是output方法,定義了拿到每一幀視頻資料后做什么事情,這里呼叫了detectService.convert檢測人臉并識別性別,然后在本地視窗顯示:
    @Override
    protected void output(Frame frame) {
        // 原始幀先交給檢測服務處理,這個處理包括物體檢測,再將檢測結果標注在原始圖片上,
        // 然后轉換為幀回傳
        Frame detectedFrame = detectService.convert(frame);
        // 預覽視窗上顯示的幀是標注了檢測結果的幀
        previewCanvas.showImage(detectedFrame);
    }
  • 最后是處理視頻的回圈結束后,程式退出前要做的事情,先關閉本地視窗,再釋放檢測服務的資源:
    @Override
    protected void releaseOutputResource() {
        if (null!= previewCanvas) {
            previewCanvas.dispose();
        }

        // 檢測工具也要釋放資源
        detectService.releaseOutputResource();
    }
  • 由于檢測有些耗時,所以兩幀之間的間隔時間要低于普通預覽:
    @Override
    protected int getInterval() {
        return super.getInterval()/8;
    }
  • 至此,功能已開發完成,再寫上main方法,代碼如下,請注意AgeDetectService構造方法的三個入參,分別是前面下載的三個檔案在本機的位置:
    public static void main(String[] args) {
        String base = "E:\\temp\\202112\\25\\opencv\\";
  
        DetectService detectService = new GenderDetectService(
                base + "haarcascade_frontalface_alt.xml",
                base + "gender\\deploy.prototxt",
                base + "gender\\gender_net.caffemodel");
                
        new PreviewCameraWithGenderAge(detectService).action(1000);
    }
  • 主程式已經寫完,接下來是核心功能

編碼:服務介面回顧

  • 本篇的核心功能是檢測性別,相關代碼被封裝在DetectService介面的實作類GenderDetectService中,這個DetectService介面是咱們的老朋友了,之前識別相關的實戰都有它的身影,再來回顧一下,如下,定義了初始化、處理原始幀、釋放資源等關鍵行為的介面:
package com.bolingcavalry.grabpush.extend;

public interface DetectService {
    /**
     * 根據傳入的MAT構造相同尺寸的MAT,存放灰度圖片用于以后的檢測
     * @param src 原始圖片的MAT物件
     * @return 相同尺寸的灰度圖片的MAT物件
     */
    static Mat buildGrayImage(Mat src) {
        return new Mat(src.rows(), src.cols(), CV_8UC1);
    }
    
    /**
     * 初始化操作,例如模型下載
     * @throws Exception
     */
    void init() throws Exception;

    /**
     * 得到原始幀,做識別,添加框選
     * @param frame
     * @return
     */
    Frame convert(Frame frame);

    /**
     * 釋放資源
     */
    void releaseOutputResource();
}
  • 接下來,就是DetectService介面的實作類,也就是今天實戰的核心:GenderDetectService.java

編碼:檢測服務實作

  • 今天的核心功能都集中在GenderDetectService.java中,直接貼出全部原始碼吧,有幾處要注意的地方稍后會提到:
package com.bolingcavalry.grabpush.extend;

import com.bolingcavalry.grabpush.Constants;
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.javacpp.indexer.Indexer;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.OpenCVFrameConverter;
import org.bytedeco.opencv.opencv_core.*;
import org.bytedeco.opencv.opencv_dnn.Net;
import org.bytedeco.opencv.opencv_objdetect.CascadeClassifier;

import static org.bytedeco.opencv.global.opencv_core.NORM_MINMAX;
import static org.bytedeco.opencv.global.opencv_core.normalize;
import static org.bytedeco.opencv.global.opencv_dnn.blobFromImage;
import static org.bytedeco.opencv.global.opencv_dnn.readNetFromCaffe;
import static org.bytedeco.opencv.global.opencv_imgproc.*;

/**
 * @author willzhao
 * @version 1.0
 * @description 音頻相關的服務
 * @date 2021/12/3 8:09
 */
@Slf4j
public class GenderDetectService implements DetectService {

    /**
     * 每一幀原始圖片的物件
     */
    private Mat grabbedImage = null;

    /**
     * 原始圖片對應的灰度圖片物件
     */
    private Mat grayImage = null;

    /**
     * 分類器
     */
    private CascadeClassifier classifier;

    /**
     * 轉換器
     */
    private OpenCVFrameConverter.ToMat converter = new OpenCVFrameConverter.ToMat();

    /**
     * 人臉檢測模型檔案的下載地址
     */
    private String classifierModelFilePath;

    /**
     * 性別識別proto檔案的下載地址
     */
    private String genderProtoFilePath;

    /**
     * 性別識別模型檔案的下載地址
     */
    private String genderModelFilePath;

    /**
     * 推理性別的神經網路物件
     */
    private Net cnnNet;

    /**
     * 構造方法,在此指定proto和模型檔案的下載地址
     * @param classifierModelFilePath
     * @param cnnProtoFilePath
     * @param cnnModelFilePath
     */
    public GenderDetectService(String classifierModelFilePath,
                               String cnnProtoFilePath,
                               String cnnModelFilePath) {
        this.classifierModelFilePath = classifierModelFilePath;
        this.genderProtoFilePath = cnnProtoFilePath;
        this.genderModelFilePath = cnnModelFilePath;
    }

    /**
     * 初始化操作,主要是創建推理用的神經網路
     * @throws Exception
     */
    @Override
    public void init() throws Exception {
        // 根據模型檔案實體化分類器
        classifier = new CascadeClassifier(classifierModelFilePath);
        // 實體化推理性別的神經網路
        cnnNet = readNetFromCaffe(genderProtoFilePath, genderModelFilePath);
    }

    @Override
    public Frame convert(Frame frame) {
        // 由幀轉為Mat
        grabbedImage = converter.convert(frame);

        // 灰度Mat,用于檢測
        if (null==grayImage) {
            grayImage = DetectService.buildGrayImage(grabbedImage);
        }

        // 當前圖片轉為灰度圖片
        cvtColor(grabbedImage, grayImage, CV_BGR2GRAY);

        // 存放檢測結果的容器
        RectVector objects = new RectVector();

        // 開始檢測
        classifier.detectMultiScale(grayImage, objects);

        // 檢測結果總數
        long total = objects.size();

        // 如果沒有檢測到結果,就用原始幀回傳
        if (total<1) {
            return frame;
        }

        int pos_x;
        int pos_y;

        Mat faceMat;

        //推理時的入參
        Mat inputBlob;

        // 推理結果
        Mat prob;

        // 如果有檢測結果,就根據結果的資料構造矩形框,畫在原圖上
        for (long i = 0; i < total; i++) {
            Rect r = objects.get(i);

            // 人臉對應的Mat實體(注意:要用彩圖,不能用灰度圖!!!)
            faceMat = new Mat(grabbedImage, r);
            // 縮放到神經網路所需的尺寸
            resize(faceMat, faceMat, new Size(Constants.CNN_PREIDICT_IMG_WIDTH, Constants.CNN_PREIDICT_IMG_HEIGHT));
            // 歸一化
            normalize(faceMat, faceMat, 0, Math.pow(2, frame.imageDepth), NORM_MINMAX, -1, null);
            // 轉為推理時所需的的blob型別
            inputBlob = blobFromImage(faceMat);
            // 為神經網路設定入參
            cnnNet.setInput(inputBlob, "data", 1.0, null);      //set the network input
            // 推理
            prob = cnnNet.forward("prob");

            // 根據推理結果得到在人臉上標注的內容
            String lable = getDescriptionFromPredictResult(prob);

            // 人臉標注的橫坐標
            pos_x = Math.max(r.tl().x()-10, 0);
            // 人臉標注的縱坐標
            pos_y = Math.max(r.tl().y()-10, 0);

            // 給人臉做標注,標注性別
            putText(grabbedImage, lable, new Point(pos_x, pos_y), FONT_HERSHEY_PLAIN, 1.5, new Scalar(0,255,0,2.0));

            // 給人臉加邊框時的邊框位置
            int x = r.x(), y = r.y(), w = r.width(), h = r.height();
            // 給人臉加邊框
            rectangle(grabbedImage, new Point(x, y), new Point(x + w, y + h), Scalar.RED, 1, CV_AA, 0);
        }

        // 釋放檢測結果資源
        objects.close();

        // 將標注過的圖片轉為幀,回傳
        return converter.convert(grabbedImage);
    }

    /**
     * 程式結束前,釋放人臉識別的資源
     */
    @Override
    public void releaseOutputResource() {
        if (null!=grabbedImage) {
            grabbedImage.release();
        }

        if (null!=grayImage) {
            grayImage.release();
        }

        if (null!=classifier) {
            classifier.close();
        }

        if (null!= cnnNet) {
            cnnNet.close();
        }
    }

    /**
     * 根據推理結果得到在頭像上要標注的內容
     * @param prob
     * @return
     */
    protected String getDescriptionFromPredictResult(Mat prob) {
        Indexer indexer = prob.createIndexer();

        // 比較兩種性別的概率,概率大的作為當前頭像的性別
        return indexer.getDouble(0,0) > indexer.getDouble(0,1)
               ? "male"
               : "female";
    }
}
  • 上述代碼,有以下幾處需要注意的:
  1. 構造方法的三個入參:classifierModelFilePath、cnnProtoFilePath、cnnModelFilePath分別是人臉檢測模型、性別檢測配置、性別檢測模型三個檔案的本地存放地址
  2. 檢測性別靠的是卷積神經網路的推理,初始化的時候通過readNetFromCaffe方法新建神經網路物件
  3. convert方法被呼叫時,會收到攝像頭捕捉的每一幀,在這里面先檢測出每個人臉,再拿每個人臉去神經網路進行推理
  4. 用神經網路的推理結果生成人臉的標注內容,這段邏輯被放入getDescriptionFromPredictResult,下一篇《年齡檢測》的實戰同樣是使用神經網路推理頭像的年齡,咱們只要寫一個GenderDetectService,并重寫getDescriptionFromPredictResult方法,里面的邏輯改成根據推理結果得到年齡,即可輕松完成任務,其他類都可以維持不變
  • 至此,編碼完成,接下來開始驗證

驗證

  • 確保攝像頭作業正常,運行PreviewCameraWithGenderAge類的main方法
  • 請群眾演員登場,讓他站在攝像頭前,如下圖,性別識別成功,且實時展示:
    在這里插入圖片描述
  • 至此,本地視窗預覽集成人臉檢測和性別檢測的功能就完成了,得益于JavaCV的強大,整個程序是如此的輕松愉快,接下來請繼續關注欣宸原創,《JavaCV的攝像頭實戰》系列還會呈現更多豐富的應用;
  • 得益于本篇所做的擴展準備,下一篇《年齡檢測》會更加簡單,一起來期待下一段輕松愉快的旅程吧;

歡迎關注博客園:程式員欣宸

學習路上,你不孤單,欣宸原創一路相伴...

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/556405.html

標籤:其他

上一篇:[滲透測驗]—7.2 社會工程學攻擊技術

下一篇:返回列表

標籤雲
其他(161925) Python(38266) JavaScript(25517) Java(18286) C(15238) 區塊鏈(8274) C#(7972) AI(7469) 爪哇(7425) MySQL(7278) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5876) 数组(5741) R(5409) Linux(5347) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4609) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2438) ASP.NET(2404) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) .NET技术(1985) HtmlCss(1979) 功能(1967) Web開發(1951) C++(1942) python-3.x(1918) 弹簧靴(1913) xml(1889) PostgreSQL(1881) .NETCore(1863) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • JavaCV的攝像頭實戰之十二:性別檢測

    ### 歡迎訪問我的GitHub > 這里分類和匯總了欣宸的全部原創(含配套原始碼):[https://github.com/zq2599/blog_demos](https://github.com/zq2599/blog_demos) ### 本篇概覽 - 本文是《JavaCV的攝像頭實戰》系列的 ......

    uj5u.com 2023-07-01 07:45:34 more
  • [滲透測驗]—7.2 社會工程學攻擊技術

    在本章節中,我們將學習社會工程學攻擊技術,包括釣魚、身份欺詐等。我們會盡量詳細、通俗易懂地講解,并提供盡可能多的實體。 ### 1.1 社會工程學概述 社會工程學是一種利用人際交往中的心理因素來獲取資訊、權限或其他目標的手段。與技術性攻擊手段相比,社會工程學更側重于利用人的弱點,如信任、懶惰、貪婪等 ......

    uj5u.com 2023-07-01 07:44:29 more
  • C++面試八股文:什么是空指標/野指標/懸垂指標?

    某日二師兄參加XXX科技公司的C++工程師開發崗位第30面: > 面試官:什么是空指標? > > 二師兄:一般我們將等于`0`/`NULL`/`nullptr`的指標稱為空指標。空指標不能被解參考,但是可以對空指標取地址。 ```c++ int* p = nullptr; //空指標 *p = 42 ......

    uj5u.com 2023-07-01 07:44:24 more
  • String決議及其方法

    #String決議及其方法 1.[前言](#jump1) 2.[什么是字串(String)](#jump2) 3.[字串(String)的兩種創建方式及其區別](#jump3) 4.[字串(String)的方法及其部分原碼決議](#jump4) 5.[字串(String)的弊端](#jump ......

    uj5u.com 2023-07-01 07:44:18 more
  • 開源通用高性能的分布式id序列組件

    業務資料的存盤,少不了資料記錄的id序列,id序列(或稱序列)的生成方式有很多種,比如當前時間戳、資料庫的序列值(Oracle的序列,MySQL的自增ID等)、UUID等方式,但這些生成方式均存在一定的局限性,本文介紹一種通用高性能的分布式id序列的設計思路…… ......

    uj5u.com 2023-07-01 07:44:09 more
  • Java-語法基礎

    > JDK8 > > 復習用 ## Java前置知識 1. JavaSE Java Standard Edition 標準版 支持面向桌面級應用(如Windows下的應用程式)的 Java平臺,提供了完整的Java核心API 此版本以前稱為 J2SE 2. JavaEE Java Enterpris ......

    uj5u.com 2023-07-01 07:43:49 more
  • Java基礎語法

    1、Java的八種基本資料型別 1、byte 1位元組 取值范圍:-128~127 2、short 2位元組 取值范圍:-32768~32767 3、int 4位元組 取值范圍:-231~231-1 # int是開發中最常用的,也是Java中默認的資料型別 4、long 8位元組 取值范圍:-263~263 ......

    uj5u.com 2023-07-01 07:43:33 more
  • 微信小程式訂閱模板訊息推送

    **背景** 在實際的小程式開發程序中往往需要用到給用戶發送訂閱訊息,比如:我們在店里掃碼點餐時在付款時往往彈出一個授權視窗(比如‘取餐通知’)這個時候我們就需要對接微信小程式的模板訊息。 [https://developers.weixin.qq.com/miniprogram/dev/OpenA ......

    uj5u.com 2023-07-01 07:43:29 more
  • 記一次Native memory leak排查程序

    路由計算服務是路由系統的核心服務,負責運單路由計劃的計算以及實操與計劃的匹配。在運維程序中,發現在長期不重啟的情況下,有TP99緩慢爬坡的現象。此外,在每周例行調度的試算程序中,能明顯看到記憶體的上漲。 ......

    uj5u.com 2023-07-01 07:43:24 more
  • 狂收 3.2k star!百度開源壓測工具,可模擬幾十億的并發場景,太強悍了

    dperf 是一款基于 DPDK 的 100Gbps 網路性能和負載測驗軟體,能夠每秒建立千萬級的 HTTP 連接、億級別的并發請求和數百 Gbps 的吞吐量。 ## 優點 ### 性能強大: - 基于 DPDK,使用一臺普通 x86 服務器就可以產生巨大的流量:千萬級的 HTTP 每秒新建連接數, ......

    uj5u.com 2023-07-01 07:43:20 more