当前位置: 首页 > news >正文

DirectShow过滤器开发-写WAV音频文件过滤器

下载本过滤器DLL
本过滤器将PCM音频流,或ADPCM,IEEE_FLOAT,ALAW,MULAW,GSM610音频流写入WAV音频文件。

写WAV音频文件过滤器信息

过滤器名称:写WAV
过滤器GUID:{CF704A9C-0C67-4712-BA33-DD0AAE01A232}
DLL注册函数名:DllRegisterServer
删除注册函数名:DllUnregisterServer
过滤器有1个输入引脚。

输入引脚标识:In
输入引脚媒体类型:
主要类型:MEDIATYPE_Audio
子类型:
MEDIASUBTYPE_PCM
{0x00000002, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
MEDIASUBTYPE_IEEE_FLOAT
{0x00000006, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
{0x00000007, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
{0x00000031, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
格式类型:FORMAT_WaveFormatEx
样本为固定大小。

写WAV音频文件过滤器开发信息

WAV音频文件使用PCM方式表示音频数据,即使用short值表示采样点音频的幅值。即无压缩,也无编码;是表示音频数据最基本的方式。文件体积较大。故添加了使用压缩方式写WAV文件的方法,生成WAV文件后,Windows播放器仍可播放。

写WAV音频文件过滤器DLL的全部代码

DLL.h

#ifndef  DLL_FILE
#define DLL_FILE#include "strmbase10.h"//过滤器基础类定义文件#if _DEBUG
#pragma comment(lib, "strmbasd10.lib")//过滤器基础类实现文件调试版本
#else
#pragma comment(lib, "strmbase10.lib")//过滤器基础类实现文件发布版本
#endif// {CF704A9C-0C67-4712-BA33-DD0AAE01A232}
DEFINE_GUID(CLSID_WavWriter,//过滤器GUID0xcf704a9c, 0xc67, 0x4712, 0xba, 0x33, 0xdd, 0xa, 0xae, 0x1, 0xa2, 0x32);DEFINE_GUID(MEDIASUBTYPE_ADPCM,//0x00000002, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);DEFINE_GUID(MEDIASUBTYPE_ALAW,//0x00000006, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);DEFINE_GUID(MEDIASUBTYPE_MULAW,//0x00000007, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);DEFINE_GUID(MEDIASUBTYPE_GSM610,//0x00000031, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71);#include "strsafe.h"struct WAVE_HEADER {char RIFF_ch[4] = { 'R','I','F','F' };//文件规范标识DWORD mSize = 0;//从下一项(文件类型)的开始位置,到文件的结束位置的大小,以字节为单位char WAVE_ch[4] = { 'W','A','V','E' };//文件类型char fmt_ch[4] = { 'f','m','t',' ' };//格式块标识DWORD fmt_Size = 16;//格式块大小WORD Format = 1;//编码方式WORD nChannels = 0;//声道数DWORD SampleRate = 0;//采样率DWORD ByteRate = 0;//传输率WORD BlockAlign = 0;//块对齐WORD BitsPerSample = 0;//样本位数
};class CFilter;class CPin : public CBaseInputPin
{friend class CFilter;
public:CPin(CFilter *pFilter, HRESULT *phr, LPCWSTR pPinName);~CPin();HRESULT CheckMediaType(const CMediaType *pmt);HRESULT SetMediaType(const CMediaType *pmt);STDMETHODIMP Receive(IMediaSample *pSample);HRESULT Active();HRESULT Inactive();STDMETHODIMP EndOfStream();CFilter *pCFilter;DWORD Data_Size = 0;HANDLE hFile = NULL;//输出文件句柄WORD cbSize = 0;//附加信息大小char Data_ch[4] = { 'd','a','t','a' };//数据块标识DWORD mSize = 0;//数据区块大小,以字节为单位BYTE* pAppend = NULL;
};class CFilter : public CBaseFilter, public CCritSec, public IFileSinkFilter
{friend class CPin;
public:CFilter(LPWSTR lpName, LPUNKNOWN pUnk, HRESULT *phr);virtual ~CFilter();DECLARE_IUNKNOWNSTDMETHODIMP NonDelegatingQueryInterface(REFIID riid, void ** ppv);virtual HRESULT STDMETHODCALLTYPE  SetFileName(LPCOLESTR pszFileName, const AM_MEDIA_TYPE *pmt);virtual HRESULT STDMETHODCALLTYPE  GetCurFile(LPOLESTR * ppszFileName, AM_MEDIA_TYPE *pmt);static CUnknown * WINAPI CreateInstance(LPUNKNOWN, HRESULT *);int GetPinCount();CBasePin *GetPin(int n);CPin *pCPin=NULL;   //输入引脚指针WCHAR* m_pFileName=NULL;//要创作的WAV文件路径WAVE_HEADER header;//WAV文件头
};template <class T> void SafeRelease(T** ppT)
{if (*ppT){(*ppT)->Release();*ppT = NULL;}
}#endif //DLL_FILE

DLL.cpp


#include "DLL.h"const AMOVIESETUP_MEDIATYPE InPinType[] =   // 输入引脚媒体类型
{{&MEDIATYPE_Audio,             //主要类型&MEDIASUBTYPE_PCM             //子类型},{&MEDIATYPE_Audio,             //主要类型&MEDIASUBTYPE_ADPCM           //子类型},{&MEDIATYPE_Audio,             //主要类型&MEDIASUBTYPE_IEEE_FLOAT      //子类型},{&MEDIATYPE_Audio,             //主要类型&MEDIASUBTYPE_ALAW            //子类型},{&MEDIATYPE_Audio,            //主要类型&MEDIASUBTYPE_MULAW          //子类型},{&MEDIATYPE_Audio,             //主要类型&MEDIASUBTYPE_GSM610          //子类型}
};const AMOVIESETUP_PIN sudPins[] =  // 引脚信息
{{(LPWSTR)"In",                 //引脚名称FALSE,                        //渲染引脚FALSE,                        //输出引脚FALSE,                        //具有该引脚的零个实例FALSE,                        //可以创建一个以上引脚的实例&CLSID_NULL,                  //该引脚连接的过滤器的类标识NULL,                         //该引脚连接的引脚名称6,                            //引脚支持的媒体类型数InPinType                     //媒体类型信息}
};const AMOVIESETUP_FILTER MP3Encoder =  //过滤器的注册信息
{&CLSID_WavWriter,             //过滤器的类标识L"写WAV",                     //过滤器的名称MERIT_DO_NOT_USE,             //过滤器优先值1,                            //引脚数量sudPins                       //引脚信息
};CFactoryTemplate g_Templates[] =   //类工厂模板数组
{{L"写WAV",                  //对象(这里为过滤器)名称&CLSID_WavWriter,          //对象CLSID的指针CFilter::CreateInstance,   //创建对象实例的函数的指针NULL,                      //指向从DLL入口点调用的函数的指针&MP3Encoder                //指向AMOVIESETUP_FILTER结构的指针}
};int g_cTemplates = 1;//模板数组大小STDAPI DllRegisterServer()//注册DLL
{return AMovieDllRegisterServer2(TRUE);
}STDAPI DllUnregisterServer()//删除DLL注册
{return AMovieDllRegisterServer2(FALSE);
}extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);BOOL APIENTRY DllMain(HANDLE hModule, DWORD  dwReason, LPVOID lpReserved)
{return DllEntryPoint((HINSTANCE)(hModule), dwReason, lpReserved);
}

CFilter.cpp

#include "DLL.h"CFilter::CFilter(LPWSTR lpName, LPUNKNOWN pUnk, HRESULT *phr) : CBaseFilter(lpName, pUnk, (CCritSec *) this, CLSID_WavWriter)
{pCPin = new CPin(this, phr, L"In");//创建输入引脚
}CFilter::~CFilter()
{delete[] m_pFileName; 
}CUnknown * WINAPI CFilter::CreateInstance(LPUNKNOWN pUnk, HRESULT *phr)
{return new CFilter(L"写WAV", pUnk, phr);//创建过滤器
}int CFilter::GetPinCount()
{return 1;
}CBasePin *CFilter::GetPin(int n)
{if (n != 0){return NULL;}return pCPin;
}STDMETHODIMP CFilter::NonDelegatingQueryInterface(REFIID iid, void ** ppv)
{if (iid == IID_IFileSinkFilter){return GetInterface(static_cast<IFileSinkFilter*>(this), ppv);}elsereturn CBaseFilter::NonDelegatingQueryInterface(iid, ppv);
}HRESULT CFilter::GetCurFile(LPOLESTR *ppszFileName, AM_MEDIA_TYPE *pmt)
{CheckPointer(ppszFileName, E_POINTER);*ppszFileName = NULL;if (m_pFileName != NULL){size_t len = 1 + lstrlenW(m_pFileName);*ppszFileName = (LPOLESTR)QzTaskMemAlloc(sizeof(WCHAR) * (len));if (*ppszFileName != NULL){HRESULT hr = StringCchCopyW(*ppszFileName, len, m_pFileName);}}if (pmt){ZeroMemory(pmt, sizeof(*pmt));pmt->majortype = MEDIATYPE_NULL;pmt->subtype = MEDIASUBTYPE_NULL;}return S_OK;
}HRESULT CFilter::SetFileName(LPCOLESTR pszFileName, const AM_MEDIA_TYPE *pmt)
{CheckPointer(pszFileName, E_POINTER);if (wcslen(pszFileName) > MAX_PATH || wcslen(pszFileName)<4)return ERROR_FILENAME_EXCED_RANGE;size_t len = 1 + lstrlenW(pszFileName);m_pFileName = new WCHAR[len];if (m_pFileName == 0)return E_OUTOFMEMORY;HRESULT hr = StringCchCopyW(m_pFileName, len, pszFileName);if (m_pFileName[len - 2] != 'v' || m_pFileName[len - 3] != 'a' || m_pFileName[len - 4] != 'w' || m_pFileName[len - 5] != '.')//如果不是WAV文件{delete[] m_pFileName; m_pFileName = NULL;return VFW_E_INVALID_FILE_FORMAT;//设置文件名失败}return S_OK;
}

CPin.cpp

#include "DLL.h"CPin::CPin(CFilter *pFilter, HRESULT *phr, LPCWSTR pPinName) : CBaseInputPin(NAME("In"), pFilter, pFilter, phr, pPinName)
{pCFilter = pFilter;}CPin::~CPin()//输入引脚析构函数
{}HRESULT CPin::CheckMediaType(const CMediaType *pmt)
{if (pmt->majortype == MEDIATYPE_Audio && pmt->formattype == FORMAT_WaveFormatEx && pmt->bFixedSizeSamples){if (pmt->subtype == MEDIASUBTYPE_PCM || pmt->subtype == MEDIASUBTYPE_ADPCM || pmt->subtype == MEDIASUBTYPE_IEEE_FLOAT|| pmt->subtype == MEDIASUBTYPE_ALAW || pmt->subtype == MEDIASUBTYPE_MULAW || pmt->subtype == MEDIASUBTYPE_GSM610)return S_OK;return S_FALSE;}elsereturn S_FALSE;
}HRESULT CPin::SetMediaType(const CMediaType *pmt)
{WAVEFORMATEX* p = (WAVEFORMATEX*)pmt->pbFormat;//给文件头参数赋值pCFilter->header.Format = p->wFormatTag;//编码方式pCFilter->header.nChannels = p->nChannels;//声道数pCFilter->header.SampleRate = p->nSamplesPerSec;//采样率pCFilter->header.ByteRate = p->nAvgBytesPerSec;;//传输率pCFilter->header.BlockAlign = p->nBlockAlign;//块对齐pCFilter->header.BitsPerSample = p->wBitsPerSample;//样本位数pCFilter->header.fmt_Size = 16;//格式块大小if (p->cbSize > 0)//如果有附加信息{cbSize = p->cbSize;pCFilter->header.fmt_Size = p->cbSize + sizeof(WAVEFORMATEX);//格式块大小if (pAppend != NULL){delete[] pAppend; pAppend = NULL;}pAppend = new BYTE[p->cbSize];if (pmt->subtype == MEDIASUBTYPE_ADPCM){BYTE info[32] = {244,7,7,0,0,1,0,0,0,2,0,255,0,0,0,0,192,0,64,0,240,0,0,0,204,1,48,255,136,1,24,255};//MEDIASUBTYPE_ADPCM附加信息CopyMemory(pAppend, &info, 32);//复制附加信息}else if (pmt->subtype == MEDIASUBTYPE_GSM610){BYTE info[2] = {64,1};CopyMemory(pAppend, &info, 2);//复制附加信息}else{CopyMemory(pAppend, pmt->pbFormat- sizeof(WAVEFORMATEX), cbSize);//复制附加信息}}return CBaseInputPin::SetMediaType(pmt);
}HRESULT CPin::Receive(IMediaSample * pSample)//接收函数
{HRESULT hr;BYTE* pBy = NULL;hr = pSample->GetPointer(&pBy);//获取引脚样本缓冲区指针long len = pSample->GetActualDataLength();//获取有效数据长度if (hFile){WriteFile(hFile, pBy, len, NULL, NULL);//写WAVE数据Data_Size += len;//记录已写数据的字节大小}return S_OK;
}HRESULT CPin::Active()
{if (pCFilter->m_pFileName == NULL){MessageBox(0, L"没有指定输出文件", L"写WAV", MB_OK); return S_FALSE;}hFile = CreateFile(pCFilter->m_pFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);//创建输出文件if (INVALID_HANDLE_VALUE == hFile){MessageBox(0, L"创建输出文件失败", L"写WAV", MB_OK); return S_FALSE;}Data_Size = 0; WriteFile(hFile, &pCFilter->header, sizeof(pCFilter->header), NULL, NULL);//写WAVE文件头if (cbSize > 0)//如果有附加信息{WriteFile(hFile, &cbSize, 2, NULL, NULL);//写附加信息大小WriteFile(hFile, pAppend, cbSize, NULL, NULL);//写附加信息}WriteFile(hFile, Data_ch, 4, NULL, NULL);//写数据块标识WriteFile(hFile, &mSize, 4, NULL, NULL);//写数据块大小,写入的并非真实大小return CBaseInputPin::Active();
}HRESULT CPin::Inactive()
{LARGE_INTEGER Move; Move.QuadPart = 4;SetFilePointerEx(hFile, Move, NULL, FILE_BEGIN);//移动文件指针,到“文件大小”位置int AppendSize = pCFilter->header.fmt_Size - 16;DWORD FileSize = Data_Size + 36 + AppendSize;WriteFile(hFile, &FileSize, sizeof(FileSize), NULL, NULL);//写WAVE文件大小Move.QuadPart = 40 + AppendSize;SetFilePointerEx(hFile, Move, NULL, FILE_BEGIN);//移动文件指针,到“数据大小”位置WriteFile(hFile, &Data_Size, sizeof(Data_Size), NULL, NULL);//写WAVE数据大小CloseHandle(hFile);//关闭输出文件hFile = NULL; cbSize = 0;if (pAppend != NULL){delete[] pAppend; pAppend = NULL;}return CBaseInputPin::Inactive();
}STDMETHODIMP CPin::EndOfStream()
{pCFilter->NotifyEvent(EC_COMPLETE, S_OK, 0);return CBaseInputPin::EndOfStream();
}

下载本过滤器DLL

相关文章:

DirectShow过滤器开发-写WAV音频文件过滤器

下载本过滤器DLL 本过滤器将PCM音频流&#xff0c;或ADPCM&#xff0c;IEEE_FLOAT&#xff0c;ALAW&#xff0c;MULAW&#xff0c;GSM610音频流写入WAV音频文件。 写WAV音频文件过滤器信息 过滤器名称&#xff1a;写WAV 过滤器GUID&#xff1a;{CF704A9C-0C67-4712-BA33-DD0A…...

php根据截止时间计算剩余的时间,并且在剩余时间不足1天时仅显示小时数

//获取政策库文章public function getIndexZckList(){$fl_id = input(fl_id);if(empty(...

Docker最佳实践进阶(一):Dockerfile介绍使用

大家好,上一个系列我们使用docker安装了一系列的基础服务,但在实际开发过程中这样一个个的安装以及繁杂命令不仅仅浪费时间,更是容易遗忘,下面我们进行Docker的进阶教程,帮助我们更快速的部署和演示项目。 一、什么是Dockerfile? Dockerfile 是一个文本文件,其中包含了…...

Anything in Any Scene:无缝融入任何场景,实现逼真视频对象插入技术

人工智能咨询培训老师叶梓 转载标明出处 现实世界的视频捕获虽然因其真实性而宝贵&#xff0c;但常常受限于长尾分布的问题&#xff0c;即常见场景过度呈现&#xff0c;而关键的罕见场景却鲜有记录。这导致了所谓的"分布外问题"&#xff0c;在模拟复杂环境光线、几何…...

安卓开发中的AppCompat框架|安卓系统|安卓应用|兼容性|UI组件|核心组件|ActionBar|Fragment|最佳实践|框架|移动开发|移动应用

目录 1. 什么是AppCompat框架 1.1 AppCompat的起源 1.2 AppCompat的重要性 2. AppCompat框架的核心组件 2.1 AppCompatActivity 2.2 AppCompat主题 2.3 AppCompat Widgets 3. 在项目中使用AppCompat框架 3.1 添加依赖项 3.2 应用AppCompat主题 4. AppCompat的高级功…...

React使用useRef ts 报错

最近在写自己的React项目&#xff0c;我在使用useRef钩子函数的时候发现 TS2322: Type MutableRefObject<HTMLDivElement | undefined> is not assignable to type LegacyRef<HTMLDivElement> | undefined Type MutableRefObject<HTMLDivElement | undefined&g…...

python-信息交互-pyautogui

python-信息交互-pyautogui 一: pyautogui1> waht?2> 功能分类3> 概念及作用二: 通用功能1> function all2> function 注释三: 鼠标控制1> mouse functions2> mouse functions demo3> mouse drag demo四: keyboard控制1> keyboard functions2> …...

flink1.18 编译遇到的问题

1. flink-runtime-web编译失败 源码编译时一直卡在 [INFO] Running ‘npm ci --cache-max0 --no-save’ in 处理方法&#xff1a; 修改flink-runtime-web/pom.xml文件 将<arguments>ci --cache-max0 --no-save ${npm.proxy}</arguments> 替换为&#xff1a;<a…...

2024年8月份编译Openwrt系统基础

概述&#xff1a; 本文档记录openwrt系统的编译过程&#xff0c;以备后续再用&#xff0c;技术支持与指导&#xff01; 1.编译环境 环境需要Linux&#xff0c;我使用的环境是WSL2、Ubuntu 20.04 2.安装编译必须的依赖&#xff08;wsl、linux&#xff09; WSL2&#xff1a;Bu…...

Vue3+vite+ts 项目使用mockjs

1、安装mockjs npm i mockjs 2、安装vite-plugin-mock npm i vite-plugin-mock -D 3、安装axios npm i axios 4.在src目录下创建mock文件夹,在文件夹内创建login.ts等文件&#xff0c;并在文件夹内放置以下内容&#xff08;注&#xff1a;URL要和真实请求地址保持一致&am…...

动态规划(二)——例题

目录 Help Jimmy 题目 解题思路 神奇的口袋 题目 枚举的解法 递归的解法 动态规划的解法 滑雪 题目 解题思路 解法一 解法二 Help Jimmy 题目 "Help Jimmy" 是在下图所示的场景上完成的游戏&#xff1a; 场景中包括多个长度和高度各不相同的平台。地面是…...

Node.js中判断是文件还是文件夹的多种方法

在Node.js中&#xff0c;我们经常需要判断一个路径是文件还是文件夹。Node.js提供了多种方法来实现这一功能&#xff0c;本文将详细介绍这些方法&#xff0c;并给出相应的示例代码。 一、使用fs.Stats对象 在Node.js中&#xff0c;fs模块提供了fs.stat()或fs.statSync()方法&…...

idea 如何打war包

idea 如何打war包 1.在IntelliJ IDEA中打包WAR文件&#xff0c;你可以按照以下步骤操作:1.设置项目结构:首先&#xff0c;打开IDEA&#xff0c;选择File>Project Structure(或使用快捷键CtrlAltShiftS)。在打开的窗口中&#xff0c;选择 Artifacts 选项 2.添加Web Applicat…...

米联客-FPGA程序设计Verilog语法入门篇连载-15 Verilog语法_跨时钟域设计

软件版本&#xff1a;无 操作系统&#xff1a;WIN10 64bit 硬件平台&#xff1a;适用所有系列FPGA 板卡获取平台&#xff1a;https://milianke.tmall.com/ 登录“米联客”FPGA社区 http://www.uisrc.com 视频课程、答疑解惑&#xff01; 1概述 本小节主要讲解Verilog语法的…...

gradio 对话界面实现支持图片、视频正常显示

参考: https://www.gradio.app/docs/gradio/chatbot 问题: gradio网页输出视频nan;图片webp显示不出来 解决方法:需要通过gradio的Video、Image包装 代码: 这里下面启动个后端vlm模型(参考:https://blog.csdn.net/weixin_42357472/article/details/141126225),前端通…...

催收业务怎么提高接通率

提高催收呼叫业务的接通率是一个综合性的任务&#xff0c;需要从多个方面进行优化。以下是一些具体的策略和建议&#xff1a; 一、优化呼叫时间与频次 1. 选择合适的呼叫时间&#xff1a;通过分析目标客户的活跃时段&#xff0c;选择他们最可能接听电话的时间进行呼叫…...

动态生成sitemaps和robots.txt文件:提升SEO与网站可爬性

本文由 ChatMoney团队出品 在现代Web开发中&#xff0c;搜索引擎优化&#xff08;SEO&#xff09;是网站成功的关键因素之一。搜索引擎通过网络爬虫来索引网页&#xff0c;而sitemaps和robots.txt文件则是帮助这些爬虫更好地理解和索引网站内容的重要工具。 sitemaps简介 Sit…...

LeetCode 第二十五天 2024.8.12

1. &#xff1a;递增子序列 题目链接: 491. 非递减子序列 - 力扣&#xff08;LeetCode&#xff09; 应用条件&#xff1a;回溯 难点&#xff1a; 这道题的难点在于如何去重&#xff0c;肯定不能像我们在组合中去重那样对数组排序。而且我们是要对每一层进行去重&#xff0c;…...

Elasticsearch 全文查询详解

全文查询&#xff08;Full-Text Query&#xff09;是 Elasticsearch 中的核心功能之一&#xff0c;用于对非结构化文本数据进行高效检索。与结构化查询不同&#xff0c;全文查询不仅仅是简单的精确匹配&#xff0c;还包括对文本进行分析和处理&#xff0c;从而实现更复杂的搜索…...

20240810在荣品RK3588S-AHD开发板的预置Android13下挂载exFAT的256GB的TF卡

df -h mount fdisk无效 20240810在荣品RK3588S-AHD开发板的预置Android13下挂载exFAT的256GB的TF卡 2024/8/10 21:19 缘起&#xff1a;当时比较便宜96.9&#xffe5;/想看看256GB的TF卡的高速卡的效果&#xff0c;就在京东入手了3张三星的高速TF卡。最近在弄RK3588S&#xff0c…...

Android Wi-Fi 连接失败日志分析

1. Android wifi 关键日志总结 (1) Wi-Fi 断开 (CTRL-EVENT-DISCONNECTED reason3) 日志相关部分&#xff1a; 06-05 10:48:40.987 943 943 I wpa_supplicant: wlan0: CTRL-EVENT-DISCONNECTED bssid44:9b:c1:57:a8:90 reason3 locally_generated1解析&#xff1a; CTR…...

智慧医疗能源事业线深度画像分析(上)

引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

前端导出带有合并单元格的列表

// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...

在四层代理中还原真实客户端ngx_stream_realip_module

一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡&#xff08;如 HAProxy、AWS NLB、阿里 SLB&#xff09;发起上游连接时&#xff0c;将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后&#xff0c;ngx_stream_realip_module 从中提取原始信息…...

将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?

Otsu 是一种自动阈值化方法&#xff0c;用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理&#xff0c;能够自动确定一个阈值&#xff0c;将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...

【单片机期末】单片机系统设计

主要内容&#xff1a;系统状态机&#xff0c;系统时基&#xff0c;系统需求分析&#xff0c;系统构建&#xff0c;系统状态流图 一、题目要求 二、绘制系统状态流图 题目&#xff1a;根据上述描述绘制系统状态流图&#xff0c;注明状态转移条件及方向。 三、利用定时器产生时…...

Spring Boot面试题精选汇总

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

NFT模式:数字资产确权与链游经济系统构建

NFT模式&#xff1a;数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新&#xff1a;构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议&#xff1a;基于LayerZero协议实现以太坊、Solana等公链资产互通&#xff0c;通过零知…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角&#xff0c;以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向&#xff0c;距离坐标原点x个像素;第二个是y坐标&#xff0c;表示当前位置为垂直方向&#xff0c;距离坐标原点y个像素。 坐标体系-像素 …...