【OpenVINO™】在 MacOS 上使用 OpenVINO™ C# API 部署 Yolov5

来源:https://www.cnblogs.com/guojin-blogs/p/18009621
-Advertisement-
Play Games

YOLOv5 是革命性的 "單階段"對象檢測模型的第五次迭代,旨在實時提供高速、高精度的結果,是世界上最受歡迎的視覺人工智慧模型,代表了Ultralytics對未來視覺人工智慧方法的開源研究,融合了數千小時研發中積累的經驗教訓和最佳實踐。同時官方發佈的模型已經支持 OpenVINO™ 部署工具加速模... ...


在 MacOS 上使用 OpenVINO™ C# API 部署 Yolov5
項目介紹

YOLOv5 是革命性的 "單階段"對象檢測模型的第五次迭代,旨在實時提供高速、高精度的結果,是世界上最受歡迎的視覺人工智慧模型,代表了Ultralytics對未來視覺人工智慧方法的開源研究,融合了數千小時研發中積累的經驗教訓和最佳實踐。同時官方發佈的模型已經支持 OpenVINO™ 部署工具加速模型推理,因此在該項目中,我們將結合之前開發的 OpenVINO™ C# API 部署 YOLOv5 DET 模型實現物體對象檢測。

項目鏈接為:

https://github.com/guojin-yan/OpenVINO-CSharp-API

項目源碼鏈接為:

https://github.com/guojin-yan/OpenVINO-CSharp-API-Samples/tree/master/model_samples/yolov5/yolov5_det_opencvsharp
https://github.com/guojin-yan/OpenVINO-CSharp-API-Samples/tree/master/model_samples/yolov5/yolov5_det_emgucv

目錄

1. 前言

1.1 OpenVINO™ C# API

英特爾發行版 OpenVINO™ 工具套件基於 oneAPI 而開發,可以加快高性能電腦視覺和深度學習視覺應用開發速度工具套件,適用於從邊緣到雲的各種英特爾平臺上,幫助用戶更快地將更準確的真實世界結果部署到生產系統中。通過簡化的開發工作流程,OpenVINO™ 可賦能開發者在現實世界中部署高性能應用程式和演算法。

OpenVINO™ 2023.2 於 2023 年 11 月 16 日發佈,該工具包帶來了挖掘生成人工智慧全部潛力的新功能。更多的生成式 AI 覆蓋和框架集成,以最大限度地減少代碼更改,並且擴展了對直接 PyTorch 模型轉換的模型支持。支持更多新的模型,包括 LLaVA、chatGLM、Bark 和 LCM 等著名模型。支持更廣泛的大型語言模型(LLM)和更多模型壓縮技術,支持運行時推理支持以下 Int4 模型壓縮格式,通過神經網路壓縮框架(NNCF) 進行本機 Int4 壓縮等一系列新的功能。

OpenVINO™ C# API 是一個 OpenVINO™ 的 .Net wrapper,應用最新的 OpenVINO™ 庫開發,通過 OpenVINO™ C API 實現 .Net 對 OpenVINO™ Runtime 調用,使用習慣與 OpenVINO™ C++ API 一致。OpenVINO™ C# API 由於是基於 OpenVINO™ 開發,所支持的平臺與 OpenVINO™ 完全一致,具體信息可以參考 OpenVINO™。通過使用 OpenVINO™ C# API,可以在 .NET、.NET Framework等框架下使用 C# 語言實現深度學習模型在指定平臺推理加速。

1.2 YOLOv5

​ YOLOv5 是革命性的 "單階段"對象檢測模型的第五次迭代,旨在實時提供高速、高精度的結果,是世界上最受歡迎的視覺人工智慧模型,代表了Ultralytics對未來視覺人工智慧方法的開源研究,融合了數千小時研發中積累的經驗教訓和最佳實踐。

2. 模型下載與轉換

2.1 環境安裝

首先創建Yolov5模型下載與轉換環境,此處為了更好的管理環境,使用Anaconda創建一個虛擬環境用於安裝Yolov5模型下載與轉換環境,首先使用conda創建一個虛擬環境,在命令行中依次輸入以下指令:

conda create -n yolo python=3.10
conda activate yolo

接下來安裝Yolov5模型下載與轉換環境,基礎的Yolov5模型下載需要通過克隆官方源碼實現,在命令行中依次輸入以下指令實現環境的安裝與配置即可:

git clone https://github.com/ultralytics/yolov5
cd yolov5
pip install -r requirements.txt
pip install --upgrade openvino-nightly

2.2 Yolov5 模型下載

Yolov5 官方提供了模型導出與轉換的方式,用戶只需要調用該介面便可以,在命令行中輸入以下指令便可以直接導出Yolov5模型:

cd yolov5
python export.py --weights yolov5s.pt --include onnx

結果輸出如下圖所示:

使用Netron工具打開模型文件,查看模型結構,如下圖所示:

官方預訓練模型是在COCO數據集上訓練的,因此導出的模型可以識別80種物體。模型輸入節點為images,輸入為歸一化後的圖像數據,其輸入大小為640×640;模型的輸出節點為output0,輸出大小為25200×85,其中25200(640÷8=80,640÷16=40,640÷32=20,3×80×80+3×40×40+3×20×20=25200)表示識別結果個數,85表示[cx, cy, w, h, confidence, score0, ···,score79],分別為識別框信息、識別結果中最大置信度以及80中類別結果的分數。

2.3 轉換IR模型

接下來直接使用 OpenVINO™ 工具直接進行模型轉換,在CMD中輸入以下指令即可:

ovc yolov5s.onnx

3. Yolov5 DET 項目配置(OpenCvSharp版)

3.1 項目創建

如果開發者第一次在MacOS系統上使用C#編程語言,可以參考《在MacOS系統上配置OpenVINO™ C# API》文章進行配置。

首先使用dotnet創建一個測試項目,在終端中輸入一下指令:

dotnet new console --framework net6.0 --use-program-main -o yolov5-det 

3.2 添加項目依賴

MacOS系統目前主要分為兩類,一類是使用intel處理器的X64位的系統,一類是使用M系列晶元的arm64位系統,目前OpenVINO官方針對這兩種系統都提供了編譯後的系統,所以目前OpenVINO.CSharp.API針對這兩種系統都提供了支持。

此處以M系列處理器的MacOS平臺為例安裝項目依賴,首先是安裝OpenVINO™ C# API項目依賴,在命令行中輸入以下指令即可:

dotnet add package OpenVINO.CSharp.API
dotnet add package OpenVINO.runtime.macos-arm64
dotnet add package OpenVINO.CSharp.API.Extensions
dotnet add package OpenVINO.CSharp.API.Extensions.OpenCvSharp

關於在MacOS上搭建 OpenVINO™ C# API 開發環境請參考以下文章: 在MacOS上搭建OpenVINO™C#開發環境

接下來安裝使用到的圖像處理庫 OpenCvSharp,在命令行中輸入以下指令即可:

dotnet add package OpenCvSharp4
dotnet add package OpenCvSharp4.Extensions
dotnet add package OpenCvSharp4.runtime.osx_arm64 --prerelease

關於在MacOS上搭建 OpenCvSharp 開發環境請參考以下文章: 【OpenCV】在MacOS上使用OpenCvSharp

添加完成項目依賴後,項目的配置文件如下所示:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <RootNamespace>yolov5_det</RootNamespace>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="OpenCvSharp4" Version="4.9.0.20240103" />
    <PackageReference Include="OpenCvSharp4.Extensions" Version="4.9.0.20240103" />
    <PackageReference Include="OpenCvSharp4.runtime.osx_arm64" Version="4.8.1-rc" />
    <PackageReference Include="OpenVINO.CSharp.API" Version="2023.2.0.4" />
    <PackageReference Include="OpenVINO.CSharp.API.Extensions" Version="1.0.1" />
    <PackageReference Include="OpenVINO.CSharp.API.Extensions.OpenCvSharp" Version="1.0.4" />
    <PackageReference Include="OpenVINO.runtime.macos-arm64" Version="2023.3.0.1" />
  </ItemGroup>

</Project>

3.3 定義預測方法

(1) 使用常規方式部署模型

Yolov5 屬於比較經典單階段目標檢測模型,其模型輸入為640*640的歸一化處理後的圖像數據,輸出為未進行NMS的推理結果,因此在獲取推理結果後,需要進行NMS,其實現代碼如下所示:

static void yolov5_det(string model_path, string image_path, string device)
{
    // -------- Step 1. Initialize OpenVINO Runtime Core --------
    Core core = new Core();
    // -------- Step 2. Read inference model --------
    Model model = core.read_model(model_path);
    OvExtensions.printf_model_info(model);
    // -------- Step 3. Loading a model to the device --------
    start = DateTime.Now;
    CompiledModel compiled_model = core.compile_model(model, device);
    // -------- Step 4. Create an infer request --------
    InferRequest infer_request = compiled_model.create_infer_request();
    // -------- Step 5. Process input images --------
    Mat image = new Mat(image_path); // Read image by opencvsharp
    int max_image_length = image.Cols > image.Rows ? image.Cols : image.Rows;
    Mat max_image = Mat.Zeros(new OpenCvSharp.Size(max_image_length, max_image_length), MatType.CV_8UC3);
    Rect roi = new Rect(0, 0, image.Cols, image.Rows);
    image.CopyTo(new Mat(max_image, roi));
    float factor = (float)(max_image_length / 640.0);
    // -------- Step 6. Set up input data --------
    Tensor input_tensor = infer_request.get_input_tensor();
    Shape input_shape = input_tensor.get_shape();
    Mat input_mat = CvDnn.BlobFromImage(max_image, 1.0 / 255.0, new OpenCvSharp.Size(input_shape[2], input_shape[3]), 0, true, false);
    float[] input_data = new float[input_shape[1] * input_shape[2] * input_shape[3]];
    Marshal.Copy(input_mat.Ptr(0), input_data, 0, input_data.Length);
    input_tensor.set_data<float>(input_data);
    // -------- Step 7. Do inference synchronously --------
    infer_request.infer();
    // -------- Step 8. Get infer result data --------
    Tensor output_tensor = infer_request.get_output_tensor();
    int output_length = (int)output_tensor.get_size();
    float[] output_data = output_tensor.get_data<float>(output_length);

    // -------- Step 9. Process reault  --------
    Mat result_data = new Mat(25200, 85, MatType.CV_32F, output_data);
    // Storage results list
    List<Rect> position_boxes = new List<Rect>();
    List<int> class_ids = new List<int>();
    List<float> confidences = new List<float>();
    // Preprocessing output results
    for (int i = 0; i < result_data.Rows; i++)
    {
        float confidence = result_data.At<float>(i, 4);
        if (confidence < 0.5)
        {
            continue;
        }
        Mat classes_scores = new Mat(result_data, new Rect(5, i, 80, 1));
        OpenCvSharp.Point max_classId_point, min_classId_point;
        double max_score, min_score;
        // Obtain the maximum value and its position in a set of data
        Cv2.MinMaxLoc(classes_scores, out min_score, out max_score,
            out min_classId_point, out max_classId_point);
        // Confidence level between 0 ~ 1
        // Obtain identification box information
        if (max_score > 0.25)
        {
            float cx = result_data.At<float>(i, 0);
            float cy = result_data.At<float>(i, 1);
            float ow = result_data.At<float>(i, 2);
            float oh = result_data.At<float>(i, 3);
            int x = (int)((cx - 0.5 * ow) * factor);
            int y = (int)((cy - 0.5 * oh) * factor);
            int width = (int)(ow * factor);
            int height = (int)(oh * factor);
            Rect box = new Rect();
            box.X = x;
            box.Y = y;
            box.Width = width;
            box.Height = height;

            position_boxes.Add(box);
            class_ids.Add(max_classId_point.X);
            confidences.Add((float)confidence);
        }
    }
    // NMS non maximum suppression
    int[] indexes = new int[position_boxes.Count];
    CvDnn.NMSBoxes(position_boxes, confidences, 0.5f, 0.5f, out indexes);
    for (int i = 0; i < indexes.Length; i++)
    {
        int index = indexes[i];
        Cv2.Rectangle(image, position_boxes[index], new Scalar(0, 0, 255), 2, LineTypes.Link8);
        Cv2.Rectangle(image, new OpenCvSharp.Point(position_boxes[index].TopLeft.X, position_boxes[index].TopLeft.Y + 30),
            new OpenCvSharp.Point(position_boxes[index].BottomRight.X, position_boxes[index].TopLeft.Y), new Scalar(0, 255, 255), -1);
        Cv2.PutText(image, class_ids[index] + "-" + confidences[index].ToString("0.00"),
            new OpenCvSharp.Point(position_boxes[index].X, position_boxes[index].Y + 25),
            HersheyFonts.HersheySimplex, 0.8, new Scalar(0, 0, 0), 2);
    }
    string output_path = Path.Combine(Path.GetDirectoryName(Path.GetFullPath(image_path)),
        Path.GetFileNameWithoutExtension(image_path) + "_result.jpg");
    Cv2.ImWrite(output_path, image);
    Slog.INFO("The result save to " + output_path);
    Cv2.ImShow("Result", image);
    Cv2.WaitKey(0);
}

(2) 使用模型結構處理處理數據

目前 OpenVINO™ 已經支持在模型結構中增加數據的前後處理流程,並且在 OpenVINO™ C# API 中也已經實現了該功能介面,所以在此處演示瞭如何將模型輸入數據處理流程封裝到模型中,通過 OpenVINO™ 進行數據處理的加速處理,如下麵代碼所示:

static void yolov5_det_with_process(string model_path, string image_path, string device)
{
    ······
    // -------- Step 2. Read inference model --------
    start = DateTime.Now;
    Model model = core.read_model(model_path);
    OvExtensions.printf_model_info(model);
    PrePostProcessor processor = new PrePostProcessor(model);
    Tensor input_tensor_pro = new Tensor(new OvType(ElementType.U8), new Shape(1, 640, 640, 3));
    InputInfo input_info = processor.input(0);
    InputTensorInfo input_tensor_info = input_info.tensor();
    input_tensor_info.set_from(input_tensor_pro).set_layout(new Layout("NHWC")).set_color_format(ColorFormat.BGR);
    PreProcessSteps process_steps = input_info.preprocess();
    process_steps.convert_color(ColorFormat.RGB).resize(ResizeAlgorithm.RESIZE_LINEAR)
        .convert_element_type(new OvType(ElementType.F32)).scale(255.0f).convert_layout(new Layout("NCHW"));
    Model new_model = processor.build();
    // -------- Step 3. Loading a model to the device --------
    CompiledModel compiled_model = core.compile_model(new_model, device);
    // -------- Step 4. Create an infer request --------
    InferRequest infer_request = compiled_model.create_infer_request();
    // -------- Step 5. Process input images --------
    Mat image = new Mat(image_path); // Read image by opencvsharp
    int max_image_length = image.Cols > image.Rows ? image.Cols : image.Rows;
    Mat max_image = Mat.Zeros(new OpenCvSharp.Size(max_image_length, max_image_length), MatType.CV_8UC3);
    Rect roi = new Rect(0, 0, image.Cols, image.Rows);
    image.CopyTo(new Mat(max_image, roi));
    Cv2.Resize(max_image, max_image, new OpenCvSharp.Size(640, 640));
    float factor = (float)(max_image_length / 640.0);
    // -------- Step 6. Set up input data --------
    Tensor input_tensor = infer_request.get_input_tensor();
    Shape input_shape = input_tensor.get_shape();
    byte[] input_data = new byte[input_shape[1] * input_shape[2] * input_shape[3]];
    Marshal.Copy(max_image.Ptr(0), input_data, 0, input_data.Length);
    IntPtr destination = input_tensor.data();
    Marshal.Copy(input_data, 0, destination, input_data.Length);
    // -------- Step 7. Do inference synchronously --------
    ······
}

由於目前還沒有完全實現所有的 OpenVINO™ 的預處理介面,因此只能實現部分預處理過程封裝到模型中,此處主要是做了以下處理:

  • 數據類型轉換:byte->float
  • 數據維度轉換:NHWC->NCHW
  • 圖像色彩空間轉換:BGR->RGB
  • 數據歸一化處理:[0,1]->[0,255]

因此將一些數據處理流程封裝到模型中後,在進行模型推理時,只需要將讀取到的圖片數據Resize為640*640後,就可以直接將數據載入到模型即可。

(3) 使用 OpenVINO™ C# API 封裝的介面

YOLOv5 是當前工業領域十分流行的目標檢測模型,因此在封裝 OpenVINO™ C# API 時,提供了快速部署 Yolov5 模型的介面,實現代碼如下所示:

static void yolov5_det_using_extensions(string model_path, string image_path, string device)
{
    Yolov5DetConfig config = new Yolov5DetConfig();
    config.set_model(model_path);
    Yolov5Det yolov8 = new Yolov5Det(config);
    Mat image = Cv2.ImRead(image_path);
    DetResult result = yolov8.predict(image);
    Mat result_im = Visualize.draw_det_result(result, image);
    Cv2.ImShow("Result", result_im);
    Cv2.WaitKey(0);
}

3.4 預測方法調用

定義好上述方法後,便可以直接在主函數中調用該方法,只需要在主函數中增加以下代碼即可:

yolov5_det("yolov5s.xml", "test_image.png", "AUTO");
yolov5_det_with_process("yolov5s.xml", "test_image.png", "AUTO");
yolov5_det_using_extensions("yolov5s.xml", "test_image.png", "AUTO");

如果開發者自己沒有進行模型下載與轉換,又同時想快速體驗該項目,我此處提供了線上的轉換後的模型以及帶預測圖片,開發者可以直接在主函數中增加以下代碼,便可以直接自動下載模型以及推理數據,並調用推理方法,實現程式直接運行。

static void Main(string[] args)
{
    string model_path = "";
    string image_path = "";
    string device = "AUTO";
    if (args.Length == 0)
    {
        if (!Directory.Exists("./model"))
        {
            Directory.CreateDirectory("./model");
        }
        if (!File.Exists("./model/yolov5s.bin") && !File.Exists("./model/yolov5s.bin"))
        {
            if (!File.Exists("./model/yolov5s.tar"))
            {
                _ = Download.download_file_async("https://github.com/guojin-yan/OpenVINO-CSharp-API-Samples/releases/download/Model/yolov5s.tar",
                    "./model/yolov5s.tar").Result;
            }
            Download.unzip("./model/yolov585s.tar", "./model/");
        }

        if (!File.Exists("./model/test_image.jpg"))
        {
            _ = Download.download_file_async("https://github.com/guojin-yan/OpenVINO-CSharp-API-Samples/releases/download/Image/test_det_02.jpg",
                "./model/test_image.jpg").Result;
        }
        model_path = "./model/yolov5s.xml";
        image_path = "./model/test_image.jpg";
    }
    else if (args.Length >= 2)
    {
        model_path = args[0];
        image_path = args[1];
        device = args[2];
    }
    else
    {
        Console.WriteLine("Please enter the correct command parameters, for example:");
        Console.WriteLine("> 1. dotnet run");
        Console.WriteLine("> 2. dotnet run <model path> <image path> <device name>");
    }
    // -------- Get OpenVINO runtime version --------

    OpenVinoSharp.Version version = Ov.get_openvino_version();

    Slog.INFO("---- OpenVINO INFO----");
    Slog.INFO("Description : " + version.description);
    Slog.INFO("Build number: " + version.buildNumber);

    Slog.INFO("Predict model files: " + model_path);
    Slog.INFO("Predict image  files: " + image_path);
    Slog.INFO("Inference device: " + device);
    Slog.INFO("Start yolov8 model inference.");

    yolov5_det(model_path, image_path, device);
    //yolov5_det_with_process(model_path, image_path, device);
    //yolov5_det_using_extensions(model_path, image_path, device);
}

為了減少文章篇幅,所以此處只提供了有差異的代碼,如果想獲取完整代碼,請訪問GitHub代碼倉庫,獲取項目源碼,鏈接為:

https://github.com/guojin-yan/OpenVINO-CSharp-API-Samples/tree/master/model_samples/yolov5/yolov5_det_opencvsharp

4. Yolov5 DET 項目配置(Emgu.CV 版)

同樣地,為了滿足Emgu.CV開發者的需求,此處同樣地提供了Emgu.CV版本的Yolov5的模型部署代碼以及使用流程,此處為了簡化文章內容,對於和上文重覆的步驟不在進行展開講述。

4.1 添加項目依賴

首先是安裝OpenVINO™ C# API項目依賴,在命令行中輸入以下指令即可:

dotnet add package OpenVINO.CSharp.API
dotnet add package OpenVINO.runtime.macos-arm64
dotnet add package OpenVINO.CSharp.API.Extensions
dotnet add package OpenVINO.CSharp.API.Extensions.EmguCV

接下來安裝使用到的圖像處理庫 Emgu.CV,在命令行中輸入以下指令即可:

dotnet add package Emgu.CV
dotnet add package Emgu.CV.runtime.mini.macos

關於在MacOS上搭建 OpenCvSharp 開發環境請參考以下文章: 【OpenCV】在MacOS上使用Emgu.CV

添加完成項目依賴後,項目的配置文件如下所示:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net6.0</TargetFramework>
    <RootNamespace>yolov5_det</RootNamespace>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Emgu.CV" Version="4.8.1.5350" />
    <PackageReference Include="Emgu.CV.runtime.mini.macos" Version="4.8.1.5350" />
    <PackageReference Include="OpenVINO.CSharp.API" Version="2023.2.0.4" />
    <PackageReference Include="OpenVINO.CSharp.API.Extensions" Version="1.0.1" />
    <PackageReference Include="OpenVINO.CSharp.API.Extensions.EmguCV" Version="1.0.4.1" />
    <PackageReference Include="OpenVINO.runtime.macos-arm64" Version="2023.3.0.1" />
  </ItemGroup>

</Project>

4.2 定義預測方法

模型部署流程與上一節中使用OpenCvSharp的基本一致,主要是替換了圖像處理的工具,同時提供瞭如上一節中所展示的三種部署方式。此處為了減少文章篇幅,此處不在展示詳細的部署代碼,如果想獲取相關代碼,請訪問項目GitHub,下載所有的測試代碼,項目鏈接為:

https://github.com/guojin-yan/OpenVINO-CSharp-API-Samples/tree/master/model_samples/yolov5/yolov5_det_emgucv

5. 項目運行與演示

5.1 項目編譯

接下來輸入項目編譯指令進行項目編譯,輸入以下指令即可:

dotnet build

程式編譯後輸出為:

5.2 項目文件運行

接下來運行編譯後的程式文件,在CMD中輸入以下指令,運行編譯後的項目文件:

dotnet run --no-build

運行後項目輸出為:

6. 總結

在該項目中,我們結合之前開發的 OpenVINO C# API 項目部署YOLOv5模型,成功實現了對象目標檢測,並且根據不同開發者的使用習慣,同時提供了OpenCvSharp以及Emgu.CV兩種版本,供各位開發者使用。最後如果各位開發者在使用中有任何問題,歡迎大家與我聯繫。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 工商銀行和華為雲牽頭,並聯合7家金融機構共同編製的《金融行業開放平臺資料庫轉型白皮書》榮獲2023年度十佳課題。 ...
  • 優秀的程式應該儘可能地規避問題。因此,以後在服務商系統里,當定義包含漢字的欄位時,使用 nvarchar2,而非 varchar2。 因此,在服務商系統作為我司系統的小眾系統的背景下,Oracle的技術特性我們不一一曉知是可以理解和接受的。而如何在不一一曉知這些技術特性的情況下,能夠規避這些技術特性... ...
  • 環境 MySQL 5.7 非GTID模式多線程複製。 現象 某MySQL資料庫從節點因故障宕機(因故障直接宕機,非正常關閉),重啟之後發現複製狀態異常,show slave的結果中Slave_SQL_Running為No,錯誤代碼為1062 error code,從系統表performance_sc ...
  • 一、為什麼要做診斷引擎 毓數平臺是奇富科技公司自主研發的一站式大數據管理、開發、分析平臺,覆蓋大數據資產管理、數據開發及任務調度、自助分析及可視化、統一指標管理等多個數據生命周期流程,讓用戶使用數據的同時,挖掘數據最大的價值。而毓數平臺的大數據任務調度底層是基於Apache DolphinSched ...
  • 作者,祝青平,華為雲資料庫內核高級工程師。擅長資料庫優化器內核研發,9年資料庫內核研發經驗,參與多個TP以及AP資料庫的研發工作。 近日,華為雲資料庫社區下麵有這樣一條用戶提問留言:請問,如何通過MySQL提升DISTINCT,尤其是多表連接下DISTINCT的查詢效率? 在回答這個問題之前,我們先 ...
  • Hello 大家好,先祝福大家新年快樂。 AgileConfig 1.9.0 版本終於趕在農曆年前發佈了。 Mongodb 當前做為一款非常成熟的 Nosql 產品,已經有越來越多的產品或項目基於它來構建。在 AgileConfig 開源的這幾年之間,陸陸續續收到不少同學問為啥不支持 M ...
  • 引言: 在現代互聯網應用程式的開發和部署中,選擇一個可靠、高性能的Web伺服器是至關重要的。Nginx是一個備受推崇的選擇,它以其卓越的性能和可靠性在開發者社區中享有盛譽。本文將介紹Nginx的概念、優勢,以及如何使用Nginx作為Web伺服器和反向代理。 什麼是Nginx? Nginx(發音為“e ...
  • 折騰Docker 有幾天了,整別的都沒這個糟心。目前已經順利部署運行起來了。順便給大家分享下處理在Windows上使用.NET部署到Docker的相關問題解決方法。 1. Docker無法安裝問題 (下圖是網上找了個類似的安裝失敗截圖,頁面大致一樣,就是提示內容是 Docker Desktop 只能 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...