0

すべての OpenCV ウィンドウのすべてのマウス ハンドラーを 1 か所で初期化する関数を作成しようとしています。コードはメイン ループで機能しますが、関数内では機能しません (はい、参照渡しです)。
この問題は、文字列へのポインタを渡すことに起因しているようです - 反対側に出ると、逆参照 (*) が成功しません。何を与える?

これは、私が話していることの最小限の例です (これは、2 つの同一のウィンドウにマウス ハンドラーを設定します。1 つのウィンドウは機能し、もう 1 つのウィンドウは機能しません)。

// mouse problem.cpp : Defines the entry point for the console application.
#include "stdafx.h"
#include "opencv2/core/core.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <opencv2/highgui/highgui.hpp>
#include <string.h>
#include <iostream>  //for cout, cin

using namespace std;
using namespace cv;

void onMouse(int event, int x, int y, int flags, void* param){ 

    string windowname = *((string*)param);  //just recasting the void* we passed into the mousehandler to string
    if(windowname.empty()){
        cout << "ERROR.";
    }else{
        cout << "SUCCESS for window:" << windowname;
    }
    cout <<  "  param: "<< param << " windowname: "<< windowname << "\n";
}

void initializer(const string& name){
        namedWindow( name, CV_WINDOW_AUTOSIZE );
        cout << " initializing mouse handler for " << name << " with string at address :" << &name << "\n";
        setMouseCallback(name, onMouse, (void*)&name);  //this line is exactly the same as the other setmousecallback line
}

int _tmain(int argc, _TCHAR* argv[]){
    string name; Mat src; VideoCapture cap(0);  cap >> src; // get a single frame from camera

    //this works just fine
    name = "frameA";
    namedWindow( name, CV_WINDOW_AUTOSIZE );
    cout << " initializing mouse handler for " << name << " with string at address :" << &name << "\n";
    setMouseCallback(name, onMouse, (void*)&name);

    //this fails even though it contains the same code and we pass by reference
    initializer("frameB");

    imshow("frameA",src);   imshow("frameB",src);  //display frame - mouseing over them triggers the OnMouse() event
    while(true){  //loop forever
        waitKey(30);
    }
    return 0;
}

そして、これが各ウィンドウに一度マウスオーバーした後 の結果です。

本当に私を殺したのは、写真でわかるように、文字列のアドレスが正常に認識されたことです! そして、それを文字列にキャストしてもエラーはありません! しかし、逆参照すると、空だと表示されます!
はい、Void* の使用を避けようとしました。悲しいことに、私は空白を避けることができません。OpenCV では、マウスハンドラ関数の最後の引数に void を指定する必要があります:(

4

1 に答える 1

2

問題はキャストとは関係ありません。一時stringオブジェクトへのポインターを保持しており、オブジェクトがスコープ外になった後にそのポインターを逆参照しようとしています。

以下:

initializer("frameB");

次と同等です。

initializer(std::string("frameB"));

つまり、テンポラリが作成され、関数はそのテンポラリのアドレスを取得して保持します。ステートメントの最後でテンポラリが消えるため、ダングリング ポインターが残ります。

于 2012-12-30T11:09:13.207 に答える