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

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

ただいまの
回答率

90.84%

  • C

    3350questions

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

  • C++

    3142questions

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

  • OpenCV

    931questions

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

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

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 460

carnage0216

score 105

<環境>

  • 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);


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

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

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

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

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • carnage0216

    2018/06/13 20:38

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

    キャンセル

  • carnage0216

    2018/06/17 22:29

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

    キャンセル

  • 退会済みユーザー

    2018/06/18 08:47

    複数のユーザーから「やってほしいことだけを記載した丸投げの質問」という意見がありました
    「質問を編集する」ボタンから編集を行い、調査したこと・試したことを記入していただくと、回答が得られやすくなります。

回答 1

checkベストアンサー

+2

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

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

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

!

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

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

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

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/06/18 01:36

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

    キャンセル

  • 2018/06/18 21:00

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

    キャンセル

  • 2018/06/18 21:12

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

    ちなみに、”試行錯誤”と書きましたが、今思うと価値のある試行錯誤ではありませんでした。

    キャンセル

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

  • ただいまの回答率 90.84%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 受付中

    OpenCVで動画の読み込みがうまくできません。

    以前別のプログラムで動画の読み込みができましたが、今現在取り組んでいるプログラムではうまくいきません。 言語はC++でopencv2.4.9を使用しています。 Os windo

  • 受付中

    OpenCVで動画の読み込みがうまくできません。

    以前別のプログラムで動画の読み込みができましたが、今現在取り組んでいるプログラムではうまくいきません。   言語はC++を使用しています。  ・ソースコード  ヘッダファ

  • 解決済

    カメラ画像の一時停止 再開

    OpenCVでカメラ画像を取得させたものに、キーのボタンを押したときに一時停止となり、その画像を画像処理し、また違うキーのボタンを押したときに画像取得が始まるようにすることは可能で

  • 解決済

    opencv 動画 再生

    #include <stdio.h> #include <cv.h> #include <highgui.h> int main(int argc, char* argv[])

  • 解決済

    OpenCvSharp3で重心を求めたいです

    以下のように、ラベリングを実行するプログラムはできたのですが、ここから重心の座標や面積を求めるプログラムを作成したいです。どなたか、教えていただけますか? 最終的な目標としては

  • 解決済

    OpenCVを使った笑顔検出での問題

    前提・実現したいこと OpenCVで元からあるサンプルコード「smiledetect.cpp」を用いて笑顔検出のシステムを作っています。 検出機能を実装中に以下の問題が発生しました

  • 受付中

    pythonで物体検出&ピクセル座標の取得

    python3.5,OpenCV3.3を使っているプログラミング初心者です。 いつもお世話になっております。 今回、画像から「赤色の物体」を検知し、検知した箇所のピクセルを

  • 受付中

    opencvで画像の切り抜き

    添付のようなアパレルの画像から輪郭を抽出、切り抜きを実現したいのですが、 経験が少ないため、どのようにアプローチすべきか悩んでします。 下記サイトを参考にプロセスを考えま

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

  • C

    3350questions

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

  • C++

    3142questions

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

  • OpenCV

    931questions

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