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

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

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

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

OpenCV

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

C++

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

Q&A

解決済

1回答

1934閲覧

カメラからの円検出のプログラムと重心を求めるプログラムを合体させたいです。

carnage0216

総合スコア194

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

OpenCV

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

C++

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

0グッド

0クリップ

投稿2018/06/12 14:34

編集2018/06/18 12:13

<環境>

  • Windows10 64bit
  • visual studio 2017
  • opencv 3.4.1

カメラからの円検出のプログラムと重心を求めるプログラムを合体させたいです。
ここで問題があるのですが、カメラからの映像をMat img = imread("sample.jpg", IMREAD_GRAYSCALE);で画像として取り出しグレースケール化してから重心を求めるプログラムのようにすればいいのでしょうか?
その方法で行うとしたらまずどのフォーマットで画像を取得するかを考えないとだめですね。

手順としてはカメラから円を検出して赤色で囲う、検出された円を画像として置き換え、重心を求める。
ただカメラからの映像から円の画像を作る?関数はopencvにあるでしょうか?

まず一つ目のプログラムはepistemeさんから頂いた重心を画像から求めるプログラム。

#include "opencv2/opencv.hpp" int main(){ using namespace cv; Mat img = imread("sample.jpg", IMREAD_GRAYSCALE); // unsigned char* img.data : 画像データの先頭 // int img.rows : 幅(pixel) // int img.cols : 高さ(pixel) // size_t img.step : 一行のbyte数 int count = 0; float x_g = 0.0f; float y_g = 0.0f; for ( int y = 0; y < img.rows; y++ ) { for ( int x = 0; x < img.cols; x++ ) { if ( img.data[y*img.step + x] == 255 ) { count++; x_g += x; y_g += y; } } } Point2f mc = Point2f( x_g/count, y_g/count); circle( img, mc, 4, Scalar(100), 2, 4); imshow("img",img); waitKey(0); }

二つ目は過去に作ったカメラの映像からハフ変換を利用して円を検出するプログラム。

#include <stdio.h> #include <opencv/cv.h> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgcodecs/imgcodecs.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <opencv2/core/core.hpp> using namespace cv; int main(int argc, char* argv[]) { int i; float *p; double w = 320, h = 240; IplImage *src_img = 0, *gray_img = 0; CvMemStorage *storage; CvSeq *circles = 0; CvCapture *capture = 0; /* この設定は,利用するカメラに依存する */ capture = cvCreateCameraCapture(0); // (2)キャプチャサイズを設定する. cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, w); cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, h); cvNamedWindow("circles", CV_WINDOW_AUTOSIZE); while (1) { src_img = cvQueryFrame(capture); CvSize sizeOfImage = cvGetSize(src_img); //IplImage *gray_img = cvCreateImage(cvGetSize(src_img), IPL_DEPTH_8U, 1); gray_img = cvCreateImage(cvGetSize(src_img), IPL_DEPTH_8U, 1); // グレイスケールに変換 cvCvtColor(src_img, gray_img, CV_BGR2GRAY); //src_img_gray = cvQueryFrame (capture); // (2)ハフ変換のための前処理(画像の平滑化を行なわないと誤検出が発生しやすい) cvSmooth(gray_img, gray_img, CV_GAUSSIAN, 11, 11, 0, 0); storage = cvCreateMemStorage(0); // (3)ハフ変換による円の検出と検出した円の描画 circles = cvHoughCircles(gray_img, storage, CV_HOUGH_GRADIENT, 1, 100, 20, 50, 10, MAX(gray_img->width, gray_img->height)); for (i = 0; i < circles->total; i++) { p = (float *)cvGetSeqElem(circles, i); cvCircle(src_img, cvPoint(cvRound(p[0]), cvRound(p[1])), 3, CV_RGB(0, 255, 0), -1, 8, 0); cvCircle(src_img, cvPoint(cvRound(p[0]), cvRound(p[1])), cvRound(p[2]), CV_RGB(255, 0, 0), 3, 8, 0); } //↓この先に重心を求めるプログラムをぶち込む? int count = 0; double x_g = 0.0, y_g = 0.0; for (int y = 0; y < gray_img->width; y++) { for (int x = 0; x < gray_img->height; x++) { if (img.at<unsigned char>(y, x) == 255) { //img.atの扱う画素が何バイトかわからないためunsigned charを定義することで、unsigned chaによりimg.atの扱う画素が入るメモリが確保できた。 count++; x_g += x; y_g += y; } } } x_g /= count; y_g /= count; Point2f mc = Point2f(x_g, y_g); // (4)検出結果表示用のウィンドウを確保し表示する cvShowImage("circles", src_img); cvWaitKey(10); } cvDestroyWindow("circles"); cvReleaseImage(&src_img); cvReleaseImage(&gray_img); cvReleaseMemStorage(&storage); return 0; }

<編集6/17>質問の編集までに時間がかかりすいませんでした。
自身で解決できないか試行錯誤したのですがうまくいかず途方に暮れていました。
合体とは載せた二つのプログラム、「重心を画像から求めるプログラム」と「カメラの映像からハフ変換を利用して円を検出するプログラム」を組み合わせて、「カメラの映像からハフ変換を利用して円を検出した後、検出した円から重心を求めて、その重心の部分に赤い点を描画するプログラムを作る」ことを言っていました。
説明不足で本当にすいません。

お願い事のようになってしまい申し訳ないのですが、

今回の解決すべき問題点は円を検出するのに働く以下の部分、

circles = cvHoughCircles(gray_img, storage, CV_HOUGH_GRADIENT, 1, 100, 20, 50, 10, MAX(gray_img->width, gray_img->height));

から検出した円の面積というか画素の塊の情報を

int count = 0; float x_g = 0.0f; float y_g = 0.0f; for ( int y = 0; y < img.rows; y++ ) { for ( int x = 0; x < img.cols; x++ ) { if ( img.data[y*img.step + x] == 255 ) { count++; x_g += x; y_g += y; } } } Point2f mc = Point2f( x_g/count, y_g/count);

に入力して重心を求められるのではないかと考えているのですが、解決法はわかるのですが、書き方がわかりません。
どのように「書き方」を調べればいいのでしょうか?
いつも皆様に解決してもらっているばかりで自分ではなにもできていません。というよりうまく学習できていません。

ペットボトルの蓋を円と認識させて中心の点を緑色としてみました。
イメージ説明

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

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

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

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

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

can110

2018/06/12 14:56

「重心」とは何でしょうか?(円の中心でしょうか?)
carnage0216

2018/06/12 15:03

はい。円の中心です。
can110

2018/06/12 15:06

では「円検出のプログラム」で円が分かるのですから中心も分かるのでは?
ippei

2018/06/12 23:40

OpenCV的にやるならfindContoursで円の輪郭を得て、moments関数を使えば重心が求められます。OpenCV 輪郭、OpenCV 重心で検索すればサンプルは多数見つかります。
episteme

2018/06/13 11:35

”合体”を説明せよ。そのふたつを合体したプログラムは何をする? 自分にしかわからん質問をしてはならない。やりなおし。
carnage0216

2018/06/13 11:38

すいません。出直してきます。この質問は一旦、保留にさせていただきます。編集します。
carnage0216

2018/06/17 13:29

編集させていただきました。
guest

回答1

0

ベストアンサー

Hough変換によって検出した円の中心と半径を基に、
黒地に白い円盤を描けばいいよね。

僕はやらない。求めたところで中心と一致するから求める意味がない。

[追記] とか言いつつやってみた、無問題。

!

投稿2018/06/17 14:58

編集2018/06/18 10:09
episteme

総合スコア16614

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

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

carnage0216

2018/06/17 16:36

どうもありがとうございます。 >>Hough変換によって検出した円の中心と半径を基に、 黒地に白い円盤を描けばいいよね。 以上の方法を使わせていただきます。
episteme

2018/06/18 12:00

気になってんですけどね、"試行錯誤"ってなにやってたん? 僕は「黒地に白丸」しか思いつかんかった。
carnage0216

2018/06/18 12:12

載せたプログラムの関数を調べて使い方があっているかの確認をしていました。他に、検出した円の重心を求めるプログラムを組み込もうと試行錯誤していました。しかし、よくよく考えたら重心ではないですが、「中心」を求めるプログラムが既にあったので円の画像から重心を求めるプログラムを組み込む必要がありませんでした。 ちなみに、”試行錯誤”と書きましたが、今思うと価値のある試行錯誤ではありませんでした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問