C#で画像ファイルをグレイスケール化するCLIコマンド

C# コンピュータ
C#

コマンドラインで画像ファイルをグレイスケールに変換します。

プロジェクトの作成

mkdir ImgToGray
cd ImgToGray
dotnet new console
dotnet add package System.CommandLine --prerelease
dotnet add package OpenCvSharp4
dotnet add package OpenCvSharp4.Windows
dotnet add package OpenCvSharp4.Extensions
dotnet add package OpenCvSharp4.runtime.win

ソースコード

using System.CommandLine;
using OpenCvSharp;

namespace ImgToGray;
class Program
{
    static readonly string Suffix = "_Gray";
    static void Filter(FileInfo file, string dir)
    {
        // ファイルが存在しない場合戻る
        if (!File.Exists(file.FullName)) return;

        // 出力ディレクトリが無い場合入力ディレクトリをセット
        if (dir == "")
        {
            dir = file.DirectoryName ?? Directory.GetCurrentDirectory();
        }
        // 出力ディレクトリが無い場合作成
        if (!Directory.Exists(dir))
        {
            Directory.CreateDirectory(dir);
        }
        // 出力ファイルのパスを生成
        string fileName = file.Name;
        if (dir == file.DirectoryName)
        {
            // 入力と出力ディレクトリが同じ場合ファイル名にSuffixを付与
            fileName = Path.GetFileNameWithoutExtension(file.Name) + Suffix + file.Extension;
        }
        string outFile = Path.Join(dir, fileName);
        
        // 画像ファイルをグレースケールで読み込み
        using var mat = Cv2.ImRead(file.FullName, ImreadModes.Grayscale);

        // ファイルに保存
        Cv2.ImWrite(outFile, mat);
        // 標準出力に出力ファイルのパスを出力
        Console.WriteLine(outFile);
    }
    static async Task<int> Main(string[] args)
    {
        var fileOption = new Option<FileInfo?>(
            name: "--file",
            description: "入力画像ファイル",
            getDefaultValue: () => null
        ){ IsRequired = false };
        var dirOption = new Option<string>(
            name: "--dir",
            description: "出力先のディレクトリ",
            getDefaultValue: () => ""
        ){ IsRequired = false };
        var rootCommand = new RootCommand(
            "画像ファイルをグレースケール化"
        );
        
        rootCommand.AddOption(fileOption);
        rootCommand.AddOption(dirOption);

        rootCommand.SetHandler((file, dir) =>
            {

                if (Console.IsInputRedirected)
                {
                    // 標準入力リダイレクト有り
                    string? line = Console.ReadLine();
                    while (line != null)
                    {
                        // Fileオプションは無視
                        Filter(new FileInfo(line), dir);
                        line = Console.ReadLine();
                    }
                }
                else
                {
                    // 標準入力リダイレクト無し
                    if (file is null) return;
                    Filter(file!, dir);
                }
            },
            fileOption, dirOption);

        return await rootCommand.InvokeAsync(args);
    }
}
Download

--previewオプションをつけることでフィルター適用後の画像のプレビューを表示
Optionの型をboolにするとオプションの有無がbool型(trueまたはfalse)で取得できる。

ビルド&インストール

Releaseでビルド

dotnet build -c Release

bin/Release/net8.0に実行ファイルおよび実行に必要なファイルが出来上がっているので、パスの切られたインストールしたい任意のディレクトリへサブディレクトリを含めて全てのファイルをコピーする。

コメント