【转】CT图像重构方法详解——傅里叶逆变换法、直接反投影法、滤波反投影法

转自:​​​​​​CT图像重构方法详解——傅里叶逆变换法、直接反投影法、滤波反投影法_Absolute Zero-CSDN博客_反投影法

      在做CT图像处理的时候遇到很多问题,对于滤波反变换有许多细节存在疑问,经过多天查找资料和利用MATLAB程序一步步实现后终于豁然开朗,于是想要总结成文,作为笔记方便今后查看。文中若有错误欢迎指出!

目 录

(1)傅里叶逆变换法

(2)直接反投影法

(3)滤波反投影法

(4)MATLAB程序


      CT图像的形成和重构,在数学上的描述分别为拉冬变换拉冬反变换(RANDON:氡)。简单点说,拉动变换是用于描述通过X射线扫描物体形成CT图像这个过程的一种数学表示,而拉东反变换描述的则是对CT投影数据进行重构,还原成物体图像的一种数学方法。本文章主要讲的是CT图像重构的方法,也就是拉东反变换的具体实现方法,当然可能也有小伙伴想了解一下什么是拉东变换,这里贴上传送门:拉冬变换。(Radon(拉冬)变换可以用来进行直线识别的算法。它是一种原始灰度图像到(p,o)二维矩阵的映射,映射关系是灰度图像的像素值对参数(p,o)的直线的线积分,或者叫投影,可理解为垂直于这个直线方向的像素值累计求和)

其中拉冬反变换在数学上的表达式如下:

由公式可看出拉冬逆变换在数学上实际上是一个二维傅里叶逆变换,但由于二维傅里叶逆变换计算量大,耗时长,因此计算机对于拉冬逆变换的具体实现方法主要为反投影法,反投影法又分为直接反投影法和滤波反投影法。由此可见CT重构方法主要为以下三种:

(1)傅里叶逆变换法

(2)直接反投影法

(3)滤波反投影法

下面将具体对这三种图像重构方法进行解释。


(1)傅里叶逆变换法

该方法基于一个重要的定理:中心切片定理。

该定理简单地理解就是:通过角度为θ扫描得到的投影,该投影的一维傅里叶变换,与对整个图像二维傅里叶变换后,二维频域中对应θ角度的一个切片信号是相同的,下面两个图理解起来更直观。

图1

图2

根据该理论,傅里叶逆变换法可以简单分成以下步骤:

① 假设每旋转1°就扫描一次,当对物体扫描了180°之后,我们就能得到180个投影信号(就是180根投影线)→在临床上,若使用平行扫描CT,我们拿到手的数据就是这个(在数学上,就是对图像进行拉冬变换)

② 对180个投影信号进行一维傅里叶变换

③ 对②得到的180个一维频域信号,根据相对应的扫描角度,在空间中旋转排列,拼成一个二维频域空间(如图3)

④ 由于数据是离散的,直接按照角度进行排列难以铺满整个二维空间,因此还需要对空缺的地方进行插值(一般三次样条插值效果最好),但插值会带来一定误差。另外,由于中心的信号密集,周围的信号稀疏,显然会损失一部分高频数据,造成高频信号失真,这就是采用傅里叶逆变换法重构图像时会使得图像边缘模糊的原因。

⑤ 对④中拼接而成的二维图像进行二维傅里叶逆变换,就可重构原图

图3  傅里叶逆变换法

该方法的缺点有:

a/高频信号有所失真

b/在插值时还涉及到极坐标和直角坐标的变换,计算量大

c/需要用到二维傅里叶逆变换,总体耗费时间长

由于计算机处理二维傅里叶逆变换的计算量太大,因此很少直接使用该方法实现拉东逆变换。

(2)直接反投影法

反投影法的原理是将所测得的投影值,按照其原投影路径,平均地分配到经过的每一个点上,把各个方向的投影值都这样反投影后,在把每个角度的反投影图像进行累加,从而推断出原图。为方便理解,下面分别用两张图,通过MATLAB编程来还原一下该过程(程序在最后):

原图如下:(图1简单,图2复杂)

①首先看一下图像经过拉东变换(即CT扫描)后的数据(图中每一列代表对应每一个角度的投影信号,在这里只是拼起来成一张图了)

②对每个角度的信号进行反投影(选了几个代表性角度):

② 把以上角度发反投影图像叠加起来:

当越来越多的反投影图像加起来之后,可以看到:

到此,直接反投影法结束。值得注意的是,由于反投影图是离散叠加的,显然在中心处信号集中,边缘处信号稀疏,因此在最后需要在空缺的地方进行插值,才能得到最终的原图像。上面演示的过程中没有进行插值,仅仅是把反投影图叠加,因此能够看出每一张图都不是很光滑。

从以上过程可以很直观地看出直接反投影法出现伪迹的原因:

①在“回抹“过程中(就是把投影信号平均到每个二维空间点的过程中),会把原图像本来是0的像素点也”抹“上一个平均值,最终使得重构的图像中存在误差;

②插值过程中会带来误差,且周围信号稀疏,高频信号有所失真,导致图像边缘模糊;

③在反投影图不断叠加过程中,能够看到这种叠加方式会带来明显的“星状伪迹“,这是造成图像边缘模糊的最重要因素。在投影数据少的时候更明显(现实中投影数据的多少取决于机器)。

关于第③点,在数学上有研究表明,反投影重构后的图像fb(x,y),和真实原图f(x,y)之间存在以下卷积关系:

如果要重构成真实的图像,就需要把这个由于反投影法本身带来的1/r效应去掉,由于1/r会使得图片变得模糊,因此1/r也称之为模糊因子。在实际操作中,把1/r影响去除的方法这就是下面这种最常用的(计算机、商业普遍使用)CT图像重构方法:滤波反投影法。

3)滤波反投影法

从上面的式(1)可以看到,1/r跟原图像是卷积关系,通过傅里叶变换转变到频域上后会变成乘积关系,这说明直接在频率上处理会更加简便。

在频域中,式(3)中的r称之为权重因子,其实就相当于一个滤波器,想要去除模糊因子的影响,重构成原始图像,只需要三步:

①把重构图像fb(x,y)进行二维傅里叶变换得到Fb(x,y)

②在频域中把Fb(x,y)与滤波器r相乘

③把r×Fb(x,y)进行二维傅里叶逆变换即能够得到原图f(x,y)

具体过程见下图,图中的ρ就是公式中的r

      

图4  直接反投影法

这种先反投影,后滤波的方法需要用到两次二维傅里叶变换,计算量太大,因此也不是一个特别理想的矫正方法。

而滤波反投影法,顾名思义就是先滤波,后反投影的重构方法。具体步骤如下:

①对180个投影信号先分别进行一维傅里叶变换

②在频域中对所有投影信号进行滤波,也就是乘上权重因子r

③把所有滤波后的信号再进行一维傅里叶逆变换,还原到时域

④对每一个已经滤波的投影信号进行反投影,最后叠加(这一步跟前面的直接反投影法步骤完全相同,只是投影信号已经过了滤波)

具体流程见下图:

图5  滤波反投影法

这个方法的好处是,把两次二维傅里叶变换变成了两次一维傅里叶变换,计算速度大大提升。于是滤波反投影法的核心问题就变成了如何选择一个合适的滤波器r。数学中的滤波器r是一个理想化的滤波函数,现实中不存在,因此只能设计一个近似的滤波函数来代替r的作用。

下面常用的滤波函数有:R-L滤波函数和S-L滤波函数。

①R-L滤波函数(Ram-Lak滤波器 Ramp Filter)

从频域图中可以看到该滤波器的作用是把低频信号减少,从而突出高频信号,因此经过该函数滤波后,重建图像的轮廓会更清晰,并且函数简单,实现起来更方便。但由于该函数在频域上有一个加窗处理(就是把高频部分直接截断了),因此在时域中会出现有许多振荡的小尾巴(截窗振荡效应),这将会让重构出来的图像存在Gibb’s现象(重构图像存在振荡,不连续)。

②S-L滤波函数(Shepp-Logan滤波器)

S-L滤波器在频域上不是直接加窗截断,而是通过一些比较平滑的窗函数对函数进行约束。因此经过S-L滤波后重构的图像振荡更少,重构的图像质量比R-L滤波器更好一些,但是因为S-L在高频段并没有直接截断,偏离了理想滤波器的效果,因此在高频段(轮廓)上的重构效果没有R-L滤波器好。

可以在下图更直观地看到两个滤波器之间的区别:

下面通过MATLAB编程来还原一下滤波反投影法的过程(程序在最后,只用复杂那个图进行展示):

①对每一列投影信号分别在频域进行R-L滤波(高频信号明显突出了)

②对每个滤波后的投影信号反投影(这里开始与直接反投影法一样)

③ 把所有反投影图像叠加起来 

为了验证手动重构的效果,下面将使用matlab中的iradon函数直接对CT投影数据进行重构,把手动重构的图像和matlab自带函数重构的图像进行对比。

(iradon是matlab中的拉东逆变换函数,但是其实际采用的重构方法并不是对数据进行二维傅里叶逆变换,而是通过滤波反投影法实现的,且默认插值方法为“线性插值linear“,默认滤波方法为”R-L滤波函数“,这在matlab的help中可以直接看到。)

仔细观察两个重构结果,会发现iradon的重构结果更光滑一些,那是因为手动方法只是简单粗暴地把全部离散的反变换图片叠加起来,而iradon则会在最后对图像进行线性插值,使得图像更连续更光滑,重构效果更好。

最后把iradon重构的图像放大来看看图像细节:

可以看到重构的图像其实并不连续,甚至能够看出一些振荡的波纹,这就是R-L滤波函数截窗振荡效应所带来的Gibb’s现象。

(4)MATLAB程序

%% CT反投影法
%%==========================Part 1==========================
%% 1、直接反投影法
% 绘制一张简单的图,进行直接反投影法
clc,clear,close all
% ================================================
% 简单图
% I=zeros(512,512);
% for i=1:512
%     for j=1:512
%         if ((i-256)*(i-256)+(j-256)*(j-256))<1024
%             I(i,j)=1;
%         end
%     end
% end
% figure,imshow(I,[]);
% ===============================================%============================================
% 复杂图
I = phantom(512); 
figure,imshow(I,[]);
%============================================% 绘制代表角度的反投影图像
R=radon(I,0:179);  %对物体CT扫描180°的数据,每1°扫描一次
figure,imshow(R,[]);title('CT图像');
% 绘制1、45、90、135、180的投影信号和反投影图像
theta=[1 45 90 135];
for i=1:length(theta)r=R(:,i);II=iradon([r r],[theta(i) theta(i)],'linear','none')/2;%回抹(反投影)之前不滤波II1{i}=II;figure,subplot(1,2,1),imshow(r,[]);title([num2str(theta(i)) '°投影信号']);subplot(1,2,2),imshow(II,[]);title(['往' num2str(theta(i)) '°方向反投影']);
end
II2=II1{1}+II1{2}+II1{3}+II1{4};
figure,imshow(II2,[]);% 对反投影图像进行叠加
r=R(:,1);
II_r=iradon([r r],[1 1])/2;
k=[30 15 10 1];
for j=1:4A=II_r;for i=2:k(j):180r=R(:,i);II=iradon([r r],[i i],'linear','none')/2;%回抹(反投影)之前不滤波A=A+II;   end
%     figure,imshow(A,[min(min(I)) max(max(I))]);figure,imshow((A),[]);
end%% =========================Part 2=============================
%% 2、滤波反投影法
clc,clear,close all
% 复杂图
I = phantom(512); 
figure,imshow(I,[]);% 对投影做傅里叶变换
R=radon(I,0:179);
width=length(R);
% 设计R-L滤波器
filter=2*[0:round(width/2-1), width/2:-1:1]'/width;
% 展示滤波前的CT投影信号
figure,imshow(R,[]),title('滤波前的CT投影信号');% 每一列做傅里叶变换
r_fft=fft(R,729); 
% 每一列做傅里叶变换后滤波
r_fft_filter=r_fft.*filter; 
% 滤波后反变换(real取实部)
r_fft_filter_v=real(ifft(r_fft_filter));
% 展示滤波后的CT投影信号
% figure,imshow(r_fft_filter_v,[]),title('滤波后的CT投影信号');
figure,imshow(r_fft_filter_v),title('滤波后的CT投影信号');% 绘制1、45、90、135、180的投影信号和反投影图像
theta=[1 45 90 135];
for i=1:length(theta)r=r_fft_filter_v(:,i);II=iradon([r r],[theta(i) theta(i)],'linear','none')/2;%由于iradon默认有滤波,因此关掉默认的滤波选项(none),直接用上面已经手动滤波的数据进行反投影II1{i}=II;figure,subplot(1,2,1),imshow(r,[]);title([num2str(theta(i)) '°投影信号']);subplot(1,2,2),imshow(II,[]);title(['往' num2str(theta(i)) '°方向反投影']);
end
II2=II1{1}+II1{2}+II1{3}+II1{4};
figure,imshow(II2,[]);% 对反投影图像进行叠加
r=r_fft_filter_v(:,1);
II_r=iradon([r r],[1 1])/2;
k=[30 15 10 1];
for j=1:4A=II_r;for i=2:k(j):180r=r_fft_filter_v(:,i);II=iradon([r r],[i i],'linear','none')/2;%由于iradon默认有滤波,因此关掉默认的滤波选项(none),直接用上面已经手动滤波的数据进行反投影A=A+II;   end
%     figure,imshow(A,[min(min(I)) max(max(I))]);figure,imshow((A),[]);
end% 上面是反投影叠加的分步计算,下面直接输入全部投影数据到iradon函数中进行验证
B=iradon(r_fft_filter_v,0:179,'linear','none');
figure,
imshow(B,[]);title('验证:滤波后图像');


以上就是对CT图像重构的整理结果,更多是自己在学习过程中的理解,若有表述不当的地方欢迎指出。

------------------------------------------------------- 2021.05.27  笔记补充 -----------------------------------------------------------

重构图像(514×514)与原图像(512×512)尺寸不一致的原因分析:

首先需要感谢楼下 study_art 同学提出了这个问题,以及 xjch1900 同学的提醒,一开始确实没考虑过这个问题,后来查看源代码找到了原因,在此更新一下笔记。

①radon函数的matlab文件解释:

% Grandfathered syntax
%   R = RADON(I,THETA,N) returns a Radon transform with the
%   projection computed at N points. R has N rows. If you do not
%   specify N, the number of points the projection is computed at
%   is:
%
%        2*ceil(norm(size(I)-floor((size(I)-1)/2)-1))+3
%
%   This number is sufficient to compute the projection at unit
%   intervals, even along the diagonal.

我们一开始先使用了radon函数来模拟了CT的扫描过程,得到的结果是每个角度的投影数据。假设我们扫描的是一张正方形的图像,大小为512×512,如果我们要把扫描的数据都存储下来,就必须设置一个足够长的数组来记录这些数据,显然,当扫描方向为45°角时得到的扫描数据是最长的(如下图所示),需要的数组长度至少为 512×√2≈725 。

回到matlab的radon函数,从上面的文件解释中可看到radon的语法中的N便是用来定义这个最长长度的。但当我们没有对这个N有专门的限制时,该函数就会自动计算出这个“最长长度”,为了涵盖图像形状的不同情况(如有的图像为长方形),它设置了一个公用的计算公式

N=2*ceil(norm(size(I)-floor((size(I)-1)/2)-1))+3

【其中ceil函数表示“向上取整”;floor表示“向下取整”;norm表示“范数计算”,用在这里其实就是计算正方形斜边的长度

如果套入这个公式,计算出来的N为:

size(I)=[512 512];
N=2*ceil(norm(size(I)-floor((size(I)-1)/2)-1))+3N =729

这比自己的理论值725大了一些,但实际上这是为了涵盖所有图像情况造成的,这并不会对最后的结果带来太大影响。

在正文最后的matlab程序中,我并没有专门定义这个N,因此radon函数自动把N通过公式计算出来了,大小为729,同时还定义了180个扫描角度,所以得到的所有投影数据的矩阵大小为729×180.

②iradon函数的matlab文件解释:

%   I = IRADON(R,THETA,INTERPOLATION,FILTER,FREQUENCY_SCALING,OUTPUT_SIZE)   
%   OUTPUT_SIZE is a scalar that specifies the number of rows and columns in
%   the reconstructed image.  If OUTPUT_SIZE is not specified, the size is
%   determined from the length of the projections:
%
%       OUTPUT_SIZE = 2*floor(size(R,1)/(2*sqrt(2)))
%
%   If you specify OUTPUT_SIZE, IRADON reconstructs a smaller or larger
%   portion of the image, but does not change the scaling of the data.

在使用iradon函数进行图像重构时,同样有一个output_size的参数可以设置(表示输出图像的大小),我们可以直接设置为原始图像的大小(即512),这样得到的图像就跟原图像大小一模一样了。但在正文最后部分,我同样没有专门设置图像大小,所以该函数就会自动套入一条涵盖了所有图像形状的计算公式

OUTPUT_SIZE = 2*floor(size(R,1)/(2*sqrt(2)))

由于我们在第一步用radon函数模拟CT扫描时没有专门定义N,得到的投影数据的矩阵R大小为729×180,因此直接套入这个output_size公式后就直接算出:

size(R,1)=729;
OUTPUT_SIZE = 2*floor(size(R,1)/(2*sqrt(2)))OUTPUT_SIZE =514

所以最后得到的重构图像大小就变成了514×514.

③解决方法

  •  使用radon函数时,自己定义N。如在正文的例子中,直接在radon函数中输入N的理论计算值725,这样在重构iradon时就不需要设置output_size了,输出结果直接为512×512
  • 使用radon函数时,不定义N,让函数自己计算图像的N,然后在重构iradon设置output_size的大小为原始图像大小512,输出结果同样为512×512

 备注:若radon和iradon函数都不专门设置时,会出现重构图像与原图像尺寸大小不一致的情况,但这并不会改变重构图像本身的缩放比例,因此若没有专门的尺寸大小必须前后一致的严格要求,可以不用专门设置。

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

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

相关文章

【转】交织容积重建技术:基本原理与临床价值

转自&#xff1a;交织容积重建技术&#xff1a;基本原理与临床价值_湃客_澎湃新闻-The Paper 原创 赵喜同学 XI区 单击上方蓝色字体 XI 区 或长按识别下方二维码关注我 大家好&#xff0c;欢迎大家访问XI区&#xff01; 所有医学成像系统的目标是从测量数据中提取最大数量的诊…

Tahoma,Arial和宋体英文字体

几年前一直用简体中文版的Widnows XP&#xff0c;从来没有觉得字体怎么怎么样。偶然看见英文版Windows XP就发现菜单或者文件夹的字体很好看&#xff0c;没怎么研究就把我的中文版XP换成了英文版并沿用至今。后来很久才知道可以在Control Panel -> Display -> Appearance…

【转】CT解析重建**

转自&#xff1a;CT解析重建 - 知乎 1、傅里叶变换&#xff08;Fourier Transform&#xff09; 白光可以分解成彩色光&#xff0c;彩色光也可合成白光&#xff1b;同样的通过傅里叶变换可将时域下的信号转变成傅里叶域的信号&#xff0c;通过傅里叶逆变换可转换回来。此外&am…

WINCE REG文件相关资料

REG文件 注册表文件&#xff0c;这个和Windows操作系统中使用的注册表文件基本一样&#xff0c;在BSP中主要是Platform.reg&#xff0c;该注册表文件描述了和硬件平台相关的配置&#xff0c;大部分是用来描述驱动的相关信息。 注册标的格式如下&#xff1a; de>[KEY1]de&g…

【转】由投影重建图像:滤波反投影、FDK、TFDK三维重建算法理论基础

转自&#xff1a;由投影重建图像&#xff1a;滤波反投影、FDK、TFDK三维重建算法理论基础_m0_37357063的博客-CSDN博客_fdk算法 1. 基础理论从&#xff1a; [1] RafaelC.Gonzalez, RichardE.Woods, Gonzalez,等. 阮秋琦等译.数字图像处理(第三版)[M]. 电子工业出版社, 2011.P2…

How to Use Hive-based Registry IN WINCE.NET

摘要&#xff1a;WINCE本身是一个完全在内存中运行的系统。每次启动都需要把NK.BIN拷贝到内存中相对应的地址。这样的系统就不需要了系统维护&#xff0c;但是如何“永久”的保存设置就成了问题。本文将介绍如何在Wince中实现设置的永久保存。 关键字&#xff1a;WINCE、嵌入式…

【转】libpcap实现机制及接口函数

转自&#xff1a;libpcap实现机制及接口函数 - 简书 1.Libpcap 的工作原理 Libpcap的工作原理可以描述为&#xff0c;当一个数据包到达网卡时&#xff0c;通过网络分接口&#xff08;即旁路机制&#xff09;将数据包发给BPF过滤器&#xff0c;匹配通过的数据包可以被libpcap利…

惊!MySQL官网巨变,下载被取消

随着欧盟的批准&#xff0c;甲骨文宣布收购Sun交易完成&#xff0c;与此同时甲骨文一系列动作也迅速展开。 甲骨文因MySQL被欧盟卡了大半年&#xff0c;在中国&#xff0c;MySQL的用户非常多&#xff0c;MySQL的前途无疑让人牵肠挂肚。并购之前&#xff0c;甲骨文说了很多&…

【转】【C++学习笔记】C++异常处理

转自&#xff1a;【C学习笔记】C异常处理&#xff01;你绝对不能错过的干货&#xff01; - 知乎 合理地使用C异常处理&#xff0c;能够使我们写出来的程序更加稳定强健&#xff0c;不易崩溃。那么&#xff0c;应该如何使用C异常处理呢&#xff1f;下面&#xff0c;我们就来向大…

【转】源码分析C++的string实现

转自&#xff1a;源码分析C的string实现 - 知乎 我们平时使用C开发过程中或多或少都会使用std::string&#xff0c;但您了解string具体是如何实现的吗&#xff0c;这里程序喵给大家从源码角度分析一下。 读完本文相信您可以回答以下问题&#xff1a; string的常见的实现方式…

做一个项目,平时都用到哪些工具提高效率(上)

做.NET 相关项目&#xff0c;Visual Studio 2008,SQL Server 2000/2005是标准的配置&#xff0c;但是&#xff0c;除此之外&#xff0c;还可以应用哪些工具来提高工作效率&#xff0c;让项目做的更轻松。 1 需要一个代码生成工具&#xff0c;生成实体层&#xff0c;数据访问代…

【转】傅里叶分析之掐死教程(完整版)更新于2014.06.06

转自&#xff1a;傅里叶分析之掐死教程&#xff08;完整版&#xff09;更新于2014.06.06 - 知乎 作 者&#xff1a;韩 昊 知 乎&#xff1a;Heinrich 微 博&#xff1a;花生油工人 知乎专栏&#xff1a;与时间无关的故事 谨以此文献给大连海事大学的吴楠老师&#xff0c;柳…

wince6.0编译命令分析

下面从CSDN帮助文档简要说明vs2005下面的系统编译命令&#xff0c;这些命令位于Build->Advanced Build Commonds 一共有六条命令&#xff0c;分别是&#xff1a; 1.Sysgen 2.Clean Sysgen 3.Build and Sysgen 4.Rebuild and Clean Sysgen 5.Build Current BSP and Subprojec…

【转】C,C++宏中#与##的讲解

转自&#xff1a;C,C宏中#与##的讲解 - MoreWindows - 博客园 文中__FILE__与示例1可以参见《使用ANSI C and Microsoft C中常用的预定义宏》 宏中的#的功能是将其后面的宏参数进行字符串化操作&#xff08;Stringizing operator&#xff09;&#xff0c;简单说就是在它引用的…

wince对中文字体的支持

最近情况真的是很糟&#xff0c;小小年纪&#xff0c;得了好几样小毛病&#xff0c;弄得每天都提不起精神来&#xff0c;恍恍惚惚的&#xff0c;幸好有妻子的支持&#xff0c;她不论自己多忙多累&#xff0c;一看到我情绪不好&#xff0c;就给与很多安慰&#xff0c;百般鼓励&a…

提示信息的窗口效果

代码 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns"http://www.w3.org/1999/xhtml"><head><title>提示信息的窗口效果<…

【转】ARM 之七 主流编译器(armcc、iar、gcc for arm、LLVM(clang))详细介绍

转自&#xff1a;ARM 之七 主流编译器&#xff08;armcc、iar、gcc for arm、LLVM(clang)&#xff09;详细介绍_itexp-CSDN博客_armcc 必备 在讲解各编译器之前&#xff0c;必须先了解一下以下文件。这些文件在编译器目录下或者编译生成目标平台的可执行程序时经常见到。此外&a…

【转】深入浅出理解有限状态机

转自&#xff1a;深入浅出理解有限状态机 - 知乎 有限状态机是一种用来进行对象行为建模的工具&#xff0c;其作用主要是描述对象在它的生命周期内所经历的状态序列&#xff0c;以及如何响应来自外界的各种事件。在计算机科学中&#xff0c;有限状态机被广泛用于建模应用行为、…

wince 环境变量

wince工程的环境变量在PBInitEnv.bat文件中存储&#xff0c;经测试&#xff0c;如果在下面增加了新的变量&#xff0c;在此文件中会出现

【转】vs平台工具集介绍,vc6~vs2019各IDE对应的工具集版本

转自&#xff1a;vs平台工具集介绍以及安装 - jack_Meng - 博客园 一、什么是平台工具集&#xff1a; 平台工具集其实是MSBuild其目录所在C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0。VS从2010之后开始支持使用之前的版本进行编译&#xff0c;可以在工程属性->常…