C#机器学习(3)-Azure AI(3)

本文详细介绍了如何使用不同的身份验证方法来访问Azure认知服务,包括使用单服务和多服务订阅密钥、访问令牌以及通过AzureActiveDirectory进行身份验证。同时,提到了OpenFileDialog类在.NET中的应用,用于用户选择文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

OpenFileDialog 类

定义

命名空间:
System.Windows.Forms

程序集:
System.Windows.Forms.dll

显示一个标准对话框,提示用户打开文件。 此类不能被继承。

public sealed class OpenFileDialog : System.Windows.Forms.FileDialog

继承
Object
MarshalByRefObject
Component
CommonDialog
FileDialog
OpenFileDialog
注解

此类允许检查文件是否存在并打开该文件。 该 ShowReadOnly 属性确定对话框中是否显示只读复选框。 该 ReadOnlyChecked 属性指示是否选中只读复选框。

此类的大部分核心功能都位于该类中 FileDialog 。

在从右到左的操作系统上,将包含窗体 RightToLeft 的属性设置为 RightToLeft.Yes 本地化对话框的 文件名、 打开 和 取消 按钮。 如果未将属性设置为 RightToLeft.Yes,则改用英语文本。

如果希望为用户提供选择文件夹而不是文件的功能,请改用 FolderBrowserDialog 。
示例

下面的代码示例创建一个、设置多个 OpenFileDialog属性来定义文件扩展名筛选器和对话行为,并使用该方法显示对话框 CommonDialog.ShowDialog 。 该示例需要一个窗体,其中包含一个 Button 放置在它的窗体,以及对添加到它的命名空间的 System.IO 引用。

var fileContent = string.Empty;
var filePath = string.Empty;

using (OpenFileDialog openFileDialog = new OpenFileDialog())
{
    openFileDialog.InitialDirectory = "c:\\";
    openFileDialog.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*";
    openFileDialog.FilterIndex = 2;
    openFileDialog.RestoreDirectory = true;

    if (openFileDialog.ShowDialog() == DialogResult.OK)
    {
        //Get the path of specified file
        filePath = openFileDialog.FileName;

        //Read the contents of the file into a stream
        var fileStream = openFileDialog.OpenFile();

        using (StreamReader reader = new StreamReader(fileStream))
        {
            fileContent = reader.ReadToEnd();
        }
    }
}

MessageBox.Show(fileContent, "File Content at path: " + filePath, MessageBoxButtons.OK);

将上一节例子的代码改下

        private void btnLoadPic_Click(object sender, EventArgs e)
        {
            var fileContent = string.Empty;
            var filePath = string.Empty;

            using (OpenFileDialog openFileDialog = new OpenFileDialog())
            {
                openFileDialog.InitialDirectory = System.AppDomain.CurrentDomain.BaseDirectory;
                openFileDialog.Filter = "jpeg files (*.jpg)|*.jpg|png files (*.png)|*.png|All files (*.*)|*.*";
                openFileDialog.FilterIndex = 1;
                openFileDialog.RestoreDirectory = true;

                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    ptbOcrPic.ImageLocation =  openFileDialog.FileName;
                }
            }          
        }

Azure 认知服务利用可增强用户体验的工具,使用基于计算机的智能功能来实现自然的上下文交互。 Azure 认知服务 REST API 中的操作提供了管理认知服务帐户的操作。

Azure 认知服务的身份验证

可用于 Azure 认知服务的身份验证标头

对 Azure 认知服务的每个请求都必须包含身份验证标头。 此标头传递订阅密钥或身份验证令牌,用于验证服务或服务组订阅。 三种对请求进行身份验证的方法。

使用单服务或多服务订阅密钥进行身份验证
使用令牌进行身份验证
使用 Azure Active Directory (AAD) 进行身份验证

身份验证标头

标头 	                           说明
Ocp-Apim-Subscription-Key 	     使用此标头通过特定服务订阅密钥或多服务订阅密钥进行身份验证。
Ocp-Apim-Subscription-Region 	只有在使用具有 Translator 服务的多服务订阅密钥时才需要此标头。 使用此标头指定订阅区域。
授权 	                        如果使用的是访问令牌,则使用此标头。 以下各节详细介绍了执行令牌交换的步骤。 提供的值遵循以下格式:Bearer <TOKEN>

使用单服务订阅密钥进行身份验证

第一个选项是使用特定服务(如 Translator)的订阅密钥对请求进行身份验证。
Azure 门户中的密钥可用于已创建的每个资源。 要使用订阅密钥对请求进行身份验证,必须将其作为 Ocp-Apim-Subscription-Key 标头传递。
对必应 Web 搜索 API

 curl -X GET 'https://api.cognitive.microsoft.com/bing/v7.0/search?q=Welsch%20Pembroke%20Corgis' \
-H 'Ocp-Apim-Subscription-Key: YOUR_SUBSCRIPTION_KEY' | json_pp

使用多服务订阅密钥进行身份验证

此选项仍使用订阅密钥对请求进行身份验证。 主要区别在于订阅密钥未绑定到特定服务,而单个密钥可用于对多个认知服务的请求进行身份验证。

订阅密钥在每个请求中作为 Ocp-Apim-Subscription-Key 标头提供。

ImageAnalysis results = await client.AnalyzeImageAsync(imageUrl, visualFeatures: features, language: "en");

支持的区域

使用多服务订阅密钥向 api.cognitive.microsoft.com 发出请求时,必须在 URL 中包含该区域。 例如:westus.api.cognitive.microsoft.com。

将多服务订阅密钥与 Translator 服务配合使用时,必须使用 Ocp-Apim-Subscription-Region 标头指定订阅区域。

使用访问令牌进行身份验证

某些 Azure 认知服务接受并在某些情况下需要访问令牌。 目前,以下服务支持访问令牌:

文本翻译 API
语音服务:语音转文本 API
语音服务:文本转语音 API

单服务订阅密钥和多服务订阅密钥均可用于交换认证令牌。 身份验证令牌有效期为 10 分钟。 它们以 JSON Web 令牌 (JWT) 格式存储,可供使用 JWT 库以编程方式查询。

访问令牌作为 Authorization 标头包含在请求中。 提供的令牌值必须以 Bearer 开头,例如:Bearer YOUR_AUTH_TOKEN。

示例请求

使用以下 URL 将订阅密钥交换为访问令牌:https://YOUR-REGION.api.cognitive.microsoft.com/sts/v1.0/issueToken。

curl -v -X POST \
"https://YOUR-REGION.api.cognitive.microsoft.com/sts/v1.0/issueToken" \
-H "Content-type: application/x-www-form-urlencoded" \
-H "Content-length: 0" \
-H "Ocp-Apim-Subscription-Key: YOUR_SUBSCRIPTION_KEY"

获得访问令牌后,需要在每个请求中将其作为 Authorization 标头传递。 这是对 Translator 服务的示例调用:

curl -X POST 'https://api.cognitive.microsofttranslator.com/translate?api-version=3.0&from=en&to=de' \
-H 'Authorization: Bearer YOUR_AUTH_TOKEN' \
-H 'Content-Type: application/json' \
--data-raw '[{ "text": "How much for the cup of coffee?" }]' | json_pp

向 Azure Active Directory 进行身份验证

使用单一服务或多服务订阅密钥完成 Azure 认知服务的身份验证。 虽然这些密钥提供了一种快速简便的途径快速开始开发,但还不足以支持需要 Azure 基于角色的访问控制 (Azure RBAC) 的更复杂的方案。 让我们来看看使用 Azure Active Directory (Azure AD) 进行身份验证所需的条件。

使用自定义子域创建资源

使用 Azure Cloud Shell 环境或 Azure CLI 创建子域、分配角色和获取持有者令牌来调用 Azure 认知服务。
第一步是创建自定义子域。 如果要使用没有自定义子域名的现有认知服务资源,为资源启用自定义子域。

Azure 认知服务对通过 Azure 门户、Azure Cloud Shell 或 Azure CLI 创建的每个资源使用自定义子域名。 不同于特定 Azure 区域中所有客户经常使用的区域终结点,自定义子域名对于资源是唯一的。 需要使用自定义子域名来启用 Azure Active Directory (Azure AD) 等功能进行身份验证。

首先打开 Azure Cloud Shell。 然后选择一个订阅:

Set-AzContext -SubscriptionName <SubscriptionName>

接下来,使用自定义子域创建认知服务资源。 子域名需为全局唯一,不能包括特殊字符,例如:“.”、“!”、“,”。

$account = New-AzCognitiveServicesAccount -ResourceGroupName <RESOURCE_GROUP_NAME> -name <ACCOUNT_NAME> -Type <ACCOUNT_TYPE> -SkuName <SUBSCRIPTION_TYPE> -Location <REGION> -CustomSubdomainName <UNIQUE_SUBDOMAIN>

如果成功,Endpoint 应会显示资源独有的子域名。

向服务主体分配角色

现在,已有了与资源关联的自定义子域,接着需要将角色分配给服务主体。
首先,注册一个 Azure AD 应用程序。

$SecureStringPassword = ConvertTo-SecureString -String <YOUR_PASSWORD> -AsPlainText -Force

$app = New-AzADApplication -DisplayName <APP_DISPLAY_NAME> -IdentifierUris <APP_URIS> -Password $SecureStringPassword

在下一步中,需要 ApplicationId。
接下来,需要为 Azure AD 应用程序创建服务主体。

New-AzADServicePrincipal -ApplicationId <APPLICATION_ID>

如果在 Azure 门户中注册应用程序,将自动为你完成此步骤。

最后一步是向服务主体分配“认知服务用户”角色(范围限定为资源)。 通过分配角色,将向服务主体授予对此资源的访问权限。 可以向服务主体授予对订阅中多个资源的访问权限。

此过程使用服务主体的 ObjectId,而不是应用程序的 ObjectId。 ACCOUNT_ID 是所创建的认知服务帐户的 Azure 资源 ID。 可以从 Azure 门户中资源的“属性”中找到 Azure 资源 ID。

New-AzRoleAssignment -ObjectId <SERVICE_PRINCIPAL_OBJECTID> -Scope <ACCOUNT_ID> -RoleDefinitionName "Cognitive Services User"

使用 Azure 密钥保管库安全地访问凭据

可以使用 Azure Key Vault 安全地开发认知服务应用程序。 Key Vault 使你能够将身份验证凭据存储在云中,并且降低了机密意外泄漏的可能性,因为你不会在应用程序中存储安全信息。

身份验证通过 Azure Active Directory 来完成。 授权可以通过 Azure 基于角色的访问控制 (Azure RBAC) 或 Key Vault 访问策略来完成。 Azure RBAC 可用于管理保管库和访问存储在该保管库中的数据,而密钥保管库访问策略仅能在尝试访问存储在保管库中的数据时使用。

ReadResults分析URL图像

var textUrlFileResults = results.AnalyzeResult.ReadResults;

AnalyzeResults属性
Newtonsoft.Json.JsonPropertyAttribute

[Newtonsoft.Json.JsonProperty(PropertyName="analyzeResult")]
public Microsoft.Azure.CognitiveServices.Vision.ComputerVision.Models.AnalyzeResults AnalyzeResult { get; set; }

继续来分析

        foreach (ReadResult page in textUrlFileResults)
        {
            foreach (Line line in page.Lines)
            {
                    tbOcrResult.Text += (line.Text);
                    tbOcrResult.Text += Environment.NewLine;
                }
        }

foreach (ReadResult page in textUrlFileResults)迭代访问结果
还可以访问更多结果信息

tbOcrResult.Text += page.Language;
tbOcrResult.Text += Environment.NewLine;
tbOcrResult.Text += page.Width;
tbOcrResult.Text += Environment.NewLine;
tbOcrResult.Text += page.Height;
tbOcrResult.Text += Environment.NewLine;
tbOcrResult.Text += page.Angle;
tbOcrResult.Text += Environment.NewLine;

改一下

        foreach (ReadResult page in textUrlFileResults)
        {
                tbOcrResult.Text += page.Language;
                tbOcrResult.Text += Environment.NewLine;
                tbOcrResult.Text += page.Width;
                tbOcrResult.Text += Environment.NewLine;
                tbOcrResult.Text += page.Height;
                tbOcrResult.Text += Environment.NewLine;
                tbOcrResult.Text += page.Angle;
                tbOcrResult.Text += Environment.NewLine;
                foreach (Line line in page.Lines)
            {
                    tbOcrResult.Text += (line.Text);
                    tbOcrResult.Text += Environment.NewLine;
                }
        }

运行一下代码便知结果

分析本地图像

不能使用ReadAsync,这个是分析URL图像,要使用另外一个API。

var textHeaders = await client.ReadAsync(urlFile);

要改成从流读取文件

  var textHeaders = await client.ReadInStreamAsync(File.OpenRead(localFile));

ComputerVisionClientExtensions.ReadInStreamAsync Method

public static System.Threading.Tasks.Task<Microsoft.Azure.CognitiveServices.Vision.ComputerVision.Models.ReadInStreamHeaders> ReadInStreamAsync (this Microsoft.Azure.CognitiveServices.Vision.ComputerVision.IComputerVisionClient operations, System.IO.Stream image, string language = default, System.Collections.Generic.IList<string> pages = default, string modelVersion = "latest", string readingOrder = "basic", System.Threading.CancellationToken cancellationToken = default);

参数

operations
IComputerVisionClient

image
Stream

language
String

pages
IList

modelVersion
String

readingOrder
String

cancellationToken
CancellationToken

最重要的参数image,这是一个流stream。

返回值

Task<ReadInStreamHeaders> 

修改后代码

using System;
using System.Collections.Generic;
using Microsoft.Azure.CognitiveServices.Vision.ComputerVision;
using Microsoft.Azure.CognitiveServices.Vision.ComputerVision.Models;
using System.Threading.Tasks;
using System.IO;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Threading;
using System.Linq;
using System.Net;
using System.Windows.Forms;

namespace azureIai_1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        // Add your Computer Vision subscription key and endpoint
        private string subscriptionKey = "subscription key";
        private string endpoint = "endpoint";
        private string READ_TEXT_URL_IMAGE = "";
        private string ImageFileName = "";
        private async void btnOcr_Click(object sender, EventArgs e)
        {
            ComputerVisionClient client = Authenticate(endpoint, subscriptionKey);
            tbOcrResult.Text += DateTime.Now;
            tbOcrResult.Text += "开始OCR识别..." + Environment.NewLine;
            if (tbxUrl.Text.Trim() != "")
            {
                await ReadFileUrl(client, READ_TEXT_URL_IMAGE);
            }
            else if (ImageFileName.Trim() != "")
            {
                await ReadFileLocal(client, ImageFileName);
            }
            READ_TEXT_URL_IMAGE = "";
            ImageFileName = "";
        }

        

    public ComputerVisionClient Authenticate(string endpoint, string key)
    {
        ComputerVisionClient client =
          new ComputerVisionClient(new ApiKeyServiceClientCredentials(key))
          { Endpoint = endpoint };
        return client;
    }

    public async Task ReadFileUrl(ComputerVisionClient client, string urlFile)
    {

        // Read text from URL
        var textHeaders = await client.ReadAsync(urlFile);
            // After the request, get the operation location (operation ID)
            string operationLocation = textHeaders.OperationLocation;
            tbOcrResult.Text += operationLocation;
            tbOcrResult.Text += Environment.NewLine;
            // Retrieve the URI where the extracted text will be stored from the Operation-Location header.
            // We only need the ID and not the full URL
            const int numberOfCharsInOperationId = 36;
        string operationId = operationLocation.Substring(operationLocation.Length - numberOfCharsInOperationId);

        // Extract the text
        ReadOperationResult results;
        tbOcrResult.Text+=($"从 URL 文件 {Path.GetFileName(urlFile)}解析文本...");
        tbOcrResult.Text += Environment.NewLine;
        do
        {
            results = await client.GetReadResultAsync(Guid.Parse(operationId));
        }
        while ((results.Status == OperationStatusCodes.Running ||
            results.Status == OperationStatusCodes.NotStarted));

        tbOcrResult.Text += Environment.NewLine;
        var textUrlFileResults = results.AnalyzeResult.ReadResults;
        foreach (ReadResult page in textUrlFileResults)
        {
                tbOcrResult.Text += page.Language;
                tbOcrResult.Text += Environment.NewLine;
                tbOcrResult.Text += page.Width;
                tbOcrResult.Text += Environment.NewLine;
                tbOcrResult.Text += page.Height;
                tbOcrResult.Text += Environment.NewLine;
                tbOcrResult.Text += page.Angle;
                tbOcrResult.Text += Environment.NewLine;
                foreach (Line line in page.Lines)
            {
                    tbOcrResult.Text += (line.Text);
                    tbOcrResult.Text += (line.Language);
                    tbOcrResult.Text += Environment.NewLine;
                }
        }
            tbOcrResult.Text += Environment.NewLine;
    }

        public async Task ReadFileLocal(ComputerVisionClient client, string localFile)
        {
            tbOcrResult.Text += ($"从 本地文件解析文本...");
            tbOcrResult.Text += Environment.NewLine;

            // Read text from LocalFile
            var textHeaders = await client.ReadInStreamAsync(File.OpenRead(localFile));
            // After the request, get the operation location (operation ID)
            string operationLocation = textHeaders.OperationLocation;


            // <snippet_extract_response>
            // Retrieve the URI where the recognized text will be stored from the Operation-Location header.
            // We only need the ID and not the full URL
            const int numberOfCharsInOperationId = 36;
            string operationId = operationLocation.Substring(operationLocation.Length - numberOfCharsInOperationId);

            // Extract the text
            ReadOperationResult results;
            tbOcrResult.Text += ($"从 本地文件 {Path.GetFileName(localFile)}解析文本...");
            tbOcrResult.Text += Environment.NewLine;
            do
            {
                results = await client.GetReadResultAsync(Guid.Parse(operationId));
            }
            while ((results.Status == OperationStatusCodes.Running ||
                results.Status == OperationStatusCodes.NotStarted));

            tbOcrResult.Text += Environment.NewLine;
            var textUrlFileResults = results.AnalyzeResult.ReadResults;
            foreach (ReadResult page in textUrlFileResults)
            {
                tbOcrResult.Text += page.Language;
                tbOcrResult.Text += Environment.NewLine;
                tbOcrResult.Text += page.Width;
                tbOcrResult.Text += Environment.NewLine;
                tbOcrResult.Text += page.Height;
                tbOcrResult.Text += Environment.NewLine;
                tbOcrResult.Text += page.Angle;
                tbOcrResult.Text += Environment.NewLine;
                foreach (Line line in page.Lines)
                {
                    tbOcrResult.Text += (line.Text);
                    tbOcrResult.Text += (line.Language);
                    tbOcrResult.Text += Environment.NewLine;
                }
            }
            tbOcrResult.Text += Environment.NewLine;
        }

        private void btnLoadPic_Click(object sender, EventArgs e)
        {
            try
            {

                if (tbxUrl.Text.Trim() == "")
                {
                    var fileContent = string.Empty;
                    var filePath = string.Empty;

                    using (OpenFileDialog openFileDialog = new OpenFileDialog())
                    {
                        openFileDialog.InitialDirectory = System.AppDomain.CurrentDomain.BaseDirectory;
                        openFileDialog.Filter = "jpeg files (*.jpg)|*.jpg|png files (*.png)|*.png|All files (*.*)|*.*";
                        openFileDialog.FilterIndex = 1;
                        openFileDialog.RestoreDirectory = true;
                        if (openFileDialog.ShowDialog() == DialogResult.OK)
                        {
                            ptbOcrPic.ImageLocation = openFileDialog.FileName;
                            ImageFileName= openFileDialog.FileName;
                            READ_TEXT_URL_IMAGE = "";
                        }
                    }
                }
                else
                {
                    ptbOcrPic.ImageLocation = tbxUrl.Text.Trim();
                    READ_TEXT_URL_IMAGE = tbxUrl.Text.Trim();
                    ImageFileName = "";
                }
                ptbOcrPic.Refresh();

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                ptbOcrPic.ImageLocation = "";
            }

        
        }

    }

}

新程序可以加载URL或分析本地图片。
在这里插入图片描述

图像分析 API

选择视觉特征

使用分析 API 可以访问所有服务的图像分析特征。 基于自己的用例选择要执行的操作。 有关每种特征的说明,请参阅概述。 以下章节中的示例添加了所有可用的视觉特征,但对于实际使用,可能只需要一两种特征。

/* 
 * ANALYZE IMAGE - URL IMAGE
 * Analyze URL image. Extracts captions, categories, tags, objects, faces, racy/adult/gory content,
 * brands, celebrities, landmarks, color scheme, and image types.
 */
public static async Task AnalyzeImageUrl(ComputerVisionClient client, string imageUrl)
{
    Console.WriteLine("----------------------------------------------------------");
    Console.WriteLine("ANALYZE IMAGE - URL");
    Console.WriteLine();

    // Creating a list that defines the features to be extracted from the image. 

    List<VisualFeatureTypes?> features = new List<VisualFeatureTypes?>()
    {
        VisualFeatureTypes.Categories, VisualFeatureTypes.Description,
        VisualFeatureTypes.Faces, VisualFeatureTypes.ImageType,
        VisualFeatureTypes.Tags, VisualFeatureTypes.Adult,
        VisualFeatureTypes.Color, VisualFeatureTypes.Brands,
        VisualFeatureTypes.Objects
    };

VisualFeatureTypes Enum具体如下:


Adult 	2 	
Brands 	8 	
Categories 	3 	
Color 	4 	
Description 	6 	
Faces 	1 	
ImageType 	0 	
Objects 	7 	
Tags 	5 	

文本提取功能是 v4.0 分析图像 REST API 的一部分。 将 Read 包括在 features 查询参数中。 然后,在获取完整 JSON 响应时,分析 “readResult” 部分内容的字符串。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值