stb_image简单使用

news2024/10/7 6:42:43

简介stb_image

stb_image 是一个非常轻量级的、单文件的图像加载库,用于加载和解码多种图像格式(如BMP、JPEG、PNG、GIF等)的图像数据。它由Sean T. Barrett开发,并以公共领域(Public Domain)许可发布,因此可以自由地用于商业和非商业项目

stb_image 提供了简单易用的接口,使得在应用程序中加载图像变得非常方便。只需包含单个头文件stb_image.h,就可以使用其中的函数来加载图像文件并返回解码后的像素数据

主要特点和功能包括:

支持多种常见的图像格式:stb_image 支持加载和解码常见的图像格式,包括 BMP、JPEG、PNG、GIF、HDR、TGA等。这使得开发者可以方便地加载各种格式的图像数据。

简单易用的接口:stb_image 提供了简洁而易用的函数接口,如 stbi_load 用于加载图像文件,stbi_image_free用于释放图像数据内存等。

支持透明通道:对于支持透明通道的图像格式(如PNG),stb_image 可以正确解码并返回带有透明度信息的像素数据。

轻量级、单文件:stb_image是一个非常轻量级的库,整个功能被包含在一个单独的头文件中,因此非常容易集成到项目中,无需复杂的配置和依赖。

下载:

git clone https://github.com/nothings/stb.git

git clone https://github.com/nothings/stb.git

我们下载得到的目录:
在这里插入图片描述

实际需要移植到我们工程里面的:
在这里插入图片描述

接口学习

stbi_load

stbi_load 函数从指定的文件加载图像数据,并返回一个指向图像数据的指针

STBIDEF stbi_uc *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp)
{
   FILE *f = stbi__fopen(filename, "rb");
   unsigned char *result;
   if (!f) return stbi__errpuc("can't fopen", "Unable to open file");
   result = stbi_load_from_file(f,x,y,comp,req_comp);
   fclose(f);
   return result;
}

filename:要加载的图像文件的路径和名称。

x:用于存储加载图像的宽度(以像素为单位)的指针变量。

y:用于存储加载图像的高度(以像素为单位)的指针变量。

comp:用于存储加载图像的颜色通道数(例如,RGB 图像为 3)的指针变量。

req_comp:请求加载图像的颜色通道数,可以指定为期望的通道数,或者使用特定的值 0,表示保持原始通道数。

函数内容:
使用 stbi__fopen 函数以二进制只读模式打开指定的图像文件。
检查文件是否成功打开,如果打开失败,则返回错误信息。
调用 stbi_load_from_file 函数,从打开的文件中读取图像数据,并将结果保存在 result 变量中。
关闭打开的文件。
返回图像数据的指针(如果加载成功)或错误信息的指针(如果加载失败)

stbir_resize

stbir_resize 函数将输入图像调整大小,并将结果存储在输出图像中

STBIRDEF int stbir_resize(         const void *input_pixels , int input_w , int input_h , int input_stride_in_bytes,
                                         void *output_pixels, int output_w, int output_h, int output_stride_in_bytes,
                                   stbir_datatype datatype,
                                   int num_channels, int alpha_channel, int flags,
                                   stbir_edge edge_mode_horizontal, stbir_edge edge_mode_vertical,
                                   stbir_filter filter_horizontal,  stbir_filter filter_vertical,
                                   stbir_colorspace space, void *alloc_context)
{
    return stbir__resize_arbitrary(alloc_context, input_pixels, input_w, input_h, input_stride_in_bytes,
        output_pixels, output_w, output_h, output_stride_in_bytes,
        0,0,1,1,NULL,num_channels,alpha_channel,flags, datatype, filter_horizontal, filter_vertical,
        edge_mode_horizontal, edge_mode_vertical, space);
}

input_pixels:指向输入图像数据的指针。
input_w:输入图像的宽度(以像素为单位)。
input_h:输入图像的高度(以像素为单位)。
input_stride_in_bytes:输入图像每行的字节步长(即每行像素数据占用的字节数)。
output_pixels:指向输出图像数据的指针。
output_w:输出图像的目标宽度(以像素为单位)。
output_h:输出图像的目标高度(以像素为单位)。
output_stride_in_bytes:输出图像每行的字节步长。
datatype:输入和输出图像的数据类型(例如,STBIR_TYPE_UINT8 表示无符号 8 位整数)。
num_channels:输入和输出图像的通道数。
alpha_channel:指定图像的 Alpha 通道索引(如果存在)。
flags:附加的处理标志。
edge_mode_horizontal 和 edge_mode_vertical:指定水平和垂直边缘处理模式。
filter_horizontal 和 filter_vertical:指定水平和垂直缩放时使用的滤波器类型。
space:指定输入和输出图像的颜色空间。

函数执行的步骤如下:

调用 stbir__resize_arbitrary 函数,提供了与输入图像和输出图像相关的参数,以及其他参数的默认值。
stbir__resize_arbitrary 函数将根据提供的参数执行图像的调整大小操作,并将结果存储在输出图像中。
返回调整大小操作的结果,即返回值表示操作是否成功

stbi_write_png

stbi_write_png 函数将图像数据保存为 PNG 格式,并写入到指定的文件中

STBIWDEF int stbi_write_png(char const *filename, int x, int y, int comp, const void *data, int stride_bytes)
{
   FILE *f;
   int len;
   unsigned char *png = stbi_write_png_to_mem((const unsigned char *) data, stride_bytes, x, y, comp, &len);
   if (png == NULL) return 0;

   f = stbiw__fopen(filename, "wb");
   if (!f) { STBIW_FREE(png); return 0; }
   fwrite(png, 1, len, f);
   fclose(f);
   STBIW_FREE(png);
   return 1;
}

filename:指定要保存的 PNG 文件的文件名。
x:图像的宽度(以像素为单位)。
y:图像的高度(以像素为单位)。
comp:图像的通道数。
data:指向图像数据的指针。
stride_bytes:图像每行的字节步长(即每行像素数据占用的字节数)

调用 stbi_write_png_to_mem 函数,将图像数据编码为 PNG 格式的内存块,并返回指向该内存块的指针。
检查返回的 PNG 内存块是否为 NULL,如果是则表示编码过程出错,返回 0 表示保存失败。
打开指定的文件以进行写入操作。
将 PNG 内存块的数据写入文件。
关闭文件。
释放 PNG 内存块的内存。
返回 1 表示保存成功。

将png图片缩小demo

#include <iostream>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"
#define STB_IMAGE_RESIZE_IMPLEMENTATION
#include "stb_image_resize.h"
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <vector>

using namespace std;

int test_xiao()
{
    std::cout << "Hello, STB_Image" << std::endl;

    string inputPath = "./001.png";
    int iw, ih, n;

    // 加载图片获取宽、高、颜色通道信息
    unsigned char *idata = stbi_load(inputPath.c_str(), &iw, &ih, &n, 0);

    int ow = iw / 2;
    int oh = ih / 2;
    auto *odata = (unsigned char *)malloc(ow * oh * n);

    // 改变图片尺寸
    stbir_resize(idata, iw, ih, 0, odata, ow, oh, 0, STBIR_TYPE_UINT8, n, STBIR_ALPHA_CHANNEL_NONE, 0,
                 STBIR_EDGE_CLAMP, STBIR_EDGE_CLAMP,
                 STBIR_FILTER_BOX, STBIR_FILTER_BOX,
                 STBIR_COLORSPACE_SRGB, nullptr);

    string outputPath = "./output.png";
    // 写入图片
    stbi_write_png(outputPath.c_str(), ow, oh, n, odata, 0);

    stbi_image_free(idata);
    stbi_image_free(odata);
    std::cout << "Voer, STB_Image" << std::endl;
    return 0;
}

图像基本知识学习

comp

comp:用于存储加载图像的颜色通道数(例如,RGB 图像为 3)的指针变量。 还有其他数字有不同的表示吗?

当加载的图像是 RGB 格式时,comp 将被设置为 3,表示有红色、绿色和蓝色三个通道。 当加载的图像是 RGBA 格式时,comp
将被设置为 4,表示有红色、绿色、蓝色和 Alpha 通道。

YUV420

YUV420是一种颜色编码格式,常用于存储和传输图像数据。它将图像的亮度(Y)和色度(U、V)分开存储,以实现数据压缩和降低存储/传输带宽的效果
YUV420的"420"指的是在水平和垂直方向上对色度(U、V)进行了抽样,即将色度通道的分辨率降低为亮度通道的四分之一。具体而言,对于每4个亮度像素,只有一个色度(U、V)样本被保留,这样可以大大减少存储和传输所需的数据量
在这里插入图片描述

RGB 数据存储格式

RGB24(RGB888):每个像素使用24位(3字节)存储,按照顺序存储红色、绿色和蓝色通道的像素值,每个通道占用8位。

RGB32(ARGB8888):每个像素使用32位(4字节)存储,按照顺序存储Alpha通道、红色通道、绿色通道和蓝色通道的像素值,每个通道占用8位。

RGB565:每个像素使用16位(2字节)存储,按照顺序存储红色、绿色和蓝色通道的像素值,其中红色通道占用5位,绿色通道占用6位,蓝色通道占用5位。

RGB444:每个像素使用12位(2字节)存储,按照顺序存储红色、绿色和蓝色通道的像素值,其中每个通道占用4位。

RGBA 数据格式

RGBA数据格式是一种将图像的红色(R)、绿色(G)、蓝色(B)和Alpha(A)通道的像素值以一定顺序存储的方法。与RGB数据格式相比,RGBA数据格式额外包含了Alpha通道,用于表示像素的透明度。

常见的RGBA数据存储格式包括:

RGBA32(ARGB8888):每个像素使用32位(4字节)存储,按照顺序存储Alpha通道、红色通道、绿色通道和蓝色通道的像素值,每个通道占用8位。

RGBA16(ARGB1555):每个像素使用16位(2字节)存储,按照顺序存储Alpha通道、红色通道、绿色通道和蓝色通道的像素值,其中Alpha通道占用1位,而红色、绿色和蓝色通道各占用5位。

RGBA4444:每个像素使用16位(2字节)存储,按照顺序存储Alpha通道、红色通道、绿色通道和蓝色通道的像素值,每个通道占用4位。

RGBA转YUV420 原理

颜色空间转换:首先将RGBA图像中的每个像素的颜色值转换为YUV颜色空间。这可以通过以下公式进行计算:
Y = 0.299 * R + 0.587 * G + 0.114 * B
U = (B - Y) * 0.565
V = (R - Y) * 0.713
这些公式将RGB颜色值转换为YUV颜色值,其中Y表示亮度,U和V表示色度。

采样:YUV420是一种色度子采样格式,意味着色度分量的采样率较低。具体来说,对于每个4x4的像素块,只有一个U和一个V值,而Y值则对应每个像素。

重排列:将Y、U和V分量的数据进行重排列,以满足YUV420的存储格式要求。对于每个4x4的像素块,先按照从左到右、从上到下的顺序排列Y值,然后按照从左到右、从上到下的顺序排列U和V值。这样可以保证Y、U和V分量的数据在存储时是连续的。

填充:由于YUV420是按照宏块(通常是16x16像素)为单位进行处理的,因此如果图像的宽度或高度不是宏块的倍数,就需要进行填充操作。填充通常是在图像边缘添加额外的像素值,使得宽度和高度能够被宏块大小整除。

RGB转YUV420 原理

颜色空间转换:首先,将RGB颜色空间的每个像素的颜色值转换为YUV颜色空间。这可以通过以下公式进行计算:
Y = 0.299 * R + 0.587 * G + 0.114 * B
U = (B - Y) * 0.564 + 128
V = (R - Y) * 0.713 + 128
这些公式将RGB颜色值转换为YUV颜色值,其中Y表示亮度,U和V表示色度。

采样和下采样:YUV420是一种色度子采样格式,意味着色度分量的采样率较低。对于每个4x4像素块,只有一个U值和一个V值,而Y值对应每个像素。

数据重排列:按照特定的规则,将Y、U和V分量的数据进行重排列以适应YUV420的存储格式要求。通常,对于每个4x4像素块,先将Y值按从左到右、从上到下的顺序排列,然后将U和V值按照特定的规则进行排列,以确保它们在存储时是连续的。

图像填充:由于YUV420是以宏块(通常是16x16像素)为单位进行处理的,因此如果图像的宽度或高度不是宏块的倍数,就需要进行填充操作。填充通常是在图像边缘添加额外的像素值,使得宽度和高度能够被宏块大小整除。

为什么RGB图像转换为YUV420格式

人类视觉特性:YUV420格式利用了人类视觉对亮度和色度的感知不均衡性。人眼对亮度的感知更为敏锐,而对色度的感知相对较弱。因此,在视频编码和传输中,将亮度和色度分开处理可以实现更高的压缩率,同时保持较好的视觉质量。

压缩效率:YUV420是一种色度子采样的格式,相对于RGB格式,它在色度分量上进行了下采样。在YUV420中,亮度分量(Y)的分辨率与原始图像相同,而色度分量(U和V)的分辨率较低。这种子采样可以大大减少数据量,从而实现更高的压缩效率。对于图像和视频的存储和传输,尤其是在带宽和存储资源有限的情况下,YUV420格式具有更高的效率。

兼容性:YUV420格式在广泛的视频编码和传输标准中被广泛使用,如H.264、H.265等。这些标准通常使用YUV420作为默认的输入格式,因此将RGB图像转换为YUV420可以方便地与这些标准进行集成和处理。

总结就是:更好的视觉效果,压缩后减少数据量,使用的场景更多

BMP图像

BMP(Bitmap)图像是一种常见的无损图像文件格式,它以像素阵列的形式存储图像数据。BMP图像最初由微软开发,是Windows操作系统中广泛使用的一种图像格式。以下是BMP图像的一些特点

无压缩格式:BMP图像使用无压缩的格式存储图像数据,即每个像素的颜色值都被直接存储,没有经过压缩算法的处理。这使得BMP图像保留了原始图像的每个像素的精确信息,不会有数据丢失。

色彩深度:BMP图像支持不同的色彩深度,包括1位、4位、8位、16位、24位和32位。其中,24位和32位的BMP图像是最常见的,它们分别使用RGB(红绿蓝)和RGBA(红绿蓝透明度)颜色模型来表示图像的每个像素。

文件结构:BMP图像文件由文件头和图像数据组成。文件头包含了一些元数据信息,如文件类型、文件大小、图像偏移等。图像数据部分存储了每个像素的颜色值。

支持透明通道:BMP图像可以支持透明通道,即RGBA格式的图像可以包含透明度信息,使得图像中的某些像素可以是部分透明的。

平台兼容性:BMP图像在多个平台上都有良好的兼容性,可以在Windows、Linux、Mac等操作系统上进行读取和显示

练习

RGBA转YUV420 YUV420转换为BMP图像

// YUV420转换为BMP图像
void yuv420_to_bmp_RGBA(uchar* yuv_data, int width, int height, const char* output_filename)
{
    int bmp_size = width * height * 3;
    uchar* bmp_data = (uchar*)malloc(bmp_size);

    int i, j;
    int bmp_idx = 0;
    int yuv_idx = 0;

    // Y分量
    for (i = 0; i < height; i++) {
        for (j = 0; j < width; j++) {
            bmp_data[bmp_idx++] = yuv_data[yuv_idx++];
        }
    }

    // U、V分量
    int uv_width = width / 2;
    int uv_height = height / 2;
    int uv_size = uv_width * uv_height;
    for (i = 0; i < uv_size; i++) {
        bmp_data[bmp_idx++] = yuv_data[yuv_idx++]; // U
        bmp_data[bmp_idx++] = yuv_data[yuv_idx++]; // V
    }

    // 写入BMP文件
    FILE* bmp_file = fopen(output_filename, "wb");
    if (bmp_file == NULL) {
        printf("Failed to open BMP file for writing\n");
        return;
    }

    // BMP文件头
    int file_size = bmp_size + 54; // BMP文件大小
    uchar bmp_header[54] = {
        'B', 'M', // 文件类型
        file_size & 0xFF, (file_size >> 8) & 0xFF, (file_size >> 16) & 0xFF, (file_size >> 24) & 0xFF, // 文件大小
        0, 0, 0, 0, // 保留
        54, 0, 0, 0, // 数据偏移量
        40, 0, 0, 0, // BITMAPINFOHEADER大小
        width & 0xFF, (width >> 8) & 0xFF, (width >> 16) & 0xFF, (width >> 24) & 0xFF, // 宽度
        height & 0xFF, (height >> 8) & 0xFF, (height >> 16) & 0xFF, (height >> 24) & 0xFF, // 高度
        1, 0, // 颜色平面数
        24, 0, // 位深度
        0, 0, 0, 0, // 无压缩
        0, 0, 0, 0, // 图像大小(可设置为0)
        0, 0, 0, 0, // 水平分辨率(可设置为0)
        0, 0, 0, 0, // 垂直分辨率(可设置为0)
        0, 0, 0, 0, // 调色板颜色数(可设置为0)
        0, 0, 0, 0  // 重要颜色数(可设置为0)
    };

    fwrite(bmp_header, sizeof(uchar), 54, bmp_file);
    fwrite(bmp_data, sizeof(uchar), bmp_size, bmp_file);

    fclose(bmp_file);
    free(bmp_data);

    printf("BMP image saved to %s\n", output_filename);
}

int IPG_YUV420_BMP_RGBA()
{
    const char* input_filename = "./002.jpg";
    const char* output_filename = "./002outputRGBA.bmp";

    int width, height, channels;
    uchar* image_data = stbi_load(input_filename, &width, &height, &channels, 0);
    if (image_data == NULL) {
        printf("Failed to load image: %s\n", input_filename);
        return 1;
    }

    if (channels != 4) {
        printf("Invalid image format: must be RGBA\n");
        stbi_image_free(image_data);
        return 1;
    }

    // 分配YUV420数据内存
    int yuv_size = width * height * 3 / 2;
    uchar* yuv_data = (uchar*)malloc(yuv_size);

    // RGBA转YUV420
    int i, j;
    int rgba_idx = 0;
    int y_idx = 0;
    int uv_idx = width * height;
    for (i = 0; i < height; i++) {
        for (j = 0; j < width; j++) {
            uchar r = image_data[rgba_idx++];
            uchar g = image_data[rgba_idx++];
            uchar b = image_data[rgba_idx++];
            uchar a = image_data[rgba_idx++];

            uchar y = (uchar)(0.299 * r + 0.587 * g + 0.114 * b);
            uchar u = (uchar)(-0.14713 * r - 0.28886 * g + 0.436 * b + 128);
            uchar v = (uchar)(0.615 * r - 0.51499 * g - 0.10001 * b + 128);

            yuv_data[y_idx++] = y;

            // 每隔一行和一列采样U、V分量
            if (i % 2 == 0 && j % 2 == 0) {
                yuv_data[uv_idx++] = u;
                yuv_data[uv_idx++] = v;
            }
        }
    }

    // 将YUV420转换为BMP图像
    yuv420_to_bmp_RGBA(yuv_data, width, height, output_filename);

    stbi_image_free(image_data);
    free(yuv_data);

    return 0;
}

RGB 转YUV420 YUV420转换为BMP图像


```c
typedef unsigned char uchar;

// YUV420转换为BMP图像
void yuv420_to_bmp(uchar *yuv_data, int width, int height, const char *output_filename)
{
    int bmp_size = width * height * 3;
    uchar *bmp_data = (uchar *)malloc(bmp_size);

    int i, j;
    int bmp_idx = 0;
    int yuv_idx = 0;

    // Y分量
    for (i = 0; i < height; i++)
    {
        for (j = 0; j < width; j++)
        {
            bmp_data[bmp_idx++] = yuv_data[yuv_idx++];
        }
    }

    // U、V分量
    int uv_width = width / 2;
    int uv_height = height / 2;
    int uv_size = uv_width * uv_height;
    for (i = 0; i < uv_size; i++)
    {
        bmp_data[bmp_idx++] = yuv_data[yuv_idx++]; // U
        bmp_data[bmp_idx++] = yuv_data[yuv_idx++]; // V
    }

    // 写入BMP文件
    FILE *bmp_file = fopen(output_filename, "wb");
    if (bmp_file == NULL)
    {
        printf("Failed to open BMP file for writing\n");
        return;
    }

    // BMP文件头
    int file_size = bmp_size + 54; // BMP文件大小
    uchar bmp_header[54] = {
        'B', 'M',                                                                                      // 文件类型
        file_size & 0xFF, (file_size >> 8) & 0xFF, (file_size >> 16) & 0xFF, (file_size >> 24) & 0xFF, // 文件大小
        0, 0, 0, 0,                                                                                    // 保留
        54, 0, 0, 0,                                                                                   // 数据偏移量
        40, 0, 0, 0,                                                                                   // BITMAPINFOHEADER大小
        width & 0xFF, (width >> 8) & 0xFF, (width >> 16) & 0xFF, (width >> 24) & 0xFF,                 // 宽度
        height & 0xFF, (height >> 8) & 0xFF, (height >> 16) & 0xFF, (height >> 24) & 0xFF,             // 高度
        1, 0,                                                                                          // 颜色平面数
        24, 0,                                                                                         // 位深度
        0, 0, 0, 0,                                                                                    // 无压缩
        0, 0, 0, 0,                                                                                    // 图像大小(可设置为0)
        0, 0, 0, 0,                                                                                    // 水平分辨率(可设置为0)
        0, 0, 0, 0,                                                                                    // 垂直分辨率(可设置为0)
        0, 0, 0, 0,                                                                                    // 调色板颜色数(可设置为0)
        0, 0, 0, 0                                                                                     // 重要颜色数(可设置为0)
    };

    fwrite(bmp_header, sizeof(uchar), 54, bmp_file);
    fwrite(bmp_data, sizeof(uchar), bmp_size, bmp_file);

    fclose(bmp_file);
    free(bmp_data);

    printf("BMP image saved to %s\n", output_filename);
}
/*
基于stbimg开源库实现jpg解码为YUV420,YUV420转换为BMP图片工程
*/
int IPG_YUV420_BMP()
{
    const char *input_filename = "./002.jpg";
    const char *output_filename = "./002output.bmp";

    int width, height, channels;
    uchar *image_data = stbi_load(input_filename, &width, &height, &channels, 0);
    if (image_data == NULL)
    {
        printf("Failed to load image: %s\n", input_filename);
        return 1;
    }
    // return 0;
    printf("%s %d channels = %d\n", __func__, __LINE__, channels);
    if (channels != 3)
    {
        printf("Invalid image format: must be RGB\n");
        stbi_image_free(image_data);
        return 1;
    }

    // 分配YUV420数据内存
    int yuv_size = width * height * 3 / 2;
    uchar *yuv_data = (uchar *)malloc(yuv_size);

    // RGB转YUV420
    int i, j;
    int rgb_idx = 0;
    int y_idx = 0;
    int uv_idx = width * height;
    for (i = 0; i < height; i++)
    {
        for (j = 0; j < width; j++)
        {
            uchar r = image_data[rgb_idx++];
            uchar g = image_data[rgb_idx++];
            uchar b = image_data[rgb_idx++];

            uchar y = (uchar)(0.299 * r + 0.587 * g + 0.114 * b);
            uchar u = (uchar)(-0.14713 * r - 0.28886 * g + 0.436 * b + 128);
            uchar v = (uchar)(0.615 * r - 0.51499 * g - 0.10001 * b + 128);

            yuv_data[y_idx++] = y;

            // 每隔一行和一列采样U、V分量
            if (i % 2 == 0 && j % 2 == 0)
            {
                yuv_data[uv_idx++] = u;
                yuv_data[uv_idx++] = v;
            }
        }
    }

    // 将YUV420转换为BMP图像
    yuv420_to_bmp(yuv_data, width, height, output_filename);

    stbi_image_free(image_data);
    free(yuv_data);

    return 0;
}



参考:
[https://mp.weixin.qq.com/s/Mh_cLQeRy5J5AufeaGaOmA](https://mp.weixin.qq.com/s/Mh_cLQeRy5J5AufeaGaOmA)
[https://blog.csdn.net/www_dong/article/details/115149370](https://blog.csdn.net/www_dong/article/details/115149370)


注意:如果代码运行有问题,慢慢检查,仔细看一下错误是什么!

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

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

相关文章

【软件测试】web测试bug定位思路总结,“我“不再背锅...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 需要掌握的知识 …

LabVIEW - 采集声音并保存 wav 文件

1. 题目 编写程序&#xff0c;实现用户点击按钮时&#xff0c;采集声音&#xff0c;显示声音波形&#xff0c;对于采集的声音进行低频段、中频段、高频段分别进行适当的比例放大或者衰减&#xff0c;然后重新合成(三段相加即可)&#xff0c;并将合成的声音下入wav格式的文件保存…

【ROS】ROS1人机界面开发:第一个最简ROS+QtGui程序(按钮启动发布者)

【ROS】郭老二博文之:ROS目录 1、创建工程 1)新建工程:Other Project --> ROS Workspace 2)设置工程名称、路径 3)可以通过点击“Browse”来创建目录 注意:使用自带ros插件的qtcreator-ros,无法创建目录、也不能选择目录,这是个bug,因此需要在终端手动创建目录…

江南大学轴承数据故障诊断(利用连续小波变换转换为二维图像,再利用CNN进行故障诊断)

1.江南大学轴承数据集介绍 采样频率&#xff1a;50khz&#xff0c;采样时间&#xff1a;10s 转速&#xff1a;600 800 1000/rpm 内圈&#xff1a;ib 外圈&#xff1a;ob 滚动体&#xff1a;tb 正常&#xff1a;N 以600转速下的内圈故障数据为例展示&#xff1a; 开始数据…

【云原生】Prometheus 之PromQL

前言 当 Prometheus 通过 Exporter 采集到相应的监控指标样本数据后&#xff0c;我们就可以通过PromQL 对监控样本数据进行查询&#xff0c;从而对相应的数据样本进行分析以及制定报警规则。 1. PromQL的简介 PromQL&#xff08;Prometheus Query Language&#xff09;是 Prome…

SaleSmartly,客户满意度调查的绝对好助手

企业使用客户满意度调查来收集反馈并评估客户满意度水平&#xff0c;包括有关产品质量、服务、支持和整体满意度的问题。客户满意度调查的主要目标是直接从客户那里收集有价值的见解&#xff0c;以了解他们的需求、偏好和期望。这种反馈可以帮助企业确定需要改进的领域&#xf…

STM32案例学习 GY-39环境监测传感器模块

STM32案例学习 GY-39环境监测传感器模块 硬件平台 野火STM32F1系列开发板正点STM32F1系列开发板STM32F103ZET6核心板GY-39环境监测传感器模块 GY-39环境监测传感器模块 GY-39 是一款低成本&#xff0c;气压&#xff0c;温湿度&#xff0c;光强度传感器模块。工作电压 3-5v…

JS-27 前端数据请求方式;HTTP协议的解析;JavaScript XHR、Fetch的数据请求与响应函数;前端文件上传XHR、Fetch

目录 1_前端数据请求方式1.1_前后端分离的优势1.2_网页的渲染过程 – 服务器端渲染1.3_网页的渲染过程 – 前后端分离 2_HTTP协议的解析2.1_HTTP概念2.2_网页中资源的获取2.3_HTTP的组成2.4_HTTP的版本2.5_HTTP的请求方式2.6_HTTP Request Header2.7_HTTP Response响应状态码 3…

京东自动化功能之商品信息监控是否有库存

这里有两个参数,分别是area和skuids area是地区编码,我这里统计了全国各个区县的area编码,用户可以根据实际地址进行构造skuids是商品的信息ID填写好这两个商品之后,会显示两种状态,判断有货或者无货状态,详情如下图所示 简单编写下python代码,比如我们的地址是北京市…

Kaggle:树叶分类(使用Jupyter)

竞赛网址&#xff1a;https://www.kaggle.com/c/classify-leaves # 首先导入包 import torch import torch.nn as nn import pandas as pd import numpy as np from torch.utils.data import Dataset, DataLoader from torchvision import transforms from PIL import Image i…

uniapp 小程序 实时拍照(仅拍照)限制上传5张 可预览 可删除

效果图&#xff1a; common.js /*** 预览图片*/ const previewImage (current,list)>{// 预览图片uni.previewImage({current: current,urls: list}); } /*** 删除图片*/ const removeImage (current,list)>{var photoFilesList list;photoFilesList.splice(curren…

AJAX:宏任务与微任务

异步任务划分为了 宏任务&#xff1a;由浏览器环境执行的异步代码 微任务&#xff1a;由 JS 引擎环境执行的异步代码 宏任务和微任务具体划分&#xff1a; 左边表格是宏任务&#xff0c;右边是微任务 事件循环模型 /*** 目标&#xff1a;阅读并回答打印的执行顺序 */ console…

国内软件外包公司开发流程

当企业发展到一定阶段后&#xff0c;现有市场上通用型的软件往往无法满足自身的业务需求&#xff0c;这就需要企业定制化开发软件系统来满足自身独特的需求。而传统企业往往没有自己的软件研发队伍&#xff0c;在开发软件系统时快速新建团队风险比较高&#xff0c;可以采用外包…

Docker 网络模型:多角度分析容器网络的原理与应用

&#x1f337;&#x1f341; 博主 libin9iOak带您 Go to New World.✨&#x1f341; &#x1f984; 个人主页——libin9iOak的博客&#x1f390; &#x1f433; 《面试题大全》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33…

FPGA adrv9002 4收4发板卡,支持NVME SATA EMMC 光口 FMC

板卡采用ADI 射频直采芯片ADRV9002 &#xff0c;支持4收4发支持外部本振 跳频 同时支持4X 10G光口对外传输&#xff0c;FMC扩展 。同时支持4X NVME接口&#xff0c;可以实时流盘&#xff0c;备份一路SAT A接口&#xff0c;板卡同时预留了EMMC&#xff0c;可以PS PL选通访问&…

【Java基础教程】Java学习路线攻略导图 · 上篇 ~

Java学习路线攻略导图 上篇 前言1、入门介绍篇2、程序基础概念篇3、包及访问权限篇4、异常处理篇5、特别篇6、面向对象篇 前言 &#x1f37a;&#x1f37a; 各位读者朋友大家好&#xff01;得益于各位朋友的支持和关注&#xff0c;我的专栏《Java基础教程》 至今已经更新近半&…

浅谈无人机遥感图像拼接与处理方法

遥感&#xff08;RS-Remote Sensing&#xff09;——不接触物体本身&#xff0c;用传感器收集目标物的电磁波信息&#xff0c;经处理、分析后&#xff0c;识别目标物&#xff0c;揭示其几何、物理性质和相互关系及其变化规律的现代科学技术。 换言之&#xff0c;即是“遥远的感…

mysal数据库的日志恢复

目录 一 物理冷备份 二 mysqldump 备份与恢复&#xff08;温备份&#xff09; 三 mgsql中的增量备份需要借助mysql日志的二进制来恢复 小结 一 物理冷备份 systemctl stop mysqld yum -y install xz 压缩备份 tar Jcvf /opt/mysql_all_$(date %F).tar.xz /usr/local/mysql/…

文件上传前前端通过魔数(magic number)去限制上传文件类型

问题 最近项目需求文件上传前判断文件类型&#xff0c;有的同学会说用文件后缀判断不就好啦。其一&#xff0c;文件后缀可以修改&#xff0c;正确性待考究&#xff1b;其二&#xff0c;有些文件并没有文件后缀。这就需要我们动动脑筋啦&#xff0c;其实我们可以根据文件的头信…

4个顶级WooCommerce商城多站点库存同步WordPress插件

经营几家网上商店是令人兴奋的。但是&#xff0c;这也是一项艰巨的工作&#xff0c;尤其是当您意识到需要同步这些商店的库存时。好消息是&#xff0c;有 WooCommerce 多站点库存同步插件和选项可以加快速度。 WooCommerce 多站点网络可让您将所有在线商店无缝地安置在一个屋檐…