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

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

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

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

963閲覧

対象の物体の輪郭を半分だけ検出したい

退会済みユーザー

退会済みユーザー

総合スコア0

OpenCV

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/08/31 15:39

編集2021/09/01 06:31

opencvのcv2.findContours()を利用し、マスク画像を通して対象の輪郭線を抽出することには成功したのですが、対象の輪郭線を半分だけ検出したい場合はどのような方法があるのでしょうか?
なかなか実践している人がいらっしゃらないので質問させていただきます。
イメージでは下図のようなものです。
イメージ説明

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fana

2021/09/01 01:07

全体的に話が不明瞭です. 対象の輪郭線を「全部」抽出できるのであれば,単に好きなように「半分だけ」を用いればよいのではないでしょうか.
guest

回答2

0

ベストアンサー

の輪郭線を半分だけ

の意味合いが不明瞭ですが,「輪郭線の全長の半分」という話であれば,

  1. 輪郭の座標を(普通に)全部検出し,
  2. 検出した座標データを半分だけ使う(不要なら「半分捨てる」)

とすれば良いのではないでしょうか.

半分というのが「どこから」「どこまで」の範囲なのかは知りませんが,とにかく必要な箇所を使って不要な箇所を使わなければよいでしょう.
「単純に,findContours が返してきた結果(輪郭の座標群)の後半を捨てる」としたコードを示します.(C++ですが)

C++

1int main() 2{ 3 cv::Mat SrcImg = cv::imread( "Regions.png", cv::IMREAD_GRAYSCALE ); //画像読込 4 if( SrcImg.empty() )return 0; //読込失敗チェック 5 cv::threshold( SrcImg, SrcImg, 128, 255, cv::THRESH_BINARY ); //2値化 6 7 //ふつーにcontour検出 8 std::vector< std::vector< cv::Point > > contours; 9 cv::findContours( SrcImg, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE ); 10 11 //表示用画像バッファを用意 12 cv::Mat ShowImg; 13 cv::cvtColor( SrcImg, ShowImg, cv::COLOR_GRAY2BGR ); 14 ShowImg *= 0.25; 15 16 //contour検出結果をまずはふつーに赤で描画 17 cv::drawContours( ShowImg, contours, -1, cv::Scalar(0,0,255), 2 ); 18 19 //輪郭データを半分だけにして,シアンで描画 20 for( auto &cont : contours ){ cont.resize( cont.size() / 2 ); } //※各輪郭のデータを半分捨てる 21 cv::polylines( ShowImg, contours, false, cv::Scalar(255,255,0), 2 ); 22 23 // 24 cv::imshow( "ShowImg", ShowImg ); 25 if( cv::waitKey() == 's' ){ cv::imwrite( "Regions_result.png", ShowImg ); } 26 return 0; 27}

処理結果例:

  • 用いた入力画像

入力

  • 処理結果画像

(輪郭の半分を赤,もう半分をシアンで描画している)
イメージ説明

投稿2021/09/03 02:10

fana

総合スコア11996

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

あってますか?わからないことは英語で探すと大体見つかります。

Python3

1import cv2 2import numpy as np 3 4img_gray= cv2.cvtColor(cv2.imread("./tri.png"),cv2.COLOR_BGR2GRAY) 5 6 7ret, thresh = cv2.threshold(img_gray,127,255,0) 8cv2.imshow("thresh",thresh) 9 10cnts, _ = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE) 11 12img_mask = np.zeros_like(img_gray) 13img_mask = cv2.drawContours(img_mask, cnts, 1, 255,5) 14 15cv2.imshow("img_mask",img_mask) 16 17out = img_mask.copy() 18out_half = img_mask.copy() 19# https://stackoverflow.com/questions/28759253/how-to-crop-the-internal-area-of-a-contour 20(y, x) = np.where(img_mask == 255) 21(topy, topx) = (np.min(y), np.min(x)) 22(bottomy, bottomx) = (np.max(y), np.max(x)) 23out = out[topy:bottomy+1, topx:bottomx+1] 24 25out_half = out_half[topy:bottomy+1, int(topx/2):int(bottomx/2)+1] 26cv2.imshow("out",out) 27 28 29cv2.imshow("out_half",out_half) 30cv2.imwrite("out_half.png",out_half) 31 32cv2.waitKey(0)

投稿2021/09/01 21:51

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fana

2021/09/02 01:42

> あってますか? と問うならば,せめて 「輪郭線を半分だけ検出したい」とかいうぼんやりとした質問文を 「どのような結果を目的とする話なのだと捉えたのか」に関しては述べねばならないのではないでしょうか. (処理内容に関してはコードを解読しろ,というスタンスだとしても)
fana

2021/09/02 01:47

単にROIを左右に真っ二つにしただけに見えるのですが, 領域形状が △ ではなく ⊿ みたいな場合でも,「輪郭線を半分」と言える結果が得られるものでしょうか? (他にも ヨ みたいな形のときだとか)
退会済みユーザー

退会済みユーザー

2021/09/02 21:52 編集

> 単にROIを左右に真っ二つにしただけに見えるのですが, 領域形状が △ ではなく ⊿ みたいな場合でも,「輪郭線を半分」と言える結果が得られるものでしょうか? > (他にも ヨ みたいな形のときだとか) 処理内容はまさに真っ二つにしただけで、「一番左と一番右の座標を調べて、絵に掲載された通り真っ二つに分断した処理」になっています。輪郭線の長さを見て云々等はしていませんので、"ヨ"であれば"≡"とよ"ヨ"のようになります。 質問した方の絵をなるべく再現する形でプログラムに起こし、質問した方が期待する(と私が思う)結果ができますよ、と計算結果を図示しました。 私の理解では、質問した方の説明文をと絵を見て、質問文の"イメージ"から「△の輪郭の左半分(なのか右半分)を検出したい」というように読み取りました。「全体の輪郭線の長さを見て半分なのか面積を見て半分」なのか、「他の何をもって半分」なのか、もしかしたらいろいろあるかもしれませんが、私にはそこまで深い意図をこの絵から私は読み取れませんでした。 と、ここまでで―-パッと見て左右に半分以上に割りたい以外の意図を読み取れませんでしたし、気にもしていませんでした。質問の内容から私が勝手にそう思っているだけの話で、実はやりたいことが違うかもしれない、と思ってきました。 というのも、話の感じからfanaさんは、私よりもいろいろな人の意見を聞いてきて、「もう既にプログラムに起こしてしまったよ。そんなことなら初めからもっと詳しく条件を教えてくれればよかったのに、無駄骨だったか――」というようなプログラムとは別の実務経験で鍛えられてきたような厚み(?)が感じられたためです。
fana

2021/09/03 01:08

1つ目のコメント(2021/09/02 10:42 )の意図は, 単に唐突に「あっているか?」とだけ書かれると判断に困る(判断するためにはコードを完全解読せねばならない)であろうから, 「x座標を基準にして左右方向に関して真っ二つにする という話であれば,こうすればできるが,そんな話であっているか?」 みたいな形で,何を示しているのかを明確に(コードとは別に)述べる方が望ましいのではないか,というだけの話です. --- 2つ目のコメント(2021/09/02 10:47 )の方は,実際に私がコードを見てみたらこんな内容だと思われた,という話ですね. 「ROIを左右に真っ二つ」とかいう語があるだけで,質問者がコードを見る際のヒントになり得るかな,と. (で,ついでに,判断基準や懸念点(?)になりそうな話を示しておいた感じです.)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問