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

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

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

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

C++

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

Q&A

解決済

2回答

7035閲覧

C++で変数を関数に渡すときに変数型が一致しない(OpenCV)

sug1t0m0

総合スコア40

OpenCV

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

C++

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

1グッド

0クリップ

投稿2017/02/07 04:05

プログラムのエラーが出る箇所を以下に抜き出しました。
なお、このプログラムは HOG特徴量の計算に掲載されているものです。

// ある矩形領域の勾配ヒストグラムを求める // ここでいう矩形はHOG特徴量のセルに該当 void calculateHOGInCell(Mat& hogCell, Rect roi, const vector<Mat>& integrals) { int x0 = roi.x, y0 = roi.y; int x1 = x0 + roi.width, y1 = y0 + roi.height; for (int i = 0; i < N_BIN; i++) { Mat integral = integrals[i]; float a = integral.at<double>(y0, x0); float b = integral.at<double>(y1, x1); float c = integral.at<double>(y0, x1); float d = integral.at<double>(y1, x0); hogCell.at<float>(0, i) = (a + b) - (c + d); } } // セルの大きさ(ピクセル数) #define CELL_SIZE 20 // ブロックの大きさ(セル数)奇数 #define BLOCK_SIZE 3 // ブロックの大きさの半分(ピクセル数) #define R (CELL_SIZE*(BLOCK_SIZE)*0.5) // HOG特徴量を計算する // pt: ブロックの中心点 Mat getHOG(Point pt, const vector<Mat>& integrals) { // ブロックが画像からはみ出していないか確認 if (pt.x - R < 0 || pt.y - R < 0 || pt.x + R >= integrals[0].cols || pt.y + R >= integrals[0].rows ) { return Mat(); } // 与点を中心としたブロックで、 // セルごとに勾配ヒストグラムを求めて連結 Mat hist(Size(N_BIN*BLOCK_SIZE*BLOCK_SIZE, 1), CV_32F); Point tl(0, pt.y - R); int c = 0; for (int i = 0; i < BLOCK_SIZE; i++) { tl.x = pt.x - R; for (int j = 0; j < BLOCK_SIZE; j++) { calculateHOGInCell(hist.colRange(c, c+N_BIN), Rect(tl, tl+Point(CELL_SIZE, CELL_SIZE)), integrals); tl.x += CELL_SIZE; c += N_BIN; } tl.y += CELL_SIZE; } // L2ノルムで正規化 normalize(hist, hist, 1, 0, NORM_L2); return hist; }

で以下のようなエラーが出ます。

HOGTest.cpp:114:13: error: no matching function for call to 'calculateHOGInCell' calculateHOGInCell(hist.colRange(c, c+N_BIN), ^~~~~~~~~~~~~~~~~~ HOGTest.cpp:71:6: note: candidate function not viable: expects an l-value for 1st argument void calculateHOGInCell(Mat& hogCell, Rect roi, const vector<Mat>& integrals) { ^ 1 error generated.
223horn👍を押しています

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

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

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

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

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

guest

回答2

0

ベストアンサー

こんにちは。

cv::Mat::colRange()はcv::Mat型のインスタンスを返却します。
変数に代入せずに直接他の関数のパラメータへ与える場合、一時変数として渡されます。
Visual C++は一時変数を参照で受け取ってもエラーにならなかったと思いますが、gccはエラーになります。(Visual Studio 2013時代の記憶ですので、2015ではまた異なるかも知れません。)

つまり、リンク先のサイトはVisual C++で動作確認しているのではないかと思います。

適切に動作させるには下記でいけると思います。

C++

1Mat temp=hist.colRange(c, c+N_BIN); 2calculateHOGInCell(temp, 3 Rect(tl, tl+Point(CELL_SIZE, CELL_SIZE)), 4 integrals);

ちょっと虚しく感じますが、標準規格的にはgccの動作の方が正しいです。


【なぜ一時変数を参照で受け取れないのか?】
通常、参照は値を返却する場合に使います。なので参照で受け取った変数はその後も「生きている」ことが期待されます。
しかし、一時変数はその文が終われば破棄されますから、関数側で何か値を設定してもそれが無駄になるのが「普通」です。
そのミスをプログラマに通知するためにエラーにしているのだろうと思います。

OpenCVのcv::Mat型はstd::shared_ptr<>のような一種のスマート・ポインタですので値の設定はそれが管理するデータへ設定します。これはcv::Matが破棄されても直ちに破棄されるわけではなく、そのデータを参照している全てのcv::Matが破棄されるまで維持されます。
つまり、上記の「普通」とは異なる使い方なので、今回の使い方では問題は発生しない筈です。

投稿2017/02/07 04:37

編集2017/02/07 04:43
Chironian

総合スコア23272

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

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

Chironian

2017/02/07 04:41 編集

書いている間に進んでました。もう少し考えてみます。 ↓ ああ、NEWBIEEBIEEさんはMatの参照(Mat& hogCell)で受けてますが、私の回答のように参照ではなく普通の変数(Mat temp)で受ければ良いはずです。
sug1t0m0

2017/02/07 04:48

ありがとうございます。コンパイラの説明までいただけて、嬉しい反面自分の勉強不足を痛感しているところです。
Chironian

2017/02/07 04:55

いえいえ。実は同様な問題に以前ハマったことがあるので、たまたま知っているだけなのですよ。
guest

0

expected l-valueとあるので今入っているのはr-value(右辺値)のはず、
Mat& hogCell = hist.colRange(c, c+N_BIN);
として左辺値に変えるのはどうですか。
それから該当する関数に代入しましょう

後、OpenCV2か3かわかりませんが
暗黙の型変換などにも注意した方がいいかもしれません。

c++

for (int j = 0; j < BLOCK_SIZE; j++) {
Mat* hogCell = hist.colRange(c, c+N_BIN); <--ここ
calculateHOGInCell(hogCell , <--ここも変えて
Rect(tl, tl+Point(CELL_SIZE, CELL_SIZE)),
integrals);
tl.x += CELL_SIZE;
c += N_BIN;
}

投稿2017/02/07 04:13

編集2017/02/07 04:37
NEWBIEEBIEE

総合スコア62

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

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

sug1t0m0

2017/02/07 04:21

早速のご回答ありがとうございます。 具体的にどこに Mat& hogCell = hist.colRange(c, c+N_BIN); を入れればいいのでしょうか? 理解力不足ですみません。
sug1t0m0

2017/02/07 04:30

やってみました。今度は HOGTest.cpp:114:16: error: non-const lvalue reference to type 'cv::Mat' cannot bind to a temporary of type 'cv::Mat' Mat& hogCell = hist.colRange(c, c+N_BIN); ^ ~~~~~~~~~~~~~~~~~~~~~~~~~ 1 error generated. というエラーが出てしまいました。
NEWBIEEBIEE

2017/02/07 04:34

const Mat& hogCell = hist.colRange(c, c+N_BIN); でやってみましょう(無保証)
NEWBIEEBIEE

2017/02/07 04:36

ごめんなさい、 Mat* hogCell = hist.colRange(c, c+N_BIN);だと思います。
sug1t0m0

2017/02/07 04:46

Mat foo = hist.colRange(c, c+N_BIN); で解決しました。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問