質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
86.02%
OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2値化した画像のopencvを用いた円検出ができない(C++)

bamm
bamm

総合スコア8

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

3回答

0グッド

0クリップ

6372閲覧

投稿2020/05/26 14:38

編集2020/05/27 08:01

2値化した画像からopencvを用いた円検出をしたい

地球の画像を2値化し,円を検出するプログラムを作りたいと考えています.しかし,プログラムを実行すると,2値化まではうまくできていると思われる画像は結果として表示されるのですが,肝心の円の輪郭が抽出されていませんでした.
自分なりに解決方法を調べたのですが,解決できませんでした.どなたかお力を貸していただきたいです.よろしくお願いします.以下,使用した画像と作成したプログラムです.

イメージ説明

該当のソースコード

C++

1#include <iostream> 2#include <opencv2/opencv.hpp> 3 4using namespace std; 5 6int main(){ 7 8// 画像を格納するオブジェクトを宣言する 9 10cv::Mat src = cv::imread("earth15.jpeg", 1); 11 12if (src.empty() == true) { 13 // 画像データが読み込めなかったときは終了する 14 return 0; 15 } 16 17cv::Mat src_gray; //グレースケール画像を入れておくためのMat 18cv::Mat src_bin; //2値画像を入れておくためのMat 19cvtColor(src, src_gray, cv::COLOR_BGR2GRAY); //グレースケールに変換 20threshold(src_gray,src_bin,1,255,cv::THRESH_BINARY); //閾値1で2値画像に変換 21 22 23// Hough円変換 24 vector<cv::Vec3f> circles; 25 26 cv::HoughCircles(src_bin, circles, cv::HOUGH_GRADIENT, 1, 100, 100, 100, 500, 10000); 27 28 for (int i = 0; i < circles.size(); i++) { 29 30 circle(src_bin, cv::Point(circles[i][0], circles[i][1]), circles[i][2], cv::Scalar(0, 255,0 ), 5, cv::LINE_AA); 31 } 32 cv::imshow("Hough円変換", src_bin); 33 34 // 何かキーが押されるまで待つ 35 cv::waitKey(); 36 37 return 0; 38}

試したこと

2値化をせずに,グレースケールの画像のままだと,円を検出した実行結果が得られました.(しかし,地球の柄を検知したため,複数個円が検出されてしまいました)

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

SHOMI

2020/05/26 15:12

使用した画像も貼っていただかないと他の人は確認できませんよ

回答3

1

ベストアンサー

輪郭抽出して cv2.minEnclosingCircle() で外接する円を求めればいいのではないでしょうか

Python ですが、C++ でも OpenCV の API は同様です。

python

1import cv2 2 3 4img = cv2.imread("sample.jpg") 5 6# グレースケール化 7gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 8 9# 2値化 10ret, binary = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) 11 12# 輪郭抽出 13contours, hierarchy = cv2.findContours( 14 binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE 15) 16 17# 最大の輪郭を取得 18max_contour = max(contours, key=lambda x: cv2.contourArea(x)) 19 20# フィッティング 21(cx, cy), radius = cv2.minEnclosingCircle(max_contour) 22 23# 描画 24img = cv2.circle(img, (int(cx), int(cy)), int(radius), color=(0, 0, 255), thickness=5) 25cv2.imwrite("result.png", img)

イメージ説明

投稿2020/07/22 05:14

編集2020/07/22 05:18
tiitoi

総合スコア21935

fana👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

fana

2020/07/22 05:32 編集

本件の場合,地球の右下の影の部分等がある程度2値化で失われたとしても面倒が生じないと思われるので良いですね. For this earth image, this fitting way is the best (or very close to the best) way, I think.
tiitoi

2020/07/22 05:37 編集

コメントありがとうございます。 ハフ変換の円検出はパラメータ調整が難しいですよね。 実用的な用途で使えてる人いるのかな。。。
fana

2020/07/22 05:49 編集

「円のサイズは(かなりきちきちなレベルで)既知だけど,どこに何個あるかはわからん」みたいな状況でもないとうまく使える気がしない… (直線のハフ変換でも既に手におえない感)
pepperleaf

2020/07/22 12:26

tiitoiさん、 ハフ変換の円検出使ってますが、、ただ、調整値は、ターゲット毎に調整。 今日も動いてる筈。
tiitoi

2020/07/22 13:11

> pepperleaf さん 実務でも使えるのですね。 ハフ変換は理論としては面白いのですが、実際の画像に適用しようとすると、なかなか安定しなくて難しいなと思ってました。 コメントありがとうございます。
pepperleaf

2020/07/23 11:55

パラメータ調整は、平滑化を数種類と、ハフ変換のパラメータ調整、それに、照明の設定。2値化も設定はしたのですが、グレースケールのままの方が、結果は良いようです。対象は機器につけられているノズル位置検出。新品だとほぼ真円ですが、その内、汚れてくる。 参考として。
bamm

2020/07/26 02:57

tiitoiさん ご回答いただき,ありがとうございます. 私が今回求めたいものに対して,外接円を抽出する方法が一番理にかなっていると考えましたので,こちらのプログラムをC++へ書き換えて,実行しようと思います.

1

  1. circle(src_bin,...だと,白黒画像に黒で描画していると思われ,結果の視認性が非常に悪いものと想像されます.(何かを検出していても見えない可能性)
  2. HoughCirclesに関しては,リファレンス等を見れば,与える画像をぼかすことが推奨されている模様.試すと良いかも.
  3. HoughCirclesのパラメータをいろいろ試すべき.(私見では,この関数のパラメータは非常に調整困難です.)

特に,第4パラメータを1にしていることが,投票値がばらけてしまってうまい結果を生じない原因となりそうに思います.
この引数を適当に大きい値(3とか4とか5とか…)で処理して,HoughCirclesでは「coarseな結果」を得ることを目指すと良いかと思います.
(結果のrefinementはfitEllipse()等の別の方法を用いると良いでしょう.)

投稿2020/07/21 07:41

fana

総合スコア10681

tiitoi👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

bamm

2020/07/22 04:52

回答ありがとうございます.HoughCircleでは,パラメータの表示の調整が難しい且つ精密な検出を期待することは難しい印象を受けましたので,このアルゴリズムとは別のものも同時に検討してみようと思います.
fana

2020/07/22 05:06

回答内容は質問に提示されたコードに即したものとなっています. そもそも【処理画像が「この貼られている(ような)絵である」ということを前提知識として利用して良い,という話なのであれば】,ハフ変換を使うこと自体が違う気もします.
bamm

2020/07/26 02:50

返信が遅れてしまい,申し訳ありません. ご助言ありがとうございます. fanaさんの仰るとおり,今回私が達成したいと考えていること対して,Hough変換での検出ではなく,外接円を求めるアルゴリズムの方が今回の場合理にかなっていると考えました.ですので,そちらの方向性でプログラムを立てようと思います.

0

こんにちは.
輪郭検出findContours及び面積計算contourAreaを用いてはいかがでしょう.
最も大きい(=最大面積)のエリアに対してHough近似を行えば達成できます.

投稿2020/07/21 06:21

branch

総合スコア69

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

bamm

2020/07/22 04:46

ありがとうございます.そちらの関数を使用した方法を試行錯誤してみます.
fana

2020/07/22 04:57

「閾値1で」の二値化というのが相応にまともな(地球と,右下の文字,および極少数の細かなノイズが背景領域に残る程度の)結果を生じるのだと仮定すれば, この回答の方策は(最終的に結局Hough変換に食わせるならば)ほとんど結果に影響を与えないであろうと想像します. (どうでもよいノイズや,右下の文字が投票行動に参加しなくなることが,果たしてこの画像での結果に優位な差をもたらすであろうか?)
fana

2020/07/22 05:01

「地球相当の領域」を最初に選り分けることができるのであれば,その外周に対して円の当てはめ処理を行うのが良いのではないかと.

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
86.02%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。