C++Builder中视频照片采集实战

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:本项目介绍如何在C++Builder集成开发环境中实现视频照片采集。涉及到使用Windows API和第三方库访问视频设备,以及使用DirectShow和WMF接口建立过滤图捕获视频流。还包括使用GDI+和OpenCV进行图像处理,以及利用C++Builder组件库创建用户界面和事件驱动编程模型。此外,还将讨论性能优化、错误处理和代码的兼容性问题,以便开发者能够构建一个高效、稳定的视频照片采集系统。
C++builder

1. 视频照片采集的C++Builder入门

1.1 理解视频照片采集的目的和重要性

在现代计算机科学中,视频照片采集技术已经广泛应用于多媒体处理、安全监控、医学成像、教育演示等领域。掌握视频照片采集技术,对于开发强大的应用程序和提供高质量的用户体验至关重要。

1.2 C++Builder环境搭建简介

C++Builder是Borland公司开发的集成开发环境(IDE),提供了强大的可视化组件和丰富的库支持,为开发者提供了一个简洁高效的工作环境。初学者需熟悉C++Builder界面布局,组件工具箱以及基础的编程逻辑。

1.3 初识视频照片采集模块

视频照片采集模块是实现视频流捕获的关键部分。开发者需要了解视频采集的基本概念,如帧率、分辨率、颜色深度等。通过创建简单的视频捕获项目,可对C++Builder中的TMediaPlayer组件或第三方媒体处理库进行初步探索。

2. 视频设备接口使用与选择

2.1 视频设备接口的选择标准

2.1.1 设备兼容性分析

在选择视频设备接口时,首先需要考虑的是设备的兼容性。兼容性指的是设备接口能否在不同的硬件平台或操作系统上正常工作。分析兼容性时,要考虑到以下几个方面:

  • 操作系统兼容 :所选接口能否在Windows、Linux、macOS等多种操作系统上运行。
  • 硬件平台兼容 :接口是否支持不同的CPU架构,如x86、ARM等。
  • 设备驱动支持 :是否有足够的设备驱动支持,特别是对于新的或非主流的视频采集设备。
  • 软件库依赖 :接口所依赖的软件库是否容易获取和安装,是否存在许可限制。

兼容性分析可以通过查阅设备制造商提供的技术文档或API文档进行。在实际操作中,开发者往往需要下载并尝试安装必要的软件包,然后在开发环境中测试接口的兼容性。

2.1.2 接口类型和特性比较

不同类型的视频设备接口有其独特的特性和用途。以下是一些常见的视频设备接口及其特性比较:

  • DirectShow :微软提供的媒体框架,适用于Windows平台,支持多种流媒体格式,开发难度适中。
  • V4L2 :Linux平台下广泛使用的视频设备驱动接口,功能强大,需要较深的内核编程知识。
  • Media Foundation :微软的现代媒体框架,支持高清视频处理,适用于Windows Vista及以后版本。

在选择接口时,开发者应考虑项目需求、团队的技能水平以及时间框架。例如,如果项目需要在多种平台上部署,可能会选择跨平台的接口,如GStreamer。如果项目时间紧张且团队熟悉Windows环境,则可能会选择DirectShow。

2.2 视频设备接口的编程实现

2.2.1 编程接口的初始化与配置

一旦选定视频设备接口,接下来就是编程实现初始化和配置。这一过程涉及到具体的API调用以及参数设置。这里以DirectShow为例进行说明:

// 初始化COM库
CoInitialize(NULL);

// 创建过滤器图表管理器
IGraphBuilder *pGraph = NULL;
IMediaControl *pControl = NULL;
IMediaEvent   *pEvent = NULL;
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
                      IID_IGraphBuilder, (void **)&pGraph);
if (SUCCEEDED(hr))
{
    // 获取其他接口
    hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
    hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
}

在这段代码中,首先调用 CoInitialize 函数初始化COM库,然后创建了一个过滤器图表管理器。通过该管理器可以构建视频处理的流程图。接下来获取 IMediaControl IMediaEvent 接口用于控制和响应媒体事件。

2.2.2 视频信号的接收与控制

视频信号的接收和控制是视频采集软件的核心功能之一。在DirectShow中,通过构建过滤器图表来管理视频数据流。以下是如何添加视频源设备到图表中,并控制其播放的示例:

// 添加视频捕获设备
IBaseFilter *pCaptureFilter = NULL;
hr = FindCaptureDevice(&pCaptureFilter);
if (SUCCEEDED(hr))
{
    // 将捕获设备添加到图表中
    hr = pGraph->AddFilter(pCaptureFilter, L"Capture Filter");
}

// 开始播放
hr = pControl->Run();

// 等待一段时间或事件
long evCode;
pEvent->WaitForCompletion(INFINITE, &evCode);

在这段代码中, FindCaptureDevice 函数用于查找并创建视频捕获设备的过滤器(通常是系统中安装的第一个摄像头)。通过 AddFilter 方法将其添加到图表中,并使用 Run 方法开始播放。最后,使用 WaitForCompletion 方法等待视频播放的结束或用户中断。

通过以上步骤,可以完成视频设备接口的基本编程实现。开发者需要根据实际项目需求调整设备选择和配置参数,以达到最佳性能。

3. 捕获框架与库选择

在进行视频照片采集的软件开发时,选择正确的捕获框架和库至关重要。本章节将详细对比和分析市面上常见的框架与库,以帮助开发者作出更合适的选择,并详细阐述如何将第三方库集成到项目中。

3.1 捕获框架的对比与选择

3.1.1 常见框架的特性分析

在C++builder环境下,开发者可以选择多种捕获框架,其中包括商业框架如Delphi VCL、FireMonkey等,开源框架如OpenCV、FFmpeg等。商业框架因其优质的文档支持和集成服务,适合对稳定性有高要求的企业级应用;而开源框架由于其灵活性和丰富的社区资源,适合对成本敏感的项目和个人开发者。

OpenCV 是一个开源的计算机视觉和机器学习软件库,提供丰富的图像处理功能。它使用C++编写,可以与C++builder无缝集成。

FFmpeg 是一个非常强大的多媒体框架,用于处理音视频的录制、转换、流式传输等功能。它支持众多的视频和音频格式,适合需要强大媒体处理能力的应用。

3.1.2 选择框架的依据与标准

选择捕获框架时,需要根据以下几个标准进行考虑:

  • 性能需求 :是否需要实时处理能力,以及对处理速度的要求。
  • 功能需求 :框架支持的功能是否满足应用需求,比如视频编码、解码、格式支持等。
  • 开发环境 :框架与开发环境的兼容性,比如是否支持C++builder。
  • 文档与社区支持 :框架是否拥有丰富的文档和活跃的开发者社区,以便于问题的解决和技术支持。
  • 扩展性 :框架的扩展能力,是否便于未来功能的添加和维护。

3.2 库的选择与集成

第三方库能够显著提高开发效率,但在选择和集成时需要考虑其特性与适用场景。

3.2.1 第三方库的特性与适用场景

OpenCV 库提供了大量现成的图像处理函数,适合进行图像识别、视频分析等任务。它的跨平台性使其在不同操作系统上都能运行。

#include <opencv2/opencv.hpp>

int main() {
    cv::Mat img = cv::imread("path_to_image");
    if(img.empty()) {
        return -1;
    }
    cv::namedWindow("Display Image");
    cv::imshow("Display Image", img);
    cv::waitKey(0);
    return 0;
}

上面的代码展示了如何使用OpenCV库加载并显示一张图片。通过这段代码,可以观察到OpenCV对于图像处理的简便性。

FFmpeg 库则在视频编解码、流媒体处理方面表现出色,非常适合视频采集和流媒体应用的开发。

3.2.2 库的集成过程与调试技巧

集成第三方库到C++builder项目中通常需要以下几个步骤:

  1. 下载并配置库文件,包括头文件(.h)和库文件(.lib)。
  2. 将库文件路径添加到项目中,以便编译器能够找到它们。
  3. 配置包含目录和链接器输入,确保库的头文件和库文件被正确引用。
  4. 在项目中引入库的相关命名空间和类。

调试第三方库时,可以使用C++builder内置的调试工具,如断点、步进、变量监视等。同时,也要注意查看编译器的错误信息和第三方库的日志输出,这些信息对于定位问题非常有用。

graph LR
A[开始集成库] --> B[下载库文件]
B --> C[配置项目路径]
C --> D[包含库头文件]
D --> E[链接库文件]
E --> F[使用调试工具]
F --> G[测试并验证]

在本章节中,我们对捕获框架和库的选择与集成进行了深入的探讨,帮助开发者在多样化的选择中找到最适合自身项目需求的方案,并提供了具体的集成与调试方法。接下来的章节将详细解读视频流捕获的编程技术及其图像处理的相关内容。

4. 视频流捕获实现与图像处理

4.1 视频流捕获的编程技术

4.1.1 视频流捕获的原理与方法

视频流捕获技术的核心在于从视频源实时获取连续的图像帧。现代操作系统和编程语言通常提供了一套API来实现这一功能,例如DirectShow、V4L2等。视频流捕获的基本原理是通过设备驱动获取视频帧数据,然后将其传输到内存中进行进一步处理。

实现视频流捕获的关键在于选择合适的捕获设备,这通常涉及到摄像头、电视卡或网络流等。捕获过程中,应用程序需要与硬件设备驱动交互,这通常通过设备特定的API进行。

以Windows平台为例,我们可以使用DirectShow接口来捕获视频流。DirectShow允许访问各种媒体输入,例如摄像头、视频文件和电视信号。它通过使用Filter Graph模型来构建媒体流的处理流程,包括视频捕获、编解码、转换和输出。

4.1.2 实现视频流捕获的关键代码

下面是一个简单的示例,演示了如何使用DirectShow API在C++中创建一个视频捕获的Filter Graph,并进行视频流捕获。

#include <dshow.h>
#pragma comment(lib, "strmiids.lib")

// 初始化COM库
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (FAILED(hr)) return -1;

// 创建Filter Graph Manager
IGraphBuilder *pGraph = NULL;
IMediaControl *pControl = NULL;
IMediaEvent   *pEvent = NULL;
hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph);
if (FAILED(hr)) goto End;

hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl);
if (FAILED(hr)) goto End;

hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent);
if (FAILED(hr)) goto End;

// 构建视频捕获Filter Graph
// 这里可能需要添加视频捕获设备的筛选和配置代码
hr = pControl->RenderFile(L"inputfile.avi");
if (FAILED(hr)) goto End;

// 开始播放视频
long eventCode;
pEvent->WaitForCompletion(INFINITE, &eventCode);

// 清理
pEvent->Release();
pControl->Release();
pGraph->Release();
CoUninitialize();

End:
return SUCCEEDED(hr) ? 0 : -1;

在上述代码中, IGraphBuilder 用于构建Filter Graph, IMediaControl 用于控制Filter Graph的运行, IMediaEvent 用于处理事件。通过调用 RenderFile 方法,我们告诉Graph Builder如何构建Filter Graph以从指定的输入源捕获视频流。

这段代码仅提供了一个基础框架,实际应用中可能需要根据具体需求进行调整和优化。在实现视频流捕获时,需要确保正确处理错误情况,并在捕获过程中添加必要的同步和异步处理机制。

4.2 图像处理技术的深入探讨

4.2.1 图像预处理技术

图像预处理是图像处理流程中的重要步骤,它的目的是改善图像质量,为后续处理提供更准确的输入。图像预处理包括但不限于去噪、灰度转换、直方图均衡化等操作。

去噪是预处理过程中的一个关键步骤,特别是在实时视频处理场景中。由于视频是由连续帧组成的,每帧图像中的噪声可能会在连续帧间产生不连贯的干扰,因此去除噪声对于提高视频质量至关重要。常见的去噪技术有高斯滤波、中值滤波等。

灰度转换将彩色图像转换为灰度图像,通常用于减少后续处理的计算量。灰度转换公式基于人眼对不同颜色的敏感度,一个常用的方法是利用加权平均的方法,例如根据下式转换:

[ Y = 0.299R + 0.587G + 0.114B ]

其中,( Y )代表灰度值,( R )、( G )、( B )分别代表红、绿、蓝三色的分量值。

直方图均衡化通过调整图像的对比度来增加图像的整体可见度,它通过将原始图像的直方图分布均匀化来实现。这个过程涉及计算累积分布函数(CDF),并将其映射回原始图像的像素值范围。

4.2.2 图像质量提升的策略

在视频流捕获和处理过程中,图像质量提升策略通常依赖于特定应用场景的需求。一些常用的图像质量提升技术包括:

  • 动态范围压缩 :用于改善图像中亮度范围较广的场景,特别是在高对比度环境下。
  • 锐化滤波 :通过增强图像边缘来提高图像的清晰度,适用于需要提高细节辨识度的应用。
  • 色彩校正 :调整图像的色彩平衡,使得图像颜色更加真实或者符合特定的视觉效果要求。
  • 图像融合 :将来自不同视频流的图像合并为单个图像,这种技术常用于360度全景视频或者多摄像头监控系统。

为了实现这些策略,开发者通常需要深入理解图像处理库如OpenCV,并能够根据需要编写或修改图像处理算法。同时,对于实时视频处理,还需要优化算法以保证性能。

值得注意的是,图像质量提升技术的选择和实现往往需要在改善图像质量与保持处理速度之间找到一个平衡点。实时系统中,对算法的计算复杂度有很高的要求,因此可能需要采用一些近似算法或硬件加速技术。

5. 图片保存格式与用户界面设计

5.1 图片保存格式的支持与选择

图片保存格式是图像处理软件的基本功能之一,它直接关系到数据存储与后期处理的便利性。在选择图片保存格式时,需要考虑多种因素,如压缩效率、文件大小、兼容性以及支持的颜色深度等。

5.1.1 常见图片格式的分析与对比

  • JPEG/JPG :广泛用于网络和数字相机,以有损压缩为特点,压缩效率高,但对压缩敏感的图像细节可能会受损。
  • PNG :作为无损压缩格式,支持透明背景和更高的颜色深度,适合网页和需要无损压缩的场景。
  • BMP :原始位图格式,无压缩,支持真彩色,但文件体积大,主要用于系统内部的图像处理。
  • GIF :有限的颜色支持(最多256色),支持动画,但不适用于复杂图片。
  • TIFF :灵活的位图格式,支持无损或有损压缩,经常用于专业图像编辑。
  • WebP :由Google推出,目的是替代JPEG、PNG和GIF格式,特点是支持有损和无损压缩,压缩率更高。

5.1.2 格式支持的实现方法与注意事项

在C++Builder中实现对不同图片保存格式的支持,通常需要使用第三方库,如libjpeg、libpng等。实现时需要注意以下几点:

  • 依赖库的集成 :确保所有必要的库文件被正确添加到项目中,特别是在不同的操作系统平台上。
  • 编码转换 :将捕获的视频帧转换成所需的图像格式,需要处理编码和解码过程。
  • 文件操作 :编写相应的文件操作代码以保存格式化的图片到磁盘,涉及文件的读写、权限、路径等操作。

示例代码实现

以下是一个使用libjpeg库保存图片为JPEG格式的示例代码:

#include <jpeglib.h>
#include <setjmp.h>

struct jpeg_error_mgr jerr;
struct jpeg_compress_struct cinfo;

void saveJPEG(const char *filename, unsigned char *img, int width, int height) {
    FILE *outfile;
    if ((outfile = fopen(filename, "wb")) == NULL) {
        fprintf(stderr, "can't open %s\n", filename);
        return;
    }
    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_compress(&cinfo);
    jpeg_stdio_dest(&cinfo, outfile);
    cinfo.image_width = width;
    cinfo.image_height = height;
    cinfo.input_components = 3;    // RGB颜色模型
    cinfo.in_color_space = JCS_RGB;
    jpeg_set_defaults(&cinfo);
    jpeg_set_quality(&cinfo, 75, TRUE); // 75是压缩质量
    jpeg_start_compress(&cinfo, TRUE);
    JSAMPROW row_pointer;
    unsigned char *img_data = img;
    while (cinfo.next_scanline < cinfo.image_height) {
        row_pointer = img_data + cinfo.next_scanline * cinfo.image_width * 3;
        jpeg_write_scanlines(&cinfo, &row_pointer, 1);
    }
    jpeg_finish_compress(&cinfo);
    fclose(outfile);
    jpeg_destroy_compress(&cinfo);
}

在代码中,首先创建了JPEG压缩结构,并设置错误处理机制,接着初始化压缩参数,设置质量参数,并将图片数据写入文件。

5.2 用户界面的设计理念与实践

用户界面(UI)设计是软件开发中不可或缺的部分,尤其是在C++Builder这种可视化开发环境中。良好的UI设计不仅提升用户满意度,还直接影响到软件的可用性和效率。

5.2.1 界面设计的原则与布局技巧

  • 简洁性 :避免过多的元素和复杂的层级,使用户能够快速理解和使用。
  • 一致性 :整个应用的布局和风格保持一致,提供统一的交互体验。
  • 可用性 :确保用户能够轻易地完成任务,例如通过按钮点击、拖放等直观操作。
  • 视觉层次 :利用颜色、大小、字体等视觉元素明确视觉层次,引导用户的注意力。

5.2.2 用户体验提升的设计案例分析

一个典型的设计案例是视频编辑软件的用户界面。该界面通常包括视频预览窗口、时间轴、控制按钮和效果列表等元素。在设计时要考虑到视频编辑的流程,将这些元素合理布局,以减少用户的操作步骤。

示例UI设计代码

在C++Builder中,可以使用其内置的VCL框架快速搭建基本的UI结构。以下是一个简单的UI布局示例代码:

procedure TForm1.FormCreate(Sender: TObject);
var
  btn: TButton;
  imgList: TImageList;
begin
  // 创建一个按钮
  btn := TButton.Create(Form1);
  btn.Parent := Form1;
  btn.Caption := 'Click Me';
  btn.Left := 100;
  btn.Top := 50;
  // 创建一个图像列表并添加图片
  imgList := TImageList.Create(Form1);
  imgList.Width := 32;
  imgList.Height := 32;
  imgList.AddIcon(TIcon.Create);
  imgList.AddIcon(TIcon.Create);
  // 将图像列表应用到按钮上
  btn.Glyph := imgList;
  // 确保图像列表与按钮控件关联
  btn.Images := imgList;
end;

该代码展示了如何在C++Builder中创建一个按钮,并为其设置图标。通过UI布局和控件属性的调整,可以实现复杂的界面设计。

界面布局技巧

  • 布局管理器 :利用布局管理器(如TPanel)控制组件的排列顺序和分布。
  • 动态调整 :在运行时动态调整控件的大小和位置,适应不同的屏幕和分辨率。
  • 响应式设计 :使界面能够响应用户的交互,例如按钮点击后改变状态、弹出菜单等。

在设计UI时,应考虑到易用性、美观性和功能性的平衡,采用迭代开发和用户测试的方式,不断完善界面设计。

6. 事件驱动编程与软件优化策略

6.1 事件驱动编程的实践应用

6.1.1 事件驱动模型的构建与逻辑

事件驱动编程是一种编程范式,在这种范式中,程序的流程是由事件的触发来驱动的,而不是传统意义上通过函数调用或循环语句来控制。在视频处理软件中,用户的各种操作(如按键、鼠标点击等)都会产生事件,程序需要对这些事件做出响应,执行相应的处理逻辑。

构建事件驱动模型通常包括以下几个关键步骤:
- 事件监听 : 程序首先要设置监听器来监听各种事件。
- 事件分发 : 当事件发生时,事件分发器将事件路由到适当的处理器。
- 事件处理 : 处理器响应事件,执行对应的函数或方法。

下面是一个简单的事件处理流程图的示例:

graph TD;
    A[启动程序] --> B[等待事件]
    B --> C{事件发生?}
    C -- 是 --> D[事件分发]
    D --> E[处理事件]
    E --> F[返回等待状态]
    C -- 否 --> B

在C++ Builder中,事件处理通常通过在设计时使用IDE的可视化编辑器来连接事件处理程序(也称为事件处理函数或方法)到组件上的事件。

6.1.2 事件响应的编程方法与优化

事件响应的编程方法主要是编写事件处理函数。这些函数通常有特定的签名,并且需要注册到事件监听器。例如,为按钮点击事件编写一个事件处理函数:

void __fastcall TForm1::Button1Click(TObject *Sender) {
    // 处理按钮点击事件
}

事件响应的优化可以从几个方面进行:
- 减少事件处理函数的执行时间 :尽量避免在事件处理函数中执行耗时的操作。
- 使用线程 :如果事件处理需要较长的处理时间,考虑使用多线程,将耗时操作移至后台线程。
- 事件节流与防抖 :对于高频触发的事件(如滚动事件),通过技术手段限制其触发频率,提高程序性能。

6.2 性能优化策略与错误处理

6.2.1 系统性能分析与优化方法

系统性能分析通常涉及以下几个方面:
- CPU使用率 :分析软件是否过度占用CPU资源。
- 内存消耗 :检测软件是否合理地使用和释放内存。
- 响应时间 :检查软件对用户操作的响应速度。

优化方法通常包括:
- 代码优化 :精简算法,使用高效的数据结构,减少不必要的计算。
- 资源管理 :及时释放不再使用的资源,避免内存泄漏。
- 并行处理 :合理利用多核处理器进行多线程处理。

6.2.2 错误处理机制的构建与实践

错误处理是软件稳定性的重要组成部分。构建错误处理机制应该包含以下几个步骤:
- 错误捕获 :捕获程序运行时可能发生的错误。
- 错误记录 :记录错误发生时的相关信息,如错误类型、发生时间和上下文。
- 错误恢复 :提供错误恢复的策略,确保程序能继续运行或优雅地退出。
- 用户通知 :向用户提供错误信息,并提供解决方案或操作指引。

一个错误处理流程的代码示例:

try {
    // 可能发生错误的代码
} catch (Exception &e) {
    // 异常处理代码,比如记录日志
    LogError(e);
    // 显示错误信息给用户
    ShowMessage("发生错误:" + e.Message);
}

6.3 软件兼容性测试与维护

6.3.1 软件兼容性的测试方法与标准

软件兼容性测试的主要目的是确保软件能够在不同的环境(操作系统、硬件、软件依赖等)中正常工作。测试方法包括:
- 环境配置 :构建不同的测试环境,模拟不同用户可能使用的配置。
- 自动化测试 :使用自动化测试工具来模拟用户操作,检测软件表现。
- 兼容性测试套件 :开发一系列专门用于测试软件兼容性的测试案例。

6.3.2 软件更新与维护策略

软件维护是软件生命周期中持续的一个过程,包括修正软件中的错误和改进软件性能等。软件更新与维护策略应当包含:
- 定期更新 :根据软件使用的反馈和新环境的需求定期发布更新。
- 文档维护 :提供详细的更新日志和用户手册。
- 用户反馈机制 :建立与用户的沟通渠道,收集用户反馈,及时解决问题。

维护软件不仅是修复问题,也是不断为软件增加新的功能,适应市场和技术的变化。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:本项目介绍如何在C++Builder集成开发环境中实现视频照片采集。涉及到使用Windows API和第三方库访问视频设备,以及使用DirectShow和WMF接口建立过滤图捕获视频流。还包括使用GDI+和OpenCV进行图像处理,以及利用C++Builder组件库创建用户界面和事件驱动编程模型。此外,还将讨论性能优化、错误处理和代码的兼容性问题,以便开发者能够构建一个高效、稳定的视频照片采集系统。


本文还有配套的精品资源,点击获取
menu-r.4af5f7ec.gif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值