﻿# 如何使用 .NET 的 Azure AI Vision SDK 來替程式加上「視覺」功能

我最近寫了一個[小程式](https://www.youtube.com/watch?v=jknJE_QymJc)，幫助我自動化審核 LINE 社群(OpenChat)的加入申請，由於 LINE 社群並沒有提供 API 可以串接，而我的審核數量又非常大，因此我就想到了透過 OCR 辨識的方式來進行自動化。不過找了幾個免費的 OCR 套件，都沒有辦法很可靠的識別截圖中的文字，直到我嘗試了 [Azure AI Vision](https://azure.microsoft.com/en-us/products/ai-services/ai-vision?WT.mc_id=DT-MVP-4015686) 服務才眼睛為之一亮，這套產品的 **Image analysis** 功能品質極高，費用也極低，實際開發出東西後，我覺得這個服務真的非常值得推薦給大家。這篇文章我就帶大家用 .NET 8 簡單上手這個好用的雲端服務！

![image](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/9a01b4794192e4741a3c-ce33d1a6-f35d-4092-b564-8c610d6f7a5f.webp)

### 建立範例專案範本

1.  建立 Console 專案
    
    ```bash
    dotnet new console -n AzureAIVisionSDKDemo
    cd AzureAIVisionSDKDemo
    ```
    
2.  加入 [Azure.AI.Vision.ImageAnalysis](https://www.nuget.org/packages/Azure.AI.Vision.ImageAnalysis) 套件
    
    由於目前該套件還沒有穩定版本，因此安裝套件時要加上 `--prerelease` 參數
    
    ```bash
    dotnet add package Azure.AI.Vision.ImageAnalysis --prerelease
    ```
    
3.  加入 `.gitignore` 檔案
    
    ```bash
    dotnet new gitignore
    ```
    
4.  加入範例圖片 `sample.jpg`
    
    請任意截圖，圖片上必須包含文字，並且將圖片放到專案根目錄中。
    
    請將以下設定加入到 `AzureAIVisionSDKDemo.csproj` 檔案中：
    
    ```bash
    <ItemGroup>
      <Content Include="sample.jpg">
        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
      </Content>
    </ItemGroup>
    ```
    
5.  初始化專案完成，加入 Git 版控
    
    ```bash
    git init
    git add .
    git commit -m "Initial commit"
    ```
    

### 撰寫主程式

我寫了一段非常簡單的範例程式，看程式應該蠻好理解的。

這段程式主要是透過 [Azure AI Vision](https://azure.microsoft.com/en-us/products/ai-services/ai-vision?WT.mc_id=DT-MVP-4015686) 來進行圖片文字辨識，並且將辨識結果顯示在 Console 畫面上。

```csharp
using Azure;
using Azure.AI.Vision.Common;
using Azure.AI.Vision.ImageAnalysis;

var visionEndpoint = Environment.GetEnvironmentVariable("VISION_ENDPOINT");
var visionKey = Environment.GetEnvironmentVariable("VISION_KEY");

if (visionEndpoint is null || visionKey is null)
{
    Console.WriteLine("The VISION_ENDPOINT or VISION_KEY environment variables are not set.");
    return;
}

var serviceOptions = new VisionServiceOptions(visionEndpoint, new AzureKeyCredential(visionKey));

using var imageSource = VisionSource.FromFile("sample.jpg");

var analysisOptions = new ImageAnalysisOptions()
{
    Features = ImageAnalysisFeature.Text,
    Language = "en",
};

using var analyzer = new ImageAnalyzer(serviceOptions, imageSource, analysisOptions);

// 這行程式會把資料轉成 API 呼叫並且等待結果
var result = await analyzer.AnalyzeAsync();

if (result.Reason == ImageAnalysisResultReason.Analyzed)
{
    if (result.Text != null)
    {
        Console.WriteLine($" Text:");
        foreach (var line in result.Text.Lines)
        {
            string pointsToString = "{" + string.Join(',', line.BoundingPolygon.Select(pointsToString => pointsToString.ToString())) + "}";
            Console.WriteLine($"   Line: '{line.Content}', Bounding polygon {pointsToString}");

            foreach (var word in line.Words)
            {
                pointsToString = "{" + string.Join(',', word.BoundingPolygon.Select(pointsToString => pointsToString.ToString())) + "}";
                Console.WriteLine($"     Word: '{word.Content}', Bounding polygon {pointsToString}, Confidence {word.Confidence:0.0000}");
            }
        }
    }
}
```

我把[這張圖](https://stwillblogassets.blob.core.windows.net/files/images/external/raw.githubusercontent.com/ccc1a570acb6d4c9711b-sample.jpg)的 OCR 識別結果整理在 [https://github.com/doggy8088/AzureAIVisionSDKDemo](https://github.com/doggy8088/AzureAIVisionSDKDemo) 這個 Repo 中，大家可以上來看一下，OCR 識別的效果非常的好，而且會清楚標示出所有文字的座標，也因此我可以透過這些座標進行一些重要的自動化操作！👍

主程式的 `result.Text.Lines` 代表他識別出來的「每一行」文字，也就是說他是以「行」為單位進行識別的，然後才取出每一個「字」(`Words`)，無論是「行」或「字」都會提供完整的座標位置 (圖片的相對位置)，以及最後還會給個「信心指數」(`Confidence`)，讓你可以判斷這個辨識結果的可信度。

### 發行注意事項

目前在發行有用到 Azure AI Vision SDK 的專案時，要注意一些地方，否則執行時會發生錯誤。

由於我的自動審核小程式必須登入 LINE 才能使用，我不想一直佔用我的滑鼠與鍵盤，所以我想把程式跑在 VM 裡面，然而一開始總是無法順利執行，會出現以下錯誤：

![您的應用程式發生未處理的例外狀況。如果您按一下繼續，應用程式會忽略錯誤並嘗試繼續。如果您按一下結束，則會立關閉應用程式。Unable to load DLL 'Azure-AI-Vision-Native' or one of its dependencies: 找不到指定的模組。( 0x8007007E )](https://stwillblogassets.blob.core.windows.net/files/images/external/github.com/5929297b7bebd57a4ccc-30a6a9ef-c725-44a8-abc1-68221485a91c.jpg)

```log
System.DllNotFoundException: Unable to load DLL 'Azure-AI-Vision-Native' or one of its dependencies: 找不到指定的模組。 (0x8007007E)
   at Azure.AI.Common.Internal.Interop.Diagnostics.native.diagnostics_eventsource_logmessage_set_callback(IntPtr callback)
   at Azure.AI.Common.Internal.Interop.Diagnostics.SetEventSourceMessageCallback(LogEventSourceMessageCallbackFunctionDelegate callback)
   at Azure.AI.Vision.Common.Diagnostics.Logging.VisionEventSource..ctor()
   at Azure.AI.Vision.Common.Diagnostics.Logging.VisionEventSource..cctor()
```

後來找了 Stack Overflow 的 [DllNotFoundException: Unable to load DLL 'Azure-AI-Vision-Core' or one of its dependencies: The specified module could not be found. (0x8007007E)](https://stackoverflow.com/q/76001031/910074) 這篇，無解。[原始的回答](https://stackoverflow.com/a/76790796/910074)只講對了一半，沒提到另一個重點，那就是還必須額外安裝 [Microsoft Visual C++ Redistributable](https://learn.microsoft.com/cpp/windows/latest-supported-vc-redist) 套件！

以下是官方文件提及的基本要求：

1.  如果要部署到 Windows 的話，僅支援 Windows 10 (或更高) 的版本
2.  目前的 Azure AI Vision SDK 僅支援 `x64` 平台
3.  目標電腦必須額外安裝 [Microsoft Visual C++ Redistributable for Visual Studio 2015, 2017, 2019, and 2022](https://learn.microsoft.com/cpp/windows/latest-supported-vc-redist)

> 我把[更完整的答案](https://stackoverflow.com/a/77686466/910074)也貼到 Stack Overflow 了，有空的人可以幫我 Up 一下！

如果你要在 LINQPad 順利執行上述範例程式，還必須做出以下設定：

![Query Properties > Advanced](https://stwillblogassets.blob.core.windows.net/files/images/external/github.com/4bd3a85634903c17029f-6e412d79-dbdd-4ead-939b-88a43f9e9adf.jpg)

### 更完整的範例程式

Azure 官方有個 [Azure-Samples](https://github.com/Azure-Samples) 組織，裡面有超多範例程式，其中就有個 [Azure-Samples/azure-ai-vision-sdk](https://github.com/Azure-Samples/azure-ai-vision-sdk/) repo 整理了許多優質且完整的範例，算是學習 Azure AI Vision SDK 的一個不錯的起點！👍

如果要用 .NET 來開發的話，可以參考以下的範例程式：

-   [Image Analysis Samples (C# .NET Core, Windows x64 & Linux x64)](https://github.com/Azure-Samples/azure-ai-vision-sdk/tree/60b722f37655cd0675ac425b3efc074521600683/samples/csharp/image-analysis/dotnet)

### 相關連結

-   [Azure AI Vision](https://azure.microsoft.com/en-us/products/ai-services/ai-vision?WT.mc_id=DT-MVP-4015686)
    -   [Computer Vision](https://azure.microsoft.com/en-us/pricing/details/cognitive-services/computer-vision/?WT.mc_id=DT-MVP-4015686)
    -   [Azure AI Vision pricing](https://azure.microsoft.com/en-us/pricing/details/cognitive-services/computer-vision/?WT.mc_id=DT-MVP-4015686)
    -   [Quickstart: Image Analysis 4.0 (C#)](https://learn.microsoft.com/en-us/azure/ai-services/computer-vision/quickstarts-sdk/image-analysis-client-library-40?tabs=visual-studio%2Clinux&pivots=programming-language-csharp&WT.mc_id=DT-MVP-4015686)
    -   [Computer Vision APIs (2023-10-01)](https://learn.microsoft.com/en-us/rest/api/computer-vision/)
    -   Demo: [https://portal.vision.cognitive.azure.com/demo/extract-text-from-images](https://portal.vision.cognitive.azure.com/demo/extract-text-from-images)
    -   Samples: [https://github.com/Azure-Samples/azure-ai-vision-sdk](https://github.com/Azure-Samples/azure-ai-vision-sdk)
