iOS正确获取图片参数深入探究及CGImageRef的使用(附源码)
一 图片参数的正确获取
先拿一张图片作为测试使用
图片参数如下:
图片的尺寸为:
-宽1236个像素点
-高748个像素点
-色彩空间为RGB
-描述文件为彩色LCD
-带有Alpha通道
请记住这几个参数,待会儿我们演示如何正确获取。
将这张图片分别放在三个位置
位置1: 2x图位置
位置2: 3x图位置
位置3: bundle中
然后我们通过代码分别获取这三个不同位置的图片,然后输出他的宽高以及CGImageRef对象获取的宽高,代码如下:
输出结果如图所示:
会发现,如果单纯的使用[UIImage imageNamed:@“”];方法来获取图片之后,直接输出图片的宽高和图片的原尺寸是不相符的:
如果是2X位置的图片,输出的高度为图片真实高度/2的结果
如果是3X位置的图片,输出的高度为图片真实高度/3的结果
如果是从bundle中直接获取图片,输出的宽高为真实的结果。
原因是因为IOS会根据我们存放图片的位置不同,在加载的时候对比例进行处理,如果只是单纯的展示的话并不会有问题,但是如果是做图片区域裁剪,那么需要注意使用[UIImage imageNamed:@“”]获取到的图片对象的size并不是图片的真实尺寸,而是要使用CGImageRef来获取到图像的结构体指针,再去获取到真正的图片尺寸。
官方文档里对[UIImage imageNamed:@“”]是这样描述的:
系统会从缓存中寻找这张图片,并对图片进行适当调整以返回适合屏幕显示的图片,所以如果这张图片在项目中会多次用到,那么可以用这个方法来加载图片以提高内存资源利用效率和加载速度,如果只是使用一次的话,更推荐使用imageWithContentsOfFile:方法来加载图片,这样图片不会被加载到缓存中,较少内存压力。
二 使用CGImageRef获得图片的详细参数
CGImageRef中还存储了很多图片的信息,打印一下
可以看到输出的参数有:
CGColorSpace
kCGColorSpaceICCBased : ICCBased颜色空间 ICCBased颜色空间基于 ICC( 国际色彩组织 ) 制定的跨平台颜色配置文件
kCGColorSpaceModelRGB:使用RGB颜色空间
LCD : 使用LCD色域
width = 1236 :图片的宽度为1236个像素点
height = 748 :图片的高度为748个像素点
bpc = 8:每个通道有8bit 也就是支持256个色值
bpp = 32: 每个像素有32位,R通道8位 + G通道8位 + B通道8位 + A通道8位 = 32位
row bytes = 4944:每行占用4944个字节,计算公式为(每个像素32位*每行1236个像素点/8bit = 4944字节
kCGImageAlphaNoneSkipLast : 有alpha通道,且在最末尾,但是不存储alhpa值
0 (default byte order):这个其实存储的是CGBitmapInfo,使用默认的字节序
kCGImagePixelFormatPacked:像素格式信息,根据像素格式压缩
is mask? No:是否为Mask图层,Mask图层是设置其显示部分与不显示部分达到特殊的效果的方法
has masking color? No:是否有mask color,如果设置有的话对应的颜色会变成透明
has soft mask:是否有渐变遮罩
has matte? No:是否有蒙版,mask和matte两个的作用都是控制图像的透明区域的。通常mask都是在图层(节点)上临时绘制的。而matte很多时候都是使用现成的黑白图作为控制透明区域的图来使用。
should interpolate? Yes:是否抗锯齿
使用CGImageRef 我们几乎可以获得我们想要的任何参数。
三 获取CGImageRef属性值的常用方法
先获取到CGImageRef的引用,本章节介绍的方法全部基于该引用演示:
UIImage *img = [UIImage imageNamed:@"8BitImg2x"];CGImageRef imgRef = [img CGImage];
1.获取图片的宽度
size_t CGImageGetWidth(CGImageRef cg_nullable image)
该方法返回一个sizt_t类型的数值,size_t 的全称是size type,是无符号整型,size_t的真实类型与操作系统有关。
在32位的系统中定义为 typedef unsigned int size_t;
在64位系统中定义为 typedef unsigned long size_t;
使用的时候把它作为无符号整数使用就可以了
CGImageGetWidth方法返回图片的像素宽度,使用及输出示例如下:
size_t imgWidth = CGImageGetWidth(imgRef);printf("图片的像素宽度为:%zu",imgWidth);
输出结果:图片的像素宽度为:1236
2.获取图片的高度
size_t CGImageGetHeight(CGImageRef cg_nullable image)
跟获取图片宽度的方法类似,该方法返回图片的高度,使用示例及结果输出如下
size_t imgHeight = CGImageGetHeight(imgRef);printf("图片的像素高度为:%zu",imgHeight);
输出结果:图片的像素高度为:748
3.获取图片每个颜色通道占用的位数(bpp)
CGImageGetBitsPerComponent(CGImageRef cg_nullable image)
使用及输出示例如下:
size_t bitsPerComponent = CGImageGetBitsPerComponent(imgRef);printf("每个通道占用的位数:%zu",bitsPerComponent);
输出结果:每个通道占用的位数:8
4.获取每个像素点占用的位数
size_t CGImageGetBitsPerPixel(CGImageRef cg_nullable image)
使用及输出示例如下:
size_t bitsPerPixel = CGImageGetBitsPerPixel(imgRef);printf("每个像素占用的位数:%zu",bitsPerPixel);
输出结果:每个像素占用的位数:32
其实通过CGImageGetBitsPerComponent方法及CGImageGetBitsPerPixel,我们已经可以得知该图片格式为32位,每个通道8位,所以该图片也就是4通道,RGBA格式,带有alpha通道的图片,这在我们需要判断图片是否带有alpha通道的场景下还是很有用的。
针对这个方法,文尾还有更进一步的深究,一定要看。(划重点)
5.获取每行像素占用的字节数
size_t CGImageGetBytesPerRow(CGImageRef cg_nullable image)
使用及输出示例如下:
size_t bitsPerRow = CGImageGetBytesPerRow(imgRef);printf("每行像素占用的位数:%zu",bitsPerRow);
输出结果:每行像素占用的位数:4944
计算方法为:图片的宽度1236(宽有1236个像素点) * 每个像素占用的位数32 ÷ 每个字节的位数8(1byte = 8bit) = 每行像素占用的字节数4944
6.获取图片的颜色空间
CGColorSpaceRef __nullable CGImageGetColorSpace(CGImageRef cg_nullable image)
使用及输出示例如下:
CGColorSpaceRef colorSpaceRef = CGImageGetColorSpace(imgRef);NSLog(@"颜色空间为%@",colorSpaceRef);
如果是8位三通道的图片,那么CGImageGetBitsPerPixel方法返回的结果就是24,拿一张不带alpha通道的图片验证一下:
使用及输出示例如下:
输出结果:颜色空间为<CGColorSpace 0x60000151fea0> (kCGColorSpaceICCBased; kCGColorSpaceModelRGB; sRGB IEC61966-2.1)
代表使用的是RGB颜色空间
7.获取图片的alpha信息
使用及输出示例如下:
CGImageAlphaInfo imageAlphaInfo = CGImageGetAlphaInfo(imgRef);NSLog(@"alpha通道信息为 %u",imageAlphaInfo);
输出结果:alpha通道信息为 5
通过CGImageAlphaInfo的枚举值来查阅
typedef CF_ENUM(uint32_t, CGImageAlphaInfo) {kCGImageAlphaNone, /* For example, RGB. */kCGImageAlphaPremultipliedLast, /* For example, premultiplied RGBA */kCGImageAlphaPremultipliedFirst, /* For example, premultiplied ARGB */kCGImageAlphaLast, /* For example, non-premultiplied RGBA */kCGImageAlphaFirst, /* For example, non-premultiplied ARGB */kCGImageAlphaNoneSkipLast, /* For example, RBGX. */kCGImageAlphaNoneSkipFirst, /* For example, XRGB. */kCGImageAlphaOnly /* No color data, alpha data only */
};
可知该图片的alpha信息为kCGImageAlphaNoneSkipLast,代表该图片有alpha通道且在末尾,但是忽略该值,并不参与图片实际显示的计算。
CGImageAlphaInfo的作用:
(1)位图是否包含alpha通道
(2)alpha位在图像数据中的位置,在bimap首位还是末尾
(3)alpha值是否被预乘,在显示的时候是否需要将每个通道的值乘上alpa值作为最终展示的值
Alpha混合是通过使用线性插值公式将源图像的颜色分量与目标图像的颜色成分相结合来实现的。
对于每个枚举值的说明如下
kCGImageAlphaFirst 阿尔法分量存储在每个像素的最高有效位中。例如,非预乘ARGB。
kCGImageAlphaLast 阿尔法分量被存储在每个像素的最低有效位中。例如,非预乘RGBA。
kCGImageAlphaNone 没有alpha通道。
kCGImageAlphaNoneSkipFirst 没有alpha通道。如果像素的总大小大于颜色空间中颜色分量数量所需的空间,则忽略最高有效位。
kCGImageAlphaOnly 没有颜色数据,只有一个alpha通道。
kCGImageAlphaNoneSkipLast 没有alpha通道。
kCGImageAlphaPremultipliedFirst 阿尔法分量存储在每个像素的最高有效位中,并且颜色分量已经乘以该阿尔法值。例如,预乘ARGB。
kCGImageAlphaPremultipliedLast 阿尔法分量存储在每个像素的最低有效位中,并且颜色分量已经乘以该阿尔法值。例如,预乘RGBA。
8.获取像素点里的字节排序
CGImageByteOrderInfo CGImageGetByteOrderInfo(CGImageRef cg_nullable image)
使用及输出示例如下:
CGImageByteOrderInfo imageByteOrderInfo = CGImageGetByteOrderInfo(imgRef);NSLog(@"imageByteOrderInfo信息为 %d",imageByteOrderInfo);
输出结果:imageByteOrderInfo信息为 0
CGImageByteOrderInfoCGImageAlphaInfo的枚举值来查阅
typedef CF_ENUM(uint32_t, CGImageByteOrderInfo) {kCGImageByteOrderMask = 0x7000,kCGImageByteOrderDefault = (0 << 12),kCGImageByteOrder16Little = (1 << 12),kCGImageByteOrder32Little = (2 << 12),kCGImageByteOrder16Big = (3 << 12),kCGImageByteOrder32Big = (4 << 12)
} CG_AVAILABLE_STARTING(10.0, 2.0);
可知该图片使用的字节排序位默认排序kCGImageByteOrderDefault
CGImageByteOrderInfo定义了一个bitmap中像素读取的顺序,主要分为大端小端读取模式
大端模式:高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中
小端模式:高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中
苹果手机使用的是小端读取模式,如果在做到需要配置像素字节读取顺序这种需求的时候,需要留意一下像素字节的读取顺序,如果读取错误的话会导致颜色和图片的显示错误
常用枚举值的定义如下
kCGImageByteOrder16Little 16位小端读取
kCGImageByteOrder16Big 16位大端读取
kCGImageByteOrder32Little 32位小端读取
kCGImageByteOrder32Big 23位大端读取
需要注意,quartz 2D引擎在iOS端只支持 kCGImageByteOrderDefault,kCGImageByteOrder16Little,kCGImageByteOrder16Big这三种读取模式
8.获取图片的CGBitmapInfo信息
CGBitmapInfo CGImageGetBitmapInfo(CGImageRef cg_nullable image)
使用及输出示例如下:
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imgRef);NSLog(@"bitmapInfo信息为 %d",bitmapInfo);
输出结果:bitmapInfo信息为 5
枚举值定义如下:
typedef CF_OPTIONS(uint32_t, CGBitmapInfo) {kCGBitmapAlphaInfoMask = 0x1F,kCGBitmapFloatInfoMask = 0xF00,kCGBitmapFloatComponents = (1 << 8),kCGBitmapByteOrderMask = kCGImageByteOrderMask,kCGBitmapByteOrderDefault = kCGImageByteOrderDefault,kCGBitmapByteOrder16Little = kCGImageByteOrder16Little,kCGBitmapByteOrder32Little = kCGImageByteOrder32Little,kCGBitmapByteOrder16Big = kCGImageByteOrder16Big,kCGBitmapByteOrder32Big = kCGImageByteOrder32Big
} CG_AVAILABLE_STARTING(10.0, 2.0);
需要注意,CGBitmapInfo 在使用的时候是需要跟适当的常量使用 | 操作符配合链接使用的 ,官方文档解释如下:
所以我们在定义CGBitmapInfo作为参数传值使用的时候,一般会使用CGImageAlphaInfo及CGImageByteOrderInfo搭配使用,来定义图片是否含有alpha通道及读取顺序,举例如下:
CGBitmapInfo alphaInfo = = kCGImageAlphaLast | kCGImageByteOrder16Little; //alpha通道在末尾,且使用16位小端读取的方式来读取
所以使用CGImageGetBitmapInfo获取该图片的信息输出5,应该搭配文初获取的图片信息来看
kCGImageAlphaNoneSkipLast | kCGImageByteOrderDefault = 5
所以当我们直接获取CGBitmapInfo的值的时候,图片输出结果为5
其余的几种方法使用频率较低,可以翻阅api文档查阅
附: CGImageGetBitsPerPixel深究
在实际的项目开发中,使用CGImageGetBitsPerPixel获取的图片位数也并不一定准确
接下来使用五张不同的图片来演示CGImageGetBitsPerPixel获取像素位数的问题:
第一张图片 格式为 8bpc 24bpp 的Png格式的图片,也就是每通道有8位,不带alpha通道,bitmap为24位,但是使用CGImageGetBitsPerPixel输出的结果却是32位,结果错误
第二张图片 格式为 8bpc 24bpp 的Jpg格式的图片,也就是每通道有8位,不带alpha通道,bitmap为24位,但是使用CGImageGetBitsPerPixel输出的结果却是32位,结果错误
第三张图片 格式为 8bpc 24bpp 的Tiff格式的图片,也就是每通道有8位,不带alpha通道,bitmap为24位,但是使用CGImageGetBitsPerPixel输出的结果是24位,结果正确
第四张图片 格式为 16bpc 48bpp 的Png格式的图片,也就是每通道有16位,不带alpha通道,bitmap为48位,但是使用CGImageGetBitsPerPixel输出的结果是48位,结果正确
第五张图片 格式为 16bpc 48bpp 的Tiff格式的图片,也就是每通道有16位,不带alpha通道,bitmap为48位,但是使用CGImageGetBitsPerPixel输出的结果是48位,结果正确
使用五张图片信息如下 【命名规则(以img3CPng8Bit为例) img + 3C(3channel 3通道) + Png(图片格式) + 8Bit(通道位深) = img3CPng8Bit,统一命名规则方便代码演示区分】
读取代码及输出结果如下:
NSString *path8BitPng = [[NSBundle mainBundle] pathForResource:@"img3CPng8Bit" ofType:@".png"];NSData *bundleImgData8BitPng = [NSData dataWithContentsOfFile:path8BitPng];UIImage *bundleImage8BitPng = [UIImage imageWithData:bundleImgData8BitPng];CGImageRef imgRef8BitPng = [bundleImage8BitPng CGImage];size_t bitsPerComponent8BitPng = CGImageGetBitsPerComponent(imgRef8BitPng );printf("img8Bit3CPng 每个通道占用的位数:%zu \n",bitsPerComponent8BitPng );size_t bitsPerPixel8BitPng = CGImageGetBitsPerPixel(imgRef8BitPng);printf("img8Bit3CPng 每个像素占用的位数:%zu \n\n",bitsPerPixel8BitPng );NSString *path8BitJpg = [[NSBundle mainBundle] pathForResource:@"img3Cjpg8Bit" ofType:@".jpg"];NSData *bundleImgData8BitJpg = [NSData dataWithContentsOfFile:path8BitJpg];UIImage *bundleImage8BitJpg = [UIImage imageWithData:bundleImgData8BitJpg];CGImageRef imgRef8BitJpg = [bundleImage8BitJpg CGImage];size_t bitsPerComponent8BitJpg = CGImageGetBitsPerComponent(imgRef8BitJpg );printf("img8Bit3CJpg 每个通道占用的位数:%zu \n",bitsPerComponent8BitJpg );size_t bitsPerPixe8BitJpg = CGImageGetBitsPerPixel(imgRef8BitJpg);printf("img8Bit3CJpg 每个像素占用的位数:%zu \n\n",bitsPerPixe8BitJpg );NSString *path8Bit3CTiff = [[NSBundle mainBundle] pathForResource:@"img3CTiff8Bit" ofType:@".tif"];NSData *bundleImgData8Bit3CTiff = [NSData dataWithContentsOfFile:path8Bit3CTiff];UIImage *bundleImage8Bit3CTiff = [UIImage imageWithData:bundleImgData8Bit3CTiff];CGImageRef imgRef8Bit3CTiff = [bundleImage8Bit3CTiff CGImage];size_t bitsPerComponent8Bit3CTiff = CGImageGetBitsPerComponent(imgRef8Bit3CTiff );printf("img8Bit3CTiff 每个通道占用的位数:%zu \n",bitsPerComponent8Bit3CTiff );size_t bitsPerPixel8Bit3CTiff = CGImageGetBitsPerPixel(imgRef8Bit3CTiff);printf("img8Bit3CTiff 每个像素占用的位数:%zu \n\n",bitsPerPixel8Bit3CTiff );NSString *path16Bit3CPng = [[NSBundle mainBundle] pathForResource:@"img3CPng16Bit" ofType:@".png"];NSData *bundleImgData16Bit3CPng = [NSData dataWithContentsOfFile:path16Bit3CPng];UIImage *bundleImage16Bit3CPng = [UIImage imageWithData:bundleImgData16Bit3CPng];CGImageRef imgRef16Bit3CPng = [bundleImage16Bit3CPng CGImage];size_t bitsPerComponent16Bit3CPng = CGImageGetBitsPerComponent(imgRef16Bit3CPng );printf("img16Bit3CPng 每个通道占用的位数:%zu \n",bitsPerComponent16Bit3CPng );size_t bitsPerPixe16Bit3CPng = CGImageGetBitsPerPixel(imgRef16Bit3CPng);printf("img16Bit3CPng 每个像素占用的位数:%zu \n\n",bitsPerPixe16Bit3CPng );NSString *path16Bit3CTiff = [[NSBundle mainBundle] pathForResource:@"img3CTiff16Bit" ofType:@".tif"];NSData *bundleImgData16Bit3CTiff = [NSData dataWithContentsOfFile:path16Bit3CTiff];UIImage *bundleImage16Bit3CTiff = [UIImage imageWithData:bundleImgData16Bit3CTiff];CGImageRef imgRef16Bit3CTiff = [bundleImage16Bit3CTiff CGImage];size_t bitsPerComponent16Bit3CTiff = CGImageGetBitsPerComponent(imgRef16Bit3CTiff );printf("img16Bit3CTiff 每个通道占用的位数:%zu \n",bitsPerComponent16Bit3CTiff );size_t bitsPerPixel16Bit3CTiff = CGImageGetBitsPerPixel(imgRef16Bit3CTiff);printf("img16Bit3CTiff 每个像素占用的位数:%zu \n\n",bitsPerPixel16Bit3CTiff );
输出结果为:
img8Bit3CPng 每个通道占用的位数:8
img8Bit3CPng 每个像素占用的位数:32 img8Bit3CJpg 每个通道占用的位数:8
img8Bit3CJpg 每个像素占用的位数:32 img8Bit3CTiff 每个通道占用的位数:8
img8Bit3CTiff 每个像素占用的位数:24 img16Bit3CPng 每个通道占用的位数:16
img16Bit3CPng 每个像素占用的位数:48 img16Bit3CTiff 每个通道占用的位数:16
img16Bit3CTiff 每个像素占用的位数:48
可以看到
8位3通道的Png及jpeg格式图片使用CGImageGetBitsPerPixel方法获取到的结果并不是24,而是32;
8位3通道tiff格式、16位3通道png格式、16位3通道tiff格式的图片输出结果都正确
猜测可能是苹果在加载最常用的8bpc格式的png及jpeg图片的时候,如果图片本身没有alpha通道,从本地读取图片数据的过程中,会默认给图片增加一个不透明的值位255的alpha通道,论证该猜想如下:
集成opencv框架,使用该框架创建一个宽度为3000,高度为4000的矩阵,再将该矩阵转化为8bpc 3通道的纯红色的图片,然后使用读取该图片信息,代码及输出如下
cv::Mat originImgMat1 = Mat(3000, 4000, CV_8UC3);for(int row = 0; row < 3000; row ++){for(int col = 0; col < 4000; col ++){originImgMat1.at<Vec3b>(row,col)[0] = 255;originImgMat1.at<Vec3b>(row,col)[1] = 0;originImgMat1.at<Vec3b>(row,col)[2] = 0;}}UIImage *image = [CVTools2 UIImageFromCVMat:originImgMat1];CGImageRef imageRef = [image CGImage];size_t imgbitsPerComponent = CGImageGetBitsPerComponent(imageRef );printf("imgbitsPerComponent 每个通道占用的位数:%zu \n",imgbitsPerComponent );size_t imgBitsPerPixe = CGImageGetBitsPerPixel(imageRef);printf("imgBitsPerPixe 每个像素占用的位数:%zu \n\n",imgBitsPerPixe );
UIImageFromCVMat 方法:
+(UIImage *)UIImageFromCVMat:(cv::Mat)cvMat
{NSData *data = [NSData dataWithBytes:cvMat.data length:cvMat.elemSize()*cvMat.total()];CGColorSpaceRef colorSpace;if (cvMat.elemSize() == 1) {colorSpace = CGColorSpaceCreateDeviceGray();} else {colorSpace = CGColorSpaceCreateDeviceRGB();}CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);// Creating CGImage from cv::MatCGBitmapInfo alphaInfo;if(cvMat.channels() == 4){alphaInfo = kCGImageAlphaLast | kCGImageByteOrder16Little;}else{alphaInfo = kCGImageAlphaNone | kCGImageByteOrderDefault;}CGImageRef imageRef = CGImageCreate(cvMat.cols, //widthcvMat.rows, //height8, //bits per component8 * cvMat.elemSize(), //bits per pixelcvMat.step[0], //bytesPerRowcolorSpace, //colorspacealphaInfo,// bitmap infoprovider, //CGDataProviderRefNULL, //decodetrue, //should interpolatekCGRenderingIntentDefault //intent);// Getting UIImage from CGImageUIImage *finalImage = [UIImage imageWithCGImage:imageRef];CGImageRelease(imageRef);CGDataProviderRelease(provider);CGColorSpaceRelease(colorSpace);return finalImage;
}
输出结果为:
imgbitsPerComponent 每个通道占用的位数:8
imgBitsPerPixe 每个像素占用的位数:24
可以看到输出的结果是正确的。
将该图片写入沙盒,然后读取出来集成到项目中再次读取。代码及输出如下
NSString *path = [[NSBundle mainBundle] pathForResource:@"red" ofType:@".png"];NSData *bundleImgData = [NSData dataWithContentsOfFile:path];UIImage *bundleImage = [UIImage imageWithData:bundleImgData];CGImageRef imgRef = [bundleImage CGImage];size_t bitsPerComponent = CGImageGetBitsPerComponent(imgRef );printf("bitsPerComponent 每个通道占用的位数:%zu \n",bitsPerComponent );size_t bitsPerPixel = CGImageGetBitsPerPixel(imgRef);printf("bitsPerPixel 每个像素占用的位数:%zu \n\n",bitsPerPixel );
输出结果:
bitsPerComponent 每个通道占用的位数:8
bitsPerPixel 每个像素占用的位数:32
可见从本地读取图片的时候,又增加上了alpha通道。所以可以论证【可能是苹果在加载最常用的8bpc格式的png及jpeg图片的时候,如果图片本身没有alpha通道,从本地读取图片数据的过程中,会默认给图片增加一个不透明的值位255的alpha通道】这个观点。
有其他想法欢迎留言一起交流学习,后续会增加使用quartz 2D来完成图片裁剪需求的多种实现方式。
相关文章:

iOS正确获取图片参数深入探究及CGImageRef的使用(附源码)
一 图片参数的正确获取 先拿一张图片作为测试使用 图片参数如下: 图片的尺寸为: -宽1236个像素点 -高748个像素点 -色彩空间为RGB -描述文件为彩色LCD -带有Alpha通道 请记住这几个参数,待会儿我们演示如何正确获取。 将这张图片分别放在…...
Typescript 5.0 发布:快速概览
探索最令人兴奋的功能和更新 作为一种不断发展的编程语言,TypeScript 带来了大量的改进和新功能。在本文中,我们将深入探讨 TypeScript 的最新版本 5.0,并探索其最值得关注的更新。 1. 装饰器 TypeScript 5.0 引入了一个重新设计的装饰器系…...
【图像处理 】卡尔曼滤波器原理
目录 一、说明 二、它是什么? 2.1 我们可以用卡尔曼滤波器做什么? 2.2 卡尔曼滤波器如何看待您的问题...

YOLOv5 实例分割入门
介绍 YOLOv5 目标检测模型以其出色的性能和优化的推理速度而闻名。因此,YOLOv5 实例分割模型已成为实时实例分割中最快、最准确的模型之一。 在这篇文章中,我们将回答以下关于 YOLOv5 实例分割的问题: YOLOv5检测模型做了哪些改动,得到了YOLOv5实例分割架构?使用的 Prot…...

数字城市发展下的技术趋势,你知道多少?
提到数字城市、智慧城市大家都会感觉经常在耳边听到,但是要确切说出具体的概念还是有一点难度的。具体来说:数字城市是一个集合多种技术的系统,以计算机技术、多媒体技术和大规模存储技术为基础,以宽带网络为纽带,运用…...

linux 串口改为固定
在/etc/udev/rules.d 目录下新建定义规则的文件 1. 文件名要按规范写否则改动无效2. 规则文件必须以.rules 结尾3. 规则文件名称必须遵循 xx-name.rules 格式(xx 为数字或字母,name 为规则名称),例如 99-serial-ports.rules。4. 规…...

【SCI一区】考虑P2G和碳捕集设备的热电联供综合能源系统优化调度模型(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...

Redis缓存数据库(四)
目录 一、概述 1、Redis Sentinel 1.1、docker配置Redis Sentinel环境 2、Redis存储方案 2.1、哈希链 2.2、哈希环 3、Redis分区(Partitioning) 4、Redis面试题 一、概述 1、Redis Sentinel Redis Sentinel为Redis提供了高可用解决方案。实际上这意味着使用Sentinel…...

View中的滑动冲突
View中的滑动冲突 1.滑动冲突的种类 滑动冲突一般有3种, 第一种是ViewGroup和子View的滑动方向不一致 比如: 父布局是可以左右滑动,子view可以上下滑动 第二种 ViewGroup和子View的滑动方向一致 第三种 第三种类似于如下图 2.滑动冲突的解决方式 滑动冲突一般情况下有2…...

java boot项目基础配置之banner与日志配置演示 并教会你如何使用文档查看配置
上文 我们简单讲了一下 springboot 项目的配置 都是写在resources下的application.properties中 springboot 项目中 配置都写在这一个文件 可以说非常方便 不像之前 写个项目配置这里一个哪里一个 看到是非常费力 我们启动项目 这里有个图案 其实 这叫 banner 我们就用配置来…...

蓝鲸平台通过标准运维 API 安装 Agent
目录 一、背景 二、目的 三、创建安装agent流程 四、通过标准运维 API 安装 Agent 五、总结 一、背景 蓝鲸平台正常情况纳管主机需要在节点管理手工安装agent,不能达到完成自动化安装agent的效果。想通过脚本一键安装agent,而不需要在蓝鲸平台进行过…...
python 图片保存成视频
👨💻个人简介: 深度学习图像领域工作者 🎉工作总结链接:https://blog.csdn.net/qq_28949847/article/details/128552785 链接中主要是个人工作的总结,每个链接都是一些常用demo,…...
uniapp 引入 Less SCSS
✨求关注~ 😀博客:www.protaos.com 本文将介绍如何在 UniApp 中引入 Less 和 SCSS,两种流行的 CSS 预处理器。通过使用 Less 和 SCSS,你可以在 UniApp 项目中更灵活地编写样式,并享受预处理器提供的便利功能。 代码实现…...
Linux程序设计:文件操作
文件操作 系统调用 write //函数定义 #include <unistd.h> size_t write(int fildes, const void *buf, size_t nbytes); //示例程序 #include <unistd.h> #include <stdlib.h> int main() { if ((write(1, “Here is some data\n”, 18)) ! 18)write(2, …...
【自制C++深度学习推理框架】Tensor模板类的设计思路
Tensor模板类的设计思路 为什么要把Armadillo线性代数库arma::fcube封装成Tensor模板类? arma::fcube是Armadillo线性代数库中的一种数据类型,它是一个三维的float类型张量。Armadillo库是一个C科学计算库,提供了高效的线性代数和矩阵运算。…...

linux--systemd、systemctl
linux--systemd、systemctl 1 介绍1.1 发展sysvinitupstart主角 systemd 登场 1.2 简介 2 优点兼容性启动速度systemd 提供按需启动能力采用 linux 的 cgroups 跟踪和管理进程的生命周期启动挂载点和自动挂载的管理实现事务性依赖关系管理日志服务systemd journal 的优点如下&a…...

加密解密软件VMProtect教程(七):主窗口之控制面板“详情”部分
VMProtect是新一代软件保护实用程序。VMProtect支持德尔菲、Borland C Builder、Visual C/C、Visual Basic(本机)、Virtual Pascal和XCode编译器。 同时,VMProtect有一个内置的反汇编程序,可以与Windows和Mac OS X可执行文件一起…...

国产仪器 4945B/4945C 无线电通信综合测试仪
4945系列无线电通信综合测试仪是多功能、便携式无线电综合测试类仪器,基于软件无线电架构,集成了跳频信号发生与分析、矢量信号发生与解调分析、模拟调制信号发生与解调分析、音频信号发生与分析、音频示波器、自动测试等功能,它可完成无线通…...

数据库原理及应用上机实验一
✨作者:命运之光 ✨专栏:数据库原理及应用上机实验报告整理 目录 ✨一、实验目的和要求 ✨二、实验内容与步骤 🍓🍓前言: 数据库原理及应用上机实验报告的一个简单整理后期还会不断完善🍓🍓…...
【操作系统】线程常用操作
线程号 就像每个进程都有一个进程号一样,每个线程也有一个线程号。进程号在整个系统中是唯一的,但线程号不同,线程号只在它所属的进程环境中有效。 进程号用 pid_t 数据类型表示,是一个非负整数。线程号则用 pthread_t 数据类型…...

【Oracle APEX开发小技巧12】
有如下需求: 有一个问题反馈页面,要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据,方便管理员及时处理反馈。 我的方法:直接将逻辑写在SQL中,这样可以直接在页面展示 完整代码: SELECTSF.FE…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

使用分级同态加密防御梯度泄漏
抽象 联邦学习 (FL) 支持跨分布式客户端进行协作模型训练,而无需共享原始数据,这使其成为在互联和自动驾驶汽车 (CAV) 等领域保护隐私的机器学习的一种很有前途的方法。然而,最近的研究表明&…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...

Spring数据访问模块设计
前面我们已经完成了IoC和web模块的设计,聪明的码友立马就知道了,该到数据访问模块了,要不就这俩玩个6啊,查库势在必行,至此,它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据(数据库、No…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...