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

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

ただいまの
回答率

90.34%

  • C

    3983questions

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

  • C++

    3764questions

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

  • OpenCV

    1231questions

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

opencvの重心を求めるプログラムにopencvの関数ではない重心を求めるプログラムを入れたいです。

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,787

carnage0216

score 124

<実行した環境>

  • Windows10 64bit
  • visual studio 2017
  • opencv 3.4.1

opencvの重心を求めるプログラムにopencvの関数ではない重心を求めるプログラムを入れたいです。
ただ質問するだけではただの投げやりなどと言われて嫌な気分になるので私なりに調べてきました。

#include <stdio.h>
#include "opencv/cv.h"
#include "opencv/highgui.h"
using namespace cv;

int main(){

    Mat img = imread("sample.jpg", IMREAD_GRAYSCALE);

    Moments mu = moments( img, false );
    Point2f mc = Point2f( mu.m10/mu.m00 , mu.m01/mu.m00 );
    circle( img, mc, 4, Scalar(100), 2, 4);

    printf("x: %f  y: %f", mc.x, mc.y);

    imshow("img",img);
    waitKey(0);
    return 0;
}


以上のプログラムのmu.m10/mu.m00 , mu.m01/mu.m00の部分が重心を求める計算式であるとわかったので
この部分を以下の重心を求めるプログラムに置き換えたいのですが問題があります。

int count=0;
double x_g=0.0,y_g=0.0,x_d=0.0,y_d=0.0,xy_d=0.0
for(int y=0; y<height; y++){
for(int x=0;x<width; x++){
if(img_src[y*width+x] == 255){
count++;
x_g +=x;
y_g +=y;
}
}
}
x_g /=conut;
y_g/=count;

まず一つにMoments muのmuとPoint2f mcのmcが何を表しているか調べたのですがわかりませんでした。
また、Point2f( mu.m10/mu.m00 , mu.m01/mu.m00 ); と circle( img, mc, 4, Scalar(100), 2, 4);にmu、mcが入っていることからただ計算式を置き換えるだけでは意味がないと考えています。
しかし、どうやってmuとmcを考慮しながら計算式を置き換えてよいかわかりません。
どうか助言を頂けないでしょうか?
どうかよろしくお願いいたします。

<編集>
関数Point2fの使い方を調べようと本家の方で検索したのですが、例題としてPoint2f a(0.3f, 0.f), b(0.f, 0.4f);となり少なくともaとbの座標を二次元で表していることはわかるのですが、mcがなにを言っているのかわかりません。
調べたサイトはhttp://opencv.jp/opencv-2.1/cpp/basic_structures.htmlです。
できれば使い方のわからない関数がそのままの形で載っていればいいのですが、そうでない今回のような場合どのように調べればよいか教えていただけないでしょうか?

調べたサイトのようにPoint2f( m10/m00 , m01/m00 );と素直に座標だけ表せてくれればいいのですがなぜかmuが入ってPoint2f( mu.m10/mu.m00 , mu.m01/mu.m00 );となるので、どうやって座標のmuを考慮しながら計算のプログラムを入れるか悩みます。
多分muはPoint2f()より引数だと思うのですが、muが何を表しているのかわからず困り果てています。

編集6/10
<実行した環境>

  • Windows10 64bit
  • visual studio 2017
  • opencv 3.4.1

ベストアンサー後に申し訳ありません。asm様からのプログラムを読んで学習のために自分なりにプログラムを作りました。

以下のプログラムをVS2017でビルドしたところエラーが出ました。

#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() {

    Mat img = imread("sample.jpg", IMREAD_GRAYSCALE);

    int count = 0;
    int conut = 0;
    double x_g = 0.0, y_g = 0.0;
        for (int y = 0; y<height; y++) {
            for (int x = 0; x<width; x++) {
                if (img_src[y*width + x] == 255) {
                    count++;
                    x_g += x;
                    y_g += y;
                }
            }
        }
        int a;
        int b;
     a= x_g / conut;
     b= y_g / conut;

    Point2f mc = Point2f(a, b);//x_g / conutとy_g / conutをaとbと置いた。
    circle(img, mc, 4, Scalar(100), 2, 4);

    printf("x: %f  y: %f", mc.x, mc.y);

    imshow("img", img);
    waitKey(0);
    return 0;
}

こちらがエラーなのですが

1>------ ビルド開始: プロジェクト: Project18, 構成: Release x64 ------
1>Source.cpp
1>c:\users\daito\source\repos\project18\project18\source.cpp(16): error C2065: 'height': 定義されていない識別子です。
1>c:\users\daito\source\repos\project18\project18\source.cpp(17): error C2065: 'width': 定義されていない識別子です。
1>c:\users\daito\source\repos\project18\project18\source.cpp(18): error C2065: 'img_src': 定義されていない識別子です。
1>c:\users\daito\source\repos\project18\project18\source.cpp(18): error C2065: 'width': 定義されていない識別子です。
1>c:\users\daito\source\repos\project18\project18\source.cpp(30): warning C4244: '引数': 'double' から 'float' への変換です。データが失われる可能性があります。
1>プロジェクト "Project18.vcxproj" のビルドが終了しました -- 失敗。
========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ==========


インクルードしたヘッダファイルにheight、width、img_srcの定義は書いてあると思ったのですが、エラーが出るということは必要なヘッダファイルが入っていないのだと思います。
変数height、widthと関数img_srcの定義が書いてあるgithubはないでしょうか?
ヘッダファイルでも構いません。
どうかよろしくお願いいたします。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

回答 4

checkベストアンサー

+3

回答依頼来たので駄文ながら

調べたサイトのようにPoint2f( m10/m00 , m01/m00 );と素直に座標だけ表せてくれればいいのですがなぜかmuが入ってPoint2f( mu.m10/mu.m00 , mu.m01/mu.m00 );となるので、どうやって座標のmuを考慮しながら計算のプログラムを入れるか悩みます。

もしかして、C言語の構造体をご存知ないのでしょうか?

くっつけるだけならば単純に

#include <stdio.h>
#include "opencv/cv.h"
#include "opencv/highgui.h"
using namespace cv;

int main(){

    Mat img = imread("sample.jpg", IMREAD_GRAYSCALE);

    int count=0;
    double x_g=0.0,y_g=0.0;
    for(int y = 0 ; y < img.rows; y++){
        for(int x = 0 ; x < img.cols; x++){
            if(img.at<uchar>( y, x ) == 255){
                count++;
                x_g += x;
                y_g += y;
            }
        }
    }
    x_g /= conut;
    y_g /= count;

    Point2f mc = Point2f( x_g, y_g);

    circle( img, mc, 4, Scalar(100), 2, 4);

    printf("x: %f  y: %f", mc.x, mc.y);

    imshow("img",img);
    waitKey(0);
    return 0;
}

とするだけですよ
修正: 指摘を受け、img.at( y, x )をimg.at<uchar>( y, x )に変更


追記
Mat1b つまり Mat_<uchar>を使うと

#include <stdio.h>
#include "opencv/cv.h"
#include "opencv/highgui.h"
using namespace cv;

int main(){
    Mat1b img = imread("sample.jpg", IMREAD_GRAYSCALE);
    int count=0;
    double x_g=0.0,y_g=0.0;
    for(int y = 0, height = img.rows; y < height; y++){
        // パフォーマンス的には↓3行を置き換えた方が速い
        // const uchar *_img = img[y];
        // for(int x = 0, width = img.cols ; x < width; x++){ //変化なし
        //     if(_img[x] == 255){
        for(int x = 0, width = img.cols ; x < width; x++){
            if(img( y, x ) == 255){
                count++;
                x_g += x;
                y_g += y;
            }
        }
    }
    x_g /= conut;
    y_g /= count;

    Point2f mc = Point2f( x_g, y_g);

    circle( img, mc, 4, Scalar(100), 2, 4);

    printf("x: %f  y: %f", mc.x, mc.y);

    imshow("img",img);
    waitKey(0);
    return 0;
}

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/06/08 21:27

    ...そなの? 構造体わかんないの?

    キャンセル

  • 2018/06/08 22:55 編集

    ご親切にどうもありがとうございます。

    えーと、構造体とはなにを引数として、なにを出力とするか、関数の使い方などのことでしょうか?
    記憶が正しければ構造体の型を宣言する時は{}の中に「struct」を書いてデータ型メンバ型を書くことは読みました。(間違っていたら申し訳ありません。)
    しかし、まだうまく使いこなせていません。
    構造体が完全にわかっているかと聞かれると自信をもってはいとは言えません。
    ですが今回の問題が自分の力で解決できなかった以上構造体を理解していないと思われても仕方ありません。

    キャンセル

  • 2018/06/08 22:58

    あ!なるほどプログラムは上から順番に処理していくのでmuを消して、重心を求めるプログラムの処理を書き込めばよかったのですね。こんなこともわからなかったとは…。恥ずかしいレベルではないですね。

    キャンセル

  • 2018/06/09 00:41

    Moments mu = moments( img, false );

    muがcv::Moments型の構造体である事を理解できていないのならばC言語の学習に戻りましょう
    https://9cguide.appspot.com/16-01.html

    // 実際の定義を確認したところC++のclassだったが
    // パブリックメンバ変数とコンストラクタのみなので構造体として扱ってもまぁ問題なし

    キャンセル

  • 2018/06/09 03:03

    ありがとうございます。
    はい。C言語の学習に戻ります。
    muが重心を求めるための計算に使われているので、
    個人的には重心を求める計算式をcv::Moments型の構造体と言っているように思えました。

    キャンセル

  • 2018/06/09 03:26

    muは変数の集まりです。
    この場合はmoments関数が複数の値を返すためにcv::Moments型の構造体を返しています。

    キャンセル

  • 2018/06/09 08:26

    > 重心を求める計算式をcv::Moments型の構造体と言っているように思えました。

    Moments はmoments()が値を格納するための器でしかない。
    重心を求めるのに必要なモーメントはmoments()が計算している。

    キャンセル

  • 2018/06/09 23:35

    どうもありがとうございました。

    キャンセル

  • 2018/06/11 02:24 編集

    asmさんに質問したいことがあります。
    せっかくasmさんにプログラムを書いていただきながら自分なりのプログラムに関して質問したいことがあります。決してasmさんのプログラムが嫌なわけではありません。ただ足りない頭で考えて書いたためどうしても原型に近い形でビルドしたいと思いました。
    怒られることを承知で質問したいことがございます。どうかお答えしていただけると嬉しいです。

    こちらがプログラムです。
    #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() {

    Mat img = imread("sample.jpg", IMREAD_GRAYSCALE);

    int count = 0;
    int conut = 0;
    double x_g = 0.0, y_g = 0.0;
    int height = 400;
    int width = 300;

    for (int y = 0; y < height; y++) {
    for (int x = 0; x < width; x++) {
    if (img_src[x][y] == 255) {
    count++;
    x_g += x;
    y_g += y;
    }
    }
    }
    int a;
    int b;
    a = x_g / conut;
    b = y_g / conut;

    Point2f mc = Point2f(a, b);//x_g / conutとy_g / conutをaとbと置いた。
    circle(img, mc, 4, Scalar(100), 2, 4);

    printf("x: %f y: %f", mc.x, mc.y);

    imshow("img", img);
    waitKey(0);
    return 0;

    }

    こちらがエラーです。
    1>------ ビルド開始: プロジェクト: Project18, 構成: Release x64 ------
    1>Source.cpp
    1>c:\users\daito\source\repos\project18\project18\source.cpp(21): error C2065: 'img_src': 定義されていない識別子です。
    1>c:\users\daito\source\repos\project18\project18\source.cpp(30): warning C4244: '=': 'double' から 'int' への変換です。データが失われる可能性があります。
    1>c:\users\daito\source\repos\project18\project18\source.cpp(31): warning C4244: '=': 'double' から 'int' への変換です。データが失われる可能性があります。
    1>c:\users\daito\source\repos\project18\project18\source.cpp(33): warning C4244: '引数': 'int' から 'float' への変換です。データが失われる可能性があります。
    1>プロジェクト "Project18.vcxproj" のビルドが終了しました -- 失敗。
    ========== ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ ==========

    img_srcはunsigned charと関係があるところまでは調べられたのですが、どうやってもimg_srcが定義できません。私はimg_srcを使っていますが愚かなことに定義の仕方がわかりません。
    どうかヒントを頂けないでしょうか?
    どのように調べれば、自力で解決できるヒントが見つかりでしょうか?
    いつもご迷惑ばかりおかけしますがどうかよそしくお願いいたします。

    キャンセル

  • 2018/06/11 19:03

    まず改変について
    teratail内にて掲載したソースコードは自由に改変して構いませんが
    その結果発生した事象について責任は持てませんし、サポートも負いかねます。
    極端な話、改変した結果あなたのHDDが初期化されようが、PCが爆発しようがあなたの責任です。

    > img_src[x][y] == 255
    以前議論したと思いますが、画像データというのは概ね
    X座標: 0~3
    Y座標: A~Cとした場合

    A0 A1 A2 A3 B0 B1 B2 B3 C0 C1 C2 C3

    と並んでいます。(実際にはなぜか形式によってY座標が上下逆になってたり、もうちょっとめんどくさい)

    C言語の2次元配列というのはimg_src[x][y]とimg_src[x][y+1]は連続していますが
    img_src[x+1][y]は連続していません。
    つまりimg_src[x][y]として画素にアクセスするのは無駄にめんどくさいです。
    (転置させるだけではあるが)
    さらに、C言語の2次元配列というのは動的に確保する事ができません。(VLAを除く)
    よって、img_src[x][y]での画素へアクセスできる配列img_srcを定義する事はほぼ不可能です。

    書籍にあったというimg_src[y*width+x]の方は上下が正しいか確認する必要はありますが
    uchar *img = img.ptr();
    で動くかもしれません。

    キャンセル

  • 2018/06/11 19:14

    もうひとつ問題があります。
    int height = 400;
    int width = 300;

    幅・高さをマジックナンバーとして埋め込んでいるせいで
    画像ファイルを読み込んでいる意味がありません。
    領域外アクセスの原因になりかねません。

    img.rowsおよびimg.colsを使うべきです。
    もしくは、表示がめんどくさくなりますが画像も配列リテラルとして埋め込んでしまうのも手ではあります。

    キャンセル

  • 2018/06/11 23:15

    素直にimg.rowsおよびimg.colsを使います。どうもありがとうございます。
    あのasmさんが書いてくださったプログラムに関して質問があるのですが、
    Mat img = imread("sample.jpg", IMREAD_GRAYSCALE);より読み込んだ画像の画素が255の時に{
    count++;
    x_g += x;
    y_g += y;
    }の処理をする。しかしなぜ画像を読み込んだときはimgとしたのにif文で処理する際にはimg.atと名前が変わっているのでしょうか?
    個人の解釈としてimg.atは画素を扱う際に使うと載っていたので、読み込んだ画像のデータの画素を直接を扱えるのがimg.atというものなのでimg( y, x )と掛けないのでimg.at( y, x )と書いたのですよね?
    画像を読み込みという処理と画素を操作する処理がごっちゃになっていました。
    ですが、画素を操作せずに読み込んだ画像の画素を一つの塊として扱えればimg.atを使わずにMat imgのみで画素の値を255にできるかもしれませんが、やり方が思いつかないので、素直に画素を操作するimg.atを使います。
    しかし、img.atを使わずに画素を操作するプログラムが載っているサイトなどはないでしょうか?

    キャンセル

  • 2018/06/11 23:27

    書き忘れていました。asmさんからのプログラムは(img.at(y, x) == 255)に<unsigned char>を付けることでビルドできました。

    こちらがプログラムです。
    #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() {

    Mat img = imread("photoshop-gradation8.jpg", IMREAD_GRAYSCALE);

    int count = 0;

    double x_g = 0.0, y_g = 0.0;
    for (int y = 0; y < img.rows; y++) {
    for (int x = 0; x < img.cols; 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);

    circle(img, mc, 4, Scalar(100), 2, 4);

    printf("x: %f y: %f", mc.x, mc.y);

    imshow("img", img);
    waitKey(0);
    return 0;
    }

    キャンセル

  • 2018/06/12 10:37

    > img.atと名前が変わっている
    Mat型の変数imgのメンバ関数atを呼び出しています。
    C++のクラスという機能です。

    > img( y, x) と掛けないのか
    ちょっと工夫することでできますが、内部の動作は変わらずメンバ関数の呼び出しです。

    キャンセル

  • 2018/06/12 12:37

    ちなみに、heightやwidthを定義した際にビルドは出来たのですが、img.rowsやimg.colsを使った時とは違う結果が出ました。というか、重心がとんでもないところにあったりします。
    なぜなのでしょうか?
    heightやwidth自体がただの変数名としてとしか認識されていないのでしょうか?

    こちらのサイトより
    https://ideone.com/3gVcUH
    include <stdio.h>をインクルードして使えているのに今回のプログラムで定義をちゃんとしたのに使えない理由がわかりません。

    キャンセル

  • 2018/06/12 13:09

    opencvとは別で画素データを収納するために必要なメモリを確保するプログラムです。

    #include "image.h"
    /* List1-2
    画像データ作成
    width :画像の横幅
    height:画像の縦幅
    depth :1画素あたりのビット数(8 or 24)
    */
    ImageData* createImage(int width,int height,int depth)
    {
    ImageData *newimg;
    int byte_per_pixel;

    if(width<0 || height<0) return NULL;
    if(depth!=8 && depth!=24) return NULL; // 1画素あたりのビット数(8,24以外はエラー)

    newimg=malloc(sizeof(ImageData));
    if(newimg==NULL) return NULL;
    // 1画素格納するのに必要なバイト数を求める
    byte_per_pixel=depth/8;
    // 画像データを格納するのに必要なメモリを確保
    newimg->pixels=malloc(sizeof(BYTE)*byte_per_pixel*width*height);
    if(newimg->pixels==NULL) {
    free(newimg);
    return NULL;
    }
    // 各プロパティ値を設定
    newimg->width=width;
    newimg->height=height;
    newimg->depth=depth;
    return newimg;
    }

    このImageData* createImage関数をプログラムに埋め込めれば
    画像を読み込むMat img の部分やimg.at<unsigned char>の部分と置き換えて使えるかもしれません。

    キャンセル

  • 2018/06/12 13:29

    > heightやwidth自体がただの変数名
    それ以外のなにだというのでしょうか?

    > 今回のプログラムで定義をちゃんとしたのに
    そう豪語する根拠はなんでしょうか?
    改変の結果、動作がおかしいのならば 当然、それは改変が間違っています。
    まずは、printf("w,h = %d, %d\n", width, height);
    等で正しい幅・高さが挿入されているかを確認すべきです。
    width,heightが正しい場合でもアラインメントが必要な場合もあり確認すべき事は多いです。

    ソースも提示されずに原因・対策を挙げるとこんなところでしょうか。

    > opencvとは別で画素データを収納するために必要なメモリを確保するプログラムです。
    はぁ、そうですか
    見つけたものを嬉しそうに見せびらかされても、私は貴方の飼い主ではないです。

    > 画像を読み込むMat img の部分やimg.at<unsigned char>の部分と置き換えて使えるかもしれません。
    必要性も利点も感じません。

    キャンセル

  • 2018/06/12 13:37 編集

    >>見つけたものを嬉しそうに見せびらかされても、私は貴方の飼い主ではないです。
    自分があほっぽく見えてきますね。あほなのですが。

    >>必要性も利点も感じません。
    どのように動いているのか知りたかっただけです。

    くだらないこだわりのせいでご迷惑おかけしました。
    どうもありがとうございます。

    キャンセル

  • 2018/06/12 14:33

    ちなみに、asmさんは必要性は別として、opencvとは別に
    画素のデータをいじるようなプログラムを作り、プログラムに打ち込んだりは出来るのでしょうか?(width,heightなどの定義、関数の自作など、めちゃくちゃ面倒なことが多いですが)
    僕には到底出来ない事ですが、asmさんほどの技術者ならば出来るのではないかと思い質問しました。

    キャンセル

  • 2018/06/12 14:54

    難しい事ではなく面倒なだけですね
    (読み込み形式を無圧縮bmp等に限り、画像の表示を行わなければ)

    キャンセル

+3

mc はモーメントmuから得られた重心
mu.m10 x方向の座標値の総和
mu.m01 y方向の座標値の総和
mu.m00 点の総数
重心は 座標値の平均なので (mu.m10/mu.m00, mu.m01/mu.m00)

...って書いてあった。

Moments muの各メンバ m00, m01, m10  については http://opencv.jp/opencv-2.1/cpp/structural_analysis_and_shape_descriptors.html?highlight=moment#moments  にきっちり書いてある。

muが何を表しているのかわからず困り果てています。

アナタそのmuを求めてるじゃん。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/06/07 23:56 編集

    >>アナタそのmuを求めてるじゃん。
    とはmu.m10 x方向の座標値の総和
    mu.m01 y方向の座標値の総和
    mu.m00 点の総数
    より
    載せました以下のプログラム
    int count=0;
    double x_g=0.0,y_g=0.0,x_d=0.0,y_d=0.0,xy_d=0.0
    for(int y=0; y<height; y++){
    for(int x=0;x<width; x++){
    if(img_src[y*width+x] == 255){
    count++;
    x_g +=x;
    y_g +=y;
    }
    }
    }
    x_g /=conut;
    y_g/=count;のプログラムがあるため求めてるじゃんということでしょうか?
    まあ、確かに載せたプログラムはxとyの総数を画素の総数分で割っているので求めているようなものかもしれません。

    キャンセル

  • 2018/06/08 00:04

    ちなみにepistemeさまは何のキーワードで http://opencv.jp/opencv-2.1/cpp/structural_analysis_and_shape_descriptors.html?highlight=moment#moments を出したのでしょうか?

    キャンセル

  • 2018/06/08 02:27

    "OpenCV Moments"

    キャンセル

  • 2018/06/08 02:29

    > ...のプログラムがあるため求めてるじゃんということでしょうか?

    じゃなかったらそのコードは何だというんです?

    キャンセル

  • 2018/06/08 09:30

    xとyの総数を画素の総数分を割り平均値(重心の座標)を求めるコードです。
    ごめんなさい。わかってはいたのですが、自信がなくてつい悩んでしまいました。

    キャンセル

  • 2018/06/08 09:33

    後は、このコードをopencvのプログラムと置き換えて動作させたいと思います。

    キャンセル

+2

こんなのがお望みか?

#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);
}

!実行結果

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/06/12 19:01

    !?
    私が参考にしたサイトのプログラムと少し違いますが、結果が同じ。

    キャンセル

  • 2018/06/12 19:28

    ならば「opencvの関数ではない重心を求めるプログラムを入れたい」って願いは叶ったかな。

    キャンセル

  • 2018/06/12 20:33

    感謝します。いつもいつもご迷惑おかけします。
    身近にepistemeさんのような先生が居たらどんなにいいことかと思ってしまいます。
    本当にどうもありがとうございます。早速ビルドしてみます。

    キャンセル

  • 2018/06/12 21:49

    ちなみにどうたってimg_src[y*whide + x]からimg.data[y*img.step + x]を作ったのですか?
    というかimg.dataとimg.stepをどうやって見つけてきたのですか?

    キャンセル

  • 2018/06/13 03:49

    あらかたマニュアルに書いてある。

    キャンセル

+1

    int conut = 0;
    double x_g = 0.0, y_g = 0.0;
    for (int y = 0; y<height; y++) {
        for (int x = 0; x<width; x++) {
            if (img_src[y*width + x] == 255) {
                count++;
                x_g += x;
                y_g += y;
            }
        }
    }
    int a;
    int b;
    a= x_g / conut;
    b= y_g / conut;

自分なりに書いたのはココ↑なんでしょ?
自分で書いたコードなら width, height, img_src が何を意味するのかわかってるハズね? 

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/06/10 09:07

    widthは画像の幅を求めるための幅を表す変数です。
    heightは画像の高さを求めるための高さを表す変数です。img_srcは画像を読み込むための関数です。

    キャンセル

  • 2018/06/10 09:24 編集

    それらがヘッダの中にあると?
    どう考えればその想いに至るわけ?

    計算対象となる画像はアナタがimgに読みこんでるんだから、
    そいつの幅と高さを手に入れればいいやん。

    てかそのものヅバリをasmさんが書いてくれてる。それをガン無視?

    キャンセル

  • 2018/06/10 22:47

    本当にすいません。無礼を働きました。

    キャンセル

  • 2018/06/10 23:33

    いや、わざわざ改悪したのはなんの意図があって?

    キャンセル

  • 2018/06/10 23:36

    asmさんのプログラムは実行できたのですが、どうしても、
    for (int y = 0; y<height; y++) {
    for (int x = 0; x<width; x++) {
    if (img_src[y*width + x] == 255)
    の方でもビルドしたいと思ったためです。いくつかの方法で実行できないかと思ったためです。
    要は欲張りなのです。

    キャンセル

  • 2018/06/11 03:38

    > インクルードしたヘッダファイルにheight、width、img_srcの定義は書いてあると思ったのですが

    これはナゼ?

    キャンセル

  • 2018/06/11 20:31

    参考にしたサイトでは
    #include <stdio.h>
    #include "opencv/cv.h"
    #include "opencv/highgui.h"ヘッダファイルをインクルードしてエラーが出なかったためです。
    しかし、今思うとそのサイトではimg_srcを使っていないので私の勘違いでした。

    キャンセル

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

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

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

  • C

    3983questions

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

  • C++

    3764questions

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

  • OpenCV

    1231questions

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

  • トップ
  • C++に関する質問
  • opencvの重心を求めるプログラムにopencvの関数ではない重心を求めるプログラムを入れたいです。