參考 題型範例 - 全國高級中等學校技藝競賽平台 工業類

題目:框選圖中物件程式


問題描述
● 請寫一隻程式,能依 LabelData.txt 檔內的座標來框選指定檔名中的物件並存檔。
● 提供的檔案說明:本題提供 5 個圖檔及 1 個座標資訊檔 LabelData.txt 供測試。
LabelData.txt 檔中的第 1 列內容為 "ap10.jpg 1 109 133 358 373",意旨在圖檔名為 ap10.jpg 中標示 1 個矩形,其左上角座標為 (109,133)、右下角座標為 (358,373),結果如下左圖。



LabelData.txt 檔中的第 2 列內容為 "carPlate.jpg 1 98 143 197 176",意旨在圖檔名為 carPlate.jpg 中標示 1 個矩形,其左上角座標為 (98,143)、右下角座標為 (197,176),結果如上中圖。
LabelData.txt 檔中的第 4 列內容為 "starfruit.jpg 2 60 64 215 250 184 31 373 259", 意旨在圖檔名為 starfruit.jpg 中標示 2 個矩形,
第 1 個矩形左上角座標為 (60,64)、右下角座標為 (215,250),
第 2 個矩形左上角座標為 (184,31)、右下角座標為 (373,259) ,結果如上右圖。

● 程式執行:
請先建一個 "imageOUT" 資料夾存放標示好的圖檔,如下左圖。
繳交檢查時,請同時提供 exe 執行檔。
程式執行的輸出畫面,請依下右圖實作。



<<注意:評判時會以其他的圖檔案測試>>

題目測資 執行結果
以下解答使用 SkiaSharp 套件,請先依照下面步驟安裝套件。
  1. 在 Visual Studio 中,右鍵點擊您的專案。
  2. 選擇「管理 NuGet 套件」。
  3. 在 NuGet 套件管理器中,搜索 "SkiaSharp"。
  4. 安裝 SkiaSharp 套件。


/// 教育部工科技藝競賽 109 年第二題 框選圖中物件程式
/// 漆家豪 於 海青工商 2024/2/18
using System;
using System.IO;
using SkiaSharp;
class Program
{
    static void Main(string[] args)
    {
        string labelDataPath = "LabelData.txt";
        string imageFolderPath = "../../../"; // 圖片所在的資料夾
        string outputFolderPath = "imageOUT";
        // 如果輸出資料夾不存在,則建立一個
        if (!Directory.Exists(outputFolderPath))
        {
            Directory.CreateDirectory(outputFolderPath);
        }
        string[] lines = File.ReadAllLines(imageFolderPath + labelDataPath);
        foreach (string line in lines)
        {
            string[] parts = line.Split(' ');
            string fileName = parts[0];
            int numRectangles = int.Parse(parts[1]);
            string imagePath = Path.Combine(imageFolderPath, fileName);
            // 創建一個新的 SKBitmap 對象
            using (var bitmap = SKBitmap.Decode(imagePath))
            {
                // 在 SKCanvas 上繪製圖形
                using (var canvas = new SKCanvas(bitmap))
                {
                    for (int i = 0; i < numRectangles; i++)
                    {
                        int startX = int.Parse(parts[2 + i * 4]);
                        int startY = int.Parse(parts[3 + i * 4]);
                        int endX = int.Parse(parts[4 + i * 4]);
                        int endY = int.Parse(parts[5 + i * 4]);
                        // 繪製矩形
                        using (var paint = new SKPaint { Color = SKColors.Red, IsAntialias = true })
                        {
                            paint.Style = SKPaintStyle.Stroke;
                            paint.StrokeWidth = 3;

                            SKRect rect = SKRect.Create(startX, startY, endX - startX, endY - startY);
                            canvas.DrawRect(rect, paint);
                        }
                    }
                }
                // 儲存加框後的圖片
                using (var output = File.Create(imageFolderPath + outputFolderPath + "/" +fileName))
                {
                    // 將 SKBitmap 保存為 PNG 檔案
                    bitmap.Encode(output, SKEncodedImageFormat.Png, 100);
                }
                Console.WriteLine($"在 {imagePath} 圖檔中加框,以相同檔名存入 {outputFolderPath} 資料夾中");
            }
        }
    }
}