0

関数を別の関数の引数として渡そうとしています。次のコードは、クラスが使用されていない場合に機能しますが、qt のクラスで試してみると、次のエラーが発生します...

error: argument of type 'void (MainWindow::)(int, int, int, int, void*)'
does not  match 'void (*)(int, int, int, int, void*)'

私のコードは

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <opencv/cv.h>
#include <opencv/cvaux.h>
#include <opencv/highgui.h>

// for filelisting
#include <stdio.h>
#include <sys/file.h>
#include<io.h>
// for fileoutput
#include <string>
#include <fstream>
#include <sstream>
#include <dirent.h>
#include <sys/types.h>
using namespace std;
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    roi_x0=0;
     roi_y0=0;
     roi_x1=0;
     roi_y1=0;
     numOfRec=0;
     startDraw = 0;
     window_name="<SPACE>add <B>save and load next <ESC>exit";
}

MainWindow::~MainWindow()
{
    delete ui;
}
string MainWindow::IntToString(int num)
{
    ostringstream myStream; //creates an ostringstream object
    myStream << num << flush;
    /*
    * outputs the number into the string stream and then flushes
    * the buffer (makes sure the output is put into the stream)
    */
    return(myStream.str()); //returns the string form of the stringstream object
}

void MainWindow::on_mouse(int event, int x, int y, int flag, void *param)
{
    if(event==CV_EVENT_LBUTTONDOWN)
    {
        if(!startDraw)
        {
            roi_x0=x;
            roi_y0=y;
            startDraw = 1;
        } else {
            roi_x1=x;
            roi_y1=y;
            startDraw = 0;
        }
    }
    if(event==CV_EVENT_MOUSEMOVE && startDraw)
    {

        //redraw ROI selection
        image2=cvCloneImage(image);
        cvRectangle(image2,cvPoint(roi_x0,roi_y0),cvPoint(x,y),CV_RGB(255,0,255),1);
        cvShowImage(window_name,image2);
        cvReleaseImage(&image2);
    }
}

void MainWindow::on_actionMark_Faces_triggered()
{
    char iKey=0;
    string strPrefix;
    string strPostfix;
    string input_directory;
    string output_file;



    input_directory ="E:/My/";
    output_file ="pos.txt";

    /* Get a file listing of all files with in the input directory */
    DIR    *dir_p = opendir (input_directory.c_str());
    struct dirent *dir_entry_p;

    if(dir_p == NULL) {
        fprintf(stderr, "Failed to open directory %s\n", input_directory.c_str());

    }

    fprintf(stderr, "Object Marker: Input Directory: %s  Output File: %s\n", input_directory.c_str(), output_file.c_str());

    //    init highgui
    cvAddSearchPath(input_directory);
    cvNamedWindow(window_name,1);
    cvSetMouseCallback(window_name,on_mouse,NULL);

    fprintf(stderr, "Opening directory...");
    //    init output of rectangles to the info file
    ofstream output(output_file.c_str());
    fprintf(stderr, "done.\n");

    while((dir_entry_p = readdir(dir_p)) != NULL)
    {
        numOfRec=0;

        if(strcmp(dir_entry_p->d_name, ""))
        fprintf(stderr, "Examining file %s\n", dir_entry_p->d_name);

        /* TODO: Assign postfix/prefix info */
        strPostfix="";
        //strPrefix=input_directory;
        strPrefix=input_directory+dir_entry_p->d_name;
        //strPrefix+=bmp_file.name;
        fprintf(stderr, "Loading image %s\n", strPrefix.c_str());

        if((image=cvLoadImage(strPrefix.c_str(),1)) != 0)
        {

            //    work on current image
            do

    {
                cvShowImage(window_name,image);

                // used cvWaitKey returns:
                //    <B>=66        save added rectangles and show next image
                //    <ESC>=27        exit program
                //    <Space>=32        add rectangle to current image
                //  any other key clears rectangle drawing only
                iKey=cvWaitKey(0);
                switch(iKey)
                {

                case 27:

                        cvReleaseImage(&image);
                        cvDestroyWindow(window_name);
                        return;
                case 32:

                        numOfRec++;
                printf("   %d. rect x=%d\ty=%d\tx2h=%d\ty2=%d\n",numOfRec,roi_x0,roi_y0,roi_x1,roi_y1);
                //printf("   %d. rect x=%d\ty=%d\twidth=%d\theight=%d\n",numOfRec,roi_x1,roi_y1,roi_x0-roi_x1,roi_y0-roi_y1);
                        // currently two draw directions possible:
                        //        from top left to bottom right or vice versa
                        if(roi_x0<roi_x1 && roi_y0<roi_y1)
                        {

                            printf("   %d. rect x=%d\ty=%d\twidth=%d\theight=%d\n",numOfRec,roi_x0,roi_y0,roi_x1-roi_x0,roi_y1-roi_y0);
                            // append rectangle coord to previous line content
                            strPostfix+=" "+IntToString(roi_x0)+" "+IntToString(roi_y0)+" "+IntToString(roi_x1-roi_x0)+" "+IntToString(roi_y1-roi_y0);

                        }
                        else
                                                    //(roi_x0>roi_x1 && roi_y0>roi_y1)
                        {
                            printf(" hello line no 154\n");
                            printf("   %d. rect x=%d\ty=%d\twidth=%d\theight=%d\n",numOfRec,roi_x1,roi_y1,roi_x0-roi_x1,roi_y0-roi_y1);
                            // append rectangle coord to previous line content
                            strPostfix+=" "+IntToString(roi_x1)+" "+IntToString(roi_y1)+" "+IntToString(roi_x0-roi_x1)+" "+IntToString      (roi_y0-roi_y1);
        }

                        break;
                }
            }
            while(iKey!='b');

            {
            // save to info file as later used for HaarTraining:
            //    <rel_path>\bmp_file.name numOfRec x0 y0 width0 height0 x1 y1 width1 height1...
            if(numOfRec>0&&iKey=='b')
            {
                //append line
                /* TODO: Store output information. */
                output << strPrefix << " "<< numOfRec << strPostfix <<"\n";

            cvReleaseImage(&image);
            }

         else
        {
            fprintf(stderr, "Failed to load image, %s\n", strPrefix.c_str());
        }
    }

    }}

    output.close();
    cvDestroyWindow(window_name);
    closedir(dir_p);
}

行でエラーが発生します

 cvSetMouseCallback(window_name,on_mouse,NULL);
4

3 に答える 3

1

メンバー関数は通常の関数とは異なります (追加の非表示の 'this' パラメーターを渡す必要があるため)。

これが、次のように言う理由です。

void (MainWindow::)(int, int, int, int, void*)

一致していません:

void ()(int, int, int, int, void*)

MainWindow::の部分が重要です。

C++11 を使用している場合は、std::function と std::bind を使用できます (この質問を参照してください)。静的メンバー関数もthisポインターを持たず、通常の関数のように動作するため、静的メンバー関数も機能します (ただし、名前空間内で、プライベート メンバー アクセスを使用します)。

于 2013-03-14T18:48:09.573 に答える
0

これは珍しい問題ではありません。解決策は、ラッパー関数を使用することです。

static void MainWindow::on_mouse_wrapper(int event, int x, int y, int flag, void *param)
{
   MainWindow* self = reinterpret_cast<MainWindow*>(param);
   self->on_mouse(event, x, y, flag, NULL);
}

次に、編集します

cvSetMouseCallback(window_name,on_mouse,NULL);

に:

cvSetMouseCallback(window_name,on_mouse,this);

于 2013-03-14T20:31:10.423 に答える
0

コールバック メソッドはstaticand public(または非メンバー関数) である必要があります。ご存知のように、非メンバー関数の場合は機能しますが、非静的メソッドの場合はエラーが発生します。次のように定義する必要がありますMainWindow::on_mouse

static void MainWindow::on_mouse(int event, int x, int y, int flag, void *param)
于 2013-03-14T18:50:14.997 に答える