【フォルダ整理】ピンボケしている画像があれば、そこに Bad フォルダを作成して移動する Windows アプリケーションを公開してみる

ボケている可能性がある画像ファイルが見つかった場合に
その画像フォルダと同じ場所に Bad フォルダを作成して
その中に移動する Windows アプリケーションを作成したため
皆さんの役に立てればと思い
ソースと本体を公開したいと思います。

[本体はこちら(BOOTH)](https://giftedstyle.booth.pm/items/5857847)
[本体はこちら(Google Drive)](https://drive.google.com/file/d/1Vhq3aHem2TZOfhhzy3LrWJMNfjL2k--U/view?usp=sharing)

***

このアプリケーションの説明

ボケている可能性がある画像ファイルが見つかった場合に
その画像ファイルと同じ場所に Bad フォルダを作成して
その中に移動する Windows アプリケーションです。
![image1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3752886/65784c6d-760d-b7c1-fd4a-e5b8649bea21.png)
![image2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3752886/770ef928-c3dc-abae-f0af-9f11ebbf393c.png)
![image3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3752886/9f5777a2-cf21-d408-1244-c065aee2499c.png)
![image4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3752886/ddcdeb01-5879-18db-761b-53f3b7ccc7ef.png)

ボケている判定が甘いですが
目視で Bad フォルダを確認して
ボケていないと思う画像は
手動で元に戻して下さい。

アルゴリズムの関係上
ボケている画像でも情報量が多ければ
ボケていると判定されないかもしれません。
逆に情報量が少ないと
ボケていると判定されるかもしれません。
ご容赦下さい。

フォルダの中にフォルダがある場合は
そのフォルダも対象になります
つまり子要素孫要素が対象になります。

png ファイルと
jpg ファイルが対象です。

SephirothBadImageAtFolder.exe を開いて使用します。
仕分けしたいフォルダごとドラッグ＆ドロップして下さい。

***

このアプリケーションのソースコード

Visual Studio の Windows フォームで作成しています。
ソースコードは下記の内容です。

```Csharp:使用したコード
using System.ComponentModel;
using System.IO;
using System.IO.Compression;
using System.Text;
using System.Windows.Forms.VisualStyles;
using OpenCvSharp;
using OpenCvSharp.LineDescriptor;
using OpenCvSharp.ML;

namespace SephirothBadImageAtFolder
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            comboBox1.Items.Add("強いぼかしのみ移動する");
            comboBox1.Items.Add("普通以上のぼかしを移動する");
            comboBox1.Items.Add("弱めのぼかしでも移動する");

            comboBox1.DropDownStyle = ComboBoxStyle.DropDownList;

            comboBox1.Text = "強いぼかしのみ移動する";
        }

        private void panel1_Paint(object sender, PaintEventArgs e)
        {

        }

        private void panel1_DragDrop(object sender, DragEventArgs e)
        {
            if (e.Data == null)
            {
                return;
            }
            object? data = e.Data.GetData(DataFormats.FileDrop, false);
            if (data == null)
            {
                return;
            }

            List<string> rootList = new List<string>();
            List<string> targetList = new List<string>();

            int progressCountMax = 0;

            foreach (string rootFolderName in (string[])data)
            {
                if (!System.IO.Directory.Exists(rootFolderName))
                {
                    continue;
                }

                if (rootFolderName.Substring(rootFolderName.LastIndexOf("\\") + 1) == "Bad")
                {
                    continue;
                }

                foreach (string oneTargetFileName in Directory.GetFiles(rootFolderName, "*", System.IO.SearchOption.AllDirectories))
                {
                    if (!oneTargetFileName.EndsWith("png") && !oneTargetFileName.EndsWith("jpg"))
                    {
                        continue;
                    }

                    progressCountMax++;
                }
            }

            this.Activate();
            progressBar1.Minimum = 0;
            progressBar1.Maximum = progressCountMax;

            int progressCount = 0;

            foreach (string rootFolderName in (string[])data)
            {
                if (!System.IO.Directory.Exists(rootFolderName))
                {
                    continue;
                }

                if (rootFolderName.Substring(rootFolderName.LastIndexOf("\\") + 1) == "Bad")
                {
                    continue;
                }

                foreach (string oneTargetFileName in Directory.GetFiles(rootFolderName, "*", System.IO.SearchOption.AllDirectories))
                {
                    if (!oneTargetFileName.EndsWith("png") && !oneTargetFileName.EndsWith("jpg"))
                    {
                        continue;
                    }

                    if(oneTargetFileName.Substring(0, oneTargetFileName.LastIndexOf("\\")).EndsWith("\\Bad"))
                    {
                        continue;
                    }

                    bool isBad = false;

                    using (Mat mat = new Mat(oneTargetFileName))
                    {
                        using (Mat Edge_Canny = new Mat())
                        {
                            Cv2.Canny(mat, Edge_Canny, 10, 410, 3);
                            int total = 0;
                            foreach (var one in Cv2.FindContoursAsArray(Edge_Canny, RetrievalModes.External, ContourApproximationModes.ApproxSimple))
                            {
                                total += one.Length;
                            }

                            int pow = 4000;

                            if(comboBox1.Text == "強いぼかしのみ移動する")
                            {
                                pow = 700;
                            }
                            else if (comboBox1.Text == "普通以上のぼかしを移動する")
                            {
                                pow = 1000;
                            }

                            if (total < pow)
                            {
                                isBad = true;
                            }
                        }
                    }

                    if (isBad)
                    {
                        string targetFolderName = oneTargetFileName.Substring(0, oneTargetFileName.LastIndexOf("\\") + 1) + "Bad";

                        if (!System.IO.Directory.Exists(targetFolderName))
                        {
                            System.IO.Directory.CreateDirectory(targetFolderName);
                        }

                        rootList.Add(oneTargetFileName);
                        targetList.Add(targetFolderName + "\\" + oneTargetFileName.Substring(oneTargetFileName.LastIndexOf("\\") + 1));
                    }

                    progressCount++;
                    progressBar1.Value = progressCount;
                }
            }

            progressBar1.Value = 0;

            if (rootList.Count != targetList.Count)
            {
                MessageBox.Show(
                        "エラー1が発生したため、安全性を考慮して何も処理を行わずに終了しました。", "確認",
                        MessageBoxButtons.OK, MessageBoxIcon.Question
                        );
                return;
            }

            for (int i = 0; i < targetList.Count; i++)
            {
                if (System.IO.File.Exists(targetList[i]))
                {
                    MessageBox.Show(
                            "移動しようとしているファイルが既に存在しているため、安全性を考慮して何も処理を行わずに終了しました。", "確認",
                            MessageBoxButtons.OK, MessageBoxIcon.Question
                            );
                    return;
                }
            }

            for (int i = 0; i < targetList.Count; i++)
            {
                for (int j = i + 1; j < targetList.Count; j++)
                {
                    if (targetList[i] == targetList[j])
                    {
                        MessageBox.Show(
                                "エラー2が発生したため、安全性を考慮して何も処理を行わずに終了しました。", "確認",
                                MessageBoxButtons.OK, MessageBoxIcon.Question
                                );
                        return;
                    }
                }
            }

            for (int i = 0; i < rootList.Count; i++)
            {
                if (!System.IO.Directory.Exists(rootList[i].Substring(0, rootList[i].LastIndexOf("\\"))))
                {
                    MessageBox.Show(
                            "エラー3が発生したため、安全性を考慮して何も処理を行わずに終了しました。", "確認",
                            MessageBoxButtons.OK, MessageBoxIcon.Question
                            );
                    return;
                }
            }

            for (int i = 0; i < targetList.Count; i++)
            {
                if (!System.IO.Directory.Exists(targetList[i].Substring(0, targetList[i].LastIndexOf("\\"))))
                {
                    MessageBox.Show(
                            "エラー4が発生したため、安全性を考慮して何も処理を行わずに終了しました。", "確認",
                            MessageBoxButtons.OK, MessageBoxIcon.Question
                            );
                    return;
                }
            }

            for (int i = 0; i < targetList.Count; i++)
            {
                System.IO.File.Move(rootList[i], targetList[i]);
            }

            MessageBox.Show(
                    "仕分けが完了しました。", "確認",
                    MessageBoxButtons.OK, MessageBoxIcon.Question
                    );

            return;
        }

        private void panel1_DragEnter(object sender, DragEventArgs e)
        {
            if (e.Data == null)
            {
                return;
            }
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
            {
                e.Effect = DragDropEffects.All;
            }
            else
            {
                e.Effect = DragDropEffects.None;
            }
        }
    }
}
```

***

以上 Windows アプリケーションを公開しました。

Visual Studio の Windows フォームは
フォルダ整理をしたい時等に
補助用のアプリケーションを
簡単に作成する事ができます。

皆さんもフォルダ整理の際は
Visual Studio を活用してみては
いかがでしょうか？

皆さんの開発の助けになれますように
閲覧ありがとうございました。