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

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

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

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

C++

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

解決済

ハフ変換を用いて角度を調べたい。

tanjiiya
tanjiiya

総合スコア2

OpenCV

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

C++

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

2回答

0グッド

0クリップ

1169閲覧

投稿2022/01/17 20:11

編集2022/01/18 04:54

斜めに置いた青い物体を上からカメラで撮りながら、画像処理を用いてハフ変換をすることで角度を導きたいのですが、どのように導いたらいいかわかりません。
今現在のプログラムです。↓
// OpenCV includes
#include <iostream>
#include <opencv2/opencv.hpp>
#include<opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv/cv.h>

using namespace cv;
using namespace std;
#pragma warning(disable:4996)

int main(int argc, char** argv) {
int hr = -1;
try {
//変数の指定
cv::Mat src, edge, dst,img, gray_ocv; /OpenCVの2次元行列型Mat/
std::vectorcv::Vec4i lines; //ベクトル

//画像の読み込み
VideoCapture cap; //カメラキャプチャ
cap.open(CAP_DSHOW);
if (!cap.isOpened()) {
printf("\n\n\n\n*******************************"
"\n* カメラが接続されていない \n"
"
******************************\n\n\n\n\n\n");
return-1;
}
cap >> img;
cvtColor(img, gray_ocv, COLOR_BGR2GRAY); // グレースケールに変換
//img = cv::imread("C:\Users\13KURAN88TU\Downloads\anemone.jpg", cv::IMREAD_GRAYSCALE);//imread関数によって画像をsrcに格納。カラーで読み込むならIMREAD_UNCHANGEDを、グレースケールで読み込むIMREAD_GRAYSCALE
cv::namedWindow("img", 1);//
cv::imshow("img", img);//imgの表示。グレースケールになった後の画像を確認

//輪郭抽出
cv::Canny(img, edge, 50, 200, 3);//2値化する関数

//画像領域確保
dst = cv::Mat::zeros(img.rows, img.cols, CV_8UC3);

//img[0]->dst[2],img[0] -> dst[1], img[0] -> dst[0].コピー元とコピー先を指定
int fromTo[] = { 0,2,0,1,0,0 };

//チャンネル数?を増やしてコピー
cv::mixChannels(&img, 1, &dst, 1, fromTo, 3);

//線分検出
cv::HoughLinesP(
edge, // 8ビット,シングルチャンネル2値入力画像.
lines, //出力先、ベクトル
1, //距離分解能、ピクセル
CV_PI / 180.0, //角度分解能、ラジアン
80, //しきい値。この値を超えている直線が出力される
30, //最小の線分長さ。たぶんピクセル
10 //2点が同一線分上にあると見なす場合に許容される最大距離。ピクセル。
);

//線分描画
for (auto line : lines) {
cv::line(dst, cv::Point(line[0], line[1]), cv::Point(line[2], line[3]), cv::Scalar(0, 0, 255), 1);//線の色と太さを指定(B,G,R,太さ)
}

cv::namedWindow("dst", 1);
cv::imshow("dst", dst);
cv::waitKey(0);
hr = 0;
}
catch (cv::Exception ex) {
std::cout << ex.err << std::endl;
}
//ウインドウの破棄
cv::destroyAllWindows();

return hr;
}

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

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

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

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

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

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

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

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

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

tanjiiya

2022/01/18 00:06

ちなみに、Pythonはいれていません。
tanjiiya

2022/01/18 00:40

あと、この物体をベルトコンベアで動かした状態にした場合でも、同じような手順で行うことは可能ですか?
fana

2022/01/18 01:21 編集

質問内容が不明瞭すぎます. 実際のところ何に困っているのか? そもそも何故「ハフ変換で」という話になっているのか? そこらへんの説明はできないのでしょうか? (ハフ変換は「角度」を得たい際の方法としては得策とも思えないのですが.)
tanjiiya

2022/01/18 02:01

すいません、自分の理解もまだまだなため、質問内容も不明瞭になってしまいました。 ハフ変換を用いた理由は、openCVを用いて水平面を水平に動く傾きのある対象物に対して直線を検出したいと考えたからです。 その上で、その線が水平線からどのくらい傾いているかを調べることで角度を出せるのではと考えたからなのですが、プログラムの書き方の手順がどうすればいいのかわからなかったのです。
yominet

2022/01/18 03:05

あなたがすでに作成されているであろうプログラムコードや、対象としている画像を提示してください。 ♯お仕事などであれば、公開できる範囲は気を付ける必要ありますが
tanjiiya

2022/01/18 04:39

今現在のプログラムです。↓ // OpenCV includes #include <iostream> #include <opencv2/opencv.hpp> #include<opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv/cv.h> using namespace cv; using namespace std; #pragma warning(disable:4996) int main(int argc, char** argv) { int hr = -1; try { //変数の指定 cv::Mat src, edge, dst,img, gray_ocv; /*OpenCVの2次元行列型Mat*/ std::vector<cv::Vec4i> lines; //?たぶんベクトル //画像の読み込み VideoCapture cap; //カメラキャプチャ cap.open(CAP_DSHOW); if (!cap.isOpened()) { printf("\n\n\n\n*******************************" "\n* カメラが接続されていない *\n" "*******************************\n\n\n\n\n\n"); return-1; } cap >> img; cvtColor(img, gray_ocv, COLOR_BGR2GRAY); // グレースケールに変換 //img = cv::imread("C:\\Users\\13KURAN88TU\\Downloads\\anemone.jpg", cv::IMREAD_GRAYSCALE);//imread関数によって画像をsrcに格納。カラーで読み込むならIMREAD_UNCHANGEDを、グレースケールで読み込むならIMREAD_GRAYSCALE cv::namedWindow("img", 1);// cv::imshow("img", img);//imgの表示。グレースケールになった後の画像を確認 //輪郭抽出 cv::Canny(img, edge, 50, 200, 3);//2値化する関数 //画像領域確保 dst = cv::Mat::zeros(img.rows, img.cols, CV_8UC3); //img[0]->dst[2],img[0] -> dst[1], img[0] -> dst[0].コピー元とコピー先を指定 int fromTo[] = { 0,2,0,1,0,0 }; //チャンネル数?を増やしてコピー cv::mixChannels(&img, 1, &dst, 1, fromTo, 3); //線分検出 cv::HoughLinesP( edge, // 8ビット,シングルチャンネル2値入力画像.この画像は関数により書き換えられる可能性がある. lines, //出力先、ベクトル 1, //距離分解能、ピクセル CV_PI / 180.0, //角度分解能、ラジアン 80, //しきい値。この値を超えている直線が出力される 30, //最小の線分長さ。たぶんピクセル 10 //2点が同一線分上にあると見なす場合に許容される最大距離。たぶんピクセル。 ); //線分描画 for (auto line : lines) { cv::line(dst, cv::Point(line[0], line[1]), cv::Point(line[2], line[3]), cv::Scalar(0, 0, 255), 1);//線の色と太さを指定(B,G,R,太さ) } cv::namedWindow("dst", 1); cv::imshow("dst", dst); cv::waitKey(0); hr = 0; } catch (cv::Exception ex) { std::cout << ex.err << std::endl; } //ウインドウの破棄 cv::destroyAllWindows(); return hr; }
tanjiiya

2022/01/18 04:41

今現在だと、外部のカメラを取得させることはできているのですが、青色の物に反応させることができていません。
fana

2022/01/18 04:44

(この欄じゃなくて,質問文に追記する形にすると良いかと)
fana

2022/01/18 05:13

既存回答に書かれている単語を用いて 例えば「OpenCV HSV inRange」とかでググれば「特定の色の範囲を狙って抽出する処理」の例を見つけることができるのではないでしょうか.

回答2

1

ベストアンサー

  1. プログラムからカメラを使えるようにする。Pythonならcv2.VideoCapture()
  2. カメラからカラー画像を取得する。
  3. カラー画像をRGBからHSVにする。理由は「青」の定義を柔軟にするため。
  4. HSVから「青」の範囲を抽出する。Pythonならcv2.inRange()
  5. [オプション] 線が揺らいでいるようなら適当に処理する。例えばPythonなら cv2.morphologyEx()でブレをつぶしたり、scikit imageのskeletonizeで線の骨格を抽出してからHough検出しやすいように線を太らせる
  6. 二値化された「青」の範囲に対してhough検出をする。Pythonならcv2.HoughLines()かcv2.HoughLinesP()
  7. 検出された線の特性が上のステップで出るので、あとは2つの直線の傾きから角度を計算する。ここから先はプログラムというより高校の数学の話。

投稿2022/01/17 21:26

編集2022/01/17 21:27
fourteenlength

総合スコア2734

tanjiiya👍を押しています

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

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

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

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

回答へのコメント

fana

2022/01/18 01:13

> あとは2つの直線の傾きから角度を計算する 「2つの直線」とは何なのでしょうか? (「青い物体」としか述べられていない:形状も何もかも不明 な状況において,まるで対象物体の形状やテクスチャといった話の前提を知っているかのような…?)
tanjiiya

2022/01/18 01:33

すいません、そこは補足します。物体は、縦・横・奥行きの順に、20mm,40mm,20mmで想定しています。この物体をベルトコンベアのようなまっすぐに動いてる状態にして、物体が水平線からどのくらい傾きがあるのかということを調べたいのです
fana

2022/01/18 02:10

物体は直方体であって,上方から観測すると,20*40 の上面しか見えず(:物体の側面は映らない),物体像は常に長方形である ……という状態なのでしょうか.
fana

2022/01/18 02:23 編集

そうであって,且つ,その直方体の領域が(この回答の 3.~4. みたいな処理とかで)安定的に得られるならば… Coarseな角度値を求める方法としてはハフ変換でなくとも ・慣性主軸を求めるとか ・OpenCV なら minAreaRect を使うとか で十分かもしれない.
tanjiiya

2022/01/18 02:25

fanaさんが想像してる状態で合ってます。慣性主軸については、全然思いつきませんでした。なので勉強してきます。プログラムの書き方や、気をつけるポイントなどのアドバイスがあれば嬉しいです。
tanjiiya

2022/01/18 02:28

あと、角度が知りたい理由は、その後にアームで掴みたいと考えているためです。
tanjiiya

2022/01/18 02:32

あともう一つ、「OpenCV なら minAreaRect を使う」方法についてもあるのですが、自分は「OpenCVで画像から回転矩形領域を切り出す」といったイメージを持っていたのですが、どうすれば角度値まで求められるかアドバイスはもらえますか?
fana

2022/01/18 02:52

とりあえず OpenCV の minAreaRect という関数について調べて(ググって)ください. 指定領域の外接矩形を求めてくれる関数です. 領域形状が傾いた長方形だとすれば,それに見合う傾いた矩形が求められます(処理結果に「角度」が含まれている).
fana

2022/01/18 03:10 編集

> プログラムの書き方や、気をつけるポイントなど 「プログラムの書き方」というか,まずはやることを実際にやってみてはどうか. 「ハフ変換」を使おうと考えていた時点で「物体領域の外周を得られる」という見込みがあるハズ. ならばまずはそこまでを実際にやってみるべき. あと,角度推定の目的が「アームで掴む」ならば,どの程度の推定精度が必要になるのか? も実験なりして把握しておくべき. 例えば「数度くらいは誤差があっても余裕で掴める」なら,角度推定処理はかなり簡単な方法で良いかもしれない. (領域が長方形だという前提を利用できるなら,極端な話,【領域の重心を求めて→その重心に最も近い外周上の点を探す】とかでも角度の荒い推定になり得るわけで,そんな処理の結果でも十分だとしたら「ハフ変換」とか考える必要すらなくなる)
fana

2022/01/18 04:42 編集

ベストアンサーになっちゃったけども,そもそものこの回答における「2つの直線」とは何だったのだろう? 【その2つを用いて(高校レベルの話で)角度を計算する】という話はどんな内容だったのか? 仮に,「直線=長方形の辺」だとしても,「2つの直線」の選び方には「2本の長い辺」,「長いのと短いの1本ずつ」,「短いの2本」,… とパターンがあるし… 「2つの直線」から1つの角度を算出する方法論は(例えば,「単純にそれぞれの直線から求めた角度を平均する」とか何とか,何かしらの具体的な話が無いと)不明瞭に思える. (少なくとも単純な平均をとることを指して「高校の数学」とは言わないだろうから別の話なのだと思うのだけども)
tanjiiya

2022/01/18 04:58

自分もその部分については、曖昧で一度計算してみて模索してみようと考えています。 ただ、動体で座標が変わってしまうため、計算をプログラムに書くことができるのかについては厳しいと感じます。
fourteenlength

2022/01/18 10:01

> 「2つの直線」 二つのーーは私の理解ミスです。青い線が二つの書き方をしてました。 写真がないので細かいことは分かりませんが、実際には青い線は一本でどこかの基準点との比較ですよね、たぶん。hough検出で傾きが出るので、あとは基準点から垂直なのか水平なのか線を伸ばしてその線とhough検出で出た線との2つの傾き同士を使って(以下略)くらいに考えていました。
tanjiiya

2022/01/18 16:05

MInAreaRectについて調べているのですが、Python用ばかりのため、プログラムをどのように書けば良いのか分かりません。参考に出来るサイトがあれば教えてほしいです。

0

C++は全く分かりませんが、以下のサイトはPython版とC++版とで違いを比較している上に、C++のコードもあるので何か参考になるかもしれません。
https://answers.opencv.org/question/224100/difference-in-output-of-minarearect-in-python-and-c/

以下は困った時のリファレンス(Pythonではなく本家のOpenCVのC++のリファレンス)です。
※日本語版ですが欲しい情報があるかまではわかりかねます。
http://opencv.jp/opencv-2svn/cpp/structural_analysis_and_shape_descriptors.html#cv-minarearect

投稿2022/01/19 12:59

fourteenlength

総合スコア2734

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

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

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

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

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

ただいまの回答率
86.12%

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

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

質問する

関連した質問

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

OpenCV

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

C++

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