基于OpenVINO™2022.1C++API部署YOLOv7预训练模型|开发者实战

OpenCV学堂 2022-09-05 21:40

点击上方↑↑↑OpenCV学堂”关注我

来源:公众号 英特尔物联网 授权


文章作者

英特尔AI高级工程师

杨亦诚



毕业于约克大学电子工程系,深度学习解决方案专家。致力于边缘智能生态推广,拥有多年人工智能应用开发与项目落地经验。 


任务背景 


作为视觉应用中最常见的任务之一,目标检测一直是各类新模型刷榜的必争之地,其中就以 YOLO 系列的网络结构最为突出。YOLO 的全称是 you only look once,指只通过 one-stage 的方式需要“浏览一次”就可以识别出图中的物体的类别和位置。近期YOLO官方团队又放出新版本——YOLOv7,速度、精度都超越其他变体。本文将分享如何基于 OpenVINO 2022.1工具套件部署 YOLOv7 官方提供的预训练模型。附 C++/Python 源码及使用方法。


代码仓库地址:

https://github.com/OpenVINO-dev-contest/YOLOv7_OpenVINO_cpp-python

OpenVINO 简介 


用于高性能深度学习的英特尔发行版 OpenVINO™ 工具套件基于 oneAPI 而开发,以期在从边缘到云的各种英特尔平台上,帮助用户更快地将更准确的真实世界结果部署到生产系统中。通过简化的开发工作流程,OpenVINO™ 可赋能开发者在现实世界中部署高性能应用程序和算法。


在推理后端,得益于 OpenVINO 工具套件提供的“一次编写,随处部署”特性,转换后的模型能够在不同的英特尔硬件平台上运行,无需重新构建,有效简化了构建与迁移过程。此外,为了支持更多的异构加速单元,OpenVINO™ 的 runtime api 底层采用了插件式的开发架构,基于oneAPI 中的 MKL-DNN、oneDNN 等函数计算加速库,针对 AVX-512 等通用指令集进行优化,为不同的硬件执行单元分别实现了一套完整的高性能算子库,提升模型在推理运行时的整体性能表现。

YOLOv7 简介


官方版的 YOLOv7 相同体量下比 YOLOv5 精度更高,速度快120%(FPS),比 YOLOX 快180%(FPS),比 Dual-Swin-T 快1200%(FPS),比 ConvNext 快550%(FPS),比 SWIN-L快500%(FPS)。在5FPS 到160FPS 的范围内,无论是速度或是精度,YOLOv7 都超过了目前已知的检测器,并且在GPU V100 上进行测试, 精度为56.8% AP的模型可达到30 FPS(batch=1)以上的检测速率,与此同时,这是目前唯一一款在如此高精度下仍能超过 30FPS 的检测器。

任务开发流程


我们先整体来看下 YOLOv7 的输入输出结构,首先对输入的图片 resize 为 640x640 大小,输入到 backbone 网络中,得到三层不同 size 大小的 feature map,并输出对应预测结果,这里以 coco 数据集为例子,输出为 80 个类别,然后每个输出(x ,y, w, h, o) 即坐标位置和是否存在物体的置信度,3 是指的 anchor 数量,因此每一层的输出为 (80+5) x 3 = 255再乘上 feature map 的大小就是最终的输出了。整个开发流程可以分为数据处理模块定义、前处理任务、推理任务、后处理任务四部分组成。


图:YOLOv7官方预训练模型的输入输出结构


1. 数据处理模块


定义 Object 结构体用来存放模型的输出数据,包含  bounding box 信息,类别标签,以及是否存在物体和类别的累计置信度。


定义 class_names 向量,用于存放 coco 数据集的所有标签。

struct Object{    cv::Rect_ rect;    int label;    float prob;};
const std::vector class_names = {    "person", "bicycle", "car", "motorcycle", "airplane", "bus", "train", "truck", "boat", "traffic light",    "fire hydrant", "stop sign", "parking meter", "bench", "bird", "cat", "dog", "horse", "sheep", "cow",    "elephant", "bear", "zebra", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase", "frisbee",    "skis", "snowboard", "sports ball", "kite", "baseball bat", "baseball glove", "skateboard", "surfboard",    "tennis racket", "bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple",    "sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake", "chair", "couch",    "potted plant", "bed", "dining table", "toilet", "tv", "laptop", "mouse", "remote", "keyboard", "cell phone",    "microwave", "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase", "scissors", "teddy bear",    "hair drier", "toothbrush"};

定义 letterbox 与 scale_box 模块,分别用于在图像前处理任务中为输入数据添加 letterbox,以及在后处理任务还原 letterbox 带来坐标位置变换。这里特别值得注意的是我们增加了一个 padd 向量,用于存放在添加 letterbox 过程中 letterbox 的 size 信息以及相较原始图片的缩放比例信息,该组数据会用于在后处理任务中还原删除 letterbox 以后的结果。

cv::Mat letterbox(cv::Mat &src, int h, int w, std::vector &padd){    // Resize and pad image while meeting stride-multiple constraints    int in_w = src.cols;    int in_h = src.rows;    int tar_w = w;    int tar_h = h;    float r = min(float(tar_h) / in_h, float(tar_w) / in_w);    int inside_w = round(in_w * r);    int inside_h = round(in_h * r);    int padd_w = tar_w - inside_w;    int padd_h = tar_h - inside_h;    cv::Mat resize_img;
   // resize    resize(src, resize_img, cv::Size(inside_w, inside_h));
   // divide padding into 2 sides    padd_w = padd_w / 2;    padd_h = padd_h / 2;    padd.push_back(padd_w);    padd.push_back(padd_h);
   // store the ratio    padd.push_back(r);    int top = int(round(padd_h - 0.1));    int bottom = int(round(padd_h + 0.1));    int left = int(round(padd_w - 0.1));    int right = int(round(padd_w + 0.1));
   // add border    copyMakeBorder(resize_img, resize_img, top, bottom, left, right, 0, cv::Scalar(114, 114, 114));    return resize_img;}
cv::Rect scale_box(cv::Rect box, std::vector &padd){      // remove the padding area    cv::Rect scaled_box;    scaled_box.x = box.x - padd[0];    scaled_box.y = box.y - padd[1];    scaled_box.width = box.width;    scaled_box.height = box.height;    return scaled_box;}

定义 generate_proposal 模块,该模块具体有以下几个功能:

01

根据定义的 anchors,在输入图像中生成各类 feature map 的候选框;

02

根据输出结果调整候选框位置和大小,并将其作为 bounding box 还原到输入图像的坐标系中;

03

过滤置信度较低的分类结果,获取类别结果。

static void generate_proposals(int stride, const float *feat, float prob_threshold, std::vector &objects){       // get the results from proposals    float anchors[18] = {12, 16, 19, 36, 40, 28, 36, 75, 76, 55, 72, 146, 142, 110, 192, 243, 459, 401};    int anchor_num = 3;    int feat_w = 640 / stride;    int feat_h = 640 / stride;    int cls_num = 80;    int anchor_group = 0;    if (stride == 8)        anchor_group = 0;    if (stride == 16)        anchor_group = 1;    if (stride == 32)        anchor_group = 2;
   // 3 x h x w x (80 + 5)    for (int anchor = 0; anchor <= anchor_num - 1; anchor++)    {        for (int i = 0; i <= feat_h - 1; i++)        {            for (int j = 0; j <= feat_w - 1; j++)            {                float box_prob = feat[anchor * feat_h * feat_w * (cls_num + 5) + i * feat_w * (cls_num + 5) + j * (cls_num + 5) + 4];                box_prob = sigmoid(box_prob);
               // filter the bounding box with low confidence                if (box_prob < prob_threshold)                    continue;                float x = feat[anchor * feat_h * feat_w * (cls_num + 5) + i * feat_w * (cls_num + 5) + j * (cls_num + 5) + 0];                float y = feat[anchor * feat_h * feat_w * (cls_num + 5) + i * feat_w * (cls_num + 5) + j * (cls_num + 5) + 1];                float w = feat[anchor * feat_h * feat_w * (cls_num + 5) + i * feat_w * (cls_num + 5) + j * (cls_num + 5) + 2];                float h = feat[anchor * feat_h * feat_w * (cls_num + 5) + i * feat_w * (cls_num + 5) + j * (cls_num + 5) + 3];
               double max_prob = 0;                int idx = 0;
               // get the class id with maximum confidence                for (int t = 5; t < 85; ++t)                {                    double tp = feat[anchor * feat_h * feat_w * (cls_num + 5) + i * feat_w * (cls_num + 5) + j * (cls_num + 5) + t];                    tp = sigmoid(tp);                    if (tp > max_prob)                    {                        max_prob = tp;                        idx = t;                    }                }
               // filter the class with low confidence                float cof = box_prob * max_prob;                if (cof < prob_threshold)                    continue;                                // convert results to xywh                x = (sigmoid(x) * 2 - 0.5 + j) * stride;                y = (sigmoid(y) * 2 - 0.5 + i) * stride;                w = pow(sigmoid(w) * 2, 2) * anchors[anchor_group * 6 + anchor * 2];                h = pow(sigmoid(h) * 2, 2) * anchors[anchor_group * 6 + anchor * 2 + 1];
               float r_x = x - w / 2;                float r_y = y - h / 2;
               // store the results                Object obj;                obj.rect.x = r_x;                obj.rect.y = r_y;                obj.rect.width = w;                obj.rect.height = h;                obj.label = idx - 5;                obj.prob = cof;                objects.push_back(obj);            }        }    }}


2. 前处理任务


前处理主要包含以下几个步骤:


01

使用 OpenCV 读取图片文件

02

对于原始图片进行 resize 并添加 letterbox

03

将色彩通道从 BGR 转化为 RGB

04

将输入数据进行 layout 转置(NHWC

=>NCHW), 与归一化操作(见模型推理部分代码)

cv::Mat src_img = cv::imread(image_path);    cv::Mat img;
   std::vector padd;    cv::Mat boxed = letterbox(src_img, img_h, img_w, padd);    cv::cvtColor(boxed, img, cv::COLOR_BGR2RGB);


3. 推理任务


图:OpenVINO 工具套件 runtime 开发流程


模型推理部分主要调用 OpenVINO™ 的 C++ API 进行实现,OpenVINO™ 推理接口的调用流程如上图所示

可参考官方说明:

https://docs.openvino.ai/latest/openvino_docs_OV_UG_Integrate_OV_with_your_application.html


在这里第2步 Complie Model 亦可分为模型读取与模型编译两个步骤执行,同时可以发现相较2021.4之前的版本,OpenVINO 2022.1在输入以及输出数据的接口调用方式上有了极大的简化,可以通过 Tensor 相关的构造函数,轻松实现模型数据的载入和读取。在整个过程中开发者需要将输入数据进行layout转置(NHWC=>NCHW),并填充到 input tensor 所对应的数据指针地址中。在结果数据提取部分,由于该模型有3个不同尺度 feature map output,因此我们需要逐一获取他们结果数据指针。

// -------- Step 1. Initialize OpenVINO Runtime Core --------    ov::Core core;
   // -------- Step 2. Read a model --------    std::shared_ptr model = core.read_model(model_path);
   // -------- Step 3. Loading a model to the device --------    ov::CompiledModel compiled_model = core.compile_model(model, device_name);
   // Get input port for model with one input    auto input_port = compiled_model.input();    // Create tensor from external memory    // ov::Tensor input_tensor(input_port.get_element_type(), input_port.get_shape(), input_data.data());    // -------- Step 4. Create an infer request --------    ov::InferRequest infer_request = compiled_model.create_infer_request();
   // -------- Step 5. Prepare input --------    ov::Tensor input_tensor1 = infer_request.get_input_tensor(0);    // NHWC => NCHW    auto data1 = input_tensor1.data();    for (int h = 0; h < img_h; h++)    {        for (int w = 0; w < img_w; w++)        {            for (int c = 0; c < 3; c++)            {                // int in_index = h * img_w * 3 + w * 3 + c;                int out_index = c * img_h * img_w + h * img_w + w;                data1[out_index] = float(img.at(h, w)[c]) / 255.0f;            }        }    }
   // -------- Step 6. Start inference --------    infer_request.infer();
   // -------- Step 7. Process output --------    auto output_tensor_p8 = infer_request.get_output_tensor(0);    const float *result_p8 = output_tensor_p8.data();    auto output_tensor_p16 = infer_request.get_output_tensor(1);    const float *result_p16 = output_tensor_p16.data();    auto output_tensor_p32 = infer_request.get_output_tensor(2);    const float *result_p32 = output_tensor_p32.data();


4. 后处理任务


后处理部分需要调用我们之前定义的 generate_proposals 用于还原每一个 feature map 的结果数据,并进行堆叠,最后使用 OpenCV DNN 模块中自带的 NMS 方法,完成对结果 bounding box 的非极大抑制过滤,获取我们在原始 input image 中的目标位置与类别信息。

 generate_proposals(8, result_p8, prob_threshold, objects8);    proposals.insert(proposals.end(), objects8.begin(), objects8.end());    generate_proposals(16, result_p16, prob_threshold, objects16);    proposals.insert(proposals.end(), objects16.begin(), objects16.end());    generate_proposals(32, result_p32, prob_threshold, objects32);    proposals.insert(proposals.end(), objects32.begin(), objects32.end());
   std::vector classIds;    std::vector confidences;    std::vector boxes;
   for (size_t i = 0; i < proposals.size(); i++)    {        classIds.push_back(proposals[i].label);        confidences.push_back(proposals[i].prob);        boxes.push_back(proposals[i].rect);    }
   std::vector picked;
   // do non maximum suppression for each bounding boxx    cv::dnn::NMSBoxes(boxes, confidences, prob_threshold, nms_threshold, picked);

此外,我们还需要进一步调整模型 input data 对应的结果数据,将其还原到原始尺寸的图片上进行展示。

 int idx = picked[i];        cv::Rect box = boxes[idx];        cv::Rect scaled_box = scale_box(box, padd);        drawPred(classIds[idx], confidences[idx], scaled_box, padd[2], raw_h, raw_w, src_img, class_names);

参考示例使用方法


该示例分别提供了 C++和 Python 的参考实现,具体使用方法如下:


1. 依赖安装

# 下载示例仓库$ git clone https://github.com/OpenVINO-dev-contest/YOLOv7_OpenVINO_cpp-python.git


C++ 环境依赖



由于本示例的 C++ 版本只依赖OpenVINO 和OpenCV 的运行库,所以需要开发者提前完成对这两个工具组件的安装:


OpenVINO C++ runtime 安装地址:

https://docs.openvino.ai/latest/openvino_docs_install_guides_installing_openvino_linux.html#install-openvino


OpenCV 环境安装地址:

https://docs.opencv.org/4.x/d7/d9f/tutorial_linux_install.html


注:由于该示例中提供的 CMakeList 使用 OpenCV 的默认路径,因此需要在完成 OpenCV 的编译后,执行 make install 命令。


Python 环境依赖



Python 环境的安装相对简单,只需通过 pip 命令行工具进行依赖安装:

$ pip install -r python/requirements


2. 预训练模型下载


可以从官方 github 仓库提供的链接中下载基于 COCO 数据集的 YOLOv7 预训练模型权重:

https://github.com/WongKinYiu/yolov7



3. 模型转换


目前 OpenVINO  runtime 可以直接支持 onnx 格式的模型部署,所以我们在得到.pt权重文件后,只需使用官方自带 export.py 脚本,就可将其导出为 onnx 格式模型,具体过程如下:

# 下载YOLOv7官方仓库:$ git clone git@github.com:WongKinYiu/yolov7.git$ cd yolov7/models$ python export.py --weights yolov7.pt


4. 测试运行


C++ 示例



编译 C++ 示例源码,编译完成后会在 build 目录下生成 YOLOv7 可执行文件:

  $ cd cpp  $ mkdir build && cd build  $ source '~/intel/openvino_2022.1.0.643/bin/setupvars.sh'  $ cmake ..  $ make

执行推理任务:

 $ yolov7 yolov7.onnx data/horses.jpg 'CPU'


Python 示例



执行推理任务:

  $ python python/main.py -m yolov7.onnx -i data/horse.jpg


5. 测试结果


运行推理示例后,会在本地目录下生成代 bounding box 以及 label 的图片,这里我们用到官方仓库中附带的马匹数据进行测试,具体结果如下:


图:推理运行结果

Benchmark App 介绍


OpenVINO 提供了性能测试工具 Benchmark App  ,方便开发者快速测试 OpenVINO 模型在不同的硬件平台上的性能。我们以下面的例子,简单介绍 benchmark app 的使用方法和相关参数,更多内容请参考 Benchmark App 官方文档。

$ benchmark_app -m yolov7.onnx  -hint throughput

-m: 指定模型路径。由于目前OpenVINO  runtime是支持直接读取 onnx 格式文件的,所以这里我们设置为导出以后 onnx 模型。


-hint: 指定性能测试的优先策略,以自动选择底层性能优化相关参数。这里我们选择 throughput 模式来提升系统整体吞吐量。如果应用对延迟比较敏感,推荐使用 latency 模式来减少推理延迟。

结论


YOLOv7 由于其出色的精度和性能表现,在推出第一时就受到了极大的关注,目前 github 上的 star 已超过5K。本示例通过OpenVINO 2022.1新版本的 C++ API 接口,实现对 YOLOv7 官方预训练模型的部署。最后使用 OpenVINO自带的 benchmark_app 工具进一步对模型的性能进行验证测试。

参考文献:

YOLOv7官方仓库:

https://github.com/WongKinYiu/yolov7


OpenVINO 开发文档:

https://docs.openvino.ai/latest/openvino_docs_OV_UG_Integrate_OV_with_your_application.html


OpenCV学堂 专注计算机视觉开发技术分享,技术框架使用,包括OpenCV,Tensorflow,Pytorch教程与案例,相关算法详解,最新CV方向论文,硬核代码干货与代码案例详解!作者在CV工程化方面深度耕耘15年,感谢您的关注!
评论
  • 本文介绍瑞芯微开发板/主板Android配置APK默认开启性能模式方法,开启性能模式后,APK的CPU使用优先级会有所提高。触觉智能RK3562开发板演示,搭载4核A53处理器,主频高达2.0GHz;内置独立1Tops算力NPU,可应用于物联网网关、平板电脑、智能家居、教育电子、工业显示与控制等行业。源码修改修改源码根目录下文件device/rockchip/rk3562/package_performance.xml并添加以下内容,注意"+"号为添加内容,"com.tencent.mm"为AP
    Industio_触觉智能 2025-01-17 14:09 164浏览
  •     IPC-2581是基于ODB++标准、结合PCB行业特点而指定的PCB加工文件规范。    IPC-2581旨在替代CAM350格式,成为PCB加工行业的新的工业规范。    有一些免费软件,可以查看(不可修改)IPC-2581数据文件。这些软件典型用途是工艺校核。    1. Vu2581        出品:Downstream     
    电子知识打边炉 2025-01-22 11:12 53浏览
  • 数字隔离芯片是一种实现电气隔离功能的集成电路,在工业自动化、汽车电子、光伏储能与电力通信等领域的电气系统中发挥着至关重要的作用。其不仅可令高、低压系统之间相互独立,提高低压系统的抗干扰能力,同时还可确保高、低压系统之间的安全交互,使系统稳定工作,并避免操作者遭受来自高压系统的电击伤害。典型数字隔离芯片的简化原理图值得一提的是,数字隔离芯片历经多年发展,其应用范围已十分广泛,凡涉及到在高、低压系统之间进行信号传输的场景中基本都需要应用到此种芯片。那么,电气工程师在进行电路设计时到底该如何评估选择一
    华普微HOPERF 2025-01-20 16:50 73浏览
  • 高速先生成员--黄刚这不马上就要过年了嘛,高速先生就不打算给大家上难度了,整一篇简单但很实用的文章给大伙瞧瞧好了。相信这个标题一出来,尤其对于PCB设计工程师来说,心就立马凉了半截。他们辛辛苦苦进行PCB的过孔设计,高速先生居然说设计多大的过孔他们不关心!另外估计这时候就跳出很多“挑刺”的粉丝了哈,因为翻看很多以往的文章,高速先生都表达了过孔孔径对高速性能的影响是很大的哦!咋滴,今天居然说孔径不关心了?别,别急哈,听高速先生在这篇文章中娓娓道来。首先还是要对各位设计工程师的设计表示肯定,毕竟像我
    一博科技 2025-01-21 16:17 101浏览
  • 随着消费者对汽车驾乘体验的要求不断攀升,汽车照明系统作为确保道路安全、提升驾驶体验以及实现车辆与环境交互的重要组成,日益受到业界的高度重视。近日,2024 DVN(上海)国际汽车照明研讨会圆满落幕。作为照明与传感创新的全球领导者,艾迈斯欧司朗受邀参与主题演讲,并现场展示了其多项前沿技术。本届研讨会汇聚来自全球各地400余名汽车、照明、光源及Tier 2供应商的专业人士及专家共聚一堂。在研讨会第一环节中,艾迈斯欧司朗系统解决方案工程副总裁 Joachim Reill以深厚的专业素养,主持该环节多位
    艾迈斯欧司朗 2025-01-16 20:51 198浏览
  • 嘿,咱来聊聊RISC-V MCU技术哈。 这RISC-V MCU技术呢,简单来说就是基于一个叫RISC-V的指令集架构做出的微控制器技术。RISC-V这个啊,2010年的时候,是加州大学伯克利分校的研究团队弄出来的,目的就是想搞个新的、开放的指令集架构,能跟上现代计算的需要。到了2015年,专门成立了个RISC-V基金会,让这个架构更标准,也更好地推广开了。这几年啊,这个RISC-V的生态系统发展得可快了,好多公司和机构都加入了RISC-V International,还推出了不少RISC-V
    丙丁先生 2025-01-21 12:10 112浏览
  • 2024年是很平淡的一年,能保住饭碗就是万幸了,公司业绩不好,跳槽又不敢跳,还有一个原因就是老板对我们这些员工还是很好的,碍于人情也不能在公司困难时去雪上加霜。在工作其间遇到的大问题没有,小问题还是有不少,这里就举一两个来说一下。第一个就是,先看下下面的这个封装,你能猜出它的引脚间距是多少吗?这种排线座比较常规的是0.6mm间距(即排线是0.3mm间距)的,而这个规格也是我们用得最多的,所以我们按惯性思维来看的话,就会认为这个座子就是0.6mm间距的,这样往往就不会去细看规格书了,所以这次的运气
    wuliangu 2025-01-21 00:15 186浏览
  •  万万没想到!科幻电影中的人形机器人,正在一步步走进我们人类的日常生活中来了。1月17日,乐聚将第100台全尺寸人形机器人交付北汽越野车,再次吹响了人形机器人疯狂进厂打工的号角。无独有尔,银河通用机器人作为一家成立不到两年时间的创业公司,在短短一年多时间内推出革命性的第一代产品Galbot G1,这是一款轮式、双臂、身体可折叠的人形机器人,得到了美团战投、经纬创投、IDG资本等众多投资方的认可。作为一家成立仅仅只有两年多时间的企业,智元机器人也把机器人从梦想带进了现实。2024年8月1
    刘旷 2025-01-21 11:15 399浏览
  • 现在为止,我们已经完成了Purple Pi OH主板的串口调试和部分配件的连接,接下来,让我们趁热打铁,完成剩余配件的连接!注:配件连接前请断开主板所有供电,避免敏感电路损坏!1.1 耳机接口主板有一路OTMP 标准四节耳机座J6,具备进行音频输出及录音功能,接入耳机后声音将优先从耳机输出,如下图所示:1.21.2 相机接口MIPI CSI 接口如上图所示,支持OV5648 和OV8858 摄像头模组。接入摄像头模组后,使用系统相机软件打开相机拍照和录像,如下图所示:1.3 以太网接口主板有一路
    Industio_触觉智能 2025-01-20 11:04 150浏览
  • 日前,商务部等部门办公厅印发《手机、平板、智能手表(手环)购新补贴实施方案》明确,个人消费者购买手机、平板、智能手表(手环)3类数码产品(单件销售价格不超过6000元),可享受购新补贴。每人每类可补贴1件,每件补贴比例为减去生产、流通环节及移动运营商所有优惠后最终销售价格的15%,每件最高不超过500元。目前,京东已经做好了承接手机、平板等数码产品国补优惠的落地准备工作,未来随着各省市关于手机、平板等品类的国补开启,京东将第一时间率先上线,满足消费者的换新升级需求。为保障国补的真实有效发放,基于
    华尔街科技眼 2025-01-17 10:44 221浏览
  •  光伏及击穿,都可视之为 复合的逆过程,但是,复合、光伏与击穿,不单是进程的方向相反,偏置状态也不一样,复合的工况,是正偏,光伏是零偏,击穿与漂移则是反偏,光伏的能源是外来的,而击穿消耗的是结区自身和电源的能量,漂移的载流子是 客席载流子,须借外延层才能引入,客席载流子 不受反偏PN结的空乏区阻碍,能漂不能漂,只取决于反偏PN结是否处于外延层的「射程」范围,而穿通的成因,则是因耗尽层的过度扩张,致使跟 端子、外延层或其他空乏区 碰触,当耗尽层融通,耐压 (反向阻断能力) 即告彻底丧失,
    MrCU204 2025-01-17 11:30 182浏览
  • 临近春节,各方社交及应酬也变得多起来了,甚至一月份就排满了各式约见。有的是关系好的专业朋友的周末“恳谈会”,基本是关于2025年经济预判的话题,以及如何稳定工作等话题;但更多的预约是来自几个客户老板及副总裁们的见面,他们为今年的经济预判与企业发展焦虑而来。在聊天过程中,我发现今年的聊天有个很有意思的“点”,挺多人尤其关心我到底是怎么成长成现在的多领域风格的,还能掌握一些经济趋势的分析能力,到底学过哪些专业、在企业管过哪些具体事情?单单就这个一个月内,我就重复了数次“为什么”,再辅以我上次写的:《
    牛言喵语 2025-01-22 17:10 41浏览
  • Ubuntu20.04默认情况下为root账号自动登录,本文介绍如何取消root账号自动登录,改为通过输入账号密码登录,使用触觉智能EVB3568鸿蒙开发板演示,搭载瑞芯微RK3568,四核A55处理器,主频2.0Ghz,1T算力NPU;支持OpenHarmony5.0及Linux、Android等操作系统,接口丰富,开发评估快人一步!添加新账号1、使用adduser命令来添加新用户,用户名以industio为例,系统会提示设置密码以及其他信息,您可以根据需要填写或跳过,命令如下:root@id
    Industio_触觉智能 2025-01-17 14:14 122浏览
我要评论
0