《数字图像处理(MATLAB版)》相关算法代码及其分析(2)

目录

1 将8连通边界转换为4连通边界

1.1 移除对角线转折

1.2 插入额外像素

2 将边界信息转换为二进制图像

2.1 函数定义

2.2 参数处理和验证

2.3 默认大小参数设置

2.4 根据参数调整边界位置

2.5 生成二进制图像

2.6 错误处理

3 对二值图像边界的跟踪和提取

3.1 函数描述

3.2 参数处理

3.3 对象标记

3.4 图像填充

3.5 边界跟踪

3.6 边界坐标存储

3.7 结果修正

3.8 结果输出


1 将8连通边界转换为4连通边界

function rc_new = bound2four(rc)
%BOUND2FOUR Convert 8-connected boundary to 4-connected boundary.
%   RC_NEW = BOUND2FOUR(RC) converts an eight-connected boundary to a
%   four-connected boundary.  RC is a P-by-2 matrix, each row of
%   which contains the row and column coordinates of a boundary
%   pixel.  BOUND2FOUR inserts new boundary pixels wherever there is
%   a diagonal connection.%   Copyright 2002-2004 R. C. Gonzalez, R. E. Woods, & S. L. Eddins
%   Digital Image Processing Using MATLAB, Prentice-Hall, 2004
%   $Revision: 1.4 $  $Date: 2003/11/21 14:20:21 $if size(rc, 1) > 1% Phase 1: remove diagonal turns, one at a time until they are all gone.done = 0;rc1 = [rc(end - 1, :); rc];while ~doned = diff(rc1, 1);diagonal_locations = all(d, 2);double_diagonals = diagonal_locations(1:end - 1) & ...(diff(diagonal_locations, 1) == 0);double_diagonal_idx = find(double_diagonals);turns = any(d(double_diagonal_idx, :) ~= ...d(double_diagonal_idx + 1, :), 2);turns_idx = double_diagonal_idx(turns);if isempty(turns_idx)done = 1;elsefirst_turn = turns_idx(1);rc1(first_turn + 1, :) = (rc1(first_turn, :) + ...rc1(first_turn + 2, :)) / 2;if first_turn == 1rc1(end, :) = rc1(2, :);endendendrc1 = rc1(2:end, :);
end% Phase 2: insert extra pixels where there are diagonal connections.rowdiff = diff(rc1(:, 1));
coldiff = diff(rc1(:, 2));diagonal_locations = rowdiff & coldiff;
num_old_pixels = size(rc1, 1);
num_new_pixels = num_old_pixels + sum(diagonal_locations);
rc_new = zeros(num_new_pixels, 2);% Insert the original values into the proper locations in the new RC
% matrix.
idx = (1:num_old_pixels)' + [0; cumsum(diagonal_locations)];
rc_new(idx, :) = rc1;% Compute the new pixels to be inserted.
new_pixel_offsets = [0 1; -1 0; 1 0; 0 -1];
offset_codes = 2 * (1 - (coldiff(diagonal_locations) + 1)/2) + ...(2 - (rowdiff(diagonal_locations) + 1)/2);
new_pixels = rc1(diagonal_locations, :) + ...new_pixel_offsets(offset_codes, :); % Where do the new pixels go?
insertion_locations = zeros(num_new_pixels, 1);
insertion_locations(idx) = 1;
insertion_locations = ~insertion_locations;% Insert the new pixels.
rc_new(insertion_locations, :) = new_pixels;

这段代码的目的是将一个8连通边界转换为4连通边界。在数字图像处理中,连通性是衡量像素之间关系的一种方式。8连通边界意味着边界上的每个像素与其周围的8个像素(水平、垂直和对角线方向)都可能相连。而4连通边界则仅考虑水平和垂直方向的相邻像素。该转换过程涉及两个阶段:首先是移除所有对角线转折点,然后是在需要的位置插入额外的像素以确保4连通性。

以下是对代码的详细分析:

1.1 移除对角线转折

  1. 初始化:复制输入的边界坐标rcrc1并在rc1的开头添加rc的倒数第二行。这样做是为了处理循环边界条件。

  2. 循环处理:通过计算rc1的差分d,找出所有对角线连接的位置。这里,对角线连接是指在两个方向(行和列)上都有变化的连接。

  3. 双重对角线和转折点检测:接下来,识别连续的对角线连接(双重对角线)并找出其中的转折点。转折点是指相邻的对角线连接在方向上有所不同的地方。

  4. 处理转折点:对于每个找到的转折点,通过在转折点位置插入一个新的像素(这个像素的坐标是转折点前后两个像素坐标的平均值)来移除转折。如果处理的是第一个转折点,还需要更新rc1的最后一行,以保持边界的闭合性。

  5. 循环结束条件:当没有更多转折点可以处理时,结束循环。

1.2 插入额外像素

  1. 计算差分:计算rc1中行和列的差分,以找出对角线连接的位置。

  2. 确定新像素数量和位置:根据对角线连接的数量,计算新的边界坐标矩阵rc_new的大小,并初始化为零矩阵。然后,计算原始像素和新插入像素在rc_new中的正确位置。

  3. 计算新像素坐标:对于每个需要插入的新像素,根据其相对于原始对角线连接的位置,计算新像素的坐标。

  4. 插入操作:在rc_new中填充原始像素和新计算的像素,完成4连通边界的构建。

2 将边界信息转换为二进制图像

function B = bound2im(b, M, N, x0, y0)
%BOUND2IM Converts a boundary to an image.
%   B = BOUND2IM(b) converts b, an np-by-2 or 2-by-np array
%   representing the integer coordinates of a boundary, into a binary
%   image with 1s in the locations defined by the coordinates in b
%   and 0s elsewhere. 
%
%   B = BOUND2IM(b, M, N) places the boundary approximately centered
%   in an M-by-N image. If any part of the boundary is outside the
%   M-by-N rectangle, an error is issued.  
%
%   B = BOUND2IM(b, M, N, X0, Y0) places the boundary in an image of
%   size M-by-N, with the topmost boundary point located at X0 and
%   the leftmost point located at Y0. If the shifted boundary is
%   outside the M-by-N rectangle, an error is issued. XO and X0 must
%   be positive integers. %   Copyright 2002-2004 R. C. Gonzalez, R. E. Woods, & S. L. Eddins
%   Digital Image Processing Using MATLAB, Prentice-Hall, 2004
%   $Revision: 1.6 $  $Date: 2003/06/14 16:21:28 $[np, nc] = size(b);
if np < ncb = b'; % To convert to size np-by-2.[np, nc] = size(b);
end% Make sure the coordinates are integers.
x = round(b(:, 1)); 
y = round(b(:, 2));% Set up the default size parameters. 
x = x - min(x) + 1;
y = y - min(y) + 1;
B = false(max(x), max(y));
C = max(x) - min(x) + 1;
D = max(y) - min(y) + 1;if nargin == 1  % Use the preceding default values.
elseif nargin == 3if C > M | D > Nerror('The boundary is outside the M-by-N region.')end% The image size will be M-by-N. Set up the parameters for this.B = false(M, N);% Distribute extra rows approx. even between top and bottom.NR = round((M - C)/2); NC = round((N - D)/2); % The same for columns.x = x + NR; % Offset the boundary to new position.y = y + NC;  
elseif nargin == 5if x0 < 0 | y0 < 0error('x0 and y0 must be positive integers.')endx = x + round(x0) - 1;y = y + round(y0) - 1;C = C + x0 - 1;D = D + y0 - 1;if C > M | D > Nerror('The shifted boundary is outside the M-by-N region.')endB = false(M, N);
elseerror('Incorrect number of inputs.') 
endB(sub2ind(size(B), x, y)) = true;

这段代码定义了一个名为 bound2im 的函数,它的主要作用是将一个边界(由一系列坐标点组成)转换成一个二进制图像。在这个二进制图像中,边界上的点被标记为 1,其他位置则为 0。

以下是对代码的详细分析:

2.1 函数定义

function B = bound2im(b, M, N, x0, y0)

这表示 bound2im 是一个函数,它可以接收从1到5个参数:

  • b:一个 np-by-2 或 2-by-np 的数组,代表边界的整数坐标。
  • M 和 N(可选):指定输出图像的大小(行数和列数)。
  • x0 和 y0(可选):指定边界在图像中的起始位置。

函数返回一个二进制图像 B

2.2 参数处理和验证

首先,函数检查输入边界 b 的尺寸,并确保其为 np-by-2 的格式。如果不是,就将其转置。这样做是为了确保后续操作中坐标的使用是正确的。

接着,函数通过取整操作确保坐标都是整数值,因为图像中的位置索引必须是整数。

2.3 默认大小参数设置

如果没有指定图像的大小(即只传入了 b 参数),函数会根据边界的最小和最大坐标计算出一个默认的图像大小。这样做的目的是让整个边界都能够被包含在生成的图像中。

2.4 根据参数调整边界位置

  • 如果只给出了边界 b,那么函数会创建一个足够大的图像来容纳整个边界,并将边界放在图像的左上角。
  • 如果给出了图像大小 M 和 N,但没有指定边界的起始位置,那么边界会被置于图像的大致中心位置。此时,如果边界超出了指定的图像大小,函数会报错。
  • 如果同时给出了图像大小和边界的起始位置 x0 和 y0,边界会根据这些位置进行偏移。同样,如果偏移后的边界超出了图像大小,函数也会报错。

2.5 生成二进制图像

最后,函数使用 false 初始化一个大小为 M-by-N 的二进制图像矩阵 B,然后根据调整后的边界坐标,在相应的位置将 B 中的值设置为 true,从而生成最终的边界图像。

2.6 错误处理

  • 如果 nargin(传入的参数数量)不符合要求,函数会报告“Incorrect number of inputs”错误。
  • 如果边界超出了指定的图像区域,或者 x0y0 不是正整数,函数同样会报错。

3 对二值图像边界的跟踪和提取

function B = boundaries(BW, conn, dir)
%BOUNDARIES Trace object boundaries.  
%   B = BOUNDARIES(BW) traces the exterior boundaries of objects in
%   the binary image BW.  B is a P-by-1 cell array, where P is the
%   number of objects in the image. Each cell contains a Q-by-2
%   matrix, each row of which contains the row and column coordinates
%   of a boundary pixel.  Q is the number of boundary pixels for the
%   corresponding object.  Object boundaries are traced in the
%   clockwise direction.
%
%   B = BOUNDARIES(BW, CONN) specifies the connectivity to use when
%   tracing boundaries.  CONN may be either 8 or 4.  The default
%   value for CONN is 8.
%
%   B = BOUNDARIES(BW, CONN, DIR) specifies the direction used for
%   tracing boundaries.  DIR should be either 'cw' (trace boundaries
%   clockwise) or 'ccw' (trace boundaries counterclockwise).  If DIR
%   is omitted BOUNDARIES traces in the clockwise direction.%   Copyright 2002-2004 R. C. Gonzalez, R. E. Woods, & S. L. Eddins
%   Digital Image Processing Using MATLAB, Prentice-Hall, 2004
%   $Revision: 1.6 $  $Date: 2003/11/21 14:22:07 $if nargin < 3dir = 'cw';
endif nargin < 2conn = 8;
endL = bwlabel(BW, conn);% The number of objects is the maximum value of L.  Initialize the
% cell array B so that each cell initially contains a 0-by-2 matrix.
numObjects = max(L(:));
if numObjects > 0B = {zeros(0, 2)};B = repmat(B, numObjects, 1);
elseB = {};
end% Pad label matrix with zeros.  This lets us write the
% boundary-following loop without worrying about going off the edge
% of the image. 
Lp = padarray(L, [1 1], 0, 'both');% Compute the linear indexing offsets to take us from a pixel to its
% neighbors.  
M = size(Lp, 1);
if conn == 8% Order is N NE E SE S SW W NW.offsets = [-1, M - 1, M, M + 1, 1, -M + 1, -M, -M-1];
else% Order is N E S W.offsets = [-1, M, 1, -M];
end% next_search_direction_lut is a lookup table.  Given the direction
% from pixel k to pixel k+1, what is the direction to start with when
% examining the neighborhood of pixel k+1?
if conn == 8next_search_direction_lut = [8 8 2 2 4 4 6 6];
elsenext_search_direction_lut = [4 1 2 3];
end% next_direction_lut is a lookup table.  Given that we just looked at
% neighbor in a given direction, which neighbor do we look at next? 
if conn == 8next_direction_lut = [2 3 4 5 6 7 8 1];
elsenext_direction_lut = [2 3 4 1];
end% Values used for marking the starting and boundary pixels.
START    = -1;
BOUNDARY = -2;% Initialize scratch space in which to record the boundary pixels as
% well as follow the boundary.
scratch = zeros(100, 1);% Find candidate starting locations for boundaries.
[rr, cc] = find((Lp(2:end-1, :) > 0) & (Lp(1:end-2, :) == 0));
rr = rr + 1;for k = 1:length(rr)r = rr(k);c = cc(k);if (Lp(r,c) > 0) & (Lp(r - 1, c) == 0) & isempty(B{Lp(r, c)})% We've found the start of the next boundary.  Compute its% linear offset, record which boundary it is, mark it, and% initialize the counter for the number of boundary pixels.idx = (c-1)*size(Lp, 1) + r;which = Lp(idx);scratch(1) = idx;Lp(idx) = START;numPixels = 1;currentPixel = idx;initial_departure_direction = [];done = 0;next_search_direction = 2;while ~done% Find the next boundary pixel.direction = next_search_direction;found_next_pixel = 0;for k = 1:length(offsets)neighbor = currentPixel + offsets(direction);if Lp(neighbor) ~= 0% Found the next boundary pixel.if (Lp(currentPixel) == START) & ...isempty(initial_departure_direction)% We are making the initial departure from% the starting pixel.initial_departure_direction = direction;elseif (Lp(currentPixel) == START) & ...(initial_departure_direction == direction)% We are about to retrace our path.% That means we're done.done = 1;found_next_pixel = 1;break;end% Take the next step along the boundary.next_search_direction = ...next_search_direction_lut(direction);found_next_pixel = 1;numPixels = numPixels + 1;if numPixels > size(scratch, 1)% Double the scratch space.scratch(2*size(scratch, 1)) = 0;endscratch(numPixels) = neighbor;if Lp(neighbor) ~= STARTLp(neighbor) = BOUNDARY;endcurrentPixel = neighbor;break;enddirection = next_direction_lut(direction);endif ~found_next_pixel% If there is no next neighbor, the object must just% have a single pixel.numPixels = 2;scratch(2) = scratch(1);done = 1;endend% Convert linear indices to row-column coordinates and save% in the output cell array. [row, col] = ind2sub(size(Lp), scratch(1:numPixels));B{which} = [row - 1, col - 1];end
endif strcmp(dir, 'ccw')for k = 1:length(B)B{k} = B{k}(end:-1:1, :);end
end

这段代码实现了对二值图像中对象的边界进行跟踪,最终输出一个包含所有对象边界坐标的 cell 数组。

主要函数 boundaries 接受三个参数:BW 表示输入的二值图像,conn 表示连接性(8 连通或 4 连通),dir 表示跟踪边界的方向(顺时针或逆时针)。根据不同的输入情况,函数会进行相应的处理。其中,首先根据输入参数确定连接性和跟踪方向,然后使用 bwlabel 函数标记输入二值图像中的对象,并初始化一个 cell 数组 B 用于存储边界坐标。

接着,对标记矩阵进行填充操作以简化边界跟踪过程,并定义了一些变量和查找表用于指导边界跟踪的方向。通过在图像中寻找起始位置,然后按照设定的方向依次跟踪边界像素,直到形成完整的边界闭合路径。最后,根据跟踪方向对边界路径进行修正,最终将每个对象的边界坐标存储在 cell 数组 B 中,并按照设定的方向进行排序。

需要注意的是,该代码是基于 MATLAB 的图像处理工具箱编写的,涉及到图像处理中的边界跟踪算法,主要通过对相邻像素进行搜索和遍历完成对象边界的提取。

以下是对代码的详细分析:

3.1 函数描述

函数名:boundaries

功能:跟踪二值图像中对象的边界

输入参数:

  • BW:二值图像
  • conn:连接性(8 连通或 4 连通,默认为 8 连通)
  • dir:跟踪方向(顺时针或逆时针,默认为顺时针)

输出参数:

  • B:包含所有对象边界坐标的 cell 数组

3.2 参数处理

  • 检查输入参数,确保足够数量
  • 如果参数缺失,设置默认值
  • 确定连接性和跟踪方向设置

3.3 对象标记

  • 使用 bwlabel 函数对输入的二值图像进行对象标记
  • 获取每个对象的唯一标识
  • 初始化存储边界坐标的 cell 数组 B

3.4 图像填充

  • 对标记矩阵进行填充操作,简化边界跟踪
  • 定义变量和查找表指导边界跟踪方向

3.5 边界跟踪

  • 在图像中搜索起始位置
  • 按照设定方向依次跟踪边界像素,形成闭合路径
  • 考虑边界的闭合性和连通性

3.6 边界坐标存储

  • 将每个对象的边界坐标存储在 cell 数组 B 中
  • 使用线性索引转换为行列坐标,并存储在对应的 cell 元素中

3.7 结果修正

  • 根据跟踪方向对边界路径进行修正,确保正确的边界顺序

3.8 结果输出

  • 将存储了对象边界坐标的 cell 数组 B 输出作为函数的返回结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/720894.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Mybatis学习记录

Mybatis学习记录 1.快速开始示例1.1 什么是MyMyBatis&#xff1f;1.2 代码示例 2.基本使用2.1 #{}和${} 2.2 参数传入2.2.1 概念说明2.2.2 单个简单类型2.2.3 实体类型2.2.4 零散简单数据类型2.2.5 Map类型 2.3 返回值2.3.1 单个简单类型2.3.2 实体类型2.3.3 Map类型2.3.4 List…

java 版本企业招标投标管理系统源码+功能描述+tbms+及时准确+全程电子化

功能描述 1、门户管理&#xff1a;所有用户可在门户页面查看所有的公告信息及相关的通知信息。主要板块包含&#xff1a;招标公告、非招标公告、系统通知、政策法规。 2、立项管理&#xff1a;企业用户可对需要采购的项目进行立项申请&#xff0c;并提交审批&#xff0c;查看所…

基于MVO优化的Bi-LSTM多输入回归预测(Matlab)多元宇宙算法优化长短期神经网络回归预测

目录 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 亮点与优势&#xff1a; 二、实际运行效果&#xff1a; 三、算法介绍&#xff1a; 四、完整程序下载&#xff1a; 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 本代码基于Matlab平台编译&am…

探索Java开发面试笔记:以听为目的,助力编程技术提升与面试准备

文章目录 一、制作背景介绍二、 Java开发面试笔记&#xff1a;为你的编程之路加速2.1 公众号主题和目标读者群体2.2 为什么面试笔记对于提高编程视野和技术至关重要2.3 親測效率 三、形式案例3.1 文章形式3.2 手机案例3.3 电脑案例 一、制作背景介绍 做公众号的背景&#xff1a…

【LeetCode:98. 验证二叉搜索树 + 递归】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

就业班 2401--3.1 Linux Day9--文件查找和压缩

一、文件查找与打包压缩 grep: 文件内容过滤 [rootqfedu.com ~]# grep root /etc/passwd #从/etc/passwd文件中过滤root字段 grep ^root root$ root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin 查找命令 [rootqfedu.com ~]# which ls ali…

【基于HTML5的网页设计及应用】——float实现页面布局

&#x1f383;个人专栏&#xff1a; &#x1f42c; 算法设计与分析&#xff1a;算法设计与分析_IT闫的博客-CSDN博客 &#x1f433;Java基础&#xff1a;Java基础_IT闫的博客-CSDN博客 &#x1f40b;c语言&#xff1a;c语言_IT闫的博客-CSDN博客 &#x1f41f;MySQL&#xff1a…

Java基础-运算符,表达式和语句

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 目录 一、Java 运算符 算术运算符 关系运算符 位运算符 逻辑运算符 赋值运算符 条件运算符&#xff…

游戏寻路之A*算法(GUI演示)

一、A*算法介绍 A*算法是一种路径搜索算法,用于在图形网络中找到最短路径。它结合了Dijkstra算法和启发式搜索的思想,通过综合利用已知的最短路径和估计的最短路径来优化搜索过程。在游戏自动寻路得到广泛应用。 二、A*算法的基本思想 在图形网络中选择一个起点和终点。维护…

常用的17个运维监控系统(必备知识)

1. Zabbix Zabbix 作为企业级的网络监控工具&#xff0c;通过从服务器&#xff0c;虚拟机和网络设备收集的数据提供实时监控&#xff0c;自动发现&#xff0c;映射和可扩展等功能。 Zabbix的企业级监控软件为用户提供内置的Java应用服务器监控&#xff0c;硬件监控&#xff0c…

Python web框架fastapi中间件的使用,CORS跨域详解

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 所属专栏&#xff1a;Fastapi 景天的主页&#xff1a;景天科技苑 文章目录 fastapi中间件与CORS1、中间件1.创建中间件方法2.中间件里面添加响应头…

跨地域传文件时 面临的安全、效率等问题要如何解决?

近年来&#xff0c;企业在异国、异地设立分支机构的越来越多&#xff0c;在日常经营中&#xff0c;企业总部和分支机构间存在平行、垂直及互相交叉的管理模式和业务往来需求&#xff0c;因此&#xff0c;大型企业存在必然的跨地域传文件场景&#xff0c;比如跨地理域文件交换、…

揭秘麦肯锡的方法:产品经理解决问题指南

您是否想知道世界上最成功的产品经理如何始终如一地提供不仅满足而且超出预期的解决方案&#xff1f;秘密可能就在于世界上最负盛名的咨询公司之一麦肯锡公司所磨练的方法论。本文深入探讨了麦肯锡的问题解决流程&#xff0c;该流程专为希望提升水平的产品经理量身定制。 01. 麦…

2024最新AI大模型产品汇总

文章目录 1. 写在前面2. 效率工具3. 聊天机器人4. 应用开发工具5. Prompt工具与社区6. 通用基础大模型7. 训练框架8. 开源数据集9. 推理与部署平台及工具 【作者主页】&#xff1a;吴秋霖 【作者介绍】&#xff1a;Python领域优质创作者、阿里云博客专家、华为云享专家。长期致…

Flutter整体框架

Flutter整体框架由三部分组成&#xff1a;Framework、Engine和Embedder。 Framework Framework提供了一个用 Dart 语言编写的现代、反应式框架&#xff0c;由许多抽象的层级组成。它包括一套丰富的布局、动画、绘制、手势UI组件及配套代码&#xff0c;以及更基础的异步、文件、…

李沐动手学习深度学习——4.5练习

1. 在本节的估计问题中使用λ的值进行实验。绘制训练和测试精度关于λ的函数。观察到了什么&#xff1f; 修改代码运行如图所示&#xff0c;可以发现对于lamda值的变化而言&#xff0c;对于训练loss和测试loss的影响不大。但是如果λ 太大后&#xff0c;train和test的loss会变得…

Databend 开源周报第 134 期

Databend 是一款现代云数仓。专为弹性和高效设计&#xff0c;为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务&#xff1a;https://app.databend.cn 。 Whats On In Databend 探索 Databend 本周新进展&#xff0c;遇到更贴近你心意的 Databend 。 支持多语句事务…

基于dashscope在线调用千问大模型

前言 dashscope是阿里云大模型服务平台——灵积提供的在线API组件。基于它&#xff0c;无需本地加载大模型&#xff0c;通过在线方式访问云端大模型来完成对话。 申请API key 老规矩&#xff1a;要想访问各家云端大模型&#xff0c;需要先申请API key。 对于阿里云&#x…

STM32(14)USART

USART:一种片上外设&#xff0c;用来实现串口通信&#xff0c;就是stm32内部的串口 USART简介 串并转换电路 串行通信和并行通信 串行&#xff1a;一根数据线&#xff0c;逐个比特位发送 为什么要串并转换 移位寄存器 USART的基本模型 通过查询SR&#xff08;状态寄存器&…

简介IP地址证书如何申请

IP地址证书通常包含在SSL/TLS证书中&#xff0c;根据验证级别可分为域名验证型(DV)、组织验证型(OV)。对于直接绑定IP地址的场景&#xff0c;需选择支持IP地址验证的SSL证书。 跟常见的域名证书一样&#xff0c;IP地址证书在申请过程中同样需要验证IP的所有权&#xff0c;常见的…