2017-12-22 15 views
1

私はC/C++をかなり新しくしており、次の問題があります。 exectuableの一部として、私はOpenCVを使用して画像にいくつかの長方形を描きたい。このため、.cpp実行ファイルを可能な限り短く保つために、別のヘッダーファイルを定義しました。それは次のようになります。ヘッダファイル内の非静的メンバー関数の無効な使用

typedef struct Rectangle { 
    cv::Point startPoint; 
    cv::Point endPoint; 

}; 

class drawSpaces { 

private: 
    Mat img; 
    int ix = 1; 
    int iy = 1; 
    std::list<Rectangle> rectList; 

public: 
//mouse callback function 
    void drawRect(int event, int x, int y, int, void *param) { 
     if (event == CV_EVENT_LBUTTONDOWN) { 
      //Save first point of rect 
      ix = x; 
      iy = y; 
     } else if (event == CV_EVENT_LBUTTONUP) { 
      //Save 2nd point of rect 
      cv::rectangle(img, Point(ix, iy), Point(x, y), cv::Scalar(0, 255, 0)); 
      Rectangle rect; 
      rect.startPoint = Point(ix, iy); 
      rect.endPoint = Point(x, y); 
      rectList.push_back(rect); 
      } 
     } 
    } 


    int draw(Mat image) { 
     img = image; 
     if (img.empty()) { 
      cout << "\nerror reading image" << endl; 
      return -1; 
     } 
     namedWindow("Image", 1); 
     imshow("Image", img); 
     setMouseCallback("Image", drawRect); 
     while (waitKey(20) != 27) // wait until ESC is pressed 
     { 
      imshow("Image", img); 
     } 
     //save image with rectangles 
     imwrite("../pics/new_Image.jpg", img); 
     return 0; 
    } 

}; 

私は今、私のメインのクラスdrawSpacesの対象とマット・イメージを作成し、新しいイメージを得るためにそれに引き分けを実行したいです。しかし、ビルド時に、私はエラーメッセージ error: invalid use of non-static member function setMouseCallback("Image", drawRect); を取得し、コンパイラはdrawRect関数を指しています。

私はこの質問で他の答えを見てきました。大多数は、drawRectを静的に変更するよう提案しています。しかし私は、私のdrawRect関数が静的関数の機能を持つ、つまり実際のdrawSpacesオブジェクトが存在しないまま呼び出せるようにすることは望ましくありません。

どのようなヘルプも、コーディングのスタイルで、感謝しています!

EDIT:

setMouseCallback("Image", drawSpaces::drawRect); 

を使用すると、いずれか助けていません。

+0

。混乱して申し訳ありませんが、可能な限り短くしたいと考えました。 – emilaz

+0

エラーの説明はエラーです。メンバ関数をパラメータとして直接使用することはできません。 drawSpaces :: drawRectを試してください – leyanpan

+0

あなたの提案をありがとう。私はそれを試みましたが、それは表示されているエラーに違いはありません。 – emilaz

答えて

2

ENV:G ++ 5.4(C++ 11)+ OpenCVの3.3

setMouseCallback("Image", callback);のコールバック関数は常に静的であるべきです。だから、あなたがに機能変更する必要があります。そして、あなたもあなたのクラス定義変更する必要があります

static void drawRect(int event, int x, int y, int, void *param) 

を正常にコンパイルする(C++に関連するいくつかの知識を、自分で学ばなければなりません)。


私の結果:私は介在物を省略して、私は、名前空間のCVとstdを設定することを省略

enter image description here


//! 2017.12.22 23:13:58 CST 
#include <iostream> 
#include <opencv2/opencv.hpp> 
using namespace std; 
using namespace cv; 

struct Rectangle { 
    cv::Point startPoint; 
    cv::Point endPoint; 

}; 

class drawSpaces { 
private: 
    static Mat img; 
    static int ix; 
    static int iy; 
    static std::list<Rectangle> rectList; 

public: 

    static void drawRect(int event, int x, int y, int, void *param) { 
     if (event == CV_EVENT_LBUTTONDOWN) { 
      //Save first point of rect 
      ix = x; 
      iy = y; 
     } else if (event == CV_EVENT_LBUTTONUP) { 
      //Save 2nd point of rect 
      cv::rectangle(img, Point(ix, iy), Point(x, y), cv::Scalar(0, 255, 0), 1, LINE_AA); 
      Rectangle rect; 
      rect.startPoint = Point(ix, iy); 
      rect.endPoint = Point(x, y); 
      rectList.push_back(rect); 
      } 
     } 

    int draw(Mat image) { 
     img = image; 
     if (img.empty()) { 
      cout << "\nerror reading image" << endl; 
      return -1; 
     } 
     namedWindow("Image", 1); 
     imshow("Image", img); 
     setMouseCallback("Image", drawRect); 
     while (waitKey(20) != 27) { 
      imshow("Image", img); 
     } 
     //save image with rectangles 
     imwrite("new_Image.jpg", img); 
     return 0; 
    } 

}; 

int drawSpaces::ix =0; 
int drawSpaces::iy =0; 
Mat drawSpaces::img = Mat() ; 
std::list<Rectangle> drawSpaces::rectList; 



int main(){ 
    Mat img = imread("test.png"); 
    drawSpaces obj; 
    obj.draw(img); 

} 
+0

これは正解です。ありがとう! – emilaz

+0

コールバック関数にオブジェクトメンバーが必要な場合は、void * paramパラメータを介してオブジェクトポインタを渡してオブジェクトクラスにキャストすることができます。たとえば、静的なdrawRectStatic(...)を追加してから、((drawSpaces *)param) - > drawRect(...)を呼び出すことができますが、動的キャストではより良いかもしれません;) – Micka

-1

メンバー関数へのポインタを引数として渡そうとしています。非静的メンバ関数は、呼び出されるインスタンスまたは別のシグネチャを必要とします。

これは、すでにここで説明されている:

Passing a member function as an argument in C++
+0

あなたのコメントは私を助けていません。私があなたが提供したリンクから取る要点は、単にleyanpanが示唆するように、drawSpaces :: signatureを使用しているだけです。それは問題を解決しません。 – emilaz

+0

"setMouseCallback"の署名を投稿できますか? –

+0

これはcv署名です。 – emilaz

関連する問題