彩色BMP转换成灰度图的原理

图像处理中,大部分的处理方法都需要事先把彩色图转换成灰度图才能进行相关的计算、识别。
彩色图转换灰度图的原理如下:
我们知道彩色位图是由R/G/B三个分量组成,其文件存储格式为
BITMAPFILEHEADER+BITMAPINFOHEADER,紧跟后面的可能是:
如果是24位真彩图,则每个点是由三个字节分别表示R/G/B,所以这里直接跟着图像的色彩信息;
如果是8位(256色),4位(16色),1位(单色)图,则紧跟后面的是调色板数据,一个RGBQUAD类型的数组,其长度由BITMAPINFOHEADER.biClrUsed来决定。
然后后面紧跟的才是图像数据(24位图是真实的图像数据,其他的则是调色板的索引数据)。
灰度图是指只含亮度信息,不含色彩信息的图象,就象我们平时看到的黑白照片:亮度由暗到明,变化是连续的。因此,要表示灰度图,就需要把亮度值进行 量化。通常划分成0到255共256个级别,其中0最暗(全黑),255最亮(全白)。在表示颜色的方法中,除了RGB外,还有一种叫YUV的表示方法, 应用也很多。电视信号中用的就是一种类似于YUV的颜色表示方法。在这种表示方法中,Y分量的物理含义就是亮度,Y分量包含了灰度图的所有信息,只用Y分 量就能完全能够表示出一幅灰度图来。
从 RGB 到 YUV 空间的 Y 转换公式为: 
Y = 0.299R+0.587G+0.114B 
在 WINDOWS 中,表示 16 位以上的图和以下的图有点不同; 16 位以下的图使用一个调色板来表示选择具体的颜色,调色板的每个单元是 4 个字节,其中一个透明度;而具体的像素值存储的是索引,分别是 1 、 2 、 4 、 8 位。 16 位以上的图直接使用像素表示颜色。 
那么如何将彩色图转换为灰度图呢? 
灰度图中有调色板,首先需要确定调色板的具体颜色取值。我们前面提到了,灰度图的三个分量相等。 
当转换为 8 位的时候,调色板中有 256 个颜色,每个正好从 0 到 255 个,三个分量都相等。 
当转换为 4 位的时候,调色板中 16 个颜色,等间隔平分 255 个颜色值,三个分量都相等。 
当转换为 2 位的时候,调色板中 4 个颜色,等间隔平分 255 个颜色,三个分量相等。 
当转换为 1 位的时候,调色板中两个颜色,是 0 和 255 ,表示黑和白。 
将彩色转换为灰度时候,按照公式计算出对应的值,该值实际上是亮度的级别;亮度从 0 到 255 ;由于不同的位有不同的亮度级别,所以 Y 的具体取值如下: 
       Y = Y/ (1<<(8- 转换的位数 )); 
所以,我们要转化成灰度图,并且存储成一幅可以看到的图像,需要做如下转换:
16位以上的图像不带调色板,只需要把图像数据按每个点的位数都转换成相同的灰度值即可
16位以下的图像,则需要修改调色板的数值,并且按照每个点所占位数修改灰度值索引即可。

 

以下是256色图转换成灰度图示例代码:

 

[cpp] view plaincopy
  1. /**************************************************************** 
  2. * 函数名称: 
  3. *      Convert256toGray() 
  4. * 
  5. * 参数: 
  6. *     HDIB hDIB     -图像的句柄 
  7. * 
  8. *  返回值: 
  9. *        无 
  10. * 
  11. *  功能: 
  12. *     将256色位图转化为灰度图 
  13. * 
  14. ***************************************************************/  
  15.   
  16. void Convert256toGray(HDIB hDIB)  
  17. {  
  18.     LPSTR   lpDIB;  
  19.       
  20.     // 由DIB句柄得到DIB指针并锁定DIB  
  21. lpDIB = (LPSTR) ::GlobalLock((HGLOBAL)hDIB);  
  22.       
  23.     // 指向DIB象素数据区的指针  
  24.     LPSTR   lpDIBBits;    
  25.   
  26.     // 指向DIB象素的指针  
  27.     BYTE *  lpSrc;    
  28.   
  29.     // 图像宽度  
  30.     LONG    lWidth;   
  31.     // 图像高度  
  32. LONG    lHeight;      
  33.   
  34.     // 图像每行的字节数  
  35.     LONG    lLineBytes;   
  36.   
  37.     // 指向BITMAPINFO结构的指针(Win3.0)  
  38.     LPBITMAPINFO lpbmi;   
  39.   
  40.     // 指向BITMAPCOREINFO结构的指针  
  41.     LPBITMAPCOREINFO lpbmc;  
  42.       
  43.     // 获取指向BITMAPINFO结构的指针(Win3.0)  
  44.     lpbmi = (LPBITMAPINFO)lpDIB;      
  45.   
  46.     // 获取指向BITMAPCOREINFO结构的指针  
  47.     lpbmc = (LPBITMAPCOREINFO)lpDIB;      
  48.   
  49.     // 灰度映射表  
  50.     BYTE bMap[256];  
  51.       
  52.     // 计算灰度映射表(保存各个颜色的灰度值),并更新DIB调色板  
  53.     int i,j;  
  54.     for (i = 0; i < 256; i ++)  
  55.     {  
  56.         // 计算该颜色对应的灰度值  
  57.         bMap[i] = (BYTE)(0.299 * lpbmi->bmiColors[i].rgbRed +  
  58.   
  59.                          0.587 * lpbmi->bmiColors[i].rgbGreen +  
  60.   
  61.                          0.114 * lpbmi->bmiColors[i].rgbBlue + 0.5);           
  62.         // 更新DIB调色板红色分量  
  63.         lpbmi->bmiColors[i].rgbRed = i;    
  64.           
  65.         // 更新DIB调色板绿色分量  
  66.         lpbmi->bmiColors[i].rgbGreen = i;      
  67.           
  68.         // 更新DIB调色板蓝色分量  
  69.         lpbmi->bmiColors[i].rgbBlue = i;  
  70.               
  71.         // 更新DIB调色板保留位  
  72.         lpbmi->bmiColors[i].rgbReserved = 0;  
  73.   
  74.     }  
  75.     // 找到DIB图像象素起始位置  
  76.     lpDIBBits = ::FindDIBBits(lpDIB);  
  77.           
  78.     // 获取图像宽度  
  79.     lWidth = ::DIBWidth(lpDIB);   
  80.   
  81.     // 获取图像高度  
  82.     lHeight = ::DIBHeight(lpDIB);     
  83.   
  84.     // 计算图像每行的字节数  
  85.     lLineBytes = WIDTHBYTES(lWidth * 8);      
  86.   
  87. // 更换每个象素的颜色索引(即按照灰度映射表换成灰度值)  
  88.   
  89. //逐行扫描  
  90. for(i = 0; i < lHeight; i++)  
  91. {  
  92.   
  93.   //逐列扫描  
  94. for(j = 0; j < lWidth; j++)  
  95. {  
  96.     // 指向DIB第i行,第j个象素的指针  
  97.     lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;  
  98.               
  99.     // 变换  
  100.     *lpSrc = bMap[*lpSrc];  
  101. }  
  102. }  
  103.   
  104. //解除锁定  
  105. ::GlobalUnlock ((HGLOBAL)hDIB);  
  106. }  

 

 

24位彩色图转换成4位灰度图

首先要声明的是,这个4位(16)色图比较特殊,不是彩色的16色图,而已一个用4位16色,模拟的灰度图

什么是灰度图?

灰度图是指只含亮度信息不含彩色信息的图象,就像我们平时看到的亮度由暗到明的黑白照片,亮度变化是连续的。因此,要表示
灰度图,就需要把亮度值进行亮化。通常分成0-255共256个级别,0最暗(全黑),255最亮(全白)。
BMP格式的文件中并没有灰度图这个概念,但是可以很容易的用BMP文件来表示灰度图。一般的方法是用256色的调色板,这个调色板

每一项的RGB值都是相同的,即从(0,0,0),(1,1,1)一直到(255,255,255),(0,0,0)表示全黑(255,255,255)表示全白

1.BMP位图的格式

BMP文件的结构分为4部分,本文假定读者都已经了解BMP位图的格式(几乎所有教VC的书上多媒体部分都有讲,再google一下也很容

易就查得到,这里主要介绍其中的调色板,和图象数据部分。

对于非真彩的位图,都有一个调色板,调色板的格式如下

typedef struct tagRGBQUAD{

 BYTE rgbBlue;//蓝色的分量
 BYTE rgbGreen;//绿色的分量
 BYTE rgbRed;//红色的分量
 BYTE rgbReserved;//保留值不用管它为0就好

}RGBQUAD;
一般的调色版是一个,由上面的结构体组成的结构体数组,存储具体的颜色信息,而位图中,图象数据部分存储的只是调色板的下标

。这样做就可以大大的节省空间。

例如:
RGBQUAD rgb[2];
rgb[0].rgbBlue = 0;
rgb[0].rgbGreen = 0;
rgb[0].rgbRed = 0;
rgb[0].rgbReserved = 0;
rgb[1].rgbBlue = 255;
rgb[1].rgbGreen = 255;
rgb[1].rgbRed = 255;
rgb[1].rgbReserved = 255;

这个长度为2的RGBQUAD数组就是一个1位2色黑白图的调色板,
在位图数据部分只需要用1位的长度存储0表示黑,1表示白就可以了,1字节可以表示8个像素的信息,比用3字节直接表示R,G,B节

省了24倍的存储空间

而真彩图则不然,比如24位图,那么他就需要一个数组大小为2的24次方的调色板,而调色板的下标也需要3个字节才储存,这样还

不如直接就R,G,B这三个分量来直接表示每一个像素的色值。使用调色板技术还浪费了一个256*256*256*3字节大的调色板空间.


而这里要用4位表示一个灰度图,那么它的调色板只有16项,每一项的RGB值同通常由256色构成的灰度图的调色板一样的道理

这里这样建立这个调色板

 RGBQUAD pa[16];
 BYTE c;
 for(int i=0;i<16;i++)
 {
  c= i * 17;
  pa[i].rgbRed = c;
  pa[i].rgbGreen = c;
  pa[i].rgbBlue = c;
  pa[i].rgbReserved = 0;
 }

2.转换算法

现在的图象是24位真彩的,表示它的数据部分,3字节表示一个像素,这三个字节分别表示RGB。
我们现在要做的是求每一像素点的RGB值的平均值,然后用16色调色板中最接近这个颜色亮度的值来表示它。
而4位的图象是1个字节表示2个像素,在这里需要特殊注意

具体算法实现代码如下,pBuffer是储存图象数据的数组

  USHORT R,G,B;

 
  // 第一个像素
  R = pBuffer[dwIndex++];
  G = pBuffer[dwIndex++];
  B = pBuffer[dwIndex++];

  int maxcolor = (R+G+B)/3;

  maxcolor /= 17;//计算在16色调色板中的下标
 

  //第二个像素
  R = pBuffer[dwIndex++];
  G = pBuffer[dwIndex++];
  B = pBuffer[dwIndex++];

  int maxcolor2 = (R+G+B)/3;

  maxcolor2 /= 17;
  
  pNew[dwOldIndex++] = ( maxcolor<<4 )| maxcolor2;//合成一个字节表示两个像素

3.实现代码

完整的实现代码如下
BOOL Convert24To4(LPCTSTR lpszSrcFile, LPCTSTR lpszDestFile)//24->4灰度图
{
 BITMAPFILEHEADER bmHdr;  // BMP文件头
 BITMAPINFOHEADER bmInfo; // BMP文件信息

 HANDLE hFile, hNewFile;
 DWORD dwByteWritten = 0;

 // 打开源文件句柄
 hFile = CreateFile(lpszSrcFile, 
        GENERIC_READ,
        FILE_SHARE_READ,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        NULL);

 if (hFile == INVALID_HANDLE_VALUE)
  return FALSE;

 // 创建新文件
 hNewFile = CreateFile(lpszDestFile,
        GENERIC_READ | GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,
        CREATE_ALWAYS,
        FILE_ATTRIBUTE_NORMAL,
        NULL);
 if (hNewFile == INVALID_HANDLE_VALUE)
 {
  CloseHandle(hFile);
  return FALSE;
 }

 // 读取源文件BMP头和文件信息
 ReadFile(hFile, &bmHdr, sizeof(bmHdr), &dwByteWritten, NULL); 
 ReadFile(hFile, &bmInfo, sizeof(bmInfo), &dwByteWritten, NULL);

 TRACE("biSize: %d , biWidth: %d , biHeight: %d , biBitCount: %d , biSizeImage: %d

/n",bmInfo.biSize,bmInfo.biWidth,bmInfo.biHeight,bmInfo.biBitCount,bmInfo.biSizeImage);
 TRACE("biX: %d , biY: %d , biClrUsed: %d , biClrImportant: %d

/n",bmInfo.biXPelsPerMeter,bmInfo.biYPelsPerMeter,bmInfo.biClrUsed,bmInfo.biClrImportant);


 // 只处理24位未压缩的图像
 if (bmInfo.biBitCount != 24 || bmInfo.biCompression!=0)
 {
  CloseHandle(hNewFile);
  CloseHandle(hFile);
  DeleteFile(lpszDestFile);
  return FALSE;
 }

 // 计算图像数据大小
 DWORD dwOldSize = bmInfo.biSizeImage;
 if(dwOldSize == 0) // 重新计算
 {
  dwOldSize = bmHdr.bfSize - sizeof(bmHdr) - sizeof(bmInfo);
 }

 TRACE("Old Width: %d , Old Height: %d ,Old Size: %d bytes/n",bmInfo.biWidth,bmInfo.biHeight,dwOldSize);

 long wid = bmInfo.biWidth % 4;

 if(wid>0)
 {
  wid = 4 - wid;
 }

 wid += bmInfo.biWidth;

 DWORD dwNewSize;

 dwNewSize = wid * bmInfo.biHeight / 2; //计算转换后新图象大小

 TRACE("New Size: %d bytes/n", dwNewSize);
 

 // 读取原始数据
 UCHAR *pBuffer = NULL;
 pBuffer = new UCHAR[dwOldSize]; // 申请原始数据空间
 if(pBuffer == NULL)
 {
  CloseHandle(hNewFile);
  CloseHandle(hFile);
  DeleteFile(lpszDestFile);
  return FALSE;
 }
 // 读取数据
 ReadFile(hFile, pBuffer, dwOldSize, &dwByteWritten, NULL);

 UCHAR *pNew = new UCHAR[dwNewSize];

 UCHAR  color = 0;
 DWORD dwIndex = 0, dwOldIndex = 0;
 while( dwIndex < dwOldSize )//一字节表示两个像素
 {
  USHORT R,G,B;

 
  // 第一个像素
  R = pBuffer[dwIndex++];
  G = pBuffer[dwIndex++];
  B = pBuffer[dwIndex++];

  int maxcolor = (R+G+B)/3;

  maxcolor /= 17;
 

  //第二个像素
  R = pBuffer[dwIndex++];
  G = pBuffer[dwIndex++];
  B = pBuffer[dwIndex++];

  int maxcolor2 = (R+G+B)/3;

  maxcolor2 /= 17;
  
  pNew[dwOldIndex++] = ( maxcolor<<4 )| maxcolor2;//合成一个字节表示两个像素

 }

 
 // 完工, 把结果保存到新文件中

 // 修改属性
 bmHdr.bfSize = sizeof(bmHdr)+sizeof(bmInfo)+sizeof(RGBQUAD)*16+dwNewSize;
 bmHdr.bfOffBits = bmHdr.bfSize - dwNewSize;
 bmInfo.biBitCount = 4;
 bmInfo.biSizeImage = dwNewSize;

 // 创建调色板
 RGBQUAD pa[16];
 UCHAR c;
 for(int i=0;i<16;i++)
 {
  c= i * 17;
  pa[i].rgbRed = c;
  pa[i].rgbGreen = c;
  pa[i].rgbBlue = c;
  pa[i].rgbReserved = 0;
 }

 // BMP头
 WriteFile(hNewFile, &bmHdr, sizeof(bmHdr), &dwByteWritten, NULL);
 // 文件信息头
 WriteFile(hNewFile, &bmInfo, sizeof(bmInfo), &dwByteWritten, NULL);
 // 调色板
 WriteFile(hNewFile, pa, sizeof(RGBQUAD)*16, &dwByteWritten, NULL);
 // 文件数据
 WriteFile(hNewFile, pNew, dwNewSize, &dwByteWritten, NULL);

 delete []pBuffer;
 delete []pNew;

 // 关闭文件句柄
 CloseHandle(hNewFile);
 CloseHandle(hFile);

 return TRUE;
}

4.疑问

既然可以由24位真菜图转换为4位灰度图,那么一定有一个合适的方法把它转换成4位彩色图,而具体的区别就是
调色板不同(调色板都要表示哪些颜色),再有最重要的是原来的颜色用现有的16色,哪个表示更合适.

 

 

                                                                    技术交流、商务合作请直接联系博主

                                                                                扫码或搜索猿说编程

 

python/C++教程

                                                                                              猿说编程

                                                                                      微信公众号 扫一扫关注

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

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

相关文章

Linux java 生效不了,linux jdk 不生效怎么办

【摘要】操作系统(Operating System&#xff0c;简称OS)是管理计算机硬件与软件资源的计算机程序。操作系统需要处理如管理与配置内存、决定系统资源供需的优先次序、控制输入设备与输出设备、操作网络与管理文件系统等基本事务。下面是linux jdk 不生效怎么办&#xff0c;让我…

程序猿 - 超实用的工具、素材、学习网站分享

文章目录------------------------------学习教程篇-------------------------------bilibili哔哩哔哩网易云课堂siki学院&#xff1a;泰课在线&#xff1a;可汗学院&#xff1a;线性代数的本质 - bilibili计算机科学速成课 - bilibiliLearnOpenGL&#xff1a;The Book of Shad…

面趣 | 马云在面试中出的一道题,据说只有一个人答对……

大神&#xff0c;求解&#xff01;据说&#xff0c;马云给新员工出了一道题然鹅&#xff0c;只有一个人答对了&#xff01;&#xff01;&#xff01;&#xff01;智商不足的小编居然打开了这道题求解&#xff01;&#xff01;&#xff01;我手里有50元钱花去剩余买衣服 20元30…

云漫圈 | 敢怼我们程序员?哼,有你好看的。。。

作者设计师静静来源非著名程序员原创作品&#xff0c;如有转载&#xff0c;请联系公众号授权。原创漫画&#xff0c;禁止转载&#xff0c;侵权必究前几天在网络上看到一个关于产品经理和设计的对话&#xff0c;非常的搞笑&#xff0c;有意思。对话如下&#xff1a;产品经理&…

这些软件太强了,Windows必装!尤其程序员!

Windows可谓是大多数人的生产力工具&#xff0c;集娱乐办公于一体&#xff0c;虽然在程序员这个群体中都说苹果是信仰&#xff0c;但是大部分不都是从Windows过来的&#xff0c;而且现在依然有很多的程序员用Windows。 所以&#xff0c;今天我就把我私藏的Windows必装的软件分享…

教师节 | 程序员都这么玩,你敢挑战吗?

课堂上的每一课您总能「抽象」出整个世界不断「重载」出覆盖这个世界的任何方法当某个「异常」陷入自己的「静态属性」难以自拔时您总会调用千百种「方法」作为一种特别的「参数」传进把「异常」从一个「死循环」中解救出来在无尽的黑夜中您「释放」所有的系统资源不断的开发我…

如何在linux安装mysql7版本的,如何在linux下用tar方式安装Mysql5.7版本

1、下载根据自己的linux系统情况选择对应的tar包2、解压tar -zxvf mysql-5.7.26-linux-glibc2.12-x86_64.tar再移动并重命名一下mv mysql-5.7.26-linux-glibc2.12-x86_64 /usr/local/mysql3、创建mysql用户组和用户并修改权限groupadd mysqluseradd -r -g mysql mysql4、创建数…

cloud一分钟 | 腾讯金融云总经理胡利明:腾讯云服务金融的“加减 乘除”法。...

Hello&#xff0c;everyone&#xff1a;9月10日早&#xff0c;星期一&#xff0c;祝大家工作愉快&#xff01;祝各位老师节日快乐&#xff01;一分钟新闻时间&#xff1a;完01微 信 群 添加小编微信&#xff1a;tangguoyemeng&#xff0c;备注“进群公司职位”即可&#xff0c…

cloud一分钟 | 李飞飞离任谷歌云,工作重心将重新转回学术界

Hello&#xff0c;everyone&#xff1a;9月11日早&#xff0c;星期二&#xff0c;祝大家工作愉快&#xff01;一分钟新闻时间&#xff1a;完01微 信 群 添加小编微信&#xff1a;tangguoyemeng&#xff0c;备注“进群公司职位”即可&#xff0c;加入【云计算学习交流群】&…

如何成为云计算专家?这些必须知道

Level 200、300、400你正处在云计算技术的哪个阶段呢&#xff1f;从进阶&#xff0c;到高级&#xff0c;再到专家AWS INNOVATE 2018 在线技术大会为不同阶段的你量身定制技术内容高屋建瓴的 “主题演讲”包罗万象的 “技术分论坛”亲历亲为的 “Builders 实验室”……我们的进度…

linux重新启动某一个项目,Linux运维知识之supervisor更改某项目配置后 需要重新启动才有效...

本文主要向大家介绍了Linux运维知识之supervisor更改某项目配置后 需要重新启动才有效&#xff0c;通过具体的内容向大家展现&#xff0c;希望对大家学习Linux运维知识有所帮助。在linux服务器上部署了node项目&#xff0c;使用supervisor进行管理梗概了该项目对的某些配置后&a…

Python Pycharm Anacanda 区别

工欲善其事必先利其器&#xff0c;在学习 Python 开发之前我们首先来熟悉几个关键字&#xff1a; 1.Python 2.Pycharm 3.Anacanda 零基础 Python 学习路线推荐 : Python 学习目录 >> Python 基础入门可能对于刚接触的小伙伴还是比较懵逼的&#xff0c;一会 Python 一会 A…

走进中国移动(宁夏)数据中心,感受不一样的运营商情怀

文章来源&#xff1a;数字中国万里行 如今&#xff0c;移动端应用已经深入我们生活的方方面面。想出门&#xff0c;“嘀”一声扫码成功&#xff0c;骑上自行车就出发了&#xff1b;家里又该交燃气费了&#xff1f;随时随地登录官网&#xff0c;输入编码就能立刻充值&#xff1b…

Python2.x 和 Python3.x,如何选择?

一.前言 Python 软件基金会宣布&#xff0c;到 2020 年元旦&#xff0c;将不再为编程语言 Python 2.x 分支提供任何支持。这一天将标志着一出延续多年的戏剧的高潮&#xff1a;Python 从较旧的、功能较弱的、广泛使用的版本过渡到更新的、更强大的版本。 然而&#xff0c;Pytho…

面趣 | 一个月面试4家,3家Offer,来看看面霸真君如何面试的

作者纪小雄已获原作者授权&#xff0c;如需转载&#xff0c;请联系原作者。自古真情留不住&#xff0c;总是套路得人心近来很多小伙伴都抱怨说面试难&#xff0c;难于上青。蚕丛及鱼凫&#xff0c;开国何茫然&#xff0c;呃&#xff5e;好像多背了两句……我&#xff0c;人称 &…

Python Hello World入门 - Python零基础入门教程

目录 一.创建 hello world 项目 1.Create New Project2.设置项目所在目录3.项目创建完成 二.编写代码三.运行项目 万丈高楼平地起&#xff0c;编程亦如此。改变世界是结果&#xff0c;坚持努力学习改 Bug 的过程&#xff0c;hello world 是开始&#xff0c;所有语言均是如此。…

统计了50万人的身高数据才发现:大家都爱虚报身高

作者二胖并不胖来源大数据前言已获原作者授权&#xff0c;如需转载&#xff0c;请联系原作者。前些天在知乎上看到一个关于身高的问题。我想既然大家都对身高这么感兴趣&#xff0c;正好之前我在相亲网上爬了50万用户的信息&#xff0c;那不妨来做个统计。关于身高&#xff0c;…

linux系统批量装机,PXE+Kickstart实现无人值守批量安装Linux

PXEKickstart实现无人值守批量安装Linux实验准备&#xff1a;主机myrhel2作为服务器端&#xff0c;新建一个没有安装操作系统的虚拟主机&#xff0c;而且其与服务器端在同一个网段安装的条件&#xff1a;服务器端&#xff1a;支持TFTP&#xff1a;提供引导文件与系统安装所必须…

Python代码注释 - Python零基础入门教程

目录 一.什么是代码注释二.为什么写代码要注释三.代码注释的方式 1.单行注释&#xff0c;使用英文符号 #2.多行注释 方法一&#xff1a;英文状态下使用单引号 ”””方法二&#xff1a;英文状态下使用双引号 “” (和方法一有点类似)方法三&#xff1a;选中单行或者多行&#…

Cloud一分钟 | 阿里云将在英国大区设立数据中心

Hello&#xff0c;everyone&#xff1a;9月17日早&#xff0c;星期一&#xff0c;祝大家工作愉快&#xff01;一分钟新闻时间&#xff1a;完01微 信 群 添加小编微信&#xff1a;tangguoyemeng&#xff0c;备注“进群公司职位”即可&#xff0c;加入【云计算学习交流群】&…