C++音视频04:音视频编码、生成图片
视频编码
#include <libavutil/log.h>
#include <libavutil/opt.h>
#include <libavcodec/avcodec.h>static int encode(AVCodecContext *ctx, AVFrame *frame, AVPacket *pkt, FILE *out) {int ret = -1;ret = avcodec_send_frame(ctx, frame);if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "Failed to send frame to encoder\n");goto _END;}while (ret >= 0) {ret = avcodec_receive_packet(ctx, pkt);// AVERROR(EAGAIN)表示出错了if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {return 0;} else if(ret < 0) {return -1;}fwrite(pkt->data, 1, pkt->size, out);av_packet_unref(pkt);}
_END:return 0;
}int main(int argc, char *argv[]) {char *dst = NULL;char *codecName = NULL;const AVCodec *codec = NULL;AVCodecContext *ctx = NULL;int ret = -1;FILE *f = NULL;AVFrame *frame = NULL;AVPacket *pkt = NULL;av_log_set_level(AV_LOG_DEBUG);// 1. 输入参数if (argc < 3) {av_log(NULL, AV_LOG_ERROR, "arguments must more than 3\n");goto _ERROR;}dst = argv[1];codecName = argv[2];// 2. 查找编码器codec = avcodec_find_encoder_by_name(codecName);if (!codec) {av_log(NULL, AV_LOG_ERROR, "don't find codec name %s\n", codecName);goto _ERROR;}// 3. 创建编码器上下文ctx = avcodec_alloc_context3(codec);if (!ctx) {av_log(NULL, AV_LOG_ERROR, "No memory\n");goto _ERROR;}// 4. 设置编码器参数ctx->width = 640;ctx->height = 480;ctx->bit_rate = 500000;// 时间基和帧率ctx->time_base = (AVRational){1, 25};ctx->framerate = (AVRational){25, 1};// 设置每10帧一个gopctx->gop_size = 10;// 设置一个gop中最多有一个b帧ctx->max_b_frames = 1;// 设置yuv格式ctx->pix_fmt = AV_PIX_FMT_YUV422P;if (codec->id == AV_CODEC_ID_H264) {av_opt_set(ctx->priv_data, "preset", "slow", 0);}// 5. 编码器与编码器上下文绑定ret = avcodec_open2(ctx, codec, NULL);if (ret < 0) {av_log(ctx, AV_LOG_ERROR, "Don't open codec: %s", av_err2str(ret));goto _ERROR;}// 6. 创建输出文件f = fopen(dst, "wb");if (!f) {av_log(NULL, AV_LOG_ERROR, "Don't open file %s\n", dst);goto _ERROR;}// 7. 创建AVFrameframe = av_frame_alloc();if (!frame) {av_log(NULL, AV_LOG_ERROR, "No memory\n");goto _ERROR;}// 必须赋值才能获取到bufferframe->width = ctx->width;frame->height = ctx->height;frame->format = ctx->pix_fmt;// frame中真正存储数据的位置不会被av_frame_alloc生成,还需要调用av_frame_get_buffer获取ret = av_frame_get_buffer(frame, 0);if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "Could't not allocate the video frame\n");goto _ERROR;}// 8. 创建AVPacketpkt = av_packet_alloc();if (!pkt) {av_log(NULL, AV_LOG_ERROR, "No memory\n");goto _ERROR;}// 9. 生成视频内容// 这里是虚拟生成25帧,即一秒钟的数据for (int i = 0; i < 25; ++i) {// 确保av_frame中的空间data可用,如果当前data域被锁定了,就会自动指定一个新的dataret = av_frame_make_writable(frame);if (ret < 0) {break;}// Y分量for (int y = 0; y < ctx->height; y++) {for (int x = 0; x < ctx->width; x++) {// data[0] 指的是yuv中的y,[frame->linesize[0] 指的是行的大小, x表示横轴位移]// x + y + i * 3表示Y分量随着x和y变化而渐变frame->data[0][y * frame->linesize[0] + x] = x + y + i * 3;}}// UV分量for (int y = 0; y < ctx->height; y++) {// 对应uv分量 422中都是y分量的一半,所以除以2for (int x = 0; x < ctx->width / 2; x++) {// U分量 128在U分量代表黑色, 后面的2是任意的frame->data[1][y * frame->linesize[1] + x] = 128 + y + i * 2;// V分量 64在V分量中代表黑色, 后面的5是任意的frame->data[2][y * frame->linesize[2] + x] = 64 + x + i * 5;}}frame->pts = i;// 10. 编码ret = encode(ctx, frame, pkt, f);if (ret == -1) {goto _ERROR;}}// 输出一个空包,用于刷新剩余数据encode(ctx, NULL, pkt, f);
_ERROR:if (ctx) {avcodec_free_context(&ctx);}if (frame) {av_frame_free(&frame);}if (pkt) {av_packet_free(&pkt);}if (f) {fclose(f);}return 0;
}
gcc -g -o encode_video encode_video.c `pkg-config --libs libavutil libavformat`./encode_video 1.h264 libx264
音频编码
#include <libavutil/log.h>
#include <libavutil/opt.h>
#include <libavcodec/avcodec.h>
#include <libavutil/samplefmt.h>static int select_best_sample_rate(const AVCodec *codec) {const int *p;int best_sample_rate = 0;if (!codec->supported_samplerates) {return 44100;}p = codec->supported_samplerates;// 找到一个离44100最近的采样率while (*p) {if (!best_sample_rate || abs(44100 - *p) < abs(44100 - best_sample_rate)) {best_sample_rate = *p;}p++;}return best_sample_rate;
}// ffmpeg源码自带
static int check_sample_fmt(const AVCodec *codec, enum AVSampleFormat sample_fmt)
{const enum AVSampleFormat *p = codec->sample_fmts;while (*p != AV_SAMPLE_FMT_NONE) {if (*p == sample_fmt)return 1;p++;}return 0;
}static int encode(AVCodecContext *ctx, AVFrame *frame, AVPacket *pkt, FILE *out) {int ret = -1;ret = avcodec_send_frame(ctx, frame);if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "Failed to send frame to encoder\n");goto _END;}while (ret >= 0) {ret = avcodec_receive_packet(ctx, pkt);// AVERROR(EAGAIN)表示出错了if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {return 0;} else if(ret < 0) {return -1;}fwrite(pkt->data, 1, pkt->size, out);av_packet_unref(pkt);}
_END:return 0;
}int main(int argc, char *argv[]) {char *dst = NULL;char *codecName = NULL;const AVCodec *codec = NULL;AVCodecContext *ctx = NULL;int ret = -1;FILE *f = NULL;AVFrame *frame = NULL;AVPacket *pkt = NULL;uint16_t *samples = NULL;av_log_set_level(AV_LOG_DEBUG);// 1. 输入参数if (argc < 2) {av_log(NULL, AV_LOG_ERROR, "arguments must more than 2\n");goto _ERROR;}dst = argv[1];// codecName = argv[2];// 2. 查找编码器:两种方式,by_name可以使用外部的库,通过CODEC_ID的则使用FFMpeg自带的库// codec = avcodec_find_encoder_by_name("libx264");codec = avcodec_find_encoder_by_name("libfdk_aac");// codec = avcodec_find_encoder(AV_CODEC_ID_AAC); // 用这个会涉及下面注释的一系列修改if (!codec) {av_log(NULL, AV_LOG_ERROR, "don't find codec name %s\n", codecName);goto _ERROR;}// 3. 创建编码器上下文ctx = avcodec_alloc_context3(codec);if (!ctx) {av_log(NULL, AV_LOG_ERROR, "No memory\n");goto _ERROR;}// 4. 设置编码器参数ctx->bit_rate = 64000;ctx->sample_fmt = AV_SAMPLE_FMT_S16;// AV_SAMPLE_FMT_FLTP,对于ffmpeg内部的编码器 用这个格式ret = check_sample_fmt(codec, AV_SAMPLE_FMT_S16); if (ret == 0) {av_log(NULL, AV_LOG_ERROR, "encoder do not support sample format\n");goto _ERROR;}// 自定义函数找到最接近44100的采样率ctx->sample_rate = select_best_sample_rate(codec);// 设置声道布局为立体声stereoav_channel_layout_copy(&ctx->ch_layout, &(AVChannelLayout)AV_CHANNEL_LAYOUT_STEREO); // AV_CHANNEL_LAYOUT_MONO ffmpeg内部编码器修改成这个// 5. 编码器与编码器上下文绑定ret = avcodec_open2(ctx, codec, NULL);if (ret < 0) {av_log(ctx, AV_LOG_ERROR, "Don't open codec: %s", av_err2str(ret));goto _ERROR;}// 6. 创建输出文件f = fopen(dst, "wb");if (!f) {av_log(NULL, AV_LOG_ERROR, "Don't open file %s\n", dst);goto _ERROR;}// 7. 创建AVFrameframe = av_frame_alloc();if (!frame) {av_log(NULL, AV_LOG_ERROR, "No memory\n");goto _ERROR;}// 必须赋值才能获取到bufferframe->nb_samples = ctx->frame_size;frame->format = ctx->sample_fmt;av_channel_layout_copy(&frame->ch_layout, &ctx->ch_layout);// frame中真正存储数据的位置不会被av_frame_alloc生成,还需要调用av_frame_get_buffer获取ret = av_frame_get_buffer(frame, 0);if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "Could't not allocate the video frame\n");goto _ERROR;}// 8. 创建AVPacketpkt = av_packet_alloc();if (!pkt) {av_log(NULL, AV_LOG_ERROR, "No memory\n");goto _ERROR;}// 9. 生成音频内容float t = 0.0;// 有空了解一下这个值float tincr = 2 * M_PI * 440 / ctx->sample_rate;for (int i = 0; i < 200; ++i) {ret = av_frame_make_writable(frame);if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "do not allocate space\n");goto _ERROR;}samples = (uint16_t*)frame->data[0]; // FLTP是32位的 所以改成uint32, 下面所有2都得改成4// 2字节一个数据for (int j = 0; j < ctx->frame_size; ++j) {samples[2 * j] = (sin(t) * 10000);// 多声道的处理for (int k = 1; k < ctx->ch_layout.nb_channels; ++k) {samples[2 * j + k] = samples[2 * j];}t += tincr;}encode(ctx, frame, pkt, f);}// 输出一个空包,用于刷新剩余数据encode(ctx, NULL, pkt, f);
_ERROR:if (ctx) {avcodec_free_context(&ctx);}if (frame) {av_frame_free(&frame);}if (pkt) {av_packet_free(&pkt);}if (f) {fclose(f);}return 0;
}
gcc -g -o encode_audio encode_audio.c `pkg-config --libs libavutil libavformat`./encode_audio 1.aac
由于ffmpeg自带的aac格式是32位的AV_SAMPLE_FMT_FLTP,如果由libfdk_aac转成ffmpeg自带的aac,需要进行重采样成FLTP才能继续其他操作
生成图片
生成黑白色图片
先把视频解码成帧序列,然后将帧保存为图片
#include <libavformat/avformat.h>
#include <libavutil/log.h>
#include <libavutil/avutil.h>
#include <libavcodec/avcodec.h>static void savePic(unsigned char *buf, int lineSize, int width, int height, char *name) {FILE *f;f = fopen(name, "wb");// 写入头信息fprintf(f, "P5\n%d %d\n%d\n", width, height, 255);for (int i = 0; i < height; ++i) {fwrite(buf + i *lineSize, 1, width, f);}fclose(f);
}static int decode(AVCodecContext *ctx, AVFrame *frame, AVPacket *pkt, const char *fileName) {int ret = -1;char buf[1024];ret = avcodec_send_packet(ctx, pkt);if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "Failed to send frame to encoder\n");goto _END;}while (ret >= 0) {ret = avcodec_receive_frame(ctx, frame);// AVERROR(EAGAIN)表示出错了if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {return 0;} else if(ret < 0) {return -1;}snprintf(buf, sizeof(buf), "%s-%d", fileName, ctx->frame_num);savePic(frame->data[0], frame->linesize[0], frame->width, frame->height, buf);if (pkt) {av_packet_unref(pkt);}}
_END:return 0;
}int main (int argc, char *argv[]) {// 1. 处理参数char *src;char *dst;int ret;int idx = -1;AVFormatContext *pFmtCtx = NULL;AVPacket *pkt = NULL;const AVCodec *codec = NULL;AVCodecContext *ctx = NULL;AVFrame *frame = NULL;AVStream *inStream = NULL;av_log_set_level(AV_LOG_DEBUG);if (argc < 3) {av_log(NULL, AV_LOG_ERROR, "argument must be more than 3\n");exit(-1);}src = argv[1];dst = argv[2];// 2. 打开多媒体文件ret = avformat_open_input(&pFmtCtx, src, NULL, NULL);if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "%s\n", av_err2str(ret));exit(-1);}// 3. 从多媒体文件中找到音频流idx = av_find_best_stream(pFmtCtx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);if (idx < 0) {av_log(pFmtCtx, AV_LOG_ERROR, "Does not include audio stream\n");goto _ERROR;}inStream = pFmtCtx->streams[idx];// 4. 查找解码器codec = avcodec_find_decoder(inStream->codecpar->codec_id);if (!codec) {av_log(NULL, AV_LOG_ERROR, "don't find codec\n");goto _ERROR;}// 5. 创建解码器上下文ctx = avcodec_alloc_context3(codec);if (!ctx) {av_log(NULL, AV_LOG_ERROR, "No memory\n");goto _ERROR;}// 拷贝编码参数到上下文对象avcodec_parameters_to_context(ctx, inStream->codecpar);// 5. 解码器与解码器上下文绑定ret = avcodec_open2(ctx, codec, NULL);if (ret < 0) {av_log(ctx, AV_LOG_ERROR, "Don't open codec: %s", av_err2str(ret));goto _ERROR;}// 6. 创建AVFrameframe = av_frame_alloc();if (!frame) {av_log(NULL, AV_LOG_ERROR, "No memory\n");goto _ERROR;}// 7. 创建AVPacketpkt = av_packet_alloc();if (!pkt) {av_log(NULL, AV_LOG_ERROR, "No memory\n");goto _ERROR;}// 8. 从源多媒体文件中读数据到目的文件中while (av_read_frame(pFmtCtx, pkt) >= 0) {if (pkt->stream_index == idx) {decode(ctx, frame, pkt, dst);}}decode(ctx, frame, NULL, dst);// 9. 将申请的资源释放掉
_ERROR:if (pFmtCtx) {avformat_close_input(&pFmtCtx);pFmtCtx = NULL;} if (ctx) {avcodec_free_context(&ctx);ctx = NULL;}if (frame) {av_frame_free(&frame);frame = NULL;}if (pkt) {av_packet_free(&pkt);pkt = NULL;}return 0;
}
gcc -g -o gen_pic gen_pic.c `pkg-config --libs libavutil libavformat`./gen_pic ~/resource/1.mp4 out/out
生成彩色图片BMP
代码目前有bug尚未找出
#include <libavformat/avformat.h>
#include <libavutil/log.h>
#include <libavutil/avutil.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>#define WORD uint64_t
#define DWORD uint32_t
#define LONG int32_t
// 去网站上拷贝对应定义:https://learn.microsoft.com/zh-cn/windows/win32/api/wingdi/ns-wingdi-bitmapinfoheader
typedef struct tagBITMAPINFOHEADER {DWORD biSize;LONG biWidth;LONG biHeight;WORD biPlanes;WORD biBitCount;DWORD biCompression;DWORD biSizeImage;LONG biXPelsPerMeter;LONG biYPelsPerMeter;DWORD biClrUsed;DWORD biClrImportant;
} BITMAPINFOHEADER, *LPBITMAPINFOHEADER, *PBITMAPINFOHEADER;typedef struct tagBITMAPFILEHEADER {WORD bfType;DWORD bfSize;WORD bfReserved1;WORD bfReserved2;DWORD bfOffBits;
} BITMAPFILEHEADER, *LPBITMAPFILEHEADER, *PBITMAPFILEHEADER;static void saveBMP(struct SwsContext *swsCtx,AVFrame *frame, int w, int h, char *name) {FILE *f = NULL;// 3是因为转换成24位的帧,刚好3个字节int dataSize = w * h * 3;// 1. 进行转换,将yuv frame 转成 BRG24 FrameAVFrame *frameBGR = av_frame_alloc();frameBGR->width = w;frameBGR->height = h;frameBGR->format = AV_PIX_FMT_BGR24;av_frame_get_buffer(frameBGR, 0);sws_scale(swsCtx, (const uint8_t *const *)frame->data,frame->linesize,0,frame->height,frameBGR->data, frameBGR->linesize);// 2. 构造 BITMAP INFO HEADERBITMAPINFOHEADER infoHeader;infoHeader.biSize = sizeof(BITMAPINFOHEADER);infoHeader.biWidth = w;infoHeader.biHeight = h * (-1); // 坐标与正常坐标相反infoHeader.biBitCount = 24;infoHeader.biCompression = 0;infoHeader.biSizeImage = 0;infoHeader.biClrImportant = 0;infoHeader.biClrUsed = 0;infoHeader.biXPelsPerMeter = 0;infoHeader.biYPelsPerMeter = 0;infoHeader.biPlanes = 0;// 3. 构造 BITMAP FILE HEADERBITMAPFILEHEADER fileHeader;fileHeader.bfType = 0x4d42; // 表示两个字符‘BM’fileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + dataSize;fileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);// 4. 将数据写到文件f = fopen(name, "wb");fwrite(&fileHeader, sizeof(BITMAPFILEHEADER), 1, f);fwrite(&infoHeader, sizeof(BITMAPINFOHEADER), 1, f);fwrite(&frame->data[0], 1, dataSize, f);// 5. 释放资源 fclose(f);av_freep(&frameBGR->data[0]);av_free(frameBGR);}static void savePic(unsigned char *buf, int lineSize, int width, int height, char *name) {FILE *f;f = fopen(name, "wb");// 写入头信息fprintf(f, "P5\n%d %d\n%d\n", width, height, 255);for (int i = 0; i < height; ++i) {fwrite(buf + i *lineSize, 1, width, f);}fclose(f);
}static int decode(AVCodecContext *ctx, struct SwsContext *swsCtx,AVFrame *frame, AVPacket *pkt, const char *fileName) {int ret = -1;char buf[1024];ret = avcodec_send_packet(ctx, pkt);if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "Failed to send frame to encoder\n");goto _END;}while (ret >= 0) {ret = avcodec_receive_frame(ctx, frame);// AVERROR(EAGAIN)表示出错了if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {return 0;} else if(ret < 0) {return -1;}snprintf(buf, sizeof(buf), "%s-%d.bmp", fileName, ctx->frame_num);// savePic(frame->data[0], frame->linesize[0], frame->width, frame->height, buf);saveBMP(swsCtx, frame, frame->width, frame->height, buf);// 释放前需要判空if (pkt) {av_packet_unref(pkt);}}
_END:return 0;
}int main (int argc, char *argv[]) {// 1. 处理参数char *src;char *dst;int ret;int idx = -1;AVFormatContext *pFmtCtx = NULL;AVPacket *pkt = NULL;const AVCodec *codec = NULL;AVCodecContext *ctx = NULL;AVFrame *frame = NULL;AVStream *inStream = NULL;struct SwsContext *swsCtx = NULL;av_log_set_level(AV_LOG_DEBUG);if (argc < 3) {av_log(NULL, AV_LOG_ERROR, "argument must be more than 3\n");exit(-1);}src = argv[1];dst = argv[2];// 2. 打开多媒体文件ret = avformat_open_input(&pFmtCtx, src, NULL, NULL);if (ret < 0) {av_log(NULL, AV_LOG_ERROR, "%s\n", av_err2str(ret));exit(-1);}// 3. 从多媒体文件中找到音频流idx = av_find_best_stream(pFmtCtx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0);if (idx < 0) {av_log(pFmtCtx, AV_LOG_ERROR, "Does not include audio stream\n");goto _ERROR;}inStream = pFmtCtx->streams[idx];// 4. 查找解码器codec = avcodec_find_decoder(inStream->codecpar->codec_id);if (!codec) {av_log(NULL, AV_LOG_ERROR, "don't find codec\n");goto _ERROR;}// 5. 创建解码器上下文ctx = avcodec_alloc_context3(codec);if (!ctx) {av_log(NULL, AV_LOG_ERROR, "No memory\n");goto _ERROR;}// 拷贝编码参数到上下文对象avcodec_parameters_to_context(ctx, inStream->codecpar);// 5. 解码器与解码器上下文绑定ret = avcodec_open2(ctx, codec, NULL);if (ret < 0) {av_log(ctx, AV_LOG_ERROR, "Don't open codec: %s", av_err2str(ret));goto _ERROR;}av_log(NULL, AV_LOG_INFO, "scale: %d, %d\n", ctx->width, ctx->height);// 5.1 获得SWS上下文sws_getCachedContext(NULL, ctx->width, // src widthctx->height, // src height AV_PIX_FMT_YUV420P, // src pix fmt 有时候ctx->pix_fmt的格式是不对的640, // dst width 这里的640 x 360 是因为需要按比例360, // dst heightAV_PIX_FMT_BGR24, // dst pix fmtSWS_BICUBIC, // 后面研究NULL, NULL, NULL);// 6. 创建AVFrameframe = av_frame_alloc();if (!frame) {av_log(NULL, AV_LOG_ERROR, "No memory\n");goto _ERROR;}// 7. 创建AVPacketpkt = av_packet_alloc();if (!pkt) {av_log(NULL, AV_LOG_ERROR, "No memory\n");goto _ERROR;}// 8. 从源多媒体文件中读数据到目的文件中while (av_read_frame(pFmtCtx, pkt) >= 0) {if (pkt->stream_index == idx) {decode(ctx, swsCtx, frame, pkt, dst);}}decode(ctx, swsCtx, frame, NULL, dst);// 9. 将申请的资源释放掉
_ERROR:if (pFmtCtx) {avformat_close_input(&pFmtCtx);pFmtCtx = NULL;} if (ctx) {avcodec_free_context(&ctx);ctx = NULL;}if (frame) {av_frame_free(&frame);frame = NULL;}if (pkt) {av_packet_free(&pkt);pkt = NULL;}return 0;
}
gcc -g -o gen_pic gen_pic.c pkg-config --libs libavutil libavformat libswscale
./gen_pic ~/resource/1.mp4 out/out
相关文章:
C++音视频04:音视频编码、生成图片
视频编码 #include <libavutil/log.h> #include <libavutil/opt.h> #include <libavcodec/avcodec.h>static int encode(AVCodecContext *ctx, AVFrame *frame, AVPacket *pkt, FILE *out) {int ret -1;ret avcodec_send_frame(ctx, frame);if (ret < …...
ImageSharp报错
错误信息 System.MissingMethodException: Method not found: System.Span1<SixLabors.ImageSharp.PixelFormats.Rgba32> SixLabors.ImageSharp.Memory.Buffer2D1.GetRowSpan(Int32).需要升级项目 原来仅升级了SixLabors.ImageSharp没有升级drawing,都升级到…...
Android中常用adb命令
目录 1.adb连接安卓模拟器 2.adb列出所有已经连接的设备 3.adb显示设备的日志信息 4.adb 电脑文件推送到安卓模拟器中 5.adb 手机传送文件到电脑 6.adb获取安卓应用的包名和Activity名 附录 1--命令 1)adb devices 2)adb install 路径> 3)…...
PostgreSQL的奥秘:全面解读JSONB——非结构化数据支持的深入探索
引言 PostgreSQL的JSONB数据类型非常灵活,提供了一套操作符来操作JSON数据。本指南将引导您创建一个包含JSONB数据的表,演示各种JSONB操作符,并讨论如何使用倒排索引和部分索引来优化性能。 理解PostgreSQL中的JSONB JSONB,即JS…...
tornado,flaskd这两个框架主要是干什么的
Tornado是一个Python的Web框架,主要用于构建高性能的异步Web应用程序。它基于非阻塞的网络I/O模型,可以处理大量并发连接,适用于需要处理实时性要求较高的应用场景,如实时聊天、实时数据推送等。 Flask是另一个Python的Web框架&a…...
Sigrity Power SI Noise coupling analysis模式如何进行压降仿真分析操作指导
Sigrity Power SI Noise coupling analysis模式如何进行压降仿真分析操作指导 Sigrity除了可以进行交流噪声分析,同样也可以进行压降仿真分析,以下图为例. 3D view...
国产游戏技术能否引领全球?
国产游戏技术能否引领全球? 引言 近年来,中国游戏产业如同春天的嫩芽,迅速成长为全球最大的市场之一。或许你会想,国内的游戏开发者到底在技术上取得了多大的成就?这些成就又能否推动中国游戏走向世界,甚…...
【前端】在 Next.js 开发服务器中应该如何配置 HTTPS?
在 Next.js 的开发环境中,默认情况下是使用 HTTP 协议的。但是,您可以通过一些配置来启用 HTTPS。这在开发阶段可能很有用,尤其是在需要测试涉及安全传输的应用场景时。 下面是如何在 Next.js 开发环境中配置 HTTPS 的步骤: 方法…...
基于深度学习算法的动物检测系统(含PyQt+代码+训练数据集)
基于深度学习算法的动物检测系统(含PyQt代码训练数据集) 前言一、数据集1.1 数据集介绍1.2 数据预处理 二、模型搭建三、训练与测试3.1 模型训练3.2 模型测试 四、PyQt界面实现五、讨论5.1 模型优缺点分析5.2 实验意义 参考资料 前言 本项目是基于Mobil…...
微信小程序美团点餐
引言:外卖已经成为了都市人的必备,在无数个来不及(懒得)做饭的时刻拯救孤单寂寞的胃。美团外卖无疑是外卖届的领头羊,它的很多功能与设计都值得我们学习。本文将从五个方面,对美团外卖展开产品分析…...
音频剪辑还花钱?2024年这4款免费工具让你告别烦恼
音乐迷们!是不是还在为找个音频剪辑软件就得花钱这事儿头疼呢?别急,2024年有好几个既免费又特别给力的音频剪辑免费的小帮手来了,保证帮你省下这笔钱,还让你用得爽歪歪!来来来,让我给你们介绍4个…...
【YOLO模型】(4)--YOLO V3超超超超详解!!!
文章目录 YOLO V3一、改进二、三种scale三、残差连接四、核心网络结构1. 结构2. 输出与先验框关系 五、softmax层替代 总结 YOLO V3 YOLO V3是由Joseph Redmon等人在2018年推出的一款目标检测算法。作为YOLO系列的第三代版本,它在实时性和准确性上取得了显著的提升…...
管理类联考 信息整理和经验分享
说明:大家在准备读MBA之前,肯定会去百度下MBA的相关常识,然而一上某度 你就发现 各种广告、各种培训机构 铺天盖地而来,想了解一些有价值的信息都有些困难,因此这些我在这里做了一些整理,方便准备参加 MBA …...
JetBrains IDE中GPU进程(JCEF)重启问题(Too many restarts of GPU-process)解决方案
目录 前言1. GPU进程重启问题概述1.1 什么是GPU进程重启问题?1.2 该问题带来的影响 2. GPU进程重启问题的原因分析2.1 显卡驱动的兼容性问题2.2 系统资源的限制2.3 JCEF组件的设置不合理 3. 解决方案3.1 方法一:通过自定义属性禁用GPU加速3.2 方法二&…...
《泛基因组:高质量参考基因组的新标准》
摘要 随着三代测序技术的进步和高质量参考基因组的发布,研究者们发现单一个体的参考基因组无法全面代表整个物种的遗传序列。这一现象导致了群体遗传变异图谱的不完整。为了解决这一问题,构建来自多个个体的泛基因组成为一种有效的方法。 泛基因组研究…...
模型其他压缩方法
文章目录 模型蒸馏模型剪枝除了模型量化之外,下面再介绍两种常见的模型压缩方法,即模型蒸馏和模型剪枝。与模型量化不同,模型蒸馏和模型剪枝则通过精简模型的结构,进而减少参数的数量。 不同表示精度的模型性能对比 模型蒸馏 模型蒸馏(ModelDistillation)的目标是将复杂…...
Python学习的自我理解和想法(22)
学的是b站的课程(千锋教育),跟老师写程序,不是自创的代码! 今天是学Python的第22天,学的内容是正则表达式,明天会出一篇详细实例介绍。电脑刚修好!开学了,时间不多&…...
基于neo4j的糖尿病知识图谱数据
基于Neo4j的糖尿病知识图谱项目:毕业设计必备💡 这个项目,专为需要深入挖掘医学或AI数据的朋友们量身定制,尤其适合用于毕业设计!如果你对图谱构建、AI问答系统、或者正在学习Neo4j,那么你不得不看看这个技…...
分布式搜索引擎elasticsearch操作文档操作介绍
1.DSL查询文档 elasticsearch的查询依然是基于JSON风格的DSL来实现的。 1.1.DSL查询分类 Elasticsearch提供了基于JSON的DSL(Domain Specific Language)来定义查询。常见的查询类型包括: 查询所有:查询出所有数据,…...
C++ 中的可调用对象
目录 一.可调用对象简介 1.什么是可调用对象? 2.可调用对象有什么用? 二.函数指针和仿函数 1.函数指针 a.函数指针的使用语法 b.函数指针的应用场景 2.仿函数 a.仿函数的基本概念 b.仿函数的优点 三.lambda表达式和function 1.lambda表达式 …...
[HBase]二 HBase原生Shell命令大全
HBase原生Shell命令汇总 1. General组 5 1.1. 查看集群状态:status 5 1.2. 查看表的操作方法:table_help 5 1.3. 查看HBase的版本信息:version 5 1.4. 查看当前用户:whoami 5 2. Namespace组 5 2.1. 创建命名空间:create_namespace 5 2.2. 显示命名空…...
Kafka之消费者客户端
1、历史上的二个版本 与生产者客户端一样,在Kafka的发展过程当中,消费者客户端主要有两个大的版本: 旧消费者客户端(Old Consumer):基于Scala语言开发的版本,又称为Scala消费者客户端。新消费…...
使用Python进行数据分析入门
文章目录 Python环境搭建安装Anaconda验证安装 必备库介绍NumPyPandasMatplotlibSciPy 数据导入与清洗导入数据清洗数据 数据探索与分析描述性统计相关性分析 数据可视化绘制直方图 高级主题机器学习深度学习 总结 随着大数据时代的到来,数据分析变得越来越重要。Py…...
ubuntu20 从源码编译升级到版本5.15.263
author: hjjdebug date: 2024年 10月 25日 星期五 15:38:48 CST description: ubuntu20 从源码编译升级到版本5.15.263 我的内核是 5.15.105, 用apt 下载源码后其版本是5.15.263 为什么要从源码编译内核. 升级内核? 目的: 练练手. 消除内核神秘性. 还可以裁减内核,也是调试内核…...
php 程序开发分层与验证思想
在PHP程序开发中,合理的层级设计可以提高代码的可维护性、可扩展性和可测试性。以下是常见的层级设计模式及建议: 1. 分层架构 通常可以将PHP应用分为以下几层: 表示层(Presentation Layer): 负责与用户交…...
关于InternVL2的单卡、多卡推理
关于InternVL2的单卡、多卡推理 前言单卡推理多卡推理总结前言 本章节将介绍如何使用上一章节微调后的模型进行推理。推理又分为单卡和多卡,这里介绍的两种方式都是Hugging Face的transformers方法进行推理。模型的话可以使用上一章微调的任意一个非lora模型进行测试。 单卡推…...
Go语言设计Web框架
如何设计一个Web框架 项目规划 在开始设计Web框架之前,我们需要对整个项目进行规划。主要包括以下几个方面: 项目结构依赖管理路由设计控制器设计日志和配置管理 项目结构 首先,我们定义项目的目录结构: ├── cmd/ │ └…...
2024年10月28日练习(双指针算法)
一.11. 盛最多水的容器 - 力扣(LeetCode) 1.题目描述: 这个题目代表的意思就是数组上每个对应的值就相当于每条垂直线的高度,就相当于短板效应,两 个高度的线会取最短的长度因为那样水才不会漏。而两条线的数组的下标…...
Objective-C 音频爬虫:实时接收数据的 didReceiveData_ 方法
在互联网技术领域,数据的获取和处理是至关重要的。尤其是对于音频内容的获取,实时性和效率是衡量一个爬虫性能的重要指标。本文将深入探讨在Objective-C中实现音频爬虫时,如何高效地使用didReceiveData:方法来实时接收数据,并通过…...
提升网站流量和自然排名的SEO基本知识与策略分析
内容概要 在当今数字化时代,SEO(搜索引擎优化)成为加强网站可见度和提升流量的重要工具。SEO的基础知识包括理解搜索引擎的工作原理,以及如何通过优化网站内容和结构来提高自然排名。白帽SEO和黑帽SEO代表了两种截然不同的策略&a…...
给手机开发网站/免费推广产品平台有哪些
今天继续接着CSS盒子模型补充,CSS基础学习十三:盒子模型和CSS基础学习十四:盒子模型补充之display属 性设置都是介绍了盒子模型中的内容概括。开始今天的主题:外边距合并。 外边距合并指的是,当两个垂直外边距相遇时&…...
网站建设小程序定制开发/seo站内优化教程
神经网络的基本单元是神经元,它是包括输入、连接、计算和输出功能的模型(MP)。其中,每个连接都对应一个权值,神经元在接受上一层神经元的不同输入信号后,通过对应的连接进行信号的加权传递,再利…...
wordpress 前台加载慢/百度一下知道首页
1 Service Kubernetes Pods 是有生命周期的。他们会被创建,被销毁,但是他们不会无条件"复活"。比如 ReplicaSets 这种 Pod 控制器会动态生成或者销毁 Pods(如在扩容或者缩容时)。当然每个Pod 都会自动被 k8s 分配IP地址…...
深圳网站建设hi0755/baidu 百度一下
关于sphinx就不多累言了,一套相当优秀的全文检索引擎.无论索引速度还是检索速度真的是非常的快.至于coreseek ,可访问李沫南的站点 http://www.coreseek.com顺便在此感谢李沫南同学为 sphinx中文化做的贡献 :0)本文着重介绍在ubuntu下安装coreseek及相应的sphinx-php扩展.具体…...
网站建设与管理教案/产品推广方案ppt模板
程序猿和架构师都应该了解“康威定律”(Conways law) 什么是康威定律 康威定律是一句格言,指出组织设计系统来反映他们自己的沟通结构。它以计算机程序员梅尔文康威的名字命名,他于1967年提出了这个想法。他最初的措辞是: organizations wh…...
沈阳网站制作定制厂家/东莞外贸推广公司
http://blog.csdn.net/pipisorry/article/details/36633451 博客内容: (个性化)推荐系统构建三大方法:基于内容的推荐content-based,协同过滤collaborative filtering,隐语义模型(LFM, latent factor model…...