当前位置: 首页 > article >正文

OpenCV在图像上绘制文字示例

OpenCV计算机视觉开发实践:基于Qt C++ - 商品搜索 - 京东

OpenCV中除了提供绘制各种图形的函数外,还提供了一个特殊的绘制函数,用于在图像上绘制文字。这个函数是putText(),它是命名空间cv中的函数,其声明如下:

void cv::putText(cv::Mat& img,          // 待绘制的图像const string& text,    // 待绘制的文字cv::Point origin,      // 文本框的左下角int fontFace,          // 字体 (如cv::FONT_HERSHEY_PLAIN)double fontScale,      // 尺寸因子,值越大,文字就越大cv::Scalar color,      // 线条的颜色(RGB)int thickness = 1,     // 线条宽度int lineType = 8,      // 线型(4邻域或8邻域,默认为8邻域)bool bottomLeftOrigin = false // true='origin at lower left'
);

这个函数可以简单地在图像上绘制一些文字,由text指定的文字将在以左上角为原点的文字框中以color指定的颜色绘制出来,除非bottomLeftOrigin标志设置为真,这种情况以左下角为原点,使用的字体由fontFace参数决定。常用的字体宏是FONT_HERSHEY_SIMPLEX(普通大小无衬线字体)和FONT_HERSHEY_PLAIN(小号无衬线字体)。任何一个字体都可以和CV::FONT_ITALIC 组合使用(通过“或”操作,或操作符号是|)来得到斜体。每种字体都有一个“自然”大小,当fontScale不是1.0时,在文字绘制之前字体大小将由这个数来缩放。

这里解释一下衬线。衬线指的是字母结构笔画之外的装饰性笔画。有衬线的字体叫衬线体(Serif),没有衬线的字体叫无衬线体(Sans-Serif)。衬线体的特征是在字的笔画开始、结束的地方有额外的装饰,而且笔画的粗细会有所不同。衬线体很容易识别,它强调了每个字母笔画的开始和结束,因此易读性比较高。中文字体中的宋体就是一种标准的衬线体。无衬线体(Sans-Serif Font)没有额外的装饰,而且笔画的粗细差不多。这类字体通常是机械的和统一线条的,它们往往拥有相同的曲率、笔直的线条和锐利的转角。无衬线体与汉字字体中的黑体相对应。

另外,在实际绘制文字之前,还可以使用cv::getTextSize()接口先获取待绘制文本框的大小,以方便放置文本框。getTextSize函数可以获取字符串的宽度和高度,该函数声明如下:

Size cv::getTextSize(const string& text,cv::Point origin,int fontFace,double fontScale,int thickness,int* baseLine);

其中参数text表示输入的文本文字;fontFace表示文字字体类型;fontScale表示字体缩放系数;thickness表示字体笔画线宽;baseLine是一个输出参数,表示文字最底部的y坐标。函数返回值中包含文本框的大小。

【例4.12】绘制文字

   新建一个控制台工程,工程名是test。

   打开main.cpp,输入如下代码:

#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include<opencv2\imgproc.hpp>
using namespace std;
using namespace cv;int main()
{string text = "Funny text inside the box";// int fontFace = FONT_HERSHEY_SCRIPT_SIMPLEX;     // 手写风格字体int fontFace = FONT_HERSHEY_SCRIPT_COMPLEX;double fontScale = 2;       // 字体缩放比int thickness = 3;Mat img(600, 800, CV_8UC3, Scalar::all(0));int baseline = 0;Size textSize = getTextSize(text, fontFace, fontScale, thickness, &baseline);baseline += thickness;// center the textPoint textOrg((img.cols - textSize.width) / 2, (img.rows - textSize.height) / 2);// draw the boxrectangle(img, textOrg + Point(0, baseline), textOrg + Point(textSize.width, -textSize.height), Scalar(0, 0, 255));line(img, textOrg + Point(0, thickness), textOrg + Point(textSize.width, thickness), Scalar(0, 0, 255));putText(img, text, textOrg, fontFace, fontScale, Scalar::all(255), thickness, 8);imshow("text", img);waitKey(0);return 0;
}

在上述代码中,我们通过getTextSize函数获取包含字体的文本框的大小,并画线显示在矩形中。最后通过文本绘制函数putText画出一段字符串“Funny text inside the box”。

   保存工程并运行,结果如图4-8所示。

图4-8

下面我们通过一个比较综合的例子来实现随机画图,比如随机画线,随机画圆,随机绘制文本等。

【例4.13】综合实例:随机画图

   新建一个控制台工程,工程名是test。

   打开main.cpp,输入如下代码:

#include <opencv2/opencv.hpp>
using namespace cv;
#include<iostream>
using namespace std;
#define FALSE 0
#define TRUE 1#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <iostream>
#include <stdio.h>
using namespace cv;
const int NUMBER = 100;
const int DELAY = 5;
const int window_width = 900;
const int window_height = 600;
int x_1 = -window_width / 2;
int x_2 = window_width * 3 / 2;
int y_1 = -window_width / 2;
int y_2 = window_width * 3 / 2;
static Scalar randomColor(RNG& rng);
int Drawing_Random_Lines(Mat image, char* window_name, RNG rng);
int Drawing_Random_Rectangles(Mat image, char* window_name, RNG rng);
int Drawing_Random_Ellipses(Mat image, char* window_name, RNG rng);
int Drawing_Random_Polylines(Mat image, char* window_name, RNG rng);
int Drawing_Random_Filled_Polygons(Mat image, char* window_name, RNG rng);
int Drawing_Random_Circles(Mat image, char* window_name, RNG rng);
int Displaying_Random_Text(Mat image, char* window_name, RNG rng);
int Displaying_Big_End(Mat image, char* window_name, RNG rng);
int main(void)
{int c;char window_name[] = "Drawing_2 Tutorial";RNG rng(0xFFFFFFFF);Mat image = Mat::zeros(window_height, window_width, CV_8UC3);  // 创建一个初始化为零的矩阵imshow(window_name, image);waitKey(DELAY);// 然后我们开始随机画图c = Drawing_Random_Lines(image, window_name, rng);if (c != 0) return 0;c = Drawing_Random_Rectangles(image, window_name, rng);if (c != 0) return 0;c = Drawing_Random_Ellipses(image, window_name, rng);if (c != 0) return 0;c = Drawing_Random_Polylines(image, window_name, rng);if (c != 0) return 0;c = Drawing_Random_Filled_Polygons(image, window_name, rng);if (c != 0) return 0;c = Drawing_Random_Circles(image, window_name, rng);if (c != 0) return 0;c = Displaying_Random_Text(image, window_name, rng);if (c != 0) return 0;c = Displaying_Big_End(image, window_name, rng);if (c != 0) return 0;waitKey(0);return 0;
}
static Scalar randomColor(RNG& rng)
{int icolor = (unsigned)rng;return Scalar(icolor & 255, (icolor >> 8) & 255, (icolor >> 16) & 255);
}
int Drawing_Random_Lines(Mat image, char* window_name, RNG rng)
{Point pt1, pt2;for (int i = 0; i < NUMBER; i++){pt1.x = rng.uniform(x_1, x_2);pt1.y = rng.uniform(y_1, y_2);pt2.x = rng.uniform(x_1, x_2);pt2.y = rng.uniform(y_1, y_2);line(image, pt1, pt2, randomColor(rng), rng.uniform(1, 10), 8);imshow(window_name, image);if (waitKey(DELAY) >= 0){return -1;}}return 0;
}
int Drawing_Random_Rectangles(Mat image, char* window_name, RNG rng)
{Point pt1, pt2;int lineType = 8;int thickness = rng.uniform(-3, 10);for (int i = 0; i < NUMBER; i++){pt1.x = rng.uniform(x_1, x_2);pt1.y = rng.uniform(y_1, y_2);pt2.x = rng.uniform(x_1, x_2);pt2.y = rng.uniform(y_1, y_2);rectangle(image, pt1, pt2, randomColor(rng), MAX(thickness, -1), lineType);imshow(window_name, image);if (waitKey(DELAY) >= 0){return -1;}}return 0;
}
int Drawing_Random_Ellipses(Mat image, char* window_name, RNG rng)
{int lineType = 8;for (int i = 0; i < NUMBER; i++){Point center;center.x = rng.uniform(x_1, x_2);center.y = rng.uniform(y_1, y_2);Size axes;axes.width = rng.uniform(0, 200);axes.height = rng.uniform(0, 200);double angle = rng.uniform(0, 180);ellipse(image, center, axes, angle, angle - 100, angle + 200,randomColor(rng), rng.uniform(-1, 9), lineType);imshow(window_name, image);if (waitKey(DELAY) >= 0){return -1;}}return 0;
}
int Drawing_Random_Polylines(Mat image, char* window_name, RNG rng)
{int lineType = 8;for (int i = 0; i < NUMBER; i++){Point pt[2][3];pt[0][0].x = rng.uniform(x_1, x_2);pt[0][0].y = rng.uniform(y_1, y_2);pt[0][1].x = rng.uniform(x_1, x_2);pt[0][1].y = rng.uniform(y_1, y_2);pt[0][2].x = rng.uniform(x_1, x_2);pt[0][2].y = rng.uniform(y_1, y_2);pt[1][0].x = rng.uniform(x_1, x_2);pt[1][0].y = rng.uniform(y_1, y_2);pt[1][1].x = rng.uniform(x_1, x_2);pt[1][1].y = rng.uniform(y_1, y_2);pt[1][2].x = rng.uniform(x_1, x_2);pt[1][2].y = rng.uniform(y_1, y_2);const Point* ppt[2] = { pt[0], pt[1] };int npt[] = { 3, 3 };polylines(image, ppt, npt, 2, true, randomColor(rng), rng.uniform(1, 10), lineType);imshow(window_name, image);if (waitKey(DELAY) >= 0){return -1;}}return 0;
}
int Drawing_Random_Filled_Polygons(Mat image, char* window_name, RNG rng)
{int lineType = 8;for (int i = 0; i < NUMBER; i++){Point pt[2][3];pt[0][0].x = rng.uniform(x_1, x_2);pt[0][0].y = rng.uniform(y_1, y_2);pt[0][1].x = rng.uniform(x_1, x_2);pt[0][1].y = rng.uniform(y_1, y_2);pt[0][2].x = rng.uniform(x_1, x_2);pt[0][2].y = rng.uniform(y_1, y_2);pt[1][0].x = rng.uniform(x_1, x_2);pt[1][0].y = rng.uniform(y_1, y_2);pt[1][1].x = rng.uniform(x_1, x_2);pt[1][1].y = rng.uniform(y_1, y_2);pt[1][2].x = rng.uniform(x_1, x_2);pt[1][2].y = rng.uniform(y_1, y_2);const Point* ppt[2] = { pt[0], pt[1] };int npt[] = { 3, 3 };fillPoly(image, ppt, npt, 2, randomColor(rng), lineType);imshow(window_name, image);if (waitKey(DELAY) >= 0){return -1;}}return 0;
}
int Drawing_Random_Circles(Mat image, char* window_name, RNG rng)
{int lineType = 8;for (int i = 0; i < NUMBER; i++){Point center;center.x = rng.uniform(x_1, x_2);center.y = rng.uniform(y_1, y_2);circle(image, center, rng.uniform(0, 300), randomColor(rng),rng.uniform(-1, 9), lineType);imshow(window_name, image);if (waitKey(DELAY) >= 0){return -1;}}return 0;
}
int Displaying_Random_Text(Mat image, char* window_name, RNG rng)
{int lineType = 8;for (int i = 1; i < NUMBER; i++){Point org;org.x = rng.uniform(x_1, x_2);org.y = rng.uniform(y_1, y_2);putText(image, "Testing text rendering", org, rng.uniform(0, 8),rng.uniform(0, 100)*0.05 + 0.1, randomColor(rng), rng.uniform(1, 10), lineType);imshow(window_name, image);if (waitKey(DELAY) >= 0){return -1;}}return 0;
}
int Displaying_Big_End(Mat image, char* window_name, RNG)
{Size textsize = getTextSize("OpenCV forever!", FONT_HERSHEY_COMPLEX, 3, 5, 0);Point org((window_width - textsize.width) / 2, (window_height - textsize.height) / 2);int lineType = 8;Mat image2;for (int i = 0; i < 255; i += 2){image2 = image - Scalar::all(i);putText(image2, "OpenCV forever!", org, FONT_HERSHEY_COMPLEX, 3,Scalar(i, i, 255), 5, lineType);imshow(window_name, image2);if (waitKey(DELAY) >= 0){return -1;}}return 0;
}

从上面代码可以看到,在主函数中,要做的第一件事是创建一个随机数生成器对象:RNG rng(0xFFFFFFFF);。在本例中,RNG使用值0xFFFFFFFF来进行初始化。

然后创建一个初始化为零的矩阵image(这意味着它将显示为黑色),并指定其高度、宽度和类型。

接着开始随机画图。查看代码可以看到,这里主要是8个自定义函数。这些函数都遵循相同的模式,因此我们只分析其中几个函数,因为相同的解释适用于所有函数。比如函数Drawing_Random_Lines用来在随机坐标处画线,因此画线函数line的首尾点pt1和pt2的坐标都是随机生成的。同样地,函数Drawing_Random_Circles用来随机画圆;函数Displaying_Random_Text用来绘制文本,并且文本的位置、颜色等也是随机产生的;函数Displaying_Big_End用来绘制程序结束时所显示的文本“OpenCV forever!”。

   保存工程并运行,结果如图4-9所示。

图4-9

相关文章:

OpenCV在图像上绘制文字示例

OpenCV计算机视觉开发实践&#xff1a;基于Qt C - 商品搜索 - 京东 OpenCV中除了提供绘制各种图形的函数外&#xff0c;还提供了一个特殊的绘制函数&#xff0c;用于在图像上绘制文字。这个函数是putText()&#xff0c;它是命名空间cv中的函数&#xff0c;其声明如下&#xff…...

Java 抗量子算法:构建后量子时代的安全基石

一、量子计算带来的加密挑战 在传统加密体系中&#xff0c;RSA、ECC 等公钥算法依赖大数分解和离散对数问题的难解性。然而&#xff0c;量子计算机的 Shor 算法可在多项式时间内破解这些算法&#xff0c;使现有加密体系面临颠覆性威胁。例如&#xff0c;2048 位 RSA 密钥的破解…...

Kubernetes 集群到 Jumpserver

以下是使用 ServiceAccount Token&#xff08;令牌&#xff09; 连接 Kubernetes 集群到 Jumpserver 的 详细分步指南&#xff0c;包括权限配置、Token 获取和常见问题排查。 1. 创建 ServiceAccount 并分配权限 1.1 创建 ServiceAccount 在 Kubernetes 集群中创建一个专用于…...

Android7 Input(十)View 处理Input事件pipeline

概述: 本文主要描述View对InputEvent事件pipeline处理过程。 本文涉及的源码路径 frameworks/base/core/java/android/view/ViewRootImpl.java InputEvent事件处理 View处理input事件是调用doProcessInputEvents方法&#xff0c;如下所示: void doProcessInputEvents() {//…...

图像数据如何表示为概率单纯形

目录 图像数据灰度图像彩色图像概率单纯形条件应用场景 图像数据 图像数据通常由像素值组成&#xff0c;这些像素值可以是灰度值&#xff08;对于黑白图像&#xff09;或RGB值&#xff08;对于彩色图像&#xff09;。每个像素的值通常在0到255之间。为了将图像数据表示为概率单…...

(11)Service Mesh架构下Java应用实现零信任安全模型

Service Mesh架构下Java应用实现零信任安全模型 📌 TL;DR: 本文详细介绍如何在Service Mesh架构中实现零信任安全模型,包括身份认证、授权控制、加密通信和持续监控四大核心技术,以及与Istio、Envoy等组件的集成方案。 目录 零信任安全模型概述关键技术实现最佳实践Service…...

什么是内网映射?如何将内网ip映射到外网访问?

随着互联网科技和信息技术的快速发展&#xff0c;很多原理及技术开始被应用到互联网信息科技领域&#xff0c;其中内网iP映射就成为非常普通常见的一个操作。那么什么是内网ip映射&#xff1f;如何将内网ip映射到外网&#xff1f; 一、什么是内网ip映射&#xff1f; 简单理解…...

为什么要选择VR看房?VR看房有什么优点?

VR看房&#xff1a;革新传统&#xff0c;重塑体验 在当今社会&#xff0c;虚拟现实&#xff08;VR&#xff09;技术正以前所未有的速度渗透到我们生活的各个领域&#xff0c;其中VR看房作为房地产领域的重要创新。本文将讨论为什么要选择VR看房以及VR看房的主要优点&#xff0…...

linux 串口调试命令 stty

linux 串口调试命令 stty 文章目录 linux 串口调试命令 sttystty 常见命令选项&#xff1a;常用参数&#xff1a;一次性设置串口所有常见参数总结 stty&#xff08;设置终端行模式&#xff09;命令是用来配置终端设备&#xff08;包括串口设备&#xff09;的输入和输出行为的工…...

C++STL-vector的使用

vector的定义方式 方式1&#xff1a;构造某一个类型的空容器 vector<int> v1;//构造一个int类型的空容器 方式2&#xff1a;构造一个含有n个val的某类型容器 vector<int> v2(10, 2);//构造一个含有10个2的int类型的容器 方式3&#xff1a;拷贝构造某类型容器 …...

图简记。。

模仿&#xff1a; algorithm-journey/src/class059/Code01_CreateGraph.java at main algorithmzuo/algorithm-journey Code01_CreateGraph C语言&#xff1a; #include <stdio.h> #include <stdlib.h> #include <string.h>#define MAXN 11 #define MAX…...

pytorch基本运算-范数

引言 前序学习进程中&#xff0c;已经对pytorch基本运算有了详细探索&#xff0c;文章链接有&#xff1a; 基本运算 广播失效 乘除法和幂运算 hadamard积、点积和矩阵乘法 上述计算都是以pytorch张量为运算元素&#xff0c;这些张量基本上也集中在一维向量和二维矩阵&#x…...

uefi协议设计目的

在EDK2的术语体系中&#xff0c;GUID定义的是协议的标识符&#xff0c;而具体实现的函数集合称为协议的实现。它们是同一协议的不同抽象层次&#xff0c;以下是详细解释&#xff1a; 1. 协议&#xff08;Protocol&#xff09;的两层含义 (1) 协议规范&#xff08;接口定义&am…...

springcloud openfeign 偶现 Caused by: java.net.UnknownHostException

背景 最近查看日志发现某服务偶现Caused by: java.net.UnknownHostException 同时查看eureka的access.log 出现如下异常 10.xxx.xxx.xxx - - [27/May/2025:23:57:29 0800] “PUT /eureka/apps/{appName}/{host}:xxx-job:8082?statusUP&lastDirtyTimestamp1748351637173 H…...

Transformer实战——词嵌入技术详解

Transformer实战——词嵌入技术详解 0. 前言1. 词嵌入基础2. 分布式表示3. 静态嵌入3.1 Word2Vec3.2 GloVe 4. 使用 Gensim 构建词嵌入5. 使用 Gensim 探索嵌入空间6. 动态嵌入小结系列链接 0. 前言 在本节中&#xff0c;我们首先介绍词嵌入的概念&#xff0c;然后介绍两种实现…...

[pdf、epub]300道《软件方法》强化自测题业务建模需求分析共257页(202505更新)

DDD领域驱动设计批评文集 做强化自测题获得“软件方法建模师”称号 《软件方法》各章合集 在本账号CSDN资源下载&#xff0c;或者访问链接&#xff1a; http://www.umlchina.com/url/quizad.html 如果需要提取码&#xff1a;umlc 文件夹中的“300道软件方法强化自测题2025…...

Vue3入门指南:从零到精通的快速上手

齐爷学vue3 一、Vue3入门 vite&#xff1a;前端构架工具&#xff0c;构建速度快于webpack。轻量快速、对TS&#xff0c;JSX&#xff0c;CSS开箱即用、按需编译。 创建Vue3工程 1.在想要创建Vue3的位置打开cmd&#xff0c;执行如下命令。 npm create vuelatest 2.功能只选择…...

前端常见错误

1. TypeError: Cannot read property xxx of undefined 错误原因&#xff1a;尝试访问一个 undefined 或 null 对象的属性 / 方法。 示例代码&#xff1a; const user { name: "John" }; console.log(user.address.street); // user.address 为 undefined 解决方…...

吴恩达MCP课程(5):mcp_chatbot_prompt_resource.py

前提条件&#xff1a; 1、吴恩达MCP课程&#xff08;5&#xff09;&#xff1a;research_server_prompt_resource.py 2、server_config_prompt_resource.json文件 {"mcpServers": {"filesystem": {"command": "npx","args"…...

关于DDOS

DDOS是一门没什么技术含量的东西&#xff0c;其本质而言是通过大量数据报文&#xff0c;发送到目标受害主机IP地址上&#xff0c;导致目标主机无法继续服务&#xff08;俗称&#xff1a;拒绝服务&#xff09; DDOS灰产人期望达成的预期目标&#xff0c;几乎都是只要把对面打到 …...

云服务器自带的防御可靠吗

最近有不少朋友问我&#xff0c;云服务器自带的防御靠不靠谱。就拿大厂的云服务器来说&#xff0c;很多都自带5G防御。但这5G防御能力&#xff0c;在如今的网络攻击环境下&#xff0c;真的有些不够看。 如今&#xff0c;网络攻击手段层出不穷&#xff0c;攻击流量更是越来越大。…...

Java详解LeetCode 热题 100(27):LeetCode 21. 合并两个有序链表(Merge Two Sorted Lists)详解

文章目录 1. 题目描述1.1 链表节点定义 2. 理解题目2.1 问题可视化2.2 核心挑战 3. 解法一&#xff1a;迭代法&#xff08;哨兵节点&#xff09;3.1 算法思路3.2 Java代码实现3.3 详细执行过程演示3.4 执行结果示例3.5 复杂度分析3.6 优缺点分析 4. 解法二&#xff1a;递归法4.…...

设计模式——抽象工厂设计模式(创建型)

摘要 抽象工厂设计模式是一种创建型设计模式&#xff0c;旨在提供一个接口&#xff0c;用于创建一系列相关或依赖的对象&#xff0c;无需指定具体类。它通过抽象工厂、具体工厂、抽象产品和具体产品等组件构建&#xff0c;相比工厂方法模式&#xff0c;能创建一个产品族。该模…...

基于LocalAI与cpolar技术协同的本地化AI模型部署与远程访问方案解析

文章目录 前言1. Docker部署2. 简单使用演示3. 安装cpolar内网穿透4. 配置公网地址5. 配置固定公网地址前言 各位极客朋友们!今天要向大家推荐一套创新性的本地部署方案——LocalAI技术架构。这款开源工具包能够将普通配置的笔记本电脑转化为具备强大算力的AI工作站,轻松实现…...

Linux 云服务器部署 Flask 项目(含后台运行与 systemd 开机自启)

一、准备工作 在开始正式部署之前,请确认以下前提条件已经准备好: 你有一台运行 Linux 系统(CentOS 或 Ubuntu)的服务器; 服务器有公网 IP,本例中使用:111.229.204.102; 你拥有该服务器的管理员权限(可以使用 sudo); 打算使用 Flask 构建一个简单的 Web 接口; 服务…...

霍尔效应传感器的革新突破:铟化铟晶体与结构演进驱动汽车点火系统升级

一、半导体材料革新&#xff1a;铟化铟晶体的电压放大机制 铟化铟&#xff08;InSb&#xff09;晶体因其独特的能带结构&#xff0c;成为提升霍尔电压的关键材料。相较于传统硅基材料&#xff0c;其载流子迁移率高出3-5倍&#xff0c;在相同磁场强度下可显著放大霍尔电压。其作…...

无法运用pytorch环境、改环境路径、隔离环境

一.未建虚拟环境时 1.创建新项目后&#xff0c;直接运行是这样的。 2.设置中Virtualenv找不到pytorch环境&#xff1f;因为此时没有创建新虚拟环境。 3.选择conda环境&#xff08;全局环境&#xff09;时&#xff0c;是可以下载环境的。 运行结果如下&#xff1a; 是全局环境…...

从0开始学vue:pnpm怎么安装

一、什么是 pnpm&#xff1f; pnpm&#xff08;Performant npm&#xff09;是新一代 JavaScript 包管理器&#xff0c;优势包括&#xff1a; 节省磁盘空间&#xff1a;通过硬链接和符号链接实现高效存储安装速度更快&#xff1a;比 npm/yarn 快 2-3 倍内置工作区支持&#xf…...

React从基础入门到高级实战:React 实战项目 - 项目二:电商平台前端

React 实战项目&#xff1a;电商平台前端 欢迎来到本 React 开发教程专栏的第 27 篇&#xff01;在前 26 篇文章中&#xff0c;我们从 React 的基础概念逐步深入到高级技巧&#xff0c;涵盖了组件、状态、路由、性能优化和设计模式等核心知识。这一次&#xff0c;我们将通过一…...

Python 网络编程 -- WebSocket编程

作者主要是为了用python构建实时网络通信程序。 概念性的东西越简单越好理解,因此,下面我从晚上摘抄的概念 我的理解。 什么是网络通信? 更确切地说&#xff0c;网络通信是两台计算机上的两个进程之间的通信。比如&#xff0c;浏览器进程和新浪服务器上的某个Web服务进程在通…...