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

简介:本文详细介绍了如何使用C#与百度OCR API实现图像文字识别。项目包括了本地和网络图片识别、API调用、结果解析等关键技术点。此外,还探讨了付费版特性、错误处理、性能优化和代码组织等重要方面,为实现高效准确的图像文字提取提供了完整的解决方案。
OCR

1. C#编程基础应用

在开始深入了解OCR技术的应用之前,我们需要掌握C#编程的基础。C#作为一种广泛使用的编程语言,其对面向对象编程和类型安全的重视让它成为了开发复杂应用程序的理想选择。本章将从基础知识开始,逐步深入到C#的核心概念。

1.1 C#的开发环境搭建

在开始编程之前,必须确保你的开发环境已经配置好。Visual Studio是微软提供的一个集成开发环境(IDE),是C#开发者的首选工具。开发者可以根据自己的需要选择合适的Visual Studio版本。安装完成后,可以通过创建一个新的C#控制台应用或Windows窗体应用来开始你的第一个项目。

1.2 基本语法与数据类型

C#语言的基本语法包括变量声明、循环控制、条件判断等。理解这些基础概念对后续开发至关重要。例如,数据类型是任何编程语言的基础,C#提供了包括整型、浮点型、字符串等在内的基本数据类型。此外,C#还支持复杂的类型,如结构体、类等面向对象的构造。

using System;

namespace HelloWorld
{
    class Program
    {
        static void Main(string[] args)
        {
            // 输出 "Hello World!" 到控制台
            Console.WriteLine("Hello World!");
        }
    }
}

上述代码是C#语言的一个基础示例,其中展示了如何创建一个控制台应用程序,以及如何在控制台中输出信息。

通过本章的学习,你将能够掌握C#编程的基本技巧,为后续章节中深入探讨百度OCR API的集成和应用打下坚实的基础。

2. 百度OCR API使用方法

2.1 API的获取与激活

2.1.1 注册百度云账号并创建OCR应用

为了使用百度的OCR服务,您首先需要注册一个百度云账号,并登录到百度云控制台。在控制台中,您需要创建一个OCR应用,以便获得API的访问权限。在这个过程中,您需要提供应用的名称和描述,并选择相应的服务类型。一旦应用创建完成,您将获得一个API Key和一个Secret Key,这两个密钥是您调用OCR API时的身份验证凭证。

2.1.2 获取API Key和Secret Key

在创建完应用后,您可以找到API Key和Secret Key,这些将在您进行API请求时用于身份验证。请确保妥善保管这两个密钥,因为任何拥有这些密钥的人都可以访问您的应用服务。如果密钥被泄露,建议立即在百度云控制台中修改或删除现有密钥,并重新创建一对新的密钥。

2.2 API调用规范

2.2.1 请求地址与参数说明

当您准备调用百度OCR API时,需要构造一个HTTP请求,请求的URL通常遵循以下格式:

https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic?access_token=您的access_token

在上述URL中,您需要替换 您的access_token 为您通过API Key和Secret Key换取的访问令牌(access token)。此外,您还需要根据API的具体功能,添加必要的参数到请求中,比如图片的URL、图片的Base64编码等。

2.2.2 签名算法详解

为了确保请求的安全性,百度OCR API要求对每个请求都进行签名验证。签名算法通常包括以下几个步骤:

  1. 对所有请求参数按照参数名的ASCII码进行升序排序;
  2. 将排序后的参数字符串拼接成一个字符串,然后与您的Secret Key一起使用HMAC-SHA256算法进行加密;
  3. 将加密结果进行Base64编码,得到最终的签名字符串;
  4. 将签名字符串附加到原始请求URL的末尾。

在编程实现时,您需要使用您编程语言提供的加密库来完成上述步骤。下面是一个Python语言实现签名的示例代码:

import hmac
import hashlib
import base64

def generate_sign(params, secret_key):
    # 对参数进行排序并拼接成字符串
    stringA = '&'.join(["{}={}".format(k, params[k]) for k in sorted(params)])
    # 将排序后的字符串与密钥进行拼接
    stringSignTemp = '{}&{}'.format(stringA, secret_key)
    # 使用HMAC-SHA256算法对拼接后的字符串进行加密
    hmac_code = hmac.new(secret_key.encode('utf-8'), stringSignTemp.encode('utf-8'), digestmod=hashlib.sha256).digest()
    # 对加密结果进行Base64编码
    sign = base64.b64encode(hmac_code)
    return sign.decode('utf-8')

# 示例参数
params = {
    'access_token': '您的access_token',
    'image': 'Base64编码的图片内容'
}

# 生成签名
secret_key = '您的Secret Key'
sign = generate_sign(params, secret_key)
print(sign)

以上代码展示了如何生成签名的过程。注意, access_token image 参数需要替换为您实际的值。

在实际应用中,您还需要处理异步请求、请求失败时的重试机制、调用频率限制等复杂的编程问题。这将涉及到更深层次的代码逻辑,包括但不限于异常处理、重试策略等。在后续章节中,我们会进一步讨论这些问题,并提供相应的解决方案。

3. 本地图片文字识别流程

在现代应用中,自动从图片中提取文字是数据录入和信息处理的关键步骤之一。C#作为.NET框架的核心编程语言,结合百度OCR API,可实现强大的文字识别功能。本章将深入探讨如何利用C#处理本地图片,并通过百度OCR API进行文字提取。

3.1 本地图片的上传与处理

在识别本地图片中的文字之前,需要确保图片上传到服务器,并进行必要的格式和大小调整。这一过程通常涉及到读取图片、调整尺寸和格式转换等步骤。

3.1.1 读取本地图片

在.NET中,可以使用 System.Drawing 命名空间中的 Bitmap 类来读取图片文件。

using System.Drawing;

public Bitmap ReadImage(string imagePath)
{
    // 创建一个Bitmap对象来存储图片
    Bitmap bitmap = new Bitmap(imagePath);
    return bitmap;
}

上述代码创建了一个Bitmap对象,该对象能够加载指定路径下的图片文件。这个过程简单直接,但需要注意的是,Bitmap对象在不再使用时应该被释放,以避免内存泄漏。

3.1.2 图片格式与大小的调整

调整图片的格式和大小可以优化OCR识别的准确性,尤其对于高分辨率的图片,缩小尺寸可以提高识别速度并减少服务器负载。

public Bitmap ResizeImage(Bitmap image, int width, int height)
{
    Bitmap resizedImage = new Bitmap(image, width, height);
    return resizedImage;
}

这段代码定义了一个方法 ResizeImage ,它接受一个Bitmap对象和目标宽度与高度作为参数,并返回一个新的调整大小后的Bitmap对象。在实际应用中,我们可能还需要保存这个调整后的图片到一个特定格式(如JPEG或PNG),以便上传到服务器。

接下来将展示如何使用这些方法对本地图片进行预处理。

// 示例使用
string imagePath = @"C:\path\to\your\image.jpg";
Bitmap originalImage = ReadImage(imagePath);
// 假设我们目标是将图片大小调整到1024x768
int width = 1024;
int height = 768;
Bitmap resizedImage = ResizeImage(originalImage, width, height);

// 保存调整后的图片到磁盘
resizedImage.Save(@"C:\path\to\save\resized_image.jpg");

在这段代码中,首先通过 ReadImage 函数读取图片,然后调用 ResizeImage 函数调整图片大小,并最终将结果保存到指定路径。

为了实现更加高效且可扩展的图片处理流程,可以将这些操作封装成一个类,并提供更加灵活的方法来满足不同的图片处理需求。

3.2 API调用与文字提取

在图片预处理完成后,下一步是使用百度OCR API进行文字提取。这里会涉及到发送HTTP请求和解析返回的数据。

3.2.1 发送HTTP请求

为了发送HTTP请求,我们将使用 HttpClient 类。以下是发送请求并获取响应的示例代码。

using System.Net.Http;
using System.Text;
using System.Threading.Tasks;

public async Task<string> SendOCRRequestAsync(string imagePath)
{
    HttpClient client = new HttpClient();
    // 构建请求URL
    string requestUrl = "https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic?access_token=YOUR_ACCESS_TOKEN";
    // 使用前面提到的方法读取并调整图片大小
    Bitmap imageToRecognize = ResizeImage(ReadImage(imagePath), width, height);
    byte[] imageBytes = ImageToBytes(imageToRecognize);

    // 设置请求头
    client.DefaultRequestHeaders.Add("Content-Type", "application/x-www-form-urlencoded");

    // 将图片转换为Base64字符串以作为请求体发送
    string base64EncodedImage = Convert.ToBase64String(imageBytes);
    var content = new FormUrlEncodedContent(new[]
    {
        new KeyValuePair<string, string>("image", base64EncodedImage)
    });

    // 发送POST请求到OCR API
    HttpResponseMessage response = await client.PostAsync(requestUrl, content);

    if (response.IsSuccessStatusCode)
    {
        string result = await response.Content.ReadAsStringAsync();
        return result;
    }
    else
    {
        throw new HttpRequestException("OCR API call was not successful");
    }
}

在这段代码中,我们构建了一个HTTP请求,读取并调整图片大小,然后将其转换成Base64编码的字符串作为请求体发送给百度OCR API。 ImageToBytes 方法负责将Bitmap对象转换成字节数组,这里没有展示它的实现细节,但可以使用 MemoryStream Image.Save 方法来完成这个转换。

3.2.2 解析返回的文字内容

请求发送成功后,我们需要解析返回的JSON格式的响应数据,从中提取识别出的文字内容。

// 示例JSON响应数据
string jsonResponse = @"{
    'words_result': [
        {'words': 'Hello', 'location': [10,20,50,30]},
        {'words': 'World', 'location': [55,25,95,35]}
    ],
    'words_num': 2
}";

// 反序列化JSON数据
var ocrResult = JsonConvert.DeserializeObject<dynamic>(jsonResponse);

// 提取识别出的文字内容
var words = ocrResult.words_result.Select(item => item.words).ToList();

在这段示例代码中,我们使用了Json.NET库来反序列化JSON响应数据,然后提取了包含在 words_result 字段中的识别文字列表。实际应用中,你可能需要将解析出的文本进行进一步处理或存储。

最终,整个文字识别流程的C#代码可以被封装到一个方法中,从而实现对本地图片文字的自动提取。这不仅提高了数据处理的效率,也为开发各种数据录入和信息提取的应用提供了便利。

通过本章的介绍,我们已经了解了如何在C#中处理本地图片并使用百度OCR API进行文字提取的基本流程。下一章节我们将进一步探讨如何处理网络图片的文字识别流程。

4. 网络图片文字识别流程

4.1 网络图片的获取方法

4.1.1 使用URL下载图片

在进行网络图片文字识别之前,我们首先需要获取到图片的网络地址。在互联网上,图片资源通常可以通过URL(统一资源定位符)来定位。要下载一张图片,我们可以使用各种编程语言中的库来完成这项任务。例如,在C#中,我们可以使用HttpClient类或者WebClient类来下载网络图片。以下是使用HttpClient类下载图片的基本步骤:

  1. 创建一个HttpClient实例。
  2. 使用HttpClient实例的GetAsync方法获取图片的HttpResponseMessage。
  3. 从HttpResponseMessage中获取图片内容。

下面是一个简单的代码示例:

using System;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        string imageUrl = "http://example.com/image.jpg";
        using (HttpClient client = new HttpClient())
        {
            HttpResponseMessage response = await client.GetAsync(imageUrl);
            if (response.IsSuccessStatusCode)
            {
                using (Stream contentStream = await response.Content.ReadAsStreamAsync(), 
                       fileStream = new FileStream("downloaded_image.jpg", FileMode.Create, FileAccess.Write, FileShare.None, 8192, true))
                {
                    await contentStream.CopyToAsync(fileStream);
                }
                Console.WriteLine("图片下载成功!");
            }
            else
            {
                Console.WriteLine("图片下载失败。");
            }
        }
    }
}

在上述代码中,我们首先定义了一个图片的URL地址,并使用HttpClient的GetAsync方法来获取图片的响应。如果响应状态码表明请求成功,我们将响应内容转换为流,并将其保存到本地文件系统中。这里使用了异步操作来提高下载效率。

4.1.2 图片URL的验证与处理

在下载网络图片之前,对图片URL进行验证是非常必要的。验证的目的在于确保图片URL有效且可以访问,这包括了检查URL格式的正确性、网站是否可达、图片资源是否存在等。如果在验证阶段发现问题,就可以避免进行无用的下载操作。

图片URL验证可以通过发送HEAD请求并检查响应头中的状态码来完成。一般情况下,如果状态码是200,则表示图片资源存在。以下是使用HttpClient发送HEAD请求的示例代码:

using System.Net.Http;
using System.Threading.Tasks;

class Program
{
    static async Task Main(string[] args)
    {
        string imageUrl = "http://example.com/image.jpg";
        using (HttpClient client = new HttpClient())
        {
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Head, imageUrl);
            HttpResponseMessage response = await client.SendAsync(request);
            if (response.IsSuccessStatusCode)
            {
                Console.WriteLine("URL有效,可以进行下载操作。");
            }
            else
            {
                Console.WriteLine("URL无效或图片资源不存在。");
            }
        }
    }
}

4.1.3 图片的处理

一旦图片被下载到本地,根据实际情况,我们可能需要对图片进行预处理,以便更好地适应OCR API的输入要求。预处理可能包括调整图片的大小、格式转换、压缩、裁剪等操作。

调整图片大小是为了确保图片符合OCR API的尺寸要求。例如,如果API规定图片最大宽度为1024像素,那么下载的图片如果超过这个宽度,就需要按比例缩放。可以使用.NET中的System.Drawing库来实现图片处理。

以下是一个调整图片大小的示例代码:

using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.IO;

public void ResizeImage(string inputFile, string outputFile, int width, int height)
{
    using (Image img = Image.FromFile(inputFile))
    {
        using (Bitmap resized = new Bitmap(img, width, height))
        {
            resized.Save(outputFile, ImageFormat.Jpeg);
        }
    }
}

在上述代码中, ResizeImage 方法接收输入图片路径、输出图片路径、目标宽度和高度,然后使用新的宽度和高度创建一个新的Bitmap对象,并保存为JPEG格式的图片。

4.2 API调用与文字提取

4.2.1 构建网络图片识别请求

一旦图片准备好,并且符合OCR API的要求,下一步就是调用API进行文字提取。与本地图片文字识别类似,网络图片文字识别也需要构建一个HTTP请求,将图片作为请求的一部分发送到服务器。

构建网络图片识别请求的步骤如下:

  1. 将图片转换为Base64字符串或进行多部分表单编码,取决于API的要求。
  2. 构建HTTP请求,其中包含必要的认证信息、图片数据以及可能的其他参数。
  3. 发送请求并等待响应。

这里是一个将图片转换为Base64字符串并构建POST请求的示例:

using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;

class Program
{
    static readonly HttpClient client = new HttpClient();

    static async Task Main(string[] args)
    {
        string imageUrl = "http://example.com/image.jpg";
        string base64String = await ConvertImageToBase64(imageUrl);
        var requestContent = new FormUrlEncodedContent(new[]
        {
            new KeyValuePair<string, string>("image", base64String)
        });

        requestContent.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
        var response = await client.PostAsync("https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic", requestContent);
        string result = await response.Content.ReadAsStringAsync();

        // 这里需要解析返回的JSON字符串并提取文字内容
        Console.WriteLine(result);
    }

    static async Task<string> ConvertImageToBase64(string imageUrl)
    {
        using (HttpClient client = new HttpClient())
        {
            HttpResponseMessage response = await client.GetAsync(imageUrl, HttpCompletionOption.ResponseHeadersRead);
            response.EnsureSuccessStatusCode();
            byte[] imageBytes = await response.Content.ReadAsByteArrayAsync();
            return Convert.ToBase64String(imageBytes);
        }
    }
}

在这个示例中,我们首先通过 ConvertImageToBase64 函数将网络图片转换为Base64字符串,然后构建一个FormUrlEncodedContent对象,并将Base64字符串作为表单数据发送。接着我们设置请求头,并使用HttpClient的PostAsync方法发送POST请求。最后读取返回的JSON响应内容,并在之后的步骤中解析它以提取文字内容。

4.2.2 异步处理返回数据

由于网络请求涉及到I/O操作,且通常情况下,请求的处理时间较长,因此建议将网络请求的操作放在异步方法中执行。在.NET 4.5及以上版本中,可以使用async/await关键字来编写异步方法。异步方法可以提高应用程序的响应性,特别是在多用户环境中,能够显著提升用户体验。

在上面的代码示例中, ConvertImageToBase64 Main 方法都被声明为异步方法,并使用 await 关键字来等待异步操作的完成。这样,当等待网络响应的时候,线程不会被阻塞,而是可以去做其他事情,例如处理其他用户的请求。

异步处理数据的另一个好处是可以在等待数据返回期间释放资源。在异步方法中,可以确保在异步等待期间,相关的资源被正确地释放,这对于高并发的网络服务尤其重要。

在实际开发中,还需要注意异步编程的一些最佳实践,如避免在异步方法中返回void、使用try/catch/finally处理异常等,以确保代码的健壮性和稳定性。在处理API返回的数据时,需要仔细地解析JSON格式的响应内容,提取出文字识别的结果,并对其进行后续处理。这个过程通常涉及到字符串操作和数据转换,确保最终能够提供给用户准确的文字信息。

总结来说,网络图片文字识别流程包括获取网络图片、进行必要的预处理、构建HTTP请求、调用API、异步处理返回数据等步骤。通过合理地组织这些步骤,并采用最佳实践,我们可以有效地实现网络图片文字识别,并提供流畅的用户体验。

5. 百度OCR付费版的高级特性与优化

在本章中,我们将深入探讨百度OCR付费版的核心特性,并提供一些实用的优化技巧来提升你的应用性能和用户体验。

5.1 API授权与调用策略

5.1.1 授权流程与注意事项

为了使用百度OCR付费版,需要先通过API Key和Secret Key进行授权。正确授权是访问付费服务的前提,否则将无法使用OCR功能。

// 示例代码:使用API Key和Secret Key进行授权
var apiKey = "你的API Key";
var secretKey = "你的Secret Key";

// 构造授权头
var authHeader = GetAuthorizationHeader(apiKey, secretKey);

// HTTP请求发送函数(伪代码)
SendRequestWithAuthorization(authHeader);

// 授权头构造函数
string GetAuthorizationHeader(string apiKey, string secretKey) {
    // 此处应有获取授权信息的逻辑
    return "Bearer your_authorization_token";
}

注意事项:

  • 确保API Key和Secret Key的安全,避免泄露给未经授权的第三方。
  • 定期更新密钥,特别是在密钥可能已经暴露的情况下。
  • 对于生产环境,考虑使用专门的权限管理系统来控制API的访问。

5.1.2 高效调用方法与优化

高效调用API是性能优化的关键。一个良好的策略是控制请求频率,合理安排请求时间,并合理使用并发。

// 示例代码:控制并发的请求发送
var tasks = new List<Task>();

foreach (var imagePath in imagePaths) {
    tasks.Add(Task.Run(() => {
        // 对单个图片进行处理的逻辑
        ProcessImage(imagePath);
    }));
}

Task.WaitAll(tasks.ToArray()); // 等待所有任务完成

void ProcessImage(string imagePath) {
    // 此处应有图片处理逻辑,包括发送OCR请求
}

优化措施包括:

  • 使用线程池来管理并发请求,避免创建过多的线程。
  • 根据API文档和业务需求,设置合适的请求间隔和超时时间。
  • 了解并利用百度OCR的限流策略,避免触发服务端限制。

5.2 JSON结果解析技术

5.2.1 JSON数据结构解析

解析JSON响应是获取OCR结果的关键步骤。你可以使用C#的 Newtonsoft.Json 库来解析JSON数据。

using Newtonsoft.Json;

// 假设responseText是从OCR API获取的JSON文本
var ocrResult = JsonConvert.DeserializeObject<OcrResult>(responseText);

// 定义OCR结果对象,需要根据实际返回的JSON结构调整属性
public class OcrResult
{
    [JsonProperty("words_result")]
    public List<WordResult> WordsResult { get; set; }
}

public class WordResult
{
    // 根据返回的字段进行定义
}

5.2.2 数据提取与处理技巧

提取数据后,根据业务需求进行适当的处理。例如,对于识别出来的文本数据,可能需要去除多余的空格,或者格式化日期和时间。

// 从OCR结果中提取文本
var text = string.Join(" ", ocrResult.WordsResult.Select(w => w.Word));

// 移除文本中的多余空格
var formattedText = text.Replace("  ", " ").Trim();

5.3 错误与异常处理策略

5.3.1 错误类型与诊断方法

在调用OCR API时,可能会遇到多种错误,如网络错误、权限错误、格式错误等。诊断这些错误通常需要查看HTTP状态码和响应体。

// 示例代码:异常处理与诊断
try {
    SendRequestWithAuthorization(authHeader);
} catch (Exception ex) {
    // 通用异常处理
    Console.WriteLine("发生异常:" + ex.Message);

    // 网络异常或服务端错误
    if (ex.InnerException is HttpRequestException httpEx) {
        Console.WriteLine("HTTP请求错误:" + httpEx.Message);
    }
}

5.3.2 异常情况的处理和恢复

合理的异常处理逻辑可以确保程序的健壮性。在识别到错误时,可以尝试重试请求,或者给出用户友好的错误提示。

int retryCount = 3;
bool shouldRetry = true;

while (retryCount > 0 && shouldRetry) {
    try {
        SendRequestWithAuthorization(authHeader);
        shouldRetry = false; // 请求成功,不需要重试
    } catch (Exception ex) when (ex is HttpRequestException || ex is JsonException) {
        Console.WriteLine("尝试重试:" + ex.Message);
        retryCount--;
        Thread.Sleep(1000); // 等待一段时间后重试
    }
}

5.4 性能优化措施

5.4.1 提升识别速度的方法

为了提升OCR识别速度,可以考虑以下措施:

  • 优化图片质量,例如通过压缩图像来减少数据量,但不牺牲识别准确度。
  • 使用更快的网络连接,减少数据传输时间。
  • 在可能的情况下使用百度OCR的批量识别API,减少网络往返次数。

5.4.2 内存与资源管理优化

良好的内存与资源管理可以提高应用程序的性能。以下是几个推荐的实践:

  • 确保在使用完毕后释放资源,如关闭文件流和数据库连接。
  • 使用对象池来管理频繁创建和销毁的对象。
  • 在处理大量数据时使用异步编程模式,避免阻塞主线程。

5.5 代码组织与测试方法

5.5.1 代码模块化与结构优化

良好的代码结构可以提升开发效率和代码质量。模块化可以帮助你将程序拆分成多个小的、可管理的部分。

// 示例代码:模块化的函数实现
public class OcrService
{
    private string _apiKey;
    private string _secretKey;

    public OcrService(string apiKey, string secretKey)
    {
        _apiKey = apiKey;
        _secretKey = secretKey;
    }

    public OcrResult RecognizeImage(string imagePath)
    {
        // 从文件读取图片,调整大小,上传,获取OCR结果等
    }
}

5.5.2 单元测试与持续集成实践

单元测试和持续集成是保证代码质量和可维护性的关键。为你的代码编写测试用例,并利用CI/CD工具自动化测试和部署。

// 示例代码:单元测试函数
[TestMethod]
public void TestRecognizeImage()
{
    var ocrService = new OcrService("test_api_key", "test_secret_key");
    var imagePath = "path_to_test_image.jpg";
    var result = ocrService.RecognizeImage(imagePath);

    Assert.IsNotNull(result);
    // 更多的断言测试...
}

在这一章节中,我们学习了如何有效地利用百度OCR付费版进行文字识别,包括授权流程、解析JSON响应、处理错误与异常、性能优化和代码组织。这些知识对于开发高性能、高可靠性的OCR应用至关重要。

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

简介:本文详细介绍了如何使用C#与百度OCR API实现图像文字识别。项目包括了本地和网络图片识别、API调用、结果解析等关键技术点。此外,还探讨了付费版特性、错误处理、性能优化和代码组织等重要方面,为实现高效准确的图像文字提取提供了完整的解决方案。


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

更多推荐