C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

拡大された画像をカウントする

[トピック内 5 記事 (1 - 5 表示)]  << 0 >>

■88234 / inTopicNo.1)  拡大された画像をカウントする
  
□投稿者/ マッチ (5回)-(2018/08/10(Fri) 20:37:53)

分類:[C#] 

C#を使ってテンプレートマッチングの練習をしております。

このメソッドを使えばBitmapの中にある等倍の画像を検索することができるのですが、

        public bool IsEqualBitmap(Bitmap bitmapTarget, Bitmap bitmapImage, int nTargetX, int nTargetY)
        {
            if((nTargetX + bitmapTarget.Width) > bitmapImage.Width)
            {
                return false;
            }

            if((nTargetY + bitmapTarget.Height) > bitmapImage.Height)
            {
                return false;
            }

            for (int nY = 0; nY < bitmapTarget.Height; nY++)
            {
                for (int nX = 0; nX < bitmapTarget.Width; nX++)
                {
                    Color colorTarget = bitmapTarget.GetPixel(nX, nY);
                    Color colorImage = bitmapImage.GetPixel(nTargetX + nX, nTargetY + nY);

                    if (colorTarget != colorImage)
                    {
                        return false;
                    }
                }
            }

            return true;
        }

https://dotup.org/uploda/dotup.org1608061.png.html

上記のURLのように元の画像を拡大して貼り付けた画像を検索することができません。
どのように改造すれば拡大された画像を検索してカウントすることができるのでしょうか。

拡大前の画像は以下の通りです。

pictureBox1.BackgroundImage = SystemIcons.Hand.ToBitmap();
pictureBox2.BackgroundImage = SystemIcons.Information.ToBitmap();
pictureBox3.BackgroundImage = SystemIcons.Question.ToBitmap();
pictureBox4.BackgroundImage = SystemIcons.Warning.ToBitmap();


引用返信 編集キー/
■88235 / inTopicNo.2)  Re[1]: 拡大された画像をカウントする
□投稿者/ Azulean (965回)-(2018/08/10(Fri) 23:39:41)
2018/08/10(Fri) 23:58:11 編集(投稿者)

No88234 (マッチ さん) に返信
> 上記のURLのように元の画像を拡大して貼り付けた画像を検索することができません。
> どのように改造すれば拡大された画像を検索してカウントすることができるのでしょうか。

今のコードを改造するレベルでは無理だと思います。

理由
 今のコードは完全一致を前提とします。
 しかし、拡大や縮小処理はピクセルが補間される関係で、色が混ざるので、同じサイズに拡縮しても、完全一致しないことがほとんどです。

よって、完全一致ではなく、何らかの評価方法によって一定以内に収まるものをカウントすることになります。
が、適切な評価関数は自分の置かれている状況によって変わるので、いろいろと探すか、考えていただくしかないです。。。
(検索キーワードは「パターンマッチ」か)


※今みたいに明確に異なる4種であり、他の画像を出身とする画像がないなら、同じサイズに拡縮して、差が一定以内なら一致と判定するのもありでしょう。
(水平移動や回転ががないことが前提)
引用返信 編集キー/
■88240 / inTopicNo.3)  Re[2]: 拡大された画像をカウントする
□投稿者/ マッチ (6回)-(2018/08/11(Sat) 22:32:53)
>今のコードを改造するレベルでは無理だと思います。
そうですか。残念です。

>何らかの評価方法によって一定以内に収まるものをカウントすることになります。
考えてみたのが比較画像を縮小して拡大前の画像と比較する方法です。
評価方法はRGBのRとGとBのそれぞれの差を求めて一定以内であれば一致という方式を考えていました。
ネットで見るとRGBの平均値をとって平均値の差を求めるやり方を見つけたので
今はそちらを採用しようと思ってます。
後は、RGBから輝度を求めて比較する方法も見つけました。
こちらも使われている例が多かったです。
本来であれば計算で評価方法の許容範囲を決めるのだろうと思いますが、
RGBの計算結果を見ながら範囲を調整しようと考えています。

困っているのが貼り付けた画像をどう縮小させるかです。
四角の画像であれば隅の4点の色を見て画像を切り出せそうですが、
三角や丸の画像の範囲をどう切り出せばいいかわかりません。
どうすればいいでしょうか。

引用返信 編集キー/
■88242 / inTopicNo.4)  Re[3]: 拡大された画像をカウントする
□投稿者/ Azulean (966回)-(2018/08/12(Sun) 22:41:25)
No88240 (マッチ さん) に返信
> 困っているのが貼り付けた画像をどう縮小させるかです。
> 四角の画像であれば隅の4点の色を見て画像を切り出せそうですが、
> 三角や丸の画像の範囲をどう切り出せばいいかわかりません。
> どうすればいいでしょうか。

画像処理をいろいろと調べて、置ける制約・前提、要求、自分のスキル、必要な実装時間のバランスが取れるものを探した方が良いと思います。
個人的には自力実装を諦めて、OpenCV の処理を組み合わせてできる範囲を狙った方が良さそうな気もします。

(どうすれば良いのでしょうか…と問われても、前提も制約も要求も曖昧で、かつ、知識・スキルが不明瞭の中での提案は難しいので…)

引用返信 編集キー/
■88245 / inTopicNo.5)  Re[3]: 拡大された画像をカウントする
□投稿者/ 魔界の仮面弁士 (1781回)-(2018/08/13(Mon) 02:35:19)
2018/08/13(Mon) 02:45:15 編集(投稿者)

No88240 (マッチ さん) に返信
> 四角の画像であれば隅の4点の色を見て画像を切り出せそうですが、

背景部も含めて矩形のままで評価して良いのではないでしょうか。

被検出画像もアイコン側も、背景色が同じ(F0F0F0)ですし、
しかも画像の重なりも無いようですから。


> 三角や丸の画像の範囲をどう切り出せばいいかわかりません。

三角や丸に切り抜く必要があるとした場合、被検出画像の方はさておき、
少なくともアイコン側は Icon.ToBitmap() で生成したものなので、
最初から Alpha 値を持っているはずです。

元画像が RGB ではなく RGBA である以上、
どこが背景部なのかは明確ではないでしょうか?

と言っても、アンチエイリアスによる半透明部もありますので、
どこまでを背景部とするか、閾値を決める必要はあるでしょうね。

たとえば下記では、Bitmap の透明部を判定するために、
25%(&H40)未満を閾値として処理しています。
http://smdn.jp/programming/tips/create_region_from_bitmap/


> 考えてみたのが比較画像を縮小して拡大前の画像と比較する方法です。
テンプレートマッチングだとスケーリングに弱いので、
拡大縮小を自前で補うことになりますね。

下記に Multi-scale Template Matching な例があります。
言語は Python ですが、考え方としては同じではないでしょうか。
https://www.pyimagesearch.com/2015/01/26/multi-scale-template-matching-using-python-opencv/

このサンプルでは、ロゴの色が変わったりしても検出できるよう、あえて
Canny アルゴリズムでエッジ検出してからテンプレートマッチしているので
今回の内容とはちょっと異なりますが、処理手順の参考にはなるかと。

ただし上記では、「拡大率を変えながら、もっともスコアの高かったもの」を
採用していますが、それは画像内に含まれるロゴ が 1 つだけだったから。

今回の場合、複数のアイコンがあるわけですから、最大スコアではなく
何らかの閾値で反転するよう調整する必要があるでしょう。


別案として、AKAZE なり SIFT なりで特徴点・特微量を得て比較する方法も
検討してみましたが…パラメータ調整が難しそうだったので途中で断念しました。(^^;

参考までに、アップロード頂いた画像を使ってマッチング処理したものを上げておきます。
SIFT で得た後に総当たりマッチング(BFMatcher)をかけています。
(パラメーターを殆ど弄っていないので、誤検出も多いですが)

http://www.vb-user.net/junk/replySamples/2018.08.13.01.01/wankuma88234_SIFT_Match1.png
http://www.vb-user.net/junk/replySamples/2018.08.13.01.01/wankuma88234_SIFT_Match2.png

1 つ目の方は、アイコンが 64x64 サイズ。当方環境でアイコンを .ToBitmap() したものです。
2 つ目の方は、アイコンが 48x48 サイズ。アップロード頂いたものから切り出したものです。
(前者の方は背景透過な RGBA 画像、後者は背景灰色の RGB 画像となっています)
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ