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

Matlab/C++源码实现RGB通道与HSV通道的转换(效果对比Halcon)

HSV通道的含义

HSV通道是指图像处理中的一种颜色模型,它由色调(Hue)、饱和度(Saturation)和明度(Value)三个通道组成。色调表示颜色的种类,饱和度表示颜色的纯度或鲜艳程度,明度表示颜色的亮度。HSV通道常用于图像处理中的颜色分析、颜色过滤、颜色调整等任务,它相对于其他颜色模型具有更直观和易于调节的特点,因此被广泛应用于计算机视觉和图像处理的领域。

Halcon算子例程

read_image (Image, 'D:/lena.jpg')
decompose3 (Image, ImageR, ImageG, ImageB)
trans_from_rgb (ImageR, ImageG, ImageB, ImageH, ImageS, ImageV, 'hsv')
trans_to_rgb (ImageH, ImageS, ImageV, ImageR1, ImageG1, ImageB1, 'hsv')
compose3 (ImageR1, ImageG1, ImageB1, MultiChannelImage)

这里先将三通道RGB三通道拆开成单独的通道,再将RGB与HSV通道互相转换,最后将三通道图像合并成RGB图像。
Halcon的图像效果是:
在这里插入图片描述

源代码实现

RGB转成HSV

在这里插入图片描述

这里需要注意的是,halcon这里将HSV三通道的取值范围作了说明,H通道的数值范围是0到2*pi,S通道的数值范围是0到1,V通道的数值范围是0到1。而常用的图像为BYTE字节型,数值范围是0到255,这里对公式做了修改,使Matlab得出的图像数据范围是0到255,可以直接显示,这里可以从matlab的workspace中看到计算过程。
以下便是使用Matlab实现trans_from_rgb的效果

trans_from_rgb (ImageR, ImageG, ImageB, ImageH, ImageS, ImageV, 'hsv')
Matlab源码
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%代码--RGB通道转HSV通道
%时间:2023.9
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clc;
image=imread('D:\lena.jpg');
[height,width,channels]=size(image);
figure;
imshow(image);
title('rgb-image');
image_R=image(:,:,1);
image_R=double(image_R);
image_G=image(:,:,2);
image_G=double(image_G);
image_B=image(:,:,3);
image_B=double(image_B);%%%转化成HSV通道
H_image = zeros(height,width);
S_image = zeros(height,width);
V_image = zeros(height,width);%%RGB转成HSV
for i=1:1:heightfor j=1:1:width%%%计算三通道的最大最小值计算image_matrix = [image_R(i,j), image_G(i,j), image_B(i,j)];maxValue = max(image_matrix);minValue = min(image_matrix);V_image(i,j) = maxValue;if(maxValue == minValue)S_image(i,j) = 0;H_image(i,j) = 0;else%%%计算饱和度S_image(i,j) = (maxValue - minValue)*255/minValue;%%%计算H通道if(maxValue == image_R(i,j))H_image(i,j) = 42.5.*(image_G(i,j) - image_B(i,j))./(maxValue - minValue);elseif(maxValue == image_G(i,j))H_image(i,j) = 42.5 * (2 + (image_B(i,j) - image_R(i,j)) / (maxValue - minValue));elseif(maxValue == image_B(i,j)) H_image(i,j) = 42.5 * (4 + (image_R(i,j) - image_G(i,j)) / (maxValue - minValue));endendend
end%%%RGB要取整
H_image = uint8(H_image);
S_image = uint8(S_image);
V_image = uint8(V_image);figure;
imshow(H_image);
title('H_image');figure;
imshow(S_image);
title('S_image');figure;
imshow(V_image);
title('V_image');

最终实现的效果是:
在这里插入图片描述
最终验证的效果与halcon效果一致;

同时,以上代码采用C++实现的话如下所示,这里为了保证精度,输出结果采用的是double类型,但是范围也是0到255之间,要显示的话,需要转化为unsigned char类型:

C++源码
//将RGB图像转化成HSV图像
/*
输入:  rData : r通道图像gData : g通道图像bData : b通道图像
输出:  hDoubleData : h通道图像, h通道采用double类型,保留精度sDoubleData : s通道图像,s通道采用double类型,保留精度vDoubleData : v通道图像,v通道采用double类型,保留精度
*/
void trans_from_rgb(unsigned char *rData, unsigned char *gData, unsigned char *bData, double *hDoubleData, double *sDoubleData, double *vDoubleData, int height, int width)
{if ((height <= 0) || (width <= 0))return;//在函数外部分配好内存空间if (rData == NULL || gData == NULL || bData == NULL || hDoubleData == NULL || sDoubleData == NULL || vDoubleData == NULL)return;int i;unsigned char minValue,maxValue;for (i = 0; i < width * height; i++){//V通道数据,三通道的最大值maxValue = std::max(std::max(rData[i], gData[i]), bData[i]);minValue = std::min(std::min(rData[i], gData[i]), bData[i]);vDoubleData[i] = maxValue;if (maxValue == minValue){sDoubleData[i] = 0;hDoubleData[i] = 0;}else{//S通道sDoubleData[i] = (maxValue - minValue)*255.0 / maxValue;//H通道if (maxValue == rData[i])hDoubleData[i] = 42.5 * (gData[i] - bData[i]) / (maxValue - minValue);    else if (maxValue == gData[i])hDoubleData[i] = 42.5 * (2 + (bData[i] - rData[i]) / (maxValue - minValue));else if (maxValue == bData[i])hDoubleData[i] = 42.5 * (4 + (rData[i] - gData[i]) / (maxValue - minValue));}}
}
HSV转成RGB

halcon给出的公式说明为:
在这里插入图片描述

Matlab源码

同样的,采用Matlab实现:

%%%%%%%%%%%%%%%%%%%%%%%%%%%
%代码--HSV通道转RGB通道
%时间:2023.9
%%%%%%%%%%%%%%%%%%%%%%%%%%%%
clc;
image1=imread('D:\lena.jpg');
[height,width,channels]=size(image1);
image_H=double(image1);
image2=imread('E:\S_image.bmp');
image_S=double(image2);
image3=imread('E:\V_image.bmp');
image_V=double(image3);%%%转化成RGB通道
R_image = zeros(height,width);
G_image = zeros(height,width);
B_image = zeros(height,width);%%%HSV转成RGB
for i=1:1:heightfor j=1:1:widthif(image_S(i,j) == 0)R_image(i,j) = image_V(i,j);G_image(i,j) = image_V(i,j);B_image(i,j) = image_V(i,j);else%%Hi = floor(image_H(i,j)*2*pi/255/deg2rad(60));    %%归一化到02*piHi = floor(image_H(i,j)*0.025);Hf = image_H(i,j)*0.025 - Hi;%%%%根据H的值,将C,X,m分别对应到RGB三个分量上if(Hi == 0)R_image(i,j) = image_V(i,j);G_image(i,j) = image_V(i,j) * (1 - image_S(i,j)/255*(1-Hf));B_image(i,j) = image_V(i,j) * (1 - image_S(i,j)/255);elseif(Hi == 1)R_image(i,j) = image_V(i,j) * (1 - image_S(i,j)/255*Hf);G_image(i,j) = image_V(i,j);B_image(i,j) = image_V(i,j) * (1 - image_S(i,j)/255);elseif(Hi == 2)R_image(i,j) = image_V(i,j) * (1 - image_S(i,j)/255);G_image(i,j) = image_V(i,j);B_image(i,j) = image_V(i,j) * (1 - image_S(i,j)/255*(1-Hf));elseif(Hi == 3)R_image(i,j) = image_V(i,j) * (1 - image_S(i,j)/255);G_image(i,j) = image_V(i,j) * (1 - image_S(i,j)/255*Hf);B_image(i,j) = image_V(i,j);elseif(Hi == 4)R_image(i,j) = image_V(i,j) * (1 - image_S(i,j)/255*(1-Hf));G_image(i,j) = image_V(i,j) * (1 - image_S(i,j)/255);B_image(i,j) = image_V(i,j);elseif(Hi == 5)R_image(i,j) = image_V(i,j);G_image(i,j) = image_V(i,j) * (1 - image_S(i,j)/255);B_image(i,j) = image_V(i,j) * (1 - image_S(i,j)/255*Hf);endendend
end%%%RGB要取整
R_image = uint8(R_image);
G_image = uint8(G_image);
B_image = uint8(B_image);figure;
imshow(R_image);
title('R_image');figure;
imshow(G_image);
title('G_image');figure;
imshow(B_image);
title('B_image');

最终实现的效果是:
在这里插入图片描述
可以看出,与Halcon效果一致;

C++源码

同样的,采用C++实现:

//将HSV图像转化成RGB图像
/*
输入:  hDoubleData : h通道图像 ,h通道采用double类型,保留精度sDoubleData : s通道图像 ,s通道采用double类型,保留精度vDoubleData : v通道图像 ,v通道采用double类型,保留精度
输出:  rDoubleData : r通道图像 ,r通道采用double类型,保留精度gDoubleData : g通道图像 ,g通道采用double类型,保留精度bDoubleData : b通道图像 ,b通道采用double类型,保留精度
*/
void trans_to_rgb(double *hDoubleData, double *sDoubleData, double *vDoubleData, double *rDoubleData, double *gDoubleData, double *bDoubleData, int height, int width)
{if ((height <= 0) || (width <= 0))return;if (rDoubleData == NULL || gDoubleData == NULL || bDoubleData == NULL || hDoubleData == NULL || sDoubleData == NULL || vDoubleData == NULL)return;int i;double Hi, Hf;for (i = 0; i < width * height; i++){if (sDoubleData[i] > 0){Hi = floor(hDoubleData[i] * 0.025);Hf = hDoubleData[i] * 0.025 - Hi;if (Hi == 0){rDoubleData[i] = vDoubleData[i];gDoubleData[i] = vDoubleData[i] * (1 - sDoubleData[i] / 255.0*(1 - Hf));bDoubleData[i] = vDoubleData[i] * (1 - sDoubleData[i] / 255.0);}else if (Hi == 1){rDoubleData[i] = vDoubleData[i] * (1 - sDoubleData[i] / 255.0 * Hf);gDoubleData[i] = vDoubleData[i];bDoubleData[i] = vDoubleData[i] * (1 - sDoubleData[i] / 255.0);}else if (Hi == 2){rDoubleData[i] = vDoubleData[i] * (1 - sDoubleData[i] / 255.0);gDoubleData[i] = vDoubleData[i];bDoubleData[i] = vDoubleData[i] * (1 - sDoubleData[i] / 255.0*(1 - Hf));}else if (Hi == 3){rDoubleData[i] = vDoubleData[i] * (1 - sDoubleData[i] / 255.0);gDoubleData[i] = vDoubleData[i] * (1 - sDoubleData[i] / 255.0 * Hf);bDoubleData[i] = vDoubleData[i];}else if (Hi == 4){rDoubleData[i] = vDoubleData[i] * (1 - sDoubleData[i] / 255.0*(1 - Hf));gDoubleData[i] = vDoubleData[i] * (1 - sDoubleData[i] / 255.0);bDoubleData[i] = vDoubleData[i];}else if (Hi == 5){rDoubleData[i] = vDoubleData[i];gDoubleData[i] = vDoubleData[i] * (1 - sDoubleData[i] / 255.0);bDoubleData[i] = vDoubleData[i] * (1 - sDoubleData[i] / 255.0 * Hf);}}else{rDoubleData[i] = gDoubleData[i] = bDoubleData[i] = vDoubleData[i];}}
}

通道拆分与合并C++源代码实现

三通道拆分

Halcon中,拆分三通道的算子为:

decompose3 (Image, ImageR, ImageG, ImageB)

对应的拆分三通道图像的C++函数为:

//拆分三通道图像
/*
输入:  srcData : 三通道图像,内存排列方式是BGRBGRBGR......
输出:  rData : r通道图像gData : g通道图像bData : b通道图像
*/
void decompose3(unsigned char *srcData, unsigned char *rData, unsigned char *gData, unsigned char *bData, int height, int width)
{if ((height <= 0) || (width <= 0))return;if (srcData == NULL || rData == NULL || gData == NULL || bData == NULL)return;int i;
#pragma omp parallel for num_threads(3)for (i = 0; i < width * height; i++){bData[i] = srcData[3 * i];gData[i] = srcData[3 * i + 1];rData[i] = srcData[3 * i + 2];}
}

三通道合并

Halcon中,拆分三通道的算子为:

compose3 (ImageR1, ImageG1, ImageB1, MultiChannelImage)

对应的合并三通道图像的C++函数为:

//合并三通道图像
/*
输入:  rData : r通道图像gData : g通道图像bData : b通道图像
输出:  bgrData:彩色图像,合并成BGRBGR.....排列
*/
void compose3(unsigned char *rData, unsigned char *gData, unsigned char *bData, unsigned char *bgrData, int height, int width)
{if ((height <= 0) || (width <= 0))return;if (bgrData == NULL || rData == NULL || gData == NULL || bData == NULL)return;int i;
#pragma omp parallel for num_threads(3)for (i = 0; i < width * height; i++){bgrData[3 * i] = bData[i];bgrData[3 * i + 1] = gData[i];bgrData[3 * i + 2] = rData[i];}
}

相关文章:

Matlab/C++源码实现RGB通道与HSV通道的转换(效果对比Halcon)

HSV通道的含义 HSV通道是指图像处理中的一种颜色模型&#xff0c;它由色调&#xff08;Hue&#xff09;、饱和度&#xff08;Saturation&#xff09;和明度&#xff08;Value&#xff09;三个通道组成。色调表示颜色的种类&#xff0c;饱和度表示颜色的纯度或鲜艳程度&#xf…...

【C进阶】动态内存管理

一、为什么存在动态内存分配 我们之前学的都是开辟固定大小的空间&#xff0c;但有时候需要空间的大小只有在程序运行时才能知道&#xff0c;那么就引入了动态内存开辟 内存分布所在&#xff1a; 二、动态内存函数的介绍 2.1malloc和free 动态内存开辟的函数 void * malloc…...

神经网络的梯度优化方法

神经网络的梯度优化是深度学习中至关重要的一部分&#xff0c;它有助于训练神经网络以拟合数据。下面将介绍几种常见的梯度优化方法&#xff0c;包括它们的特点、优缺点以及原理。 梯度下降法 (Gradient Descent): 特点: 梯度下降是最基本的优化算法&#xff0c;它试图通过迭代…...

linux 装机教程(自用备忘)

文章目录 安装 pyenv 管理多版本 python 环境安装使用使用 pyenv 和 virtualenv 管理虚拟 python 环境 vscode 连接远程服务器tmux 美化zsh 安装 pyenv 管理多版本 python 环境 安装 &#xff08;教程参考&#xff1a;https://www.modb.pro/db/155036&#xff09; sudo apt-…...

Tensorboard安装及简单使用

Tensorboard 1. tensorboard 简单介绍2. 安装必备环境3. Tensorboard安装4. 可视化命令 1. tensorboard 简单介绍 TensorBoard是一个可视化的模块&#xff0c;该模块功能强大&#xff0c;可用于深度学习网络模型训练查看模型结构和训练效果&#xff08;预测结果、网络模型结构…...

SpringCloud 微服务全栈体系(二)

第三章 Eureka 注册中心 假如我们的服务提供者 user-service 部署了多个实例&#xff0c;如图&#xff1a; 思考几个问题&#xff1a; order-service 在发起远程调用的时候&#xff0c;该如何得知 user-service 实例的 ip 地址和端口&#xff1f;有多个 user-service 实例地址…...

flutter 常用组件:列表ListView

文章目录 总结#1、通过构造方法直接构建 ListView 提供了一个默认构造函数 ListView,我们可以通过设置它的 children 参数,很方便地将所有的子 Widget 包含到 ListView 中。 不过,这种创建方式要求提前将所有子 Widget 一次性创建好,而不是等到它们真正在屏幕上需要显示时才…...

十四天学会C++之第七天:STL(标准模板库)

1. STL容器 什么是STL容器&#xff0c;为什么使用它们。向量&#xff08;vector&#xff09;&#xff1a;使用向量存储数据。列表&#xff08;list&#xff09;&#xff1a;使用列表实现双向链表。映射&#xff08;map&#xff09;&#xff1a;使用映射实现键值对存储。 什么…...

Linux 下安装 miniconda,管理 Python 多环境

安装 miniconda 1、下载安装包 Miniconda3-py37_22.11.1-1-Linux-x86_64.sh&#xff0c;或者自行选择版本 2、把安装包上传到服务器上&#xff0c;这里放在 /home/software 3、安装 bash Miniconda3-py37_22.11.1-1-Linux-x86_64.sh 4、按回车 Welcome to Miniconda3 py37…...

Django和jQuery,实现Ajax表格数据分页展示

1.需求描述 当存在重新请求接口才能返回数据的功能时&#xff0c;若页面的内容很长&#xff0c;每次点击一个功能&#xff0c;页面又回到了顶部&#xff0c;对于用户的体验感不太友好&#xff0c;我们希望当用户点击这类的功能时&#xff0c;能直接加载到数据&#xff0c;请求…...

k8s认证

1. 证书介绍 服务端保留公钥和私钥&#xff0c;客户端使用root CA认证服务端的公钥 一共有多少证书&#xff1a; *Etcd&#xff1a; Etcd对外提供服务&#xff0c;要有一套etcd server证书Etcd各节点之间进行通信&#xff0c;要有一套etcd peer证书Kube-APIserver访问Etcd&a…...

基于python开发的IP修改工具

工作中调试设备需要经常修改电脑IP&#xff0c;非常麻烦&#xff0c;这里使用Pythontkinter做了一个IP修改工具 说明: 1.启动程序读取config.json文件2.如果没有该文件则创建&#xff0c;写入当前网卡信息3.通过配置信息进行网卡状态修改4.更新文件状态&#xff0c;删除或修…...

Mybatis源码分析

1. Mybatis整体三层设计 SSM中&#xff0c;Spring、SpringMVC已经在前面文章源码分析总结过了&#xff0c;Mybatis源码相对Spring和SpringMVC而言是的简单的&#xff0c;只有一个项目&#xff0c;项目下分了很多包。从宏观上了解Mybatis的整体框架分为三层&#xff0c;分别是基…...

python树结构包treelib入门及其计算应用

树是计算机科学中重要的数据结构。例如决策树等机器学习算法设计、文件系统索引等。创建treelib包是为了在Python中提供树数据结构的有效实现。 Treelib的主要特点包括&#xff1a; 节点搜索的高效操作。支持常见的树操作&#xff0c;如遍历、插入、删除、节点移动、浅/深复制…...

Rust之自动化测试(三): 测试组合

开发环境 Windows 10Rust 1.73.0 VS Code 1.83.1 项目工程 这里继续沿用上次工程rust-demo 测试组合 正如本章开始时提到的&#xff0c;测试是一个复杂的学科&#xff0c;不同的人使用不同的术语和组织。Rust社区根据两个主要类别来考虑测试:单元测试和集成测试。单元测试很…...

专业管理菜单的增删改、查重

1&#xff0c;点击专业管理菜单------查询所有专业信息列表 ①点击菜单&#xff0c;切换专业组件 ②切换到列表组件后&#xff0c;向后端发送请求到Servlet ③调用DAO层&#xff0c;查询数据库&#xff08;sql&#xff09;&#xff0c;封装查询到的内容 ④从后端向前端做出…...

vue3插件开发,上传npm

创建插件 在vue3工程下&#xff0c;创建组件vue页: toolset.vue。并设置组件名称。注册全局组件。新建index.js文件。内容如下&#xff0c;可在main.js中引入index.js&#xff0c;注册该组件进行测试。![在这里插入图片描述](https://img-blog.csdnimg.cn/a3409d2cbeec41c797d5…...

python【多线程、单线程、异步编程】三个版本--在爬虫中的应用

并发编程在爬虫中的应用 之前的课程&#xff0c;我们已经为大家介绍了 Python 中的多线程、多进程和异步编程&#xff0c;通过这三种手段&#xff0c;我们可以实现并发或并行编程&#xff0c;这一方面可以加速代码的执行&#xff0c;另一方面也可以带来更好的用户体验。爬虫程…...

大模型LLM相关面试题整理-位置编码-tokenizer-激活函数-layernorm

10 LLMs 位置编码篇 10.1.1 什么是位置编码&#xff1f; 位置编码是一种用于在序列数据中为每个位置添加位置信息的技术。在自然语言处理中&#xff0c;位置编码通常用于处理文本序列。由于传统的神经网络无法直接捕捉输入序列中的位置信息&#xff0c;位置编码的引入可以帮助…...

python在nacos注册微服务

安装 首先需要安装python的nacos sdk pip install nacos-sdk-python 注册 注册过程非常简单&#xff0c;需要注意的是&#xff0c;注册完要定时发送心跳&#xff0c;否则服务会被nacos删掉。 import nacos import timeSERVER_ADDRESSES "http://1.2.3.4:8848" …...

PHP和Node.js哪个更爽?

先说结论&#xff0c;rust完胜。 php&#xff1a;laravel&#xff0c;swoole&#xff0c;webman&#xff0c;最开始在苏宁的时候写了几年php&#xff0c;当时觉得php真的是世界上最好的语言&#xff0c;因为当初活在舒适圈里&#xff0c;不愿意跳出来&#xff0c;就好比当初活在…...

centos 7 部署awstats 网站访问检测

一、基础环境准备&#xff08;两种安装方式都要做&#xff09; bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats&#xff0…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

蓝桥杯 2024 15届国赛 A组 儿童节快乐

P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡&#xff0c;轻快的音乐在耳边持续回荡&#xff0c;小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下&#xff0c;六一来了。 今天是六一儿童节&#xff0c;小蓝老师为了让大家在节…...

Python爬虫(一):爬虫伪装

一、网站防爬机制概述 在当今互联网环境中&#xff0c;具有一定规模或盈利性质的网站几乎都实施了各种防爬措施。这些措施主要分为两大类&#xff1a; 身份验证机制&#xff1a;直接将未经授权的爬虫阻挡在外反爬技术体系&#xff1a;通过各种技术手段增加爬虫获取数据的难度…...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

自然语言处理——Transformer

自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效&#xff0c;它能挖掘数据中的时序信息以及语义信息&#xff0c;但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN&#xff0c;但是…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作

一、上下文切换 即使单核CPU也可以进行多线程执行代码&#xff0c;CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短&#xff0c;所以CPU会不断地切换线程执行&#xff0c;从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

佰力博科技与您探讨热释电测量的几种方法

热释电的测量主要涉及热释电系数的测定&#xff0c;这是表征热释电材料性能的重要参数。热释电系数的测量方法主要包括静态法、动态法和积分电荷法。其中&#xff0c;积分电荷法最为常用&#xff0c;其原理是通过测量在电容器上积累的热释电电荷&#xff0c;从而确定热释电系数…...

JVM 内存结构 详解

内存结构 运行时数据区&#xff1a; Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器&#xff1a; ​ 线程私有&#xff0c;程序控制流的指示器&#xff0c;分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 ​ 每个线程都有一个程序计数…...