视音频数据处理入门:颜色空间(一)---转换理解

2023-10-28 18:50

本文主要是介绍视音频数据处理入门:颜色空间(一)---转换理解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

一、YUV颜色空间

概述 

I420的理解

YV12的理解

NV12的理解

NV21的理解

YV12​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​与I420颜色空间相互转换

转换代码

NV12与I420颜色空间相互转换

转换代码

NV21与YV12颜色空间相互转换

转换代码

二、YUV转RGB

概述 

RGB32的理解

RGB24的理解

I420与RGB32颜色空间相互转换

转换代码

I420与RGB24颜色空间相互转换

转换代码

 三、代码路径


​​​​​​​

一、YUV颜色空间

概述 

 简单说一下I420、YV12、NV12、NV21的颜色空间排列方式,更容易理解它们直接相互方式。对于I420、YV12、NV12、NV21四中格式都属于YUV 4:2:0的的排列方式,我的理解是4个Y分量公用一个U和V分量。

I420的理解

I420(YU12)属于YUV420P又称YUV420plane平面模式;Y、U、V分别在不同平面,也就是有三个平面,它是YUV标准格式4:2:0,且与YV12同属于YUV420P;对于I420的图像上排列方式如图-I420(1),首先是Y分量的排布,排布Y分量的宽为图像的宽(W),Y分量的高为图像的高(H);  其次是U分量的排布,排布U分量的宽为图像的宽的一半(W/2),U分量的高为图像的高(H/2);再次是V分量的排布,排布V分量的宽与U分量一致,分别为图像的宽的一半(W/2)和图像的高(H/2)。Y分量、U分量、V分量依次排列。

Y0Y1Y2Y3Y4Y5Y6Y7
Y8Y9Y10Y11Y12Y13Y14Y15
Y16Y17Y18Y19Y20Y21Y22Y23
Y24Y25Y26Y27Y28Y29Y30Y31
U0U1U2U3U4U5U6U7
V0V1V2V3V4V5V6V7

                                                                   图-I420(1)

 如 图-I420(1)红色部分Y0、Y1、Y8、Y9共用U0和V0分量;依次类推,对应颜色的Y分量共用对应颜色的U和V分量。

i420的内存排列,如图-I420(2),依次是Y分量、U分量、V分量;

其中Y分量内存大小为:

Y分量buff_size = W * H ;

其中U分量内存大小为:

U分量buff_size = W/2 * H/2 ,即W * H /4 ;

其中V分量内存大小为:

V分量buff_size = W/2 * H/2 ,即W * H /4 ;

i420图像大小 = Y分量大小 + U分量大小 +V分量大小

即:

i420图像大小 =W * H *3/2

                                                 图-I420(2)

YV12的理解

YV12属于YUV420P又称YUV420plane平面模式;Y、U、V分别在不同平面,也就是有三个平面,它是YUV标准格式4:2:0,且与(I420)YU12同属于YUV420P;对于YV12的图像上排列方式如图-YV12(1),首先是Y分量的排布,排布Y分量的宽为图像的宽(W),Y分量的高为图像的高(H);  其次是U分量的排布,排布U分量的宽为图像的宽的一半(W/2),U分量的高为图像的高(H/2);再次是V分量的排布,排布V分量的宽与U分量一致,分别为图像的宽的一半(W/2)和图像的高(H/2)。Y分量、U分量、V分量依次排列。

Y0Y1Y2Y3Y4Y5Y6Y7
Y8Y9Y10Y11Y12Y13Y14Y15
Y16Y17Y18Y19Y20Y21Y22Y23
Y24Y25Y26Y27Y28Y29Y30Y31
V0V1V2V3V4V5V6V7
U0U1U2U3U4U5U6U7

                                                               图-YV12(1)

 如 图-YV12(1)红色部分Y0、Y1、Y8、Y9共用U0和V0分量;依次类推,对应颜色的Y分量共用对应颜色的U和V分量。

YV12的内存排列,如图-YV12(2),依次是Y分量、U分量、V分量;

其中Y分量内存大小为:

Y分量buff_size = W * H ;

其中U分量内存大小为:

U分量buff_size = W/2 * H/2 ,即W * H /4 ;

其中V分量内存大小为:

V分量buff_size = W/2 * H/2 ,即W * H /4 ;

YV12图像大小 = Y分量大小 + U分量大小 +V分量大小

即:

YV12图像大小 =W * H *3/2

                                                     图-YV12(2)

NV12的理解

 NV12属于YUV420SP,即Y和UV分为两个Plane,但是UV为交错存储,而不是分为三个plane。对于NV12的图像上排列方式如图-NV12(1),首先是Y分量的排布,排布Y分量的宽为图像的宽(W),Y分量的高为图像的高(H);  其次是UV分量的交错排布。Y分量、UV分量依次排列。

Y0Y1Y2Y3Y4Y5Y6Y7
Y8Y9Y10Y11Y12Y13Y14Y15
Y16Y17Y18Y19Y20Y21Y22Y23
Y24Y25Y26Y27Y28Y29Y30Y31
U0V0U1V1U2V2U3V3
U4V4U5V5U6V6U7V7

                                                         图-NV12(1)

如 图-NV12(1)红色部分Y0、Y1、Y8、Y9共用U0和V0分量;依次类推,对应颜色的Y分量共用对应颜色的U和V分量。

NV12的内存排列,如图-NV12(2),依次是Y分量、U分量、V分量;

其中Y分量内存大小为:

Y分量buff_size = W * H ;

其中U分量内存大小为:

U分量buff_size = W/2 * H/2 ,即W * H /4 ;

其中V分量内存大小为:

V分量buff_size = W/2 * H/2 ,即W * H /4 ;

NV12图像大小 = Y分量大小 + U分量大小 +V分量大小

即:

YV12图像大小 =W * H *3/2

                                               图-NV12(2)

NV21的理解

 NV21属于YUV420SP,即Y和UV分为两个Plane,但是VU为交错存储,而不是分为三个plane。对于NV21的图像上排列方式如图-NV21(1),首先是Y分量的排布,排布Y分量的宽为图像的宽(W),Y分量的高为图像的高(H);  其次是VU分量的交错排布。Y分量、VU分量依次排列。

NV21与NV12 本质区别是V和U的先后区别。

Y0Y1Y2Y3Y4Y5Y6Y7
Y8Y9Y10Y11Y12Y13Y14Y15
Y16Y17Y18Y19Y20Y21Y22Y23
Y24Y25Y26Y27Y28Y29Y30Y31
V0U0V1U1V2U2V3U3
V4U4V5U5V6U6V7U7

                                                                        图-NV21(1)

如 图-NV21(1)红色部分Y0、Y1、Y8、Y9共用U0和V0分量;依次类推,对应颜色的Y分量共用对应颜色的U和V分量。

YV12的内存排列,如图-NV21(2),依次是Y分量、U分量、V分量;

其中Y分量内存大小为:

Y分量buff_size = W * H ;

其中U分量内存大小为:

U分量buff_size = W/2 * H/2 ,即W * H /4 ;

其中V分量内存大小为:

V分量buff_size = W/2 * H/2 ,即W * H /4 ;

NV21图像大小 = Y分量大小 + U分量大小 +V分量大小

即:

NV21​​​​​​​图像大小 =W * H *3/2

​​​​​​​

                                            图-NV21(2)

YV12​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​与I420颜色空间相互转换

由YV12和I420的内存排列可知,Y的排列方式是相同的,不同的是U和V的排列;YV12的排列依次是Y 、V 、U ;而I420的排列顺序依次是Y 、U 、V。由此可见只要改变U、V的排列顺序即可实现YV12与I420的相互转换。

转换代码

int YV12_2_I420(uint8_t* src, uint8_t* dst, uint32_t width, uint32_t height)
{uint8_t* src_y = src;uint8_t* src_u = src + width * height;uint8_t* src_v = src + width * height * 5 / 4;uint8_t* dst_y = dst;uint8_t* dst_v = dst + width * height;uint8_t* dst_u = dst + width * height * 5 / 4;memcpy(dst_y, src_y, width * height);memcpy(dst_v, src_v, width * height / 4);memcpy(dst_u, src_u, width * height / 4);return 0;
}int I420_2_YV12(uint8_t* src, uint8_t* dst, uint32_t width, uint32_t height)
{uint8_t* src_y = src;uint8_t* src_u = src + width* height;uint8_t* src_v = src + width * height*5/4;uint8_t* dst_y = dst;uint8_t* dst_v = dst + width * height;uint8_t* dst_u = dst + width * height * 5 / 4;memcpy(dst_y, src_y, width * height);memcpy(dst_v, src_v, width * height/4);memcpy(dst_u, src_u, width * height/4);return 0;
}

NV12与I420颜色空间相互转换

由NV12和I420的内存排列可知,Y的排列方式是相同的,不同的是U和V的排列;NV12的U、V是交错式排列排列顺序依次是Y、UV排列。而I420的U、V依次排序。由此可见只要改变U、V的排列顺序即可实现NV12与I420的相互转换。

转换代码

int I420_2_NV12(uint8_t* src, uint8_t* dst, uint32_t width, uint32_t height)
{uint8_t* src_y = src;uint8_t* src_u = src + width * height;uint8_t* src_v = src + width * height * 5 / 4;uint8_t* dst_y = dst;uint8_t* dst_uv = dst + width * height;memcpy(dst_y, src_y, width * height);//UV交错排列for (int i = 0; i < width / 2 * height / 2; i++){dst_uv[2*i] = src_u[i];dst_uv[2 * i+1] = src_v[i];}return 0;
}int NV21_2_YV12(uint8_t* src, uint8_t* dst, uint32_t width, uint32_t height)
{uint8_t* src_y = src;uint8_t* src_uv = src + width * height;uint8_t* dst_y = dst;uint8_t* dst_v = dst + width * height;uint8_t* dst_u = dst + width * height * 5 / 4;memcpy(dst_y, src_y, width * height);//UV交错排列for (int i = 0; i < width / 2 * height / 2; i++){dst_v[i] = src_uv[2 * i];dst_u[i] = src_uv[2 * i + 1];}return 0;
}

NV21与YV12颜色空间相互转换

由NV12和YV12的内存排列可知,Y的排列方式是相同的,不同的是U和V的排列;NV12的U、V是交错式排列排列顺序依次是Y、UV排列。而YV12的U、V依次排序。由此可见只要改变U、V的排列顺序即可实现NV12与I420的相互转换。基本与I420转换一样。

转换代码

int NV21_2_YV12(uint8_t* src, uint8_t* dst, uint32_t width, uint32_t height)
{uint8_t* src_y = src;uint8_t* src_uv = src + width * height;uint8_t* dst_y = dst;uint8_t* dst_v = dst + width * height;uint8_t* dst_u = dst + width * height * 5 / 4;memcpy(dst_y, src_y, width * height);for (int i = 0; i < width / 2 * height / 2; i++){dst_v[i] = src_uv[2 * i];dst_u[i] = src_uv[2 * i + 1];}return 0;
}int YV12_2_NV21(uint8_t* src, uint8_t* dst, uint32_t width, uint32_t height)
{uint8_t* src_y = src;uint8_t* src_v = src + width * height;uint8_t* src_u = src + width * height * 5 / 4;uint8_t* dst_y = dst;uint8_t* dst_uv = dst + width * height;memcpy(dst_y, src_y, width * height);for (int i = 0; i < width / 2 * height / 2; i++){dst_uv[2 * i] = src_v[i];dst_uv[2 * i + 1] = src_u[i];}return 0;
}

二、YUV转RGB

概述 

RGB32与RGB24整体排列方式是一致,RGB32比RGB24多了一个预留位。也称做A通道。

RGB32的理解

RGB32由图-RGB32(1)可以看出来,R、G、B、A组成一个像素点;同事一个像素点占4个字节;R、G、B、A是交错排列的。

R0G0B0A0R1G1B1A1R2G2B2A2R3G3B3A3R4G4B4A4R5G5B5A5R6G6B6A6R7G7B7A7
R8G8B8A8R9G9B9A9R10G10B10A10R11G11B11A11R12G12B12A12R13G13B13A13R14G14B14A14R15G15B15A15
R16G16B16A16R17G17B17A17R18G18B18A18R19G19B19A19R20G20B20A20R21G21B21A21R22G22B22A22R23G23B23A23
R24G24B24A24R25G25B25A25R26G26B26A26R27G27B27A27R28G28B28A28R29G29B29A29R30G30B30A30R31G31B31A31

                                                                                                                                                    图-RGB32(1)

RGB24的理解

RGB32由图-RGB24(1)可以看出来,R、G、B组成一个像素点;同事一个像素点占3个字节;R、G、B是交错排列的。

R0G0B0R1G1B1R2G2B2R3G3B3R4G4B4R5G5B5R6G6B6R7G7B7
R8G8B8R9G9B9R10G10B10R11G11B11R12G12B12R13G13B13R14G14B14R15G15B15
R16G16B16R17G17B17R18G18B18R19G19B19R20G20B20R21G21B21R22G22B22R23G23B23
R24G24B24R25G25B25R26G26B26R27G27B27R28G28B28R29G29B29R30G30B30R31G31B31

                                                                                                                                           图-RGB24(1)

I420与RGB32颜色空间相互转换

I420与RGB32相互转换不同于yuv的转换。I420 2行共用一个U分量和V分量。所以RGB转yuv的时候应该注意排列方式。

转换代码

typedef  struct  RGB32 {uint8_t     rgbBlue;       // 蓝色分量uint8_t     rgbGreen;      // 绿色分量uint8_t     rgbRed;        // 红色分量uint8_t     rgbReserved;   // 保留字节(用作Alpha通道或忽略)RGB32(){rgbBlue = 0;rgbGreen = 0;rgbRed = 0;rgbReserved = 0;}
} RGB32;int I420_2_rgb32(uint8_t* src, uint8_t* dst, uint32_t width, uint32_t height)
{uint8_t* src_y = src;uint8_t* src_u = src + width * height;uint8_t* src_v = src + width * height * 5 / 4;RGB32* prgb = reinterpret_cast<RGB32*>(dst);int rgbindex = 0;for (int y = 0; y < height; y++){for (int x = 0; x < width; x++){RGB32* rgbNode = &prgb[rgbindex];//读取YUVuint8_t Y = src_y[y * width + x];uint8_t U = src_u[y / 2 * width / 2 + x / 2];uint8_t V = src_v[y / 2 * width / 2 + x / 2];//计算rgbint tmpr = Y + 1.402 * (V - 128);int tmpg = Y - 0.34413 * (U - 128) - 0.71414 * (V - 128);int tmpb = Y + 1.772 * (U - 128);//越界保护rgbNode->rgbRed = tmpr > 255 ? 255 : (tmpr < 0 ? 0 : tmpr);rgbNode->rgbGreen =tmpg > 255 ? 255 : (tmpg < 0 ? 0 : tmpg);rgbNode->rgbBlue = tmpb > 255 ? 255 : (tmpb < 0 ? 0 : tmpb);rgbindex++;}}return 0;
}int rgb32_2_I420(uint8_t* src, uint8_t* dst, uint32_t width, uint32_t height)
{RGB32* prgb = reinterpret_cast<RGB32*>(src);uint8_t* dst_y = dst;uint8_t* dst_u = dst + width * height;uint8_t* dst_v = dst + width * height * 5 / 4;//Y = 0.298R + 0.612G + 0.117B;//U = -0.168R - 0.330G + 0.498B + 128;//V = 0.449R - 0.435G - 0.083B + 128;int rgbindex = 0;int u_index = 0;int v_index = 0;int y_index = 0;for (int y = 0; y < height; y++){for (int x = 0; x < width; x++){rgbindex = y * width + x;RGB32* rgbNode = &prgb[rgbindex];//Y = 0.298R + 0.612G + 0.117B;int tmp_y = 0.298*rgbNode->rgbRed + 0.612 * rgbNode->rgbGreen + 0.117*rgbNode->rgbBlue;dst_y[y_index] = tmp_y > 255 ? 255 : (tmp_y < 0 ? 0 : tmp_y);y_index++;if (y%2 ==0 &&x%2 == 0){//U = -0.168R - 0.330G + 0.498B + 128;int tmp_u = -0.168 * rgbNode->rgbRed - 0.330 * rgbNode->rgbGreen + 0.498 * rgbNode->rgbBlue + 128;//V = 0.449R - 0.435G - 0.083B + 128;int tmp_v = 0.449 * rgbNode->rgbRed - 0.435 * rgbNode->rgbGreen + 0.083 * rgbNode->rgbBlue + 128;dst_u[u_index] = tmp_u > 255 ? 255 : (tmp_u < 0 ? 0 : tmp_u);dst_v[v_index] = tmp_v > 255 ? 255 : (tmp_v < 0 ? 0 : tmp_v);v_index++;u_index++;}}}return 0;
}

I420与RGB24颜色空间相互转换

rgb24与rgb32计算方式基本一致。却别在于rgb32每个像素点4字节;gb24每个像素点3字节。

转换代码

typedef  struct  RGB24 {uint8_t     rgbBlue;       // 蓝色分量uint8_t     rgbGreen;      // 绿色分量uint8_t     rgbRed;        // 红色分量RGB24(){rgbBlue = 0;rgbGreen = 0;rgbRed = 0;}
} RGB24;int I420_2_rgb24(uint8_t* src, uint8_t* dst, uint32_t width, uint32_t height)
{uint8_t* src_y = src;uint8_t* src_u = src + width * height;uint8_t* src_v = src + width * height * 5 / 4;RGB24* prgb = reinterpret_cast<RGB24*>(dst);int rgbindex = 0;for (int y = 0; y < height; y++){for (int x = 0; x < width; x++){RGB24* rgbNode = &prgb[rgbindex];//读取YUVuint8_t Y = src_y[y * width + x];uint8_t U = src_u[y / 2 * width / 2 + x / 2];uint8_t V = src_v[y / 2 * width / 2 + x / 2];//计算rgb//R = Y + 1.4075(V - 128);//G = Y - 0.3455(U - 128) - 0.7169(V - 128);//B = Y + 1.779(U - 128);int tmpr = Y + 1.402 * (V - 128);int tmpg = Y - 0.34413 * (U - 128) - 0.71414 * (V - 128);int tmpb = Y + 1.772 * (U - 128);//越界保护rgbNode->rgbRed = tmpr > 255 ? 255 : (tmpr < 0 ? 0 : tmpr);rgbNode->rgbGreen = tmpg > 255 ? 255 : (tmpg < 0 ? 0 : tmpg);rgbNode->rgbBlue = tmpb > 255 ? 255 : (tmpb < 0 ? 0 : tmpb);rgbindex++;}}return 0;
}int rgb24_2_I420(uint8_t* src, uint8_t* dst, uint32_t width, uint32_t height)
{RGB24* prgb = reinterpret_cast<RGB24*>(src);uint8_t* dst_y = dst;uint8_t* dst_u = dst + width * height;uint8_t* dst_v = dst + width * height * 5 / 4;//Y = 0.298R + 0.612G + 0.117B;//U = -0.168R - 0.330G + 0.498B + 128;//V = 0.449R - 0.435G - 0.083B + 128;int rgbindex = 0;int u_index = 0;int v_index = 0;int y_index = 0;for (int y = 0; y < height; y++){for (int x = 0; x < width; x++){rgbindex = y * width + x;RGB24* rgbNode = &prgb[rgbindex];//Y = 0.298R + 0.612G + 0.117B;int tmp_y = 0.298 * rgbNode->rgbRed + 0.612 * rgbNode->rgbGreen + 0.117 * rgbNode->rgbBlue;dst_y[y_index] = tmp_y > 255 ? 255 : (tmp_y < 0 ? 0 : tmp_y);y_index++;if (y % 2 == 0 &&x % 2 == 0){//U = -0.168R - 0.330G + 0.498B + 128;int tmp_u = -0.168 * rgbNode->rgbRed - 0.330 * rgbNode->rgbGreen + 0.498 * rgbNode->rgbBlue + 128;//V = 0.449R - 0.435G - 0.083B + 128;int tmp_v = 0.449 * rgbNode->rgbRed - 0.435 * rgbNode->rgbGreen + 0.083 * rgbNode->rgbBlue + 128;dst_u[u_index] = tmp_u > 255 ? 255 : (tmp_u < 0 ? 0 : tmp_u);dst_v[v_index] = tmp_v > 255 ? 255 : (tmp_v < 0 ? 0 : tmp_v);v_index++;u_index++;}}}return 0;
}

 三、代码路径

csdn:https://download.csdn.net/download/u011645307/21113273

github:https://github.com/liangqidong/ColorConversion.git

这篇关于视音频数据处理入门:颜色空间(一)---转换理解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/295220

相关文章

Python3脚本实现Excel与TXT的智能转换

《Python3脚本实现Excel与TXT的智能转换》在数据处理的日常工作中,我们经常需要将Excel中的结构化数据转换为其他格式,本文将使用Python3实现Excel与TXT的智能转换,需要的可以... 目录场景应用:为什么需要这种转换技术解析:代码实现详解核心代码展示改进点说明实战演练:从Excel到

Java数字转换工具类NumberUtil的使用

《Java数字转换工具类NumberUtil的使用》NumberUtil是一个功能强大的Java工具类,用于处理数字的各种操作,包括数值运算、格式化、随机数生成和数值判断,下面就来介绍一下Number... 目录一、NumberUtil类概述二、主要功能介绍1. 数值运算2. 格式化3. 数值判断4. 随机

C语言中自动与强制转换全解析

《C语言中自动与强制转换全解析》在编写C程序时,类型转换是确保数据正确性和一致性的关键环节,无论是隐式转换还是显式转换,都各有特点和应用场景,本文将详细探讨C语言中的类型转换机制,帮助您更好地理解并在... 目录类型转换的重要性自动类型转换(隐式转换)强制类型转换(显式转换)常见错误与注意事项总结与建议类型

Python实现视频转换为音频的方法详解

《Python实现视频转换为音频的方法详解》这篇文章主要为大家详细Python如何将视频转换为音频并将音频文件保存到特定文件夹下,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. python需求的任务2. Python代码的实现3. 代码修改的位置4. 运行结果5. 注意事项

使用Python实现图片和base64转换工具

《使用Python实现图片和base64转换工具》这篇文章主要为大家详细介绍了如何使用Python中的base64模块编写一个工具,可以实现图片和Base64编码之间的转换,感兴趣的小伙伴可以了解下... 简介使用python的base64模块来实现图片和Base64编码之间的转换。可以将图片转换为Bas

Linux环境变量&&进程地址空间详解

《Linux环境变量&&进程地址空间详解》本文介绍了Linux环境变量、命令行参数、进程地址空间以及Linux内核进程调度队列的相关知识,环境变量是系统运行环境的参数,命令行参数用于传递给程序的参数,... 目录一、初步认识环境变量1.1常见的环境变量1.2环境变量的基本概念二、命令行参数2.1通过命令编程

深入理解Apache Airflow 调度器(最新推荐)

《深入理解ApacheAirflow调度器(最新推荐)》ApacheAirflow调度器是数据管道管理系统的关键组件,负责编排dag中任务的执行,通过理解调度器的角色和工作方式,正确配置调度器,并... 目录什么是Airflow 调度器?Airflow 调度器工作机制配置Airflow调度器调优及优化建议最

Linux使用dd命令来复制和转换数据的操作方法

《Linux使用dd命令来复制和转换数据的操作方法》Linux中的dd命令是一个功能强大的数据复制和转换实用程序,它以较低级别运行,通常用于创建可启动的USB驱动器、克隆磁盘和生成随机数据等任务,本文... 目录简介功能和能力语法常用选项示例用法基础用法创建可启动www.chinasem.cn的 USB 驱动

Python xmltodict实现简化XML数据处理

《Pythonxmltodict实现简化XML数据处理》Python社区为提供了xmltodict库,它专为简化XML与Python数据结构的转换而设计,本文主要来为大家介绍一下如何使用xmltod... 目录一、引言二、XMLtodict介绍设计理念适用场景三、功能参数与属性1、parse函数2、unpa

一文带你理解Python中import机制与importlib的妙用

《一文带你理解Python中import机制与importlib的妙用》在Python编程的世界里,import语句是开发者最常用的工具之一,它就像一把钥匙,打开了通往各种功能和库的大门,下面就跟随小... 目录一、python import机制概述1.1 import语句的基本用法1.2 模块缓存机制1.