FFmpeg中硬解码后深度学习模型的图像处理dnn_processing(一)

news2024/9/24 15:28:57

ffmpeg 硬件解码

ffmpeg硬件解码可以使用最新的vulkan来做,基本上来说,不挑操作系统是比较重要的,如果直接使用cuda也是非常好的选择。

	AVPixelFormat sourcepf = AV_PIX_FMT_NV12;// AV_PIX_FMT_NV12;// AV_PIX_FMT_YUV420P;
	AVPixelFormat destpf = AV_PIX_FMT_YUV420P; //AV_PIX_FMT_BGR24
	AVBufferRef* hw_device_ctx = NULL;

下面的class 是我封装了一些功能,只是示例,读者可以自行修改,读的是rtsp 流,后面准备推流到gb28181上。


class c_AVDecoder:public TThreadRunable
{
	AVPixelFormat sourcepf = AV_PIX_FMT_NV12;// AV_PIX_FMT_NV12;// AV_PIX_FMT_YUV420P;
	AVPixelFormat destpf = AV_PIX_FMT_YUV420P; //AV_PIX_FMT_BGR24
	AVBufferRef* hw_device_ctx = NULL;

	SDLDraw v_draw;
	int hw_decoder_init(AVCodecContext* ctx, const enum AVHWDeviceType type)
	{
		int err = 0;

		if ((err = av_hwdevice_ctx_create(&hw_device_ctx, type,
			NULL, NULL, 0)) < 0) {
			fprintf(stderr, "Failed to create specified HW device.\n");
			return err;
		}
		ctx->hw_device_ctx = av_buffer_ref(hw_device_ctx);

		return err;
	}

	

	
	//SDLDraw g_draw;
	struct SwsContext* img_convert_ctx = NULL;


	AVFormatContext* input_ctx = NULL;
	int video_stream, ret;
	AVStream* video = NULL;
	AVCodecContext* decoder_ctx = NULL;
	AVCodec* decoder = NULL;
	AVPacket packet;
	enum AVHWDeviceType type;
	//转换成yuv420 或者rgb
	

	int decode_write(AVCodecContext* avctx, AVPacket* packet)
	{
		AVFrame* frame = NULL, * sw_frame = NULL;
		AVFrame* tmp_frame = NULL;
		//AVFrame* pFrameDst = NULL;
		unsigned char* out_buffer = NULL;
		int ret = 0;
		ret = avcodec_send_packet(avctx, packet);
		if (ret < 0) {
			fprintf(stderr, "Error during decoding\n");
			return ret;
		}


		if (img_convert_ctx == NULL)
		{
			img_convert_ctx = sws_getContext(avctx->width, avctx->height, sourcepf,
				WIDTH, HEIGHT, destpf, SWS_FAST_BILINEAR, NULL, NULL, NULL);
		}
		static int i = 0;
		while (1) {
			if (!(frame = av_frame_alloc()) || !(sw_frame = av_frame_alloc())) {
				fprintf(stderr, "Can not alloc frame\n");
				ret = AVERROR(ENOMEM);
				goto fail;
			}
			//avctx->get_buffer2
			ret = avcodec_receive_frame(avctx, frame);
			if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
				av_frame_free(&frame);
				av_frame_free(&sw_frame);
				return 0;
			}
			else if (ret < 0) {
				fprintf(stderr, "Error while decoding\n");
				goto fail;
			}

			if (frame->format == hw_pix_fmt) {
				/* retrieve data from GPU to CPU */
				sw_frame->format = sourcepf; // AV_PIX_FMT_NV12;// AV_PIX_FMT_YUV420P;// AV_PIX_FMT_NV12;// AV_PIX_FMT_BGR24;// AV_PIX_FMT_YUV420P;
				if ((ret = av_hwframe_transfer_data(sw_frame, frame, 0)) < 0) {
					fprintf(stderr, "Error transferring the data to system memory\n");
					goto fail;
				}
				//av_frame_copy_props(sw_frame, frame);
				tmp_frame = sw_frame;
			}
			else
				tmp_frame = frame;

			

#if 0
			if (out_buffer == NULL)
			{
				out_buffer = (unsigned char*)av_malloc(av_image_get_buffer_size(destpf,
					WIDTH,
					HEIGHT,
					1));
				//av_image_alloc()
				av_image_fill_arrays(pFrameDst.data, pFrameDst.linesize, out_buffer,
					destpf, WIDTH, HEIGHT, 1);
			}

#endif
			AVFrame* pFrameDst = av_frame_alloc();
			av_image_alloc(pFrameDst->data, pFrameDst->linesize, WIDTH, HEIGHT, destpf, 1);
#if 1
			sws_scale(img_convert_ctx, tmp_frame->data, tmp_frame->linesize,
				0, avctx->height, pFrameDst->data, pFrameDst->linesize);

#endif
			//cout << "into " << i++ << endl;

#if 1
			if (!v_draw.push(pFrameDst))
			{
				av_freep(&pFrameDst->data[0]);
				av_frame_free(&pFrameDst);
			}

#endif
#if 0
			size = av_image_get_buffer_size((AVPixelFormat)tmp_frame->format, tmp_frame->width,
				tmp_frame->height, 1);
			buffer = (uint8_t*)av_malloc(size);
			if (!buffer) {
				fprintf(stderr, "Can not alloc buffer\n");
				ret = AVERROR(ENOMEM);
				goto fail;
			}
			ret = av_image_copy_to_buffer(buffer, size,
				(const uint8_t* const*)tmp_frame->data,
				(const int*)tmp_frame->linesize, (AVPixelFormat)tmp_frame->format,
				tmp_frame->width, tmp_frame->height, 1);
			if (ret < 0) {
				fprintf(stderr, "Can not copy image to buffer\n");
				goto fail;
			}

			if ((ret = (int)fwrite(buffer, 1, size, output_file)) < 0) {
				fprintf(stderr, "Failed to dump raw data.\n");
				goto fail;
			}
#endif

		fail:
			av_frame_free(&frame);
			av_frame_free(&sw_frame);

			//av_freep(&buffer);
			if (ret < 0)
				return ret;
		}
	}

	int func_init(const char* url)
	{
		const char* stype = "dxva2";
		type = av_hwdevice_find_type_by_name(stype);
		if (type == AV_HWDEVICE_TYPE_NONE) {
			fprintf(stderr, "Device type %s is not supported.\n", stype);
			fprintf(stderr, "Available device types:");
			while ((type = av_hwdevice_iterate_types(type)) != AV_HWDEVICE_TYPE_NONE)
				fprintf(stderr, " %s", av_hwdevice_get_type_name(type));
			fprintf(stderr, "\n");
			return -1;
		}

		/* open the input file */
		//const char * filename = "h:/video/a.mp4";
		AVDictionary* opts = NULL;
		av_dict_set(&opts, "rtsp_transport", "tcp", 0);
		av_dict_set(&opts, "buffer_size", "1048576", 0);
		av_dict_set(&opts, "fpsprobesize", "5", 0);
		av_dict_set(&opts, "analyzeduration", "5000000", 0);
		if (avformat_open_input(&input_ctx, url, NULL, &opts) != 0) {
			fprintf(stderr, "Cannot open input file '%s'\n", url);
			return -1;
		}

		if (avformat_find_stream_info(input_ctx, NULL) < 0) {
			fprintf(stderr, "Cannot find input stream information.\n");
			return -1;
		}

		/* find the video stream information */
		ret = av_find_best_stream(input_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &decoder, 0);
		if (ret < 0) {
			fprintf(stderr, "Cannot find a video stream in the input file\n");
			return -1;
		}
		video_stream = ret;

		AVStream* stream = input_ctx->streams[video_stream];

		float frame_rate = stream->avg_frame_rate.num / stream->avg_frame_rate.den;//每秒多少帧
		std::cout << "frame_rate is:" << frame_rate << std::endl;

		//优化直接定死
		/*for (int i = 0;; i++) {
			const AVCodecHWConfig* config = avcodec_get_hw_config(decoder, i);
			if (!config) {
				fprintf(stderr, "Decoder %s does not support device type %s.\n",
					decoder->name, av_hwdevice_get_type_name(type));
				return -1;
			}
			if (config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX &&
				config->device_type == type) {
				hw_pix_fmt = config->pix_fmt;
				break;
			}
		}*/

		if (!(decoder_ctx = avcodec_alloc_context3(decoder)))
			return AVERROR(ENOMEM);

		video = input_ctx->streams[video_stream];
		if (avcodec_parameters_to_context(decoder_ctx, video->codecpar) < 0)
			return -1;

		decoder_ctx->get_format = get_hw_format;

		if (hw_decoder_init(decoder_ctx, type) < 0)
			return -1;

		if ((ret = avcodec_open2(decoder_ctx, decoder, NULL)) < 0) {
			fprintf(stderr, "Failed to open codec for stream #%u\n", video_stream);
			return -1;
		}

		/* open the file to dump raw data */
		//output_file = fopen(argv[3], "w+");

		v_draw.init(1280, 720, (int)frame_rate);
		v_draw.Start();
		/* actual decoding and dump the raw data */
		while (ret >= 0) {
			if ((ret = av_read_frame(input_ctx, &packet)) < 0)
				break;

			if (video_stream == packet.stream_index)
			{
				//这里需要更加精确的计算
				ret = decode_write(decoder_ctx, &packet);
				//SDL_Delay(1000 / frame_rate);
			}
			av_packet_unref(&packet);
			if (IsStop())
				break;
		}

		/* flush the decoder */
		packet.data = NULL;
		packet.size = 0;
		ret = decode_write(decoder_ctx, &packet);
		av_packet_unref(&packet);

		
		avcodec_free_context(&decoder_ctx);
		avformat_close_input(&input_ctx);
		av_buffer_unref(&hw_device_ctx);

		return 0;
	}

public:
	void Run()
	{
		while (1)
		{
			if(!IsStop())
				func_init(rtspurl);
		}
	}
};

使用sdl来绘制画面

首先声明,使用sdl来渲染画面并不是有多好,如果可以,可以使用新的绘制方式,比如直接使用opengl,直接使用vulkan来绘制是更好的,sdl封装了opengl,d3d等绘制方式,但是也失去了灵活性,当然,你从头到尾读遍了源码,另当别论,如果要使用均值处理函数来做消除百叶窗效果,摩尔纹,还是直接使用opengl 渲染更为简单,使用glsl语言就行了,甚至要使用非线性函数来增亮图形,最好也是直接使用opengl来绘制。

#pragma once

#include<chrono>
#define __STDC_CONSTANT_MACROS
#define SDL_MAIN_HANDLED
extern "C"
{
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/pixdesc.h>
#include <libavutil/hwcontext.h>
#include <libavutil/opt.h>
#include <libavutil/avassert.h>
#include <libavutil/imgutils.h>
#include <libswscale/swscale.h>
#include "SDL2\SDL.h"
};

#include "c_ringbuffer.h"
#include "TThreadRunable.h"

#include "TYUVMerge.h"


#define SFM_REFRESH_EVENT  (SDL_USEREVENT + 1)
#define SFM_BREAK_EVENT  (SDL_USEREVENT + 2)

#define WIDTH 640
#define HEIGHT 360

typedef struct
{
	int g_fps = 40;
	int thread_exit = 0;
	int thread_pause = 0;
}s_param;
static int sfp_refresh_thread(void *opaque)
{
	s_param * param = (s_param*)opaque;
	param->thread_exit = 0;
	param->thread_pause = 0;

	while (!param->thread_exit)
	{
		if (!param->thread_pause)
		{
			SDL_Event event;
			event.type = SFM_REFRESH_EVENT;
			SDL_PushEvent(&event);
		}
		SDL_Delay(1000 / param->g_fps);
	}
	param->thread_exit = 0;
	param->thread_pause = 0;
	//Break
	SDL_Event event;
	event.type = SFM_BREAK_EVENT;
	SDL_PushEvent(&event);
	return 0;
}

class TicToc
{
public:
	TicToc()
	{
		tic();
	}

	void tic()
	{
		start = std::chrono::system_clock::now();
	}

	double toc()
	{
		end = std::chrono::system_clock::now();
		std::chrono::duration<double> elapsed_seconds = end - start;
		return elapsed_seconds.count() * 1000;
	}

private:
	std::chrono::time_point<std::chrono::system_clock> start, end;
};


class SDLDraw :public TThreadRunable//实际上这里可以编码发送出去
{

	int					m_w = 0, m_h = 0;
	SDL_Window			*screen = NULL;
	SDL_Renderer		*sdlRenderer = NULL;
	SDL_Texture			*sdlTexture = NULL;
	SDL_Rect			sdlRect;
	SDL_Thread			*video_tid;
	SDL_Event			event;
	//struct SwsContext	*img_convert_ctx = NULL;
	bool m_window_init = false;
	lfringqueue<AVFrame, 20> v_frames;
	lfringqueue<AVFrame, 20> v_frames_1;
	lfringqueue<AVFrame, 20> v_frames_2;
	s_param v_param;
	//画布
	AVFrame * v_canvas_frame = NULL;
public:
	void init(int w, int h,int fps)
	{
		if (w != m_w || h != m_h)
		{
			m_w = w;
			m_h = h;
			if (v_canvas_frame != NULL)
			{
				func_uninit();
			}
		}
		v_param.g_fps = fps;
		//这是背景画布
		if (v_canvas_frame == NULL)
		{
			v_canvas_frame = av_frame_alloc();
			av_image_alloc(v_canvas_frame->data, v_canvas_frame->linesize, 1280, 720, AV_PIX_FMT_YUV420P, 1);
		}
	}
	void func_uninit()
	{
		av_freep(&v_canvas_frame->data[0]);
		av_frame_free(&v_canvas_frame);
	}
	bool push(AVFrame * frame)
	{
		//尝试三次插入
		return v_frames.enqueue(frame,3);
	}

protected:
	int draw_init(/*HWND hWnd,*/ )
	{
		//m_w = 1280;
		//m_h = 720;
		if (m_window_init == false)
		{
			SDL_Init(SDL_INIT_VIDEO);
			SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "1");
			screen = SDL_CreateWindow("FF", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
				1920, 1000, SDL_WINDOW_SHOWN/* SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE*/);
			//screen = SDL_CreateWindowFrom((void *)(hWnd));
			for (int i = 0; i < SDL_GetNumRenderDrivers(); ++i)
			{
				SDL_RendererInfo rendererInfo = {};
				SDL_GetRenderDriverInfo(i, &rendererInfo);
				cout << i << " " << rendererInfo.name << endl;
				//if (rendererInfo.name != std::string("direct3d11"))
				//{
				//	continue;
				//}
			}

			if (screen == NULL)
			{
				//printf("Window could not be created! SDL_Error: %s\n", SDL_GetError());
				return -1;
			}
			sdlRenderer = SDL_CreateRenderer(screen,0, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
			//sdlRenderer = SDL_CreateRenderer(screen, -1, SDL_RENDERER_ACCELERATED);
			//SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl");
			
			m_window_init = true;
			SDL_Thread	*video_tid = SDL_CreateThread(sfp_refresh_thread, NULL, &v_param);
		}
		return 0;
	}

	void draw(uint8_t *data[], int linesize[])
	{
		if (sdlTexture != NULL)
		{
			SDL_DestroyTexture(sdlTexture);
			sdlTexture = NULL;
		}

		//m_w = w;
		//m_h = h;
		if (sdlTexture == NULL)
		{
			sdlTexture = SDL_CreateTexture(sdlRenderer, SDL_PIXELFORMAT_IYUV,
				SDL_TEXTUREACCESS_STREAMING, m_w, m_h);
			sdlRect.x = 0;
			sdlRect.y = 0;
			sdlRect.w = m_w;
			sdlRect.h = m_h;// nh;
		}
		SDL_UpdateYUVTexture(sdlTexture, &sdlRect,
				data[0], linesize[0],
				data[1], linesize[1],
				data[2], linesize[2]);
		
		//SDL_RenderClear(sdlRenderer);
		SDL_RenderCopy(sdlRenderer, sdlTexture, NULL, NULL);
		SDL_RenderPresent(sdlRenderer);
		//video_tid = SDL_CreateThread(sfp_refresh_thread, NULL, NULL);

	}
public:
	void Run()
	{
		draw_init();
		AVFrame * frame = NULL;


		//while (!IsStop())
		//{
		//	//解码播放 直接播放
		//	if (v_frames.dequeue(&frame))
		//	{
		//		//播放
		//		draw(frame->data, frame->linesize,WIDTH,HEIGHT);
		//		av_frame_free(&frame);
		//		SDL_Delay(10);
		//	}
		//	else
		//	{
		//		SDL_Delay(10);
		//	}
		//}


#if 1
		/*SDL_Thread	*video_tid = SDL_CreateThread(sfp_refresh_thread, NULL, &v_param);*/
		int tick = 0;
		double x = 0.0f;
		for (;;)
		{
			if (IsStop())
			{
				v_param.thread_exit = 1;
				//break;
			}
			SDL_WaitEvent(&event);
			if (event.type == SFM_REFRESH_EVENT)
			{
				if (v_frames.dequeue(&frame))
				{
					tick++;
					TicToc tt;
					//MergeYUV(v_canvas_frame->data[0], 1280, 720,
					//	frame->data[0], WIDTH, HEIGHT, 1, 10, 10);
					MergeYUV_S(v_canvas_frame->data[0], 1280, 720,
						frame->data[0], WIDTH, HEIGHT, 10, 10);
					x += tt.toc();

					//播放
					draw(v_canvas_frame->data, v_canvas_frame->linesize);
					av_freep(&frame->data[0]);
					av_frame_free(&frame);
					
					if (tick == 10)
					{
						tick = 0;
						cout << x << endl;
						x = 0.0f;
					}
				}
			}
			else if (event.type == SDL_KEYDOWN)
			{
				if (event.key.keysym.sym == SDLK_SPACE)
					v_param.thread_pause = !v_param.thread_pause;
			}
			else if (event.type == SDL_QUIT)
			{
				v_param.thread_exit = 1;
			}
			else if (event.type == SFM_BREAK_EVENT)
			{
				break;
			}
		}
#endif
	}
	SDLDraw()
	{

	}
	~SDLDraw()
	{
		func_uninit();
	}

};

//SDL_FillRect(gScreenSurface, NULL, SDL_MapRGB(gScreenSurface->format, 0xFF, 0x00, 0x00));

ffmpeg 深度学习处理filter

    dnn_processing从2018年开始就已经是FFmpeg中的一个视频filter,支持所有基于深度学习模型的图像处理算法,即输入和输出都是AVFrame,而处理过程使用的是深度学习模型。为什么要开发这样一个filter,因为作为FFmpeg DNN模块的maintainer,dnn_processing就是一个很好的使用者入手功能,读ffmpeg的代码就可以知道,其实自己写这些功能就行了,至于支持视频分析功能的filter,先不进行编码,主要考虑如何支持异步建立流水线,如何启用batch size,从而最大化的用好系统的并行计算能力,本来ffmpeg硬件解码后,如何直接在gpu中进行swscale,其实是不支持的,这一部分要自己写代码来支持,这是另外一回话,我们先使用dnn_processing模块再说,
这个模块可以完成针对灰度图的sobel算子的调用,其输入输出的格式是grayf32。除了这个dnn_processing还可以完成sr(超分辨率)和derain(去除雨点)filter的功能,下面使用ffmpeg命令演示对yuv和rgb格式的支持

./ffmpeg -i night.jpg -vf scale=iw*2:ih*2,format=yuv420p,dnn_processing=dnn_backend=tensorflow:model=./srcnn.pb:input=x:output=y srcnn.jpg

./ffmpeg -i small.jpg -vf format=yuv420p,scale=iw*2:ih*2,dnn_processing=dnn_backend=native:model=./srcnn.model:input=x:output=y -q:v 2 small.jpgsrcnn.jpg

./ffmpeg -i small.jpg -vf format=yuv420p,dnn_processing=dnn_backend=native:model=./espcn.model:input=x:output=y small_b.jpg

./ffmpeg -i rain.jpg -vf format=rgb24,dnn_processing=dnn_backend=native:model=./can.model:input=x:output=y derain.jpg

下图可以看出放大两倍以后还是可以的,不是很模糊,其实是因为我们的训练模型很浅,还没有好好做训练,即使如此,我仔细查看过线性差值比这个图像要差。
在这里插入图片描述

连贯执行

后面第二篇就要进行硬件解码,到提升质量filter,到输出编码了,请等待第二篇

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

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

相关文章

Linux-centos花生壳实现内网穿透

Linux-centos花生壳实现内网穿透 官网教程 1.安装花生壳 下载网址 点击复制就可以复制下载命令了 wget "https://dl.oray.com/hsk/linux/phddns_5.2.0_amd64.rpm" -O phddns_5.2.0_amd64.rpm# 下载完成之后会多一个rpm文件 [rootlocalhost HuaSheng]# ls phddns_…

UE5+Paperzd问题

TopDown的2D游戏&#xff0c;遇到两个问题&#xff0c;第一问题是游戏一开始就会从tilemap上掉下去。第二个问题是没法和图层2上的物体做碰撞。 一、碰撞问题 1、创建的TileSet后&#xff0c;左侧选中一个tile后&#xff0c;一定要点击上边的Add Box&#xff0c;否则创建出来的…

jenkins的cicd操作

cicd概念 持续集成&#xff08; Continuous Integration&#xff09; 持续频繁的&#xff08;每天多次&#xff09;将本地代码“集成”到主干分支&#xff0c;并保证主干分支可用 持续交付&#xff08;Continuous Delivery&#xff09; 是持续集成的下一步&#xff0c;持续…

Julia 字典和集合

数组是一种集合&#xff0c;此外 Julia 也有其他类型的集合&#xff0c;比如字典和 set&#xff08;无序集合列表&#xff09;。 字典 字典是一种可变容器模型&#xff0c;且可存储任意类型对象。 字典的每个键值 key>value 对用 > 分割&#xff0c;每个键值对之间用逗…

STM32的电动自行车信息采集上报系统(学习)

摘要 针对电动自行车实时监管不便的问题&#xff0c;设计了一种基于STM32的电动自行车信息采集系统&#xff0c;通过获取电池、位置和行驶状态信息并上报到服务器中&#xff0c;实现实时监管。 通过多路串口请求电池、行驶状态和位置信息&#xff0c;以并发方式进行数据接收、…

亿欧智库:2023中国宠物行业新趋势洞察报告(附下载)

关于报告的所有内容&#xff0c;公众【营销人星球】获取下载查看 核心观点 户外赛道本质上迎合了全球共性需求的增长&#xff0c;从养宠意愿的转化到养宠生活的需求&#xff0c;多层次的需求推动行业发展新趋势 从需求端进行分析&#xff0c;可以将养宠意愿的转化分为三个层…

nginx部署以及反向代理多域名实现HTTPS访问

nginx部署以及反向代理多域名实现 1.nginx部署 1.1 编写nginx部署文件 docker-compose.yml version: 3 services: nginx:restart: always image: nginx:1.20container_name: nginx-mainports:- 80:80- 443:443volumes: # 基础配置- /opt/nginx_main/nginx-info/nginx.conf:/…

并查集模板-两个操作:合并集合和查询两个元素是否属于同一个集合

一、链接 836. 合并集合 二、题目 一共有 nn 个数&#xff0c;编号是 1∼n1∼n&#xff0c;最开始每个数各自在一个集合中。 现在要进行 mm 个操作&#xff0c;操作共有两种&#xff1a; M a b&#xff0c;将编号为 aa 和 bb 的两个数所在的集合合并&#xff0c;如果两个数…

在 aosp 中启用 Material You design

作者&#xff1a;Mr_万能胶 近期研究了一下如何在 aosp 中启用 Material You design&#xff0c;在把踩过的坑记录一下&#xff0c;方便后续有厂商可以快速集成。 本文基于 aosp 最新代码&#xff0c;版本号为 Android 13&#xff0c;并使用 Cuttlefish 快速验证。 Material …

消息队列项目(3)

Message 存储 由于 Message 以后会是一个比较庞大的数据, 放在数据库里并不合适, 因此我们要将它放在二进制文件中 因为 Message 和 Queue 是捆绑在一起的, 因此我们将目录名设置成 QueueName, 然后这些目录是存储在之前的 data 里 就像这样: 在 testQueue 中有包含两个文件…

LeetCode 0021. 合并两个有序链表

【LetMeFly】21.合并两个有序链表 力扣题目链接&#xff1a;https://leetcode.cn/problems/merge-two-sorted-lists/ 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1&#xff1a; 输入&#xff1a;l1 [1,2,4], l…

-bash: fork: retry: Resource temporarily unavailable 问题解决

错误提示&#xff1a; -bash: fork: retry: Resource temporarily unavailable 错误分析&#xff1a;之前已经出现过这种资源限制的报错提醒&#xff0c;然后整个系统可用的连接数就已经用完了&#xff0c;无法使用工具来获取系统信息&#xff0c;所以将运行的任务脚本kill后开…

Cesium引入vite + vue3

下载Cesium yarn add cesium下载cesium-vite 插件 yarn add vite-plugin-cesium使用 vite.config.js import { defineConfig } from vite import vue from vitejs/plugin-vue import WindiCSS from vite-plugin-windicss import cesium from vite-plugin-cesium; //引入插件…

Stephen Wolfram:嵌入的概念

The Concept of Embeddings 嵌入的概念 Neural nets—at least as they’re currently set up—are fundamentally based on numbers. So if we’re going to to use them to work on something like text we’ll need a way to represent our text with numbers. And certain…

如何制作网红小和尚视频

文章目录 写在前面需要用到的工具制作过程制作一张自己喜欢的底图制作爆款文案将文案转为语音使用底图和语音生成动画去除水印使用剪映生成视频 写在后面 写在前面 最近我尝试制作小和尚的视频&#xff0c;使用了一些AI技术&#xff0c;制作成本相对较低。这次经历让我感受到了…

工厂模式(C++)

定义 定义一个用于创建对象的接口&#xff0c;让子类决定实例化哪一个类。Factory Method使得一个类的实例化延迟(目的:解耦&#xff0c;手段:虚函数)到子类。 应用场景 在软件系统中&#xff0c;经常面临着创建对象的工作;由于需求的变化&#xff0c;需要创建的对象的具体类…

c语言——计算一串字符的长度

//计算一串字符的长度 //在main函数中输出一个字符&#xff0c;并且计算出该字符的长度。 #include<stdio.h> #include<stdlib.h> int length(char *s){int i0;while(*s!\0){i;s;}return i;} int main() {int len;char str[20];printf("输入字符串&#xff1a…

215. 数组中的第K个最大元素(快排+大根堆+小根堆)

题目链接&#xff1a;力扣 解题思路&#xff1a; 方法一&#xff1a;基于快速排序 因为题目中只需要找到第k大的元素&#xff0c;而快速排序中&#xff0c;每一趟排序都可以确定一个最终元素的位置。 当使用快速排序对数组进行降序排序时&#xff0c;那么如果有一趟排序过程…

大数据课程G2——Hbase的基本架构

文章作者邮箱&#xff1a;yugongshiyesina.cn 地址&#xff1a;广东惠州 ▲ 本章节目的 ⚪ 掌握Hbase的基本架构&#xff1b; ⚪ 掌握Hbase的读写流程&#xff1b; ⚪ 掌握Hbase的设计与优化&#xff1b; 一、基本架构 1. HRegion 1. 在HBase中&#xff0c;会…

林大数据结构【2019】

关键字&#xff1a; 哈夫曼树权值最小、哈夫曼编码、邻接矩阵时间复杂度、二叉树后序遍历、二叉排序树最差时间复杂度、非连通无向图顶点数&#xff08;完全图&#xff09;、带双亲的孩子链表、平衡二叉树调整、AOE网关键路径 一、判断 二、单选 三、填空 四、应用题