- ベストアンサー
画像の円形内による画素検出について
画像内にある円形範囲を設定し、その範囲内の画素を検出したいのですが、円形の範囲指定をするプログラムの書き方がわかりません。 c言語でプログラムを作成したいのですが、どのようなプログラムを記述したらよいのでしょうか?
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
画像処理のことはよくわかりませんが、こんなかんじでどうでしょう? [ step 1 ] まず、「円」を中心と半径で定義します。中心座標を cx, cy 、半径を r とすると、任意の点 x, y が次式を満たす場合、その点は円の内部の点であると言えます。 ((cx - x) * (cx - x) + (cy - y) * (cy - y)) < (r * r) ・・・式(1) [ step 2 ] しかし、そのままでは画素数を数えられないので、中心座標と半径から画素数を数える範囲を正方形で切り出します。具体的にはx座標は cx - r から cx + r まで、y座標も同様に cy - r から cy + r までの正方形の中で、すべての座標について上記の式(1)を満たす座標の数を数えれば画素数が求まります。 [ step 3 ] しかし、このままでは計算量が多くなってしまうので、step 2 を円の1/4で考えて、計算結果を4倍すればもっと計算量を減らせます。さらに、円の1/8で考えても同じことなので、切り出す正方形を直角三角形にして計算結果を8倍すればもっともっと計算量を減らせます。 あとはこれをソースコードに落とせば良いでしょう。 また、もっと効率的な方法がないものかと思い、全然別なアプローチも考えてみました。考え方は次の通り。 まず、1辺の長さが 2r の正方形を考えます。この正方形の面積は 4 * r * r です。続いて半径 r の円の面積は PI * r * rですから、面積比は (円の面積)/(正方形の面積)= (PI*r*r) / (4*r*r) = PI / 4 であることがわかります。この結果を使って半径 r の円内にある画素数を考えると、 (円の画素数)= PI / 4 * (正方形の画素数) ・・・式(2) で求まりますね。 すごくシンプルになりました。 そういうことじゃなくて?
その他の回答 (1)
- chie65536(@chie65535)
- ベストアンサー率44% (8740/19838)
Windowsでの最も簡単な方法。 1.画像と同一サイズのBITMAPを用意する。BITMAPは256階調のグレースケールにする 2.GDI関数のFillRectを用いてBITMAPの全面を画素値0で塗り潰す http://msdn.microsoft.com/ja-jp/library/cc428605.aspx 3.GDI関数のEllipticを用いてBITMAPに画素値255で塗り潰した円を描く http://msdn.microsoft.com/ja-jp/library/cc428585.aspx 4.作製したBITMAPの画素をスキャンする。スキャンの範囲は円の左上と右下を対角とする矩形の範囲で良い。BITMAPの矩形内に画素値255の画素があったら、同じ座標にある画像データの画素を拾う この方法の利点は、2の部分を色々と改造すると★型多角形など、複雑な形状の領域を検出できる、と言う事。 また、BITMAPで描画する際の画素値が0~255の256段階なので、画素値に重みを設け、元画像と演算する事も可能。 例えば、BITMAPに領域を描画する際にスムージング処理を施せば BITMAPの画素値が0⇒元画像のデータの0%を拾う BITMAPの画素値が64⇒元画像のデータの25%を拾う BITMAPの画素値が128⇒元画像のデータの50%を拾う BITMAPの画素値が192⇒元画像のデータの75%を拾う BITMAPの画素値が255⇒元画像のデータの100%を拾う という処理をして「輪郭をスムージングした領域のデータを拾う」と言う事も可能。 この方法は「画像のマスクを作成する」と言う、画像処理の基本テクニック。 普通は「領域の方程式を用いて、方程式で範囲の判定をする」と言う汎用性の無い方法は使用しない。
お礼
返事が遅くなってすいません。 確かにマスクを作成した方が汎用性がありますね。 とても参考になりました。
補足
ありがとうございます。すごい参考になりました。 step1,step2を簡単にプログラムを書くと ※__は空白の意味 for(j=0;j<ysize;j++){______//xsizeは画像の縦、ysizeは横の長さ __for(i=0;i<xsize;i++){____//画像の画素値全てを確認 ___if(中心座標){ ____if(((cx - x) * (cx - x) + (cy - y) * (cy - y)) < (r * r)){ ______//中心座標を中心とした正方形の範囲内の画素値を読み込み ____} ___} __} } という感じになりました。 また、もう一つの計算方法についてもプログラムを書いてみたいと思います。 ただ、[step3]についてですが、読み込んだ部分の画素値で読み込まなかった部分の画素値を補うということでしょうか?