基于深度学习的车牌识别项目的APP部分之图像预处理(一):C语言读取bmp图像信息

2023-05-16

车牌识别项目之图像预处理一:C语言读取bmp图像信息

    • 一、什么是bmp文件
    • 二、BMP格式结构
      • 1、文件信息头
      • 2、图像描述信息块
      • 3、BMP调色板
      • 4、BMP图像数据区
        • ①像素存储
        • ②像素数据
        • ③位图像素格式
    • 三、原理实现:
    • 1、打开一张bmp文件
    • 2、查看图像属性
    • 3、用ULtraEdit打开bmp文件。显示的是16进制的代码。
    • 四、完整代码实现

本文是将用SoC FPGA 板子实现的车牌识别项目,用的改写的LeNet网络。主要实现分俩个大的部分:1、是用fpga实现的卷积、偏置激活、池化和全连接操作。2、是在ARM端实现摄像头读进来的图像数据的预处理操作。我们先介绍的是在ARM对图像的操作,后续继续更新。

一、什么是bmp文件

BMP是bitmap的缩写形式,bitmap顾名思义,就是位图也即Windows位图。它一般由4部分组成:文件头信息块、图像描述信息块、颜色表(在真彩色模式无颜色表)和图像数据区组成。在系统中以BMP为扩展名保存。

图像通常保存的颜色深度有2(1位)、16(4位)、256(8位)、65536(16位)和1670万(24位)种颜色(其中位是表示每点所用的数据位)。8位图像可以是索引彩色图像外,也可以是灰阶图像。表示透明的alpha通道也可以保存在一个类似于灰阶图像的独立文件中。带有集成的alpha通道的32位版本已经随着Windows XP出现,它在Windows系统的登录界面和系统主题中都有使用。

关键:
在读取bmp图片的时候,一定要注意内存对齐的问题,譬如文件头,否则无法读取出正确结果。

关于图片的像素数据,每一行的像素的字节数必须是4的整数倍。如果不是,则需要补齐。一般来说,bmp图像文件的数据是从下到上,从左到右的。即从文件中最先读到的是图像最下面一行的左边第一个像素,然后是坐标第二个…接下来是倒数第二行的第一个像素。

二、BMP格式结构

BMP文件的数据按照从文件头开始的先后顺序分为四个部分:
◆ 位图文件头(bmp file header): 提供文件的格式、大小等信息
◆ 位图信息头(bitmap information):提供图像数据的尺寸、位平面数、压缩方式、颜色索引等信息
◆ 调色板(color palette):可选,如使用索引来表示图像,调色板就是索引与其对应的颜色的映射表
◆ 位图数据(bitmap data):图像数据区

BMP图片文件数据表如下:
在这里插入图片描述

1、文件信息头

文件信息头 (14字节)存储着文件类型,文件大小等信息。

// 文件信息头结构体
typedef struct tagBITMAPFILEHEADER
{
   /unsigned short bfType;        // 19778,必须是BM字符串,对应的十六进制为0x4d42,十进制为19778,否则不是bmp格式文件
    unsigned int   bfSize;        // 文件大小 以字节为单位(2-5字节)
    unsigned short bfReserved1;   // 保留,必须设置为0 (6-7字节)
    unsigned short bfReserved2;   // 保留,必须设置为0 (8-9字节)
    unsigned int   bfOffBits;     // 从文件头到像素数据的偏移  (10-13字节)
} BITMAPFILEHEADER;

2、图像描述信息块

图片信息头 (40字节)存储着图像的尺寸,颜色索引,位平面数等信息

//图像信息头结构体
typedef struct tagBITMAPINFOHEADER
{
    unsigned int    biSize;          // 此结构体的大小 (14-17字节)
    long            biWidth;         // 图像的宽  (18-21字节)
    long            biHeight;        // 图像的高  (22-25字节)
    unsigned short  biPlanes;        // 表示bmp图片的平面属,显然显示器只有一个平面,所以恒等于1 (26-27字节)
    unsigned short  biBitCount;      // 一像素所占的位数,一般为24   (28-29字节)
    unsigned int    biCompression;   // 说明图象数据压缩的类型,0为不压缩。 (30-33字节)
    unsigned int    biSizeImage;     // 像素数据所占大小, 这个值应该等于上面文件头结构中bfSize-bfOffBits (34-37字节)
    long            biXPelsPerMeter; // 说明水平分辨率,用象素/米表示。一般为0 (38-41字节)
    long            biYPelsPerMeter; // 说明垂直分辨率,用象素/米表示。一般为0 (42-45字节)
    unsigned int    biClrUsed;       // 说明位图实际使用的彩色表中的颜色索引数(设为0的话,则说明使用所有调色板项)。 (46-49字节)
    unsigned int    biClrImportant;  // 说明对图象显示有重要影响的颜色索引的数目,如果是0,表示都重要。(50-53字节)
} BITMAPINFOHEADER;

3、BMP调色板

调色板 (由颜色索引数决定)【可以没有此信息】这部分定义了图像中所用的颜色。如上所述,位图图像一个像素接着一个像素储存,每个像素使用一个或者多个字节的值表示,所以调色板的目的就是要告诉应用程序这些值所对应的实际颜色。

典型的位图文件使用RGB彩色模型。在这种模型中,每种颜色都是由不同强度(从0到最大强度)的红色(R)、绿色(G)和蓝色(B)组成的,也就是说,每种颜色都可以使用红色、绿色和蓝色的值所定义。

在位图文件的实现中,调色板可以包含很多条目,条目个数就是图像中所使用的颜色的个数。

//24位图像素信息结构体,即调色板
typedef struct tagRGBQUAD{
    unsigned char rgbBlue;   //该颜色的蓝色分量  (值范围为0-255)
    unsigned char rgbGreen;  //该颜色的绿色分量  (值范围为0-255)
    unsigned char rgbRed;    //该颜色的红色分量  (值范围为0-255)
    unsigned char rgbReserved;// 保留,必须为0
} RGBQUAD;

每个条目用来描述一种颜色,包含4个字节,其中三个表示蓝色、绿色和红色,第四个字节没有使用(大多数应用程序将它设为0);对于每个字节,数值0表示该颜色分量在当前的颜色中没有使用,而数值255表示这种颜色分量使用最大的强度。

注意

  • 1,4,8位图像才会使用调色板数据,16,24,32位图像不需要调色板数据,即调色板最多只需要256项(索引0 - 255)。
  • 颜色表的大小根据所使用的颜色模式而定:2色图像为8字节;16色图像位64字节;256色图像为1024字节。其中,每4字节表示一种颜色,并以B(蓝色)、G(绿色)、R(红色)、alpha(32位位图的透明度值,一般不需要)。即首先4字节表示颜色号1的颜色,接下来表示颜色号2的颜色,依此类推。
  • 颜色表中RGBQUAD结构数据的个数有biBitCount来确定,当biBitCount=1,4,8时,分别有2,16,256个表项。
  • 当biBitCount=1时,为2色图像,BMP位图中有2个数据结构RGBQUAD,一个调色板占用4字节数据,所以2色图像的调色板长度为2*4为8字节。
  • 当biBitCount=4时,为16色图像,BMP位图中有16个数据结构RGBQUAD,一个调色板占用4字节数据,所以16像的调色板长度为16*4为64字节。
  • 当biBitCount=8时,为256色图像,BMP位图中有256个数据结构RGBQUAD,一个调色板占用4字节数据,所以256色图像的调色板长度为256*4为1024字节。
  • 当biBitCount=16,24或32时,没有颜色表。

4、BMP图像数据区

①像素存储

表示位图中像素的比特是以行为单位对齐存储的,每一行的大小都向上取整为4字节(32位DWORD)的倍数。如果图像的高度大于1,多个经过填充实现对齐的行就形成了像素数组。

完整存储的一行像素所需的字节数可以通过这个公式计算:
在这里插入图片描述
Windows规定一个扫描行所占的字节数必须是4的倍数(即以long为单位),不足的以0填充,

//一个扫描行所占的字节数计算方法:
DataSizePerLine= (biWidth* biBitCount+31)/8;
//一个扫描行所占的字节数
DataSizePerLine= DataSizePerLine/4*4; // 字节数必须是4的倍数
//位图数据的大小(不压缩情况下):
DataSize= DataSizePerLine* biHeight;

BMP位图要求一行的字节数为4的整数倍,4字节就是32位,根据整数除法的规则,所以加31(这其实就是数学上的取整运算的计算机实现)!

 (biWidth*biBitCount+31)/32*4 公式算出来的是一行的字节数。

②像素数据

位图数据记录了位图的每一个像素值,记录顺序是在扫描行内是从左到右,扫描行之间是从下到上。
在这里插入图片描述
通常,像素是从下到上、从左到右保存的。但如果使用的不是BITMAPCOREHEADER,那么未压缩的Windows位图还可以从上到下存储,此时图像高度为负值。

每一行的末尾通过填充若干个字节的数据(并不一定为0)使该行的长度为4字节的倍数。像素数组读入内存后,每一行的起始地址必须为4的倍数。这个限制仅针对内存中的像素数组,针对存储时,仅要求每一行的大小为4字节的倍数,对文件的偏移没有限制。

例如:对于24位色的位图,如果它的宽度为1像素,那么除了每一行的数据(蓝、绿、红)需要占3字节外,还会填充1字节;而如果宽为2像素,则需要2字节的填充;宽为3像素时,需要3字节填充;宽为4像素时则不需要填充。

图像相同的条件下,位图图像文件通常比使用其它压缩算法的图像文件大很多。

③位图像素格式

无论是磁盘上的位图文件还是内存中的位图图像,像素都由一组位(英语:bit)表示。

  • 每像素占1位(色深为1位,1bpp)的格式支持2种不同颜色。像素值直接对应一个位的值,最左像素对应第一个字节的最高位。使用该位的值用来对色表的索引:为0表示色表中的第一项,为1表示色表中的第二项(即最后一项)。
  • 每像素占2位(色深为2位,2bpp)的格式支持4种不同颜色。每个字节对应4个像素,最左像素为最高的两位(仅在WindowsCE中有效)。需要使用像素值来对一张含有4个颜色值的色表进行索引。
  • 每像素占4位(色深为4位,4bpp)的格式支持16种不同的颜色。每个字节对应2个像素,最左像素为最高的四位。需要使用像素值来对一张含有16个颜色值的色表进行索引。
  • 每像素占8位(色深为8位,8bpp)的格式支持256种不同的颜色。每个字节对应1个像素。需要使用像素值来对一张含有256个颜色值的色表进行索引。
  • 每像素占16位(色深为16位,16bpp)的格式支持65536种不同的颜色,每2个字节(byte)对应一个像素。该像素的不透明度(英语:alpha)、红、绿、蓝采样值即存储在该2个字节中。
  • 每像素占24位(色深为24位,24bpp)的格式支持16777216种不同的颜色,每3个字节对应一个像素。
  • 每像素占32位(色深为32位,32bpp)的格式支持4294967296种不同的颜色,每4个字节对应一个像素。

简单来说就是如下:
位图的一个像素值所占的字节数:
当biBitCount=1时,8个像素占1个字节;
当biBitCount=4时,2个像素占1个字节;
当biBitCount=8时,1个像素占1个字节;
当biBitCount=16时,1个像素占2个字节;
当biBitCount=24时,1个像素占3个字节;
当biBitCount=32时,1个像素占4个字节;

三、原理实现:

这里我们先用Lena.bmp图像实现,后续便于我们给你更好的理解车牌。

1、打开一张bmp文件

在这里插入图片描述

2、查看图像属性

在这里插入图片描述

3、用ULtraEdit打开bmp文件。显示的是16进制的代码。

用其他软件打开也是可以的
在这里插入图片描述
现在我们来读取这些代码,看看他们到底保存了一些啥东西。 在这里要注意的是Windows的数据是倒着念的,(小端存储:低地址存低数据 。如果不理解的可以参考此文连接,请点击:)这是PC电脑的特色。如果一段数据为42 4D,倒着念就是4D 42,即0x4D42。 因此,如果bfSize的数据为A2 1E 04 00,实际上就成了0x00041EA2,也就是0x41EA2。
在这里插入图片描述
在这里插入图片描述
上述圈起来的信息用代码读出来发现一一对应:

unsigned short bfType          = 0x4D42     = 19778
unsigned int   bfSize          = 0xC0036    = 786486字节=786486/1024=768kb
unsigned short bfReserved1     = 00 00
unsigned short bfReserved2     = 00 00
unsigned int   bfOffBits       = 0X0000036 = 0x36 = 54字节

unsigned int   biSize          = 0x00000028 = 0x28  = 40字节
int            biWidth         = 0x00000200 = 0x200 = 512像素;
int            biHeight        = 0x00000200 = 0x200 = 512像素 ;
unsigned short biPlanes        = 0x0001 =0x1 = 1;
unsigned short biBitCount      = 0x0018     = 0x18  = 24;
unsigned int   biCompression   = 0x00000000 = 0;
unsigned int   biSizeImage     = 0x000C0000 = 0xC0000=786,432;
int            biXPelsPerMeter = 0x00000000 = 0;
int            biYPelsPerMeter = 0x00000000 = 0;  
unsigned int   biClrUsed       = 0x00000000 = 0;
unsigned int   biClrImportant  = 0x00000000 = 0;

unsigned char rgbBlue  = 0x9E5137 其中R:0X37 G:0X51 B:0X9E ;   //该颜色的蓝色分量  (值范围为0-255)
unsigned char rgbGreen = 0xA5583E 其中R:0X3E G:0X58 B:0XA5 ;   //该颜色的绿色分量  (值范围为0-255)
unsigned char rgbRed   = 0x7A5A3E 其中R:0X3E G:0X5A B:0X7A ;   //该颜色的红色分量  (值范围为0-255)
unsigned char rgbReserved;  // 保留,必须为0

四、完整代码实现

BmpFormat.h

# ifndef BMP_H
# define BMP_H
/*
BMP格式
这种格式内的数据分为三到四个部分,依次是:
文件信息头 (14字节)存储着文件类型,文件大小等信息
图片信息头 (40字节)存储着图像的尺寸,颜色索引,位平面数等信息
调色板 (由颜色索引数决定)【可以没有此信息】
位图数据 (由图像尺寸决定)每一个像素的信息在这里存储

一般的bmp图像都是24位,也就是真彩。每8位为一字节,24位也就是使用三字节来存储每一个像素的信息,三个字节对应存放r,g,b三原色的数据,
每个字节的存贮范围都是0-255。那么以此类推,32位图即每像素存储r,g,b,a(Alpha通道,存储透明度)四种数据。8位图就是只有灰度这一种信息,
还有二值图,它只有两种颜色,黑或者白。
*/
// 文件信息头结构体
typedef struct tagBITMAPFILEHEADER
{
    //unsigned short bfType;        // 19778,必须是BM字符串,对应的十六进制为0x4d42,十进制为19778,否则不是bmp格式文件
    unsigned int   bfSize;        // 文件大小 以字节为单位(2-5字节)
    unsigned short bfReserved1;   // 保留,必须设置为0 (6-7字节)
    unsigned short bfReserved2;   // 保留,必须设置为0 (8-9字节)
    unsigned int   bfOffBits;     // 从文件头到像素数据的偏移  (10-13字节)
} BITMAPFILEHEADER;

//图像信息头结构体
typedef struct tagBITMAPINFOHEADER
{
    unsigned int    biSize;          // 此结构体的大小 (14-17字节)
    long            biWidth;         // 图像的宽  (18-21字节)
    long            biHeight;        // 图像的高  (22-25字节)
    unsigned short  biPlanes;        // 表示bmp图片的平面属,显然显示器只有一个平面,所以恒等于1 (26-27字节)
    unsigned short  biBitCount;      // 一像素所占的位数,一般为24   (28-29字节)
    unsigned int    biCompression;   // 说明图象数据压缩的类型,0为不压缩。 (30-33字节)
    unsigned int    biSizeImage;     // 像素数据所占大小, 这个值应该等于上面文件头结构中bfSize-bfOffBits (34-37字节)
    long            biXPelsPerMeter; // 说明水平分辨率,用象素/米表示。一般为0 (38-41字节)
    long            biYPelsPerMeter; // 说明垂直分辨率,用象素/米表示。一般为0 (42-45字节)
    unsigned int    biClrUsed;       // 说明位图实际使用的彩色表中的颜色索引数(设为0的话,则说明使用所有调色板项)。 (46-49字节)
    unsigned int    biClrImportant;  // 说明对图象显示有重要影响的颜色索引的数目,如果是0,表示都重要。(50-53字节)
} BITMAPINFOHEADER;

//24位图像素信息结构体,即调色板
typedef struct tagRGBQUAD{
    unsigned char rgbBlue;   //该颜色的蓝色分量  (值范围为0-255)
    unsigned char rgbGreen;  //该颜色的绿色分量  (值范围为0-255)
    unsigned char rgbRed;    //该颜色的红色分量  (值范围为0-255)
    unsigned char rgbReserved;// 保留,必须为0
} RGBQUAD;

#endif

read_bmp.c

#include <stdio.h>
#include <malloc.h>
#include "BmpFormat.h"

BITMAPFILEHEADER fileHeader;
BITMAPINFOHEADER infoHeader;

void showBmpHead(BITMAPFILEHEADER pBmpHead)
{  //定义显示信息的函数,传入文件头结构体
    printf("BMP文件大小:%dkb\n", fileHeader.bfSize/1024);
    printf("保留字必须为0:%d\n",  fileHeader.bfReserved1);
    printf("保留字必须为0:%d\n",  fileHeader.bfReserved2);
    printf("实际位图数据的偏移字节数: %d\n",  fileHeader.bfOffBits);
}
void showBmpInfoHead(BITMAPINFOHEADER pBmpinfoHead)
{//定义显示信息的函数,传入的是信息头结构体
   printf("位图信息头:\n" );
   printf("信息头的大小:%d\n" ,infoHeader.biSize);
   printf("位图宽度:%d\n" ,infoHeader.biWidth);
   printf("位图高度:%d\n" ,infoHeader.biHeight);
   printf("图像的位面数(位面数是调色板的数量,默认为1个调色板):%d\n" ,infoHeader.biPlanes);
   printf("每个像素的位数:%d\n" ,infoHeader.biBitCount);
   printf("压缩方式:%d\n" ,infoHeader.biCompression);
   printf("图像的大小:%d\n" ,infoHeader.biSizeImage);
   printf("水平方向分辨率:%d\n" ,infoHeader.biXPelsPerMeter);
   printf("垂直方向分辨率:%d\n" ,infoHeader.biYPelsPerMeter);
   printf("使用的颜色数:%d\n" ,infoHeader.biClrUsed);
   printf("重要颜色数:%d\n" ,infoHeader.biClrImportant);
}

int main()
{
    FILE* fp;
    fp = fopen("lena.bmp", "rb");//读取同目录下的image.bmp文件。
    if(fp == NULL)
    {
        printf("打开'lena.bmp'失败!\n");
        return -1;
    }
    //如果不先读取bifType,根据C语言结构体Sizeof运算规则——整体大于部分之和,从而导致读文件错位
    unsigned short  fileType;
    fread(&fileType,1,sizeof (unsigned short), fp);  
    if (fileType == 0x4d42)
    {
        printf("文件类型标识正确!" );  
        printf("\n文件标识符:%d\n", fileType);
        fread(&fileHeader, 1, sizeof(BITMAPFILEHEADER), fp);
        showBmpHead(fileHeader);
        fread(&infoHeader, 1, sizeof(BITMAPINFOHEADER), fp);
        showBmpInfoHead(infoHeader);
        fclose(fp);
    }
}

运行结果:
在这里插入图片描述
原理:参考百度百科和维基百科

完整的车牌识别项目若有需要请私聊博主。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于深度学习的车牌识别项目的APP部分之图像预处理(一):C语言读取bmp图像信息 的相关文章

  • c语言编程规范第三部分

    3 头文件应向稳定的方向包含 头文件的包含关系是一种依赖 xff0c 一般来说 xff0c 应当让不稳定的模块依赖稳定的模块 xff0c 从而当不稳定的模块发生变化时 xff0c 不会影响 xff08 编译 xff09 稳定的模块 就我们的
  • 看完《C++ primer》后,我都收获了什么?

    文章目录 1 语言只是一个工具2 光学会一门语言还不够3 结语 迫于读研和未来就业的压力 xff0c 我研一上自学了C 43 43 的这门语言 xff0c 自我感觉比较认真的看完了 C 43 43 primer 这本书的大部分章节 xff0
  • Ubuntu18.04 ROS Melodic版本安装gazebo_ros_pkgs包

    疫情期间宅在家没法做实验 xff0c 只能上手gazebo做仿真 xff0c 导入实验室机器人的相关文件后 xff0c 打算看看效果 xff0c 运行代码 roslaunch probot gazebo probot anno gazebo
  • vim如何批量注释

    1 ctrl 43 v 进入 2 按箭头 选中要注释的首行 3 按下大写 i 进入插入模式 4输入 按esc 就可以看到如下内容
  • 还弄不明白【委托和事件】么?看这一篇就足够了!!!

    这两个概念长时间不用了 xff0c 今天看到CAD二次开发中用到了自定义事件 xff0c 有点迷糊了 xff0c 索性再整理一下加深印象 xff01 一说到委托和事件 xff0c 他们总是绑定在一起的不可分割 xff01 可能你会说啊 xf
  • 三种简单排序(冒泡、插入、选择)的比较和图解

    冒泡排序 这种排序方式是最容易理解的 xff0c 主体思想就是 xff1a 指针重复地走访过要排序的数列 xff0c 一次比较两个元素 xff0c 如果他们的顺序错误就把他们交换过来 走访数列的工作是重复地进行直到没有再需要交换 xff0c
  • ModuleNotFoundError: No module named 'XXX'的解决办法

    类似问题一 ModuleNotFoundError No module named 39 captcha 39 pycharm打开的项目 xff0c 在虚拟环境里通过终端命令python manage py runserver运行pytho
  • 微信小程序实现搜索功能以及效果(超详细)

    我们先来看一下实现哪些功能 1 搜索历史记录以及清空历史记录 2 热门搜索推荐以及更新推荐内容 3 根据输入框输入的内容来自动搜索相关查询 后台逻辑是模糊查询 后台就先不扯了 这里我用的是自己定义的虚拟数据 暂时没用后台接口 可能有点问题
  • 微信小程序实现收货地址城市选择效果(添加收货地址)

    先来张效果图 这里主要是城市选择效果 请忽视其他 不要吐槽 谢谢 接下来看一下代码吧 wxml lt pages my my add address index wxml gt lt view class 61 34 redact addr
  • uni-app实现商城多商家购物车功能(超详细, 附带源码)

    我们先来看一下效果 有什么不懂可以直接下方留言 先来看代码 lt template gt lt view class 61 34 cart 34 gt lt 购物车为空 S gt lt view v if 61 34 cartList le
  • 微信小程序web-view的使用教程

    最近公司有需求 xff0c 需要点击小程序首页banner xff0c 跳转到别人的h5页面 首先是域名的问题 xff1a 步骤 xff1a 先登录小程序开发平台 xff0c 将页面需要跳转的域名写上去 xff0c 注意了 xff0c 域名
  • uni-app实现上传图片裁剪效果(附源码)

    我们先来看一下效果 封装一个组件在components下创建一个 文件夹随意命名 xff0c 这里我是uni img cropper uni img cropper vue lt template gt lt view class 61 3
  • js 一维数组和二维数组实现足迹、浏览记录等场景

    再开发过程中 xff0c 再没有接口提供的情况下来实现浏览记录或者搜索记录等场景 我们可以利用本地缓存实现 xff0c 废话不多说 xff0c 直接上代码 xff1a 多维数组 64 param Array arr 数组 64 param
  • Markdown使用(超详细)

    xff08 HBuilderX xff09 掌握md及HBuilderX对md的强大支持 如果没有点右键设置自动换行 xff0c 可按Alt 43 滚轮横向滚动查看 很多人只把markdown用于网络文章发表 xff0c 这糟蹋了markd
  • 宫格导航 (自定义更灵活,超详细)

    先来看一下效果 调用方法 lt 页面调用 gt lt nav grid list 61 34 menu 34 64 click 61 34 34 gt lt nav grid gt 数据 export default data return
  • Firefox和Chromedriver驱动下载及安装步骤

    Mozilla Firefox Mozilla Firefox 中文名称 34 火狐 34 是由一个自由及开放源代码的网页浏览器 使用Gecko排版引擎 支持多种操作系统 如 Windows Mac OS X 及GNU Linux等 该浏览
  • 流媒体选择Nginx是福还是祸?

    流媒体选择Nginx是福还是祸 xff1f CDN xff0c 视频云 xff0c 已经 僧多粥少 视频直播的持续升温 xff0c 无意间也让带宽生意的争夺变得异常残酷 一时间 xff0c 各种云计算 CDN 视频云提供商都在视频尤其是直播
  • xpath去除换行\空格

    使用xpath获取文本内容 有空格或者换行就用normalize space 方法 例 intro li 61 div xpath 39 normalize space div 64 class 61 34 bookinfo 34 p te
  • Java 静态域和静态方法

    main方法都被标记为static修饰符 xff0c 本文讨论一下该修饰符含义 静态域和静态方法 一 静态域静态常量 二 静态方法三 工厂方法 一 静态域 若把域定义为static xff0c 则每个类中只有一个这样的域 而每一个对象对于所
  • Linux下传感器驱动。rk3399

    基于rk3399的Linux下的陀螺仪mpu9250传感器驱动 mpu6050 bh1750传感器 xff0c sht30 35温湿度传感器驱动 已经成功移植 xff0c 通过iic驱动获取到数据 Linux驱动开发

随机推荐