【音視頻】FFmpeg 編碼H265

一、概述

實現了讀入本地yuv文件,通過libx265編碼為H265格式,并存儲到本地文件中

二、實現流程

準備文件

build路徑下準備yuv文件

在這里插入圖片描述

在項目中添加文件參數,輸出為h265文件,使用libx265編碼

在這里插入圖片描述

初始化解碼器
  • 通過傳進來的libx265找到指定的編碼器
codec = avcodec_find_encoder_by_name(codec_name);
if (!codec) {fprintf(stderr, "Codec '%s' not found\n", codec_name);exit(1);
}
  • 為編碼器分配上下文
codec_ctx = avcodec_alloc_context3(codec);
if (!codec_ctx) {fprintf(stderr, "Could not allocate video codec context\n");exit(1);
}
  • 綁定解碼器和解碼器上下文
ret = avcodec_open2(codec_ctx, codec, NULL);
if (ret < 0) {fprintf(stderr, "Could not open codec: %s\n", av_err2str(ret));exit(1);
}
  • 設置編碼的視頻參數,如分辨率,幀率,時間基、比特率等
#define ENCODE_TIME_BASE 1000   // 設置時間基數,編碼需要根據時間來判斷碼率
#define ENCODE_FRAME_RATE 25   // 設置幀率
#define YUV_WIDTH 1280
#define YUV_HEIGH 720/* 設置分辨率*/
codec_ctx->width = YUV_WIDTH;        // 根據實際去寫入
codec_ctx->height = YUV_HEIGH;
/* 設置time base */
codec_ctx->time_base = (AVRational){1, ENCODE_TIME_BASE};  // 1/1000
codec_ctx->framerate = (AVRational){ENCODE_FRAME_RATE, 1};
codec_ctx->pix_fmt = AV_PIX_FMT_YUV420P;
  • 也可以設置編碼的碼率,可以設置一個碼率的范圍
  • 也可以設置編碼的緩存大小,用于在碼率波動的時候做緩存
codec_ctx->bit_rate = 3000000;codec_ctx->rc_max_rate = 3000000;
codec_ctx->rc_min_rate = 3000000;codec_ctx->rc_buffer_size = 2000000;
  • 配置編碼器的高級參數,這里指的是而外的設置
  • 比如編碼模式,GOP大小,B幀大小、I幀間隔、編碼profile級別、畫質等等
  • preset參數是影響編碼速度的,比如ultrafast編碼最快,但是畫質最差
codec_ctx->gop_size = 25;
codec_ctx->max_b_frames = 0;
codec_ctx->keyint_min = 25;ret = av_opt_set(codec_ctx->priv_data, "preset", "medium", 0);
ret = av_opt_set(codec_ctx->priv_data, "profile", "main", 0);
ret = av_opt_set(codec_ctx->priv_data, "tune","film",0);
  • 也可以通過av_opt_set的方法,將修改的內容直接發送到libx265編碼器內部進行修改
ret = av_opt_set(codec_ctx->priv_data, "x265-param", "--keyint=25, --bframes=2",0);
ret = av_opt_set(codec_ctx->priv_data, "x265-params", "--keyint=25:--frame-threads=4", 0);
ret = av_opt_set(codec_ctx->priv_data, "x265-params", "--keyint=25:--bframes=2", 0);
ret = av_opt_set(codec_ctx->priv_data, "x265-params", "--keyint=25:--frame-threads=4", 0);
  • 比如我們設置了B幀為0,并且關閉了多線程,此時的延遲就為0了,觀察如下
  • 可以發現,一幀數據傳入編碼器,立馬就編碼出一幀數據

在這里插入圖片描述

  • 初始之外,還可以通過設置零延遲的方法,當同時必須關閉多線程
ret = av_opt_set(codec_ctx->priv_data, "tune","zerolatency",0);
  • 如果開啟多線程,就會存在編碼延遲,不過可以提高編碼速度
  • 打印發現,傳入多幀數據后,才從編碼器中取出編碼后的幀
ret = av_opt_set(codec_ctx->priv_data, "x265-params", "--keyint=25:--frame-threads=4", 0);
  • 也可以這樣設置多線程
codec_ctx->thread_count = 4;  // 開了多線程后也會導致幀輸出延遲, 需要緩存thread_count幀后再編程。     
codec_ctx->thread_type = FF_THREAD_FRAME; // 并 設置為FF_THREAD_FRAME            

在這里插入圖片描述

  • 以下的設置,是將SPS、PPS、VPS放入擴展變量里面,即codec->extradata里面
  • 此時就不會而外編碼一幀了,觀察打印結果
codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; 

啟動后,沒發現SPS、PPS、VPS
在這里插入圖片描述

關閉后,前幾幀為SPS、PPS、VPS

在這里插入圖片描述

更多的libx265的設置,可以使用對應的命令查詢

ffmpeg -h encoder=libx265 > libx265.log

在這里插入圖片描述

編碼H265
  • 打開輸入、輸出文件
// 打開輸入和輸出文件
infile = fopen(in_yuv_file, "rb");
if (!infile) {fprintf(stderr, "Could not open %s\n", in_yuv_file);exit(1);
}
outfile = fopen(out_h264_h265_file, "wb");
if (!outfile) {fprintf(stderr, "Could not open %s\n", out_h264_h265_file);exit(1);
}
  • 分配對應的AVFrame和AVPacket的內存
// 分配pkt和frame
pkt = av_packet_alloc();
if (!pkt) {fprintf(stderr, "Could not allocate video frame\n");exit(1);
}
frame = av_frame_alloc();
if (!frame) {fprintf(stderr, "Could not allocate video frame\n");exit(1);
}
  • 設置frame的參數,如分辨率、像素
// 為frame分配buffer
frame->format = codec_ctx->pix_fmt;
frame->width  = codec_ctx->width;
frame->height = codec_ctx->height;ret = av_frame_get_buffer(frame, 0);
if (ret < 0) {fprintf(stderr, "Could not allocate the video frame data\n");exit(1);
}
  • 通過分辨率和像素格式,計算出一幀數據對應的buffer大小,并且分配對應的緩沖區
int frame_bytes = av_image_get_buffer_size(frame->format, frame->width,frame->height, 1);
uint8_t *yuv_buf = (uint8_t *)malloc(frame_bytes);
  • 循環編碼文件,直到讀到文件結束
  • av_frame_make_writable確保幀可用,不開啟的話可能會寫入失敗
for (;;) {memset(yuv_buf, 0, frame_bytes);size_t read_bytes = fread(yuv_buf, 1, frame_bytes, infile);if(read_bytes <= 0) {printf("read file finish\n");break;}/* 確保該frame可寫, 如果編碼器內部保持了內存參考計數,則需要重新拷貝一個備份目的是新寫入的數據和編碼器保存的數據不能產生沖突*/ret = av_frame_make_writable(frame);if(ret != 0) {printf("av_frame_make_writable failed, ret = %d\n", ret);break;}int need_size = av_image_fill_arrays(frame->data, frame->linesize, yuv_buf,frame->format,frame->width, frame->height, 1);if(need_size != frame_bytes) {printf("av_image_fill_arrays failed, need_size:%d, frame_bytes:%d\n",need_size, frame_bytes);break;}pts += (ENCODE_TIME_BASE/ENCODE_FRAME_RATE);// 設置ptsframe->pts = pts;       // 使用采樣率作為pts的單位,具體換算成秒 pts*1/采樣率begin_time = get_time();ret = encode(codec_ctx, frame, pkt, outfile);end_time = get_time();printf("encode time:%lldms\n", end_time - begin_time);if(ret < 0) {printf("encode failed\n");break;}
}
  • encode函數如下,主要是送入一幀數據,然后循環讀取AVPacket,直到輸出AVERROR_EOF表示當前幀編碼完成
static int encode(AVCodecContext *enc_ctx, AVFrame *frame, AVPacket *pkt,FILE *outfile)
{int ret;/* send the frame to the encoder */if (frame)printf("send frame pts:%3"PRId64"\n", frame->pts);/* 通過查閱代碼,使用x265進行編碼時,具體緩存幀是在x265源碼進行,* 不會增加avframe對應buffer的reference*/ret = avcodec_send_frame(enc_ctx, frame);if (ret < 0){fprintf(stderr, "Error sending a frame for encoding\n");return -1;}while (ret >= 0){ret = avcodec_receive_packet(enc_ctx, pkt);if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {return 0;}else if (ret < 0) {fprintf(stderr, "Error encoding audio frame\n");return -1;}printf("avcodec_receive_packet:pts:%3"PRId64" dts:%3"PRId64" (size:%5d)\n", pkt->pts, pkt->dts, pkt->size);fwrite(pkt->data, 1, pkt->size, outfile); print_h265_nal_unit_type(pkt->data, pkt->size);  // 只針對H265}return 0;
}
  • print_h265_nal_unit_type函數主要是通過H265的結構,找到startcode,然后解析NALU的頭部,用于輸出調試
void print_h265_nal_unit_type(uint8_t *data, size_t size)
{int i = 0;while (i+3 < size ) {if(data[i] == 0 && data[i+1]==0 && data[i+2] == 0 && data[i+3] == 1 ) {i += 4;printf("%02x nal_type:%d, pos:%d\n", data[i],(data[i]&0x7e)>>1, i);continue;}if(data[i] == 0 && data[i+1]==0 && data[i+2] == 1) {i += 3;printf("%02x nal_type:%d, pos:%d\n",data[i], (data[i]&0x7e)>>1, i);continue;}i++;}
}
沖刷編碼器
  • 編碼結束后,編碼器內部可能還緩存了部分幀,此時需要傳入NULL,將編碼器中剩余的幀沖刷出來
/* 沖刷編碼器 */
encode(codec_ctx, NULL, pkt, outfile);
關閉文件
  • 關閉文件、并且釋放相關內存,確保正確結束程序
// 關閉文件
fclose(infile);
fclose(outfile);// 釋放內存
if(yuv_buf) {free(yuv_buf);
}av_frame_free(&frame);
av_packet_free(&pkt);
avcodec_free_context(&codec_ctx);

完整代碼

/**
* @projectName   02-encode_h265
* @brief         視頻編碼,從本地讀取YUV數據進行H265編碼
* @author        Liao Qingfu
* @date          2022-09-16
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>#include <libavcodec/avcodec.h>
#include <libavutil/time.h>
#include <libavutil/opt.h>
#include <libavutil/imgutils.h>
#define ENCODE_TIME_BASE 1000   // 設置時間基數,編碼需要根據時間來判斷碼率
#define ENCODE_FRAME_RATE 25   // 設置幀率
#define YUV_WIDTH 1280
#define YUV_HEIGH 720void print_h265_nal_unit_type(uint8_t *data, size_t size);
int64_t get_time()
{return av_gettime_relative() / 1000;  // 換算成毫秒
}
static int encode(AVCodecContext *enc_ctx, AVFrame *frame, AVPacket *pkt,FILE *outfile)
{int ret;/* send the frame to the encoder */if (frame)printf("send frame pts:%3"PRId64"\n", frame->pts);/* 通過查閱代碼,使用x264進行編碼時,具體緩存幀是在x264源碼進行,* 不會增加avframe對應buffer的reference*/ret = avcodec_send_frame(enc_ctx, frame);if (ret < 0){fprintf(stderr, "Error sending a frame for encoding\n");return -1;}while (ret >= 0){ret = avcodec_receive_packet(enc_ctx, pkt);if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {return 0;}else if (ret < 0) {fprintf(stderr, "Error encoding audio frame\n");return -1;}printf("avcodec_receive_packet:pts:%3"PRId64" dts:%3"PRId64" (size:%5d)\n", pkt->pts, pkt->dts, pkt->size);fwrite(pkt->data, 1, pkt->size, outfile); print_h265_nal_unit_type(pkt->data, pkt->size);  // 只針對H265}return 0;
}
/*** @brief 提取測試文件:ffmpeg -i test_1280x720.flv -t 5 -r 25 -pix_fmt yuv420p yuv420p_1280x720.yuv*           參數輸入: yuv420p_1280x720.yuv yuv420p_1280x720.h265 libx265* @param argc* @param argv* @return*/
int main(int argc, char **argv)
{char *in_yuv_file = NULL;char *out_h264_h265_file = NULL;FILE *infile = NULL;FILE *outfile = NULL;const char *codec_name = NULL;const AVCodec *codec = NULL;AVCodecContext *codec_ctx= NULL;AVFrame *frame = NULL;AVPacket *pkt = NULL;int ret = 0;if (argc < 4) {fprintf(stderr, "Usage: %s <input_file out_file codec_name >, argc:%d\n",argv[0], argc);return 0;}in_yuv_file = argv[1];      // 輸入YUV文件out_h264_h265_file = argv[2];codec_name = argv[3];/* 查找指定的編碼器 */codec = avcodec_find_encoder_by_name(codec_name);if (!codec) {fprintf(stderr, "Codec '%s' not found\n", codec_name);exit(1);}codec_ctx = avcodec_alloc_context3(codec);if (!codec_ctx) {fprintf(stderr, "Could not allocate video codec context\n");exit(1);}/* 設置分辨率*/codec_ctx->width = YUV_WIDTH;        // 根據實際去寫入codec_ctx->height = YUV_HEIGH;/* 設置time base */codec_ctx->time_base = (AVRational){1, ENCODE_TIME_BASE};  // 1/1000codec_ctx->framerate = (AVRational){ENCODE_FRAME_RATE, 1};/* 設置I幀間隔* 如果frame->pict_type設置為AV_PICTURE_TYPE_I, 則忽略gop_size的設置,一直當做I幀進行編碼*/codec_ctx->gop_size = 25;   // I幀間隔, H265單獨設置這里不起作用codec_ctx->keyint_min = 25;codec_ctx->max_b_frames = 0; // 如果不想包含B幀則設置為0codec_ctx->pix_fmt = AV_PIX_FMT_YUV420P;//if (codec->id == AV_CODEC_ID_H264) {// 相關的參數可以參考libx264.c的 AVOption options// ultrafast all encode time:2270ms// medium all encode time:5815ms// veryslow all encode time:19836msret = av_opt_set(codec_ctx->priv_data, "preset", "medium", 0);if(ret != 0) {printf("av_opt_set preset failed\n");}ret = av_opt_set(codec_ctx->priv_data, "profile", "main", 0); // 默認是highif(ret != 0) {printf("av_opt_set profile failed\n");}
//        ret = av_opt_set(codec_ctx->priv_data, "tune","zerolatency",0); // 直播是才使用該設置
//        ret = av_opt_set(codec_ctx->priv_data, "tune","film",0); //  畫質filmif(ret != 0) {printf("av_opt_set tune failed\n");}}else if (codec->id == AV_CODEC_ID_H265) {// 相關的參數可以參考libx265.c的 AVOption options// ultrafast all encode time:// medium all encode time:// veryslow all encode time:ret = av_opt_set(codec_ctx->priv_data, "preset", "medium", 0);if(ret != 0) {printf("av_opt_set preset failed\n");}ret = av_opt_set(codec_ctx->priv_data, "profile", "main", 0); // 默認是highif(ret != 0) {printf("av_opt_set profile failed\n");}ret = av_opt_set(codec_ctx->priv_data, "tune","zerolatency",0); // 直播是才使用該設置
//        ret = av_opt_set(codec_ctx->priv_data, "tune","film",0); //  畫質filmif(ret != 0) {printf("av_opt_set tune failed\n");}// libx265/source\common\param.cpp
//        ret = av_opt_set(codec_ctx->priv_data, "x265-param", "--keyint=25, --bframes=2",0);
//        ret = av_opt_set(codec_ctx->priv_data, "x265-params", "--keyint=25:--frame-threads=4", 0);
//        ret = av_opt_set(codec_ctx->priv_data, "x265-params", "--keyint=25:--bframes=2", 0);
//        ret = av_opt_set(codec_ctx->priv_data, "x265-params", "--keyint=25:--frame-threads=4", 0);if(ret != 0) {printf("av_opt_set x265-param failed\n");return -1;}} else {printf("no support the codec :%s\n", codec_name);return -1;}/** 設置編碼器參數*//* 設置bitrate */codec_ctx->bit_rate = 3000000; //3000k
//    codec_ctx->rc_max_rate = 3000000;
//    codec_ctx->rc_min_rate = 3000000;
//    codec_ctx->rc_buffer_size = 2000000;
//    codec_ctx->thread_count = 4;  // 開了多線程后也會導致幀輸出延遲, 需要緩存thread_count幀后再編程。
//    codec_ctx->thread_type = FF_THREAD_FRAME; // 并 設置為FF_THREAD_FRAME/* 對于H264 AV_CODEC_FLAG_GLOBAL_HEADER  設置則只包含I幀,此時sps pps需要從codec_ctx->extradata讀取*  不設置則每個I幀都帶 sps pps sei*/codec_ctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; // 存本地文件時不要去設置/* 將codec_ctx和codec進行綁定 */ret = avcodec_open2(codec_ctx, codec, NULL);if (ret < 0) {fprintf(stderr, "Could not open codec: %s\n", av_err2str(ret));exit(1);}printf("thread_count: %d, thread_type:%d\n", codec_ctx->thread_count, codec_ctx->thread_type);// 打開輸入和輸出文件infile = fopen(in_yuv_file, "rb");if (!infile) {fprintf(stderr, "Could not open %s\n", in_yuv_file);exit(1);}outfile = fopen(out_h264_h265_file, "wb");if (!outfile) {fprintf(stderr, "Could not open %s\n", out_h264_h265_file);exit(1);}// 分配pkt和framepkt = av_packet_alloc();if (!pkt) {fprintf(stderr, "Could not allocate video frame\n");exit(1);}frame = av_frame_alloc();if (!frame) {fprintf(stderr, "Could not allocate video frame\n");exit(1);}// 為frame分配bufferframe->format = codec_ctx->pix_fmt;frame->width  = codec_ctx->width;frame->height = codec_ctx->height;ret = av_frame_get_buffer(frame, 0);if (ret < 0) {fprintf(stderr, "Could not allocate the video frame data\n");exit(1);}// 計算出每一幀的數據 像素格式 * 寬 * 高// 1382400int frame_bytes = av_image_get_buffer_size(frame->format, frame->width,frame->height, 1);printf("frame_bytes %d\n", frame_bytes);uint8_t *yuv_buf = (uint8_t *)malloc(frame_bytes);if(!yuv_buf) {printf("yuv_buf malloc failed\n");return 1;}int64_t begin_time = get_time();int64_t end_time = begin_time;int64_t all_begin_time = get_time();int64_t all_end_time = all_begin_time;int64_t pts = 0;printf("start enode\n");for (;;) {memset(yuv_buf, 0, frame_bytes);size_t read_bytes = fread(yuv_buf, 1, frame_bytes, infile);if(read_bytes <= 0) {printf("read file finish\n");break;}/* 確保該frame可寫, 如果編碼器內部保持了內存參考計數,則需要重新拷貝一個備份目的是新寫入的數據和編碼器保存的數據不能產生沖突*/ret = av_frame_make_writable(frame);if(ret != 0) {printf("av_frame_make_writable failed, ret = %d\n", ret);break;}int need_size = av_image_fill_arrays(frame->data, frame->linesize, yuv_buf,frame->format,frame->width, frame->height, 1);if(need_size != frame_bytes) {printf("av_image_fill_arrays failed, need_size:%d, frame_bytes:%d\n",need_size, frame_bytes);break;}pts += (ENCODE_TIME_BASE/ENCODE_FRAME_RATE);// 設置ptsframe->pts = pts;       // 使用采樣率作為pts的單位,具體換算成秒 pts*1/采樣率begin_time = get_time();ret = encode(codec_ctx, frame, pkt, outfile);end_time = get_time();printf("encode time:%lldms\n", end_time - begin_time);if(ret < 0) {printf("encode failed\n");break;}}/* 沖刷編碼器 */encode(codec_ctx, NULL, pkt, outfile);all_end_time = get_time();printf("all encode time:%lldms\n", all_end_time - all_begin_time);// 關閉文件fclose(infile);fclose(outfile);// 釋放內存if(yuv_buf) {free(yuv_buf);}av_frame_free(&frame);av_packet_free(&pkt);avcodec_free_context(&codec_ctx);printf("main finish, please enter Enter and exit\n");getchar();return 0;
}void print_h265_nal_unit_type(uint8_t *data, size_t size)
{int i = 0;while (i+3 < size ) {if(data[i] == 0 && data[i+1]==0 && data[i+2] == 0 && data[i+3] == 1 ) {i += 4;printf("%02x nal_type:%d, pos:%d\n", data[i],(data[i]&0x7e)>>1, i);continue;}if(data[i] == 0 && data[i+1]==0 && data[i+2] == 1) {i += 3;printf("%02x nal_type:%d, pos:%d\n",data[i], (data[i]&0x7e)>>1, i);continue;}i++;}
}

更多資料:https://github.com/0voice

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/83485.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/83485.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/83485.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

ECreator低代碼平臺-文件管理器的使用說明

Ecreator是中山華拓信息技術公司旗下的一款低代碼平臺&#xff0c;主要功能包含&#xff1a;文件管理器&#xff0c;表單數據管理器&#xff0c;儀表盤設計界面&#xff0c;內容頁面自定義等功能&#xff0c;可以用于快速低成本的構建網站和企業內部應用。 下面介紹一下文件管…

高考加油!UI界面生成器!

這個高考助力標語生成器具有以下特點&#xff1a; 視覺設計&#xff1a;采用了藍色為主色調&#xff0c;搭配漸變背景和圓形裝飾元素&#xff0c;營造出寧靜而充滿希望的氛圍&#xff0c;非常適合高考主題。 標語生成&#xff1a;內置了超過 100 條精心挑選的高考加油標語&a…

阿姆達爾定律的演進:古斯塔夫森定律

前言 在上一篇文章《使用阿姆達爾定律來提升效率》中提到的阿姆達爾定律前提是假設問題的規模保持不變&#xff0c;并且給定一臺速度更快的機器&#xff0c;目標是更快地解決問題。然而&#xff0c;在大多數情況下&#xff0c;這并不完全正確。當有一臺更快的機器時&#xff0…

【RabbitMQ】- Channel和Delivery Tag機制

在 RabbitMQ 的消費者代碼中&#xff0c;Channel 和 tag 參數的存在是為了實現消息確認機制&#xff08;Acknowledgment&#xff09;和精細化的消息控制。 Channel 參數 作用 Channel 是 AMQP 協議的核心操作接口&#xff0c;通過它可以直接與 RabbitMQ 交互&#xff1a; 手…

核心機制:流量控制

搭配滑動窗口使用的 窗口大小 窗口越大,傳輸速度就越快,但是也不能無限大,太大了,對于可靠性會有影響 比如發生方以非常快的速度,發送,接收方的處理速度跟不上,也就會導致有效數據被接受方丟棄(又得重傳) 流量控制,就是根據接收方的處理能力(如何衡量?),干預到發送方的發送…

深度強化學習賦能城市消防優化,中科院團隊提出DRL新方法破解設施配置難題

在城市建設與發展中&#xff0c;地理空間優化至關重要。從工業園區選址&#xff0c;到公共服務設施布局&#xff0c;它都發揮著關鍵作用。但傳統求解方法存在諸多局限&#xff0c;如今&#xff0c;深度學習技術為其帶來了新的轉機。 近日&#xff0c;在中國地理學會地理模型與…

安科電動機保護器通過ModbusRTU轉profinet網關與PLC通訊

安科電動機保護器通過ModbusRTU轉profinet網關與PLC通訊 在工業自動化領域&#xff0c;設備間的通信和數據交互至關重要。Modbus作為一種常用的通訊協議&#xff0c;廣泛應用于各種工業現場&#xff1b;而Profinet則憑借其高效、實時性&#xff0c;在工業以太網通訊中占據重要…

python直方圖

在Python中&#xff0c;繪制直方圖&#xff08;Histogram&#xff09;是一項非常常見的任務&#xff0c;通常用于數據可視化&#xff0c;以展示數據的分布情況。Python中有多種庫可以繪制直方圖&#xff0c;其中最常用的兩個庫是Matplotlib和Seaborn。此外&#xff0c;Pandas庫…

在Oxygen編輯器中使用DeepSeek

羅馬尼亞公司研制開發的Oxygen編輯器怎樣與國產大模型結合&#xff0c;這是今年我在tcworld大會上給大家的分享&#xff0c;需要ppt的朋友請私信聯系 - 1 - Oxygen編輯器中的人工智能助手 Oxygen編輯器是羅馬尼亞的Syncro Soft公司開發的一款結構化文檔編輯器。 它是用來編寫…

neo4j 5.19.0安裝、apoc csv導入導出 及相關問題處理

前言 突然有需求需要用apoc 導入 低版本的圖譜數據&#xff0c;網上資料又比較少&#xff0c;所以就看官網資料并處理了apoc 導入的一些問題。 相關地址 apoc 官方安裝網址 apoc 官方導出csv 教程地址 apoc 官方 導入 csv 地址 docker 安裝 執行如下命令啟動鏡像 doc…

macos常見且應該避免被覆蓋的系統環境變量(避免用 USERNAME 作為你的自定義變量名)

文章目錄 macos避免用 USERNAME 作為你的自定義變量名macos常見且應該避免被覆蓋的系統環境變量 macos避免用 USERNAME 作為你的自定義變量名 問題&#xff1a; 你執行了&#xff1a;export USERNAME“admin” 然后執行&#xff1a;echo ${USERNAME} 輸出卻是&#xff1a;xxx …

Python訓練打卡Day41

簡單CNN 知識回顧 數據增強卷積神經網絡定義的寫法batch歸一化&#xff1a;調整一個批次的分布&#xff0c;常用與圖像數據特征圖&#xff1a;只有卷積操作輸出的才叫特征圖調度器&#xff1a;直接修改基礎學習率 卷積操作常見流程如下&#xff1a; 1. 輸入 → 卷積層 → Batch…

【親測有效】Mybatis-Plus中更新字段為null

Mybatis-Plus中更新字段為null 遇到問題 Mybatis-Plus更新的默認行為如下: Mybatis-Plus默認如果某個字段為null, 默認不更新這個字段, 例如有個Double類型的字段, 當前數據庫數據為10, 然后傳參時當前字段為null, 實際上Mybatis-Plus是不會覆蓋該字段為null的 在傳參的時候如…

如何使用插件和子主題添加WordPress自定義CSS(附:常見錯誤)

您是否曾經想更改網站外觀的某些方面&#xff0c;但不知道怎么做&#xff1f;有一個解決方案——您可以將自定義 CSS&#xff08;層疊樣式表&#xff09;添加到您的WordPress網站&#xff01; 在本文中&#xff0c;我們將討論您需要了解的有關CSS的所有知識以及如何使用它來修…

左值引用和右值引用

一、基本概念 左值&#xff08;lvalue&#xff09;和右值&#xff08;rvalue&#xff09; 左值指的是有確定存儲位置&#xff08;地址&#xff09;的對象&#xff0c;通常可以出現在賦值語句左側。例如&#xff1a;變量名、解引用指針得到的對象、數組元素等都屬于左值。 右值…

django入門-orm數據庫操作

一&#xff1a;下載數據庫依賴項mysqlclient pip install mysqlclient 二&#xff1a;django配置文件配置數據庫鏈接 路徑&#xff1a;mysite2\mysite2\settings.py DATABASES {default: {ENGINE: django.db.backends.mysql,NAME: data, # 數據庫名稱USER: root, …

國標GB28181設備管理軟件EasyGBS視頻平臺筑牢文物保護安全防線創新方案

一、方案背景? 文物作為人類文明的珍貴載體&#xff0c;具有不可再生性。當前&#xff0c;盜竊破壞、游客不文明行為及自然侵蝕威脅文物安全&#xff0c;傳統保護手段存在響應滯后、覆蓋不全等局限。隨著5G與信息技術發展&#xff0c;基于GB28181協議的EasyGBS視頻云平臺&…

NetSuite Bundle - Dashboard Refresh

兒童節快樂&#xff01; 今朝發一個Bundle&#xff0c;解決一個NetSuite Dashboard的老問題。出于性能上的考慮&#xff0c;NetSuite的Dashboard中的Portlet&#xff0c;只能逐一手工刷新。有人基于瀏覽器做了插件&#xff0c;可以進行自動刷新。但是在我們做項目部署時&#…

<PLC><socket><西門子>基于西門子S7-1200PLC,實現手機與PLC通訊(通過websocket轉接)

前言 本系列是關于PLC相關的博文,包括PLC編程、PLC與上位機通訊、PLC與下位驅動、儀器儀表等通訊、PLC指令解析等相關內容。 PLC品牌包括但不限于西門子、三菱等國外品牌,匯川、信捷等國內品牌。 除了PLC為主要內容外,PLC相關元器件如觸摸屏(HMI)、交換機等工控產品,如…

【AI論文】推理語言模型的強化學習熵機制

摘要&#xff1a;本文旨在克服將強化學習擴展到使用 LLM 進行推理的主要障礙&#xff0c;即策略熵的崩潰。 這種現象在沒有熵干預的RL運行中一直存在&#xff0c;其中策略熵在早期訓練階段急劇下降&#xff0c;這種探索能力的減弱總是伴隨著策略性能的飽和。 在實踐中&#xff…