我在一个程序中使用函数setMouseCallback,它在GUI中显示了ASUS XITON PRO的图像/深度图。现在我想从深度图中获取点击点远离华硕的信息。 我已经尝试过像这样使用setMousCallback的一些程序,它可以工作:
namedWindow("Tiefe",1);
setMouseCallback( "Tiefe", onMouse,0);
功能:
void onMouse( int event, int x, int y, int flags, void* param )
{
if( event == CV_EVENT_LBUTTONUP)
{
distancePt = Point(x,y);
Vec3f s = world.at<Vec3f>(distancePt.y, distancePt.x);
float dx = s[0];
float dy = s[1];
float dz = s[2];
dist = sqrt(dx*dx + dy*dy + dz*dz);
}
}
问题是,如果我尝试在我的程序(GUI)中使用此功能,我总是会收到错误:
/home/eye/Desktop/firstTry/GUI4DEPTHCAM/mainwindow.cpp:509: Fehler:argument of type 'void (MainWindow::)(int, int, int, int, void*)' does not match 'cv::MouseCallback {aka void (*)(int, int, int, int, void*)}'
像这样使用setMouseCallback:
setWindowTitle("Tiefe");
setMouseCallback("Tiefe",onMouse,0);
GUI(QLabel)中的窗口称为lblshow。 但如果我在setMouseCallback中将名称更改为“lblshow”,我会得到同样的错误。
感谢您的帮助,我已经尝试过这种方式......但现在我得到了这个错误:
OpenCV错误:cvSetMouseCallback中的空指针(NULL窗口处理程序),文件/home/eye/Downloads/opencv-2.4.6.1/modules/highgui/src/window_QT.cpp,第652行 在抛出'cv :: Exception'的实例后终止调用 what():/ home / eye / Downloads / opencv-2.4.6.1 / modules / highgui / src /window_QT.cpp:652:error:( - 27)函数cvSetMouseCallback中的NULL窗口处理程序
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QWidget>
#include <iostream>
#include <QTimer>
#include <QImage>
#include <string>
#include <cstdlib>
#include <cstdio>
/***************OPENCV_Headers*************/
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/opencv.hpp"
#include "opencv2/imgproc/imgproc.hpp"
/***************Namespaces****************/
using namespace cv;
using namespace std;
void mouseWrapper( int event, int x, int y, int flags, void* param );
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
void colorizeDisparity( const Mat &gray, Mat &rgb);
void onMouse( int event, int x, int y, int flags, void* param );
public slots:
void RefreshImage();
void Start();
void Grauwert();
void Bilateral();
void Gaussian();
void Median();
void Canny();
void Sobel();
void Video();
void Tief();
void Cam();
void adaptBilateral();
void scharr();
void Fil2D();
void Tief_Farbe();
void Tiefenmessung();
private:
Ui::MainWindow *ui;
bool bilateral_f;
bool Gaussian_f;
bool Grauwert_f;
bool Sobel_f;
bool Canny_f;
bool Median_f;
bool Tief_Farbe_f;
bool Video_f;
bool cam;
bool adapt_bil_f;
bool scharr_f;
bool zweiD_f;
bool Tief_f;
bool Tiefenmessung_f;
bool einmalig;
float *dist;
QTimer *timer;
VideoCapture *cap;
Mat *image;
Mat *Hilf;
Mat *Hilf2;
Mat *Hilf3;
Mat *Hilf4;
Mat *Hilf5;
Mat *Hilf6;
Mat *Hilf7;
Mat *world;
QImage *qimage;
VideoWriter *writer;
QString *Ordner;
String Ordnerstring;
char *buffer;
QString *Info_Cam;
QString *Info_Grau;
QString *Info_Bil;
QString *Info_Gau;
QString *Info_Med;
QString *Info_Can;
QString *Info_Sob;
QString *Info_Tief;
QString *Info_Auf;
QString *Info_Adapt_Bil;
QString *Info_Scharr;
QString *Info_zweiD;
QString *Info_Tief_Farbe;
};
#endif // MAINWINDOW_H
main.ccp
#include "mainwindow.h"
#include <QApplication>
/**************Main***********************/
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
//while(1);
return a.exec();
}
mainwindow.ccp
#include "mainwindow.h"
#include "ui_mainwindow.h"
void mouseWrapper( int event, int x, int y, int flags, void* param )
{
MainWindow * mainWin = (MainWindow *) (param);
if(mainWin != NULL)
mainWin->onMouse(event,x,y,flags,0);
}
MainWindow::MainWindow(QWidget *parent) ://Konstruktor
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
timer = new QTimer();
timer->setInterval(1);
cap = new VideoCapture(0);
cap->set(CV_CAP_PROP_OPENNI_REGISTRATION,1);
cout << "Gerät wird vorbereitet..." << endl;
// Print some avalible device settings.
cout << "\nDepth generator output mode:" << endl <<
cout <<"\n REGISTRATION " << cap->get( CV_CAP_PROP_OPENNI_REGISTRATION ) << endl<<
"FRAME_WIDTH " << cap->get( CV_CAP_PROP_FRAME_WIDTH ) << endl <<
"FRAME_HEIGHT " << cap->get( CV_CAP_PROP_FRAME_HEIGHT ) << endl <<
"FRAME_MAX_DEPTH " << cap->get( CV_CAP_PROP_OPENNI_FRAME_MAX_DEPTH ) << " mm" << endl <<
"FPS " << cap->get( CV_CAP_PROP_FPS ) << endl <<
"REGISTRATION " << cap->get( CV_CAP_PROP_OPENNI_REGISTRATION ) << endl;
if( cap->get( CV_CAP_OPENNI_IMAGE_GENERATOR_PRESENT ) )
{
cout <<"\nImage generator output mode:" << endl <<
"FRAME_WIDTH " << cap->get( CV_CAP_OPENNI_IMAGE_GENERATOR+CV_CAP_PROP_FRAME_WIDTH ) << endl <<
"FRAME_HEIGHT " << cap->get( CV_CAP_OPENNI_IMAGE_GENERATOR+CV_CAP_PROP_FRAME_HEIGHT ) << endl <<
"FPS " << cap->get( CV_CAP_OPENNI_IMAGE_GENERATOR+CV_CAP_PROP_FPS ) << endl;
}
image = new Mat;
Hilf = new Mat;
Hilf2 = new Mat;
Hilf3 = new Mat;
Hilf4 = new Mat;
Hilf5 = new Mat;
Hilf6 = new Mat;
Hilf7 = new Mat;
world = new Mat;
dist = new float;
qimage = new QImage;
Ordner = new QString;
buffer = new char;
Info_Cam = new QString;
Info_Grau = new QString;
Info_Bil = new QString;
Info_Gau = new QString;
Info_Med = new QString;
Info_Can = new QString;
Info_Sob = new QString;
Info_Tief_Farbe = new QString;
Info_Auf = new QString;
Info_Adapt_Bil = new QString;
Info_Scharr = new QString;
Info_zweiD = new QString;
Info_Tief = new QString;
writer = new VideoWriter;
connect(timer, SIGNAL(timeout()), this, SLOT(RefreshImage()));
connect(ui->Grau_Button,SIGNAL(clicked()),this,SLOT(Grauwert()));
connect(ui->Bilateral_Button,SIGNAL(clicked()),this,SLOT(Bilateral()));
connect(ui->Gaussian_Button,SIGNAL(clicked()),this,SLOT(Gaussian()));
connect(ui->Median_Button,SIGNAL(clicked()),this,SLOT(Median()));
connect(ui->Canny_Button,SIGNAL(clicked()),this,SLOT(Canny()));
connect(ui->Sobel_Button,SIGNAL(clicked()),this,SLOT(Sobel()));
connect(ui->pushButtonStart,SIGNAL(clicked()),this,SLOT(Start()));
connect(ui->VideoButton,SIGNAL(clicked()),this,SLOT(Video()));
connect(ui->Tief_Farbe_Button,SIGNAL(clicked()),this,SLOT(Tief_Farbe()));
connect(ui->CameraButton,SIGNAL(clicked()),this,SLOT(Cam()));
connect(ui->Adapt_Bilateral_Button,SIGNAL(clicked()),this,SLOT(adaptBilateral()));
connect(ui->Scharr_Button,SIGNAL(clicked()),this,SLOT(scharr()));
connect(ui->ZweiD_Button,SIGNAL(clicked()),this,SLOT(Fil2D()));
connect(ui->Tief_Button,SIGNAL(clicked()),this,SLOT(Tief()));
connect(ui->Tiefenmessung_Button,SIGNAL(clicked()),this,SLOT(Tiefenmessung()));
bilateral_f=false;
Gaussian_f=false;
Grauwert_f=false;
Sobel_f=false;
Canny_f=false;
Median_f=false;
Tief_f=false;
Video_f=false;
cam = false;//entspricht cam 0
adapt_bil_f=false;
scharr_f=false;
zweiD_f=false;
Tief_Farbe_f=false;
Tiefenmessung_f = false;
einmalig = true;
*Info_Cam = "Cam 0 gewählt";
*Info_Grau = "inaktiv";
*Info_Bil = "inaktiv";
*Info_Gau = "inaktiv";
*Info_Med = "inaktiv";
*Info_Can = "inaktiv";
*Info_Sob = "inaktiv";
*Info_Tief = "inaktiv";
*Info_Auf = "inaktiv";
*Info_Adapt_Bil = "inaktiv";
*Info_Scharr = "inaktiv";
*Info_zweiD = "inaktiv";
*Info_Tief_Farbe = "inaktiv";
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::Start()
{
timer->start();
}
void MainWindow::Bilateral()
{
if(bilateral_f)
{
bilateral_f=false;
*Info_Bil = "inaktiv";
}
else
{
bilateral_f=true;
*Info_Bil = "aktiv";
}
}
void MainWindow::adaptBilateral()
{
if(adapt_bil_f)
{
adapt_bil_f=false;
*Info_Adapt_Bil = "inaktiv";
}
else
{
adapt_bil_f=true;
*Info_Adapt_Bil = "aktiv";
}
}
void MainWindow::scharr()
{
if(scharr_f)
{
scharr_f=false;
*Info_Scharr = "inaktiv";
}
else
{
scharr_f=true;
*Info_Scharr = "aktiv";
}
}
void MainWindow::Fil2D()
{
if(zweiD_f)
{
zweiD_f=false;
*Info_zweiD = "inaktiv";
}
else
{
zweiD_f=true;
*Info_zweiD = "aktiv";
}
}
void MainWindow::Grauwert()
{
if(Grauwert_f)
{
Grauwert_f=false;
*Info_Grau = "inaktiv";
}
else
{
Grauwert_f=true;
*Info_Grau = "aktiv";
}
}
void MainWindow::Gaussian()
{
if(Gaussian_f)
{
Gaussian_f=false;
*Info_Gau = "inaktiv";
}
else
{
Gaussian_f=true;
*Info_Gau = "aktiv";
}
}
void MainWindow::Median()
{
if(Median_f)
{
Median_f=false;
*Info_Med = "inaktiv";
}
else
{
Median_f=true;
*Info_Med = "aktiv";
}
}
void MainWindow::Canny()
{
if(Canny_f)
{
Canny_f=false;
*Info_Can = "inaktiv";
}
else
{
Canny_f=true;
*Info_Can = "aktiv";
}
}
void MainWindow::Sobel()
{
if(Sobel_f)
{
Sobel_f=false;
*Info_Sob = "inaktiv";
}
else
{
Sobel_f=true;
*Info_Sob = "aktiv";
}
}
void MainWindow::Tief()
{
if(Tief_f)
{
Tief_f=false;
*Info_Tief = "inaktiv";
}
else
{
Tief_f=true;
*Info_Tief = "aktiv";
}
}
void MainWindow::Tief_Farbe()
{
if(Tief_Farbe_f)
{
Tief_Farbe_f=false;
*Info_Tief_Farbe = "inaktiv";
}
else
{
Tief_Farbe_f=true;
*Info_Tief_Farbe = "aktiv";
}
}
void MainWindow::Video()
{
if(Video_f)
{
Video_f=false;
einmalig = true;
*Info_Auf = "inaktiv";
}
else
{
Video_f=true;
einmalig = false;
*Info_Auf = "aktiv";
}
}
void MainWindow::Tiefenmessung()
{
if(Tiefenmessung_f)
{
Tiefenmessung_f=false;
}
else
{
Tiefenmessung_f=true;
}
}
void MainWindow::Cam()
{
if(cam)
{
cap->release();
*cap=VideoCapture(1);
*Info_Cam = "Cam 1 gewählt";
cam = false;
}
else
{
cap->release();
*cap=VideoCapture(0);
*Info_Cam = "Cam 0 gewählt";
cam = true;
}
}
void MainWindow::colorizeDisparity( const Mat &gray, Mat &rgb)
{
//Checks a condition at runtime and throws exception if it fails (0)
CV_Assert( !gray.empty() && gray.type() == CV_8UC1 );
//Wenn der Inhalt von gray ein 8-bit single-channel array ist und es gefüllt ein Wert übergeben wurde
double maxDisp=-1.f;
float S=1.f;
float V=1.f;
if( maxDisp <= 0 )
{
maxDisp = 0;
minMaxLoc( gray, 0, &maxDisp );
}
rgb.create( gray.size(), CV_8UC3 );
rgb = Scalar::all(0);
if( maxDisp < 1 )
return;
for( int y = 0; y < gray.rows; y++ )
{
for( int x = 0; x < gray.cols; x++ )
{
uchar d = gray.at<uchar>(y,x);
unsigned int H = ((uchar)maxDisp - d) * 240 / (uchar)maxDisp;
unsigned int hi = (H/60) % 6;
float f = H/60.f - H/60;
float p = V * (1 - S);
float q = V * (1 - f * S);
float t = V * (1 - (1 - f) * S);
Point3f res;
if( hi == 0 ) //R = V, G = t, B = p
res = Point3f( p, t, V );
if( hi == 1 ) // R = q, G = V, B = p
res = Point3f( p, V, q );
if( hi == 2 ) // R = p, G = V, B = t
res = Point3f( t, V, p );
if( hi == 3 ) // R = p, G = q, B = V
res = Point3f( V, q, p );
if( hi == 4 ) // R = t, G = p, B = V
res = Point3f( V, p, t );
if( hi == 5 ) // R = V, G = p, B = q
res = Point3f( q, p, V );
uchar b = (uchar)(std::max(0.f, std::min (res.x, 1.f)) * 255.f);
uchar g = (uchar)(std::max(0.f, std::min (res.y, 1.f)) * 255.f);
uchar r = (uchar)(std::max(0.f, std::min (res.z, 1.f)) * 255.f);
rgb.at<Point3_<uchar> >(y,x) = Point3_<uchar>(b, g, r);
}
}
}
void MainWindow::onMouse( int event, int x, int y, int flags, void* param )
{
Point distancePt(0,0);
if( event == CV_EVENT_LBUTTONUP)
{
distancePt = Point(x,y);
Mat i;
i= *world;
Vec3f s = i.at<Vec3f>(distancePt.y, distancePt.x);
float dx = s[0];
float dy = s[1];
float dz = s[2];
*dist =sqrt(dx*dx + dy*dy + dz*dz);
}
}
void MainWindow::RefreshImage()
{
cap->grab();
cap->open(CV_CAP_OPENNI);
//cap->set( CV_CAP_OPENNI_IMAGE_GENERATOR_OUTPUT_MODE, CV_CAP_OPENNI_VGA_30HZ );
cap->retrieve( *image, CV_CAP_OPENNI_BGR_IMAGE);
if (Grauwert_f)
{
cap->retrieve(*image,CV_CAP_OPENNI_GRAY_IMAGE);
//cvtColor(*image,*image,CV_BGR2GRAY); //src,dst,Farbraumwandlung(,dstCn)
}
if(bilateral_f)
{
bilateralFilter(*image,*Hilf,9,9,9); //src,dst,sigmaColor,sigmaSpace(,bordeType)
*image=*Hilf;
}
if(adapt_bil_f)
{
//adaptiveBilateralFilter(*image,*Hilf2,Size(3,3),2);//src,dst,ksize,sigmaSpace,sigmaMax(,borderType)
//*image=*Hilf2; MUSS NOCH EINGEBUNDEN WERDEN
}
if(scharr_f)
{
Scharr(*image,*Hilf3,image->depth(),1,0);//src,dst,ddepth,dx,dy(,ksize,scale,delta,borderType)
*image=*Hilf3;
}
if(zweiD_f)
{
sepFilter2D(*image,*Hilf4,image->depth(),1.5,1.5);//src,dst,ddepth,dx,dy(,ksize,scale,delta,borderType)
*image=*Hilf4;
}
if (Gaussian_f)
{
int kernelsize = 5;
GaussianBlur(*image,*image,Size(kernelsize,kernelsize), 1.5, 1.5); //src,dst,ksize,sigmaX,sigmaY(,borderType)
}
if (Median_f)
{
medianBlur(*image,*image,9); //src,dst,ksize
}
if (Sobel_f)
{
cv::Sobel(*image,*image,image->depth(),1,0,3); //src,dst,ddepth,dx,dy(,ksize,scale,delta,borderType)
}
if (Canny_f)
{
cv::Canny(*image,*image, 0, 50, 3); //src,dst,threshold1,threshold2(,apertureSize,L2gradient)
}
if(Tief_f)
{
Mat depthMap;
cap->retrieve( depthMap, CV_CAP_OPENNI_DEPTH_MAP);
const float scaleFactor = 0.05f;
depthMap.convertTo( *image, CV_8UC1, scaleFactor );
if(Tief_Farbe_f)
{
Mat disparityMap;
Mat colorDisparityMap;
cap->retrieve( disparityMap, CV_CAP_OPENNI_DISPARITY_MAP );
colorizeDisparity(disparityMap,*image);
}
if (Tiefenmessung_f)
{
cap->retrieve(*world, CV_CAP_OPENNI_POINT_CLOUD_MAP);
setWindowTitle("Tiefe");
setMouseCallback("Tiefe",mouseWrapper,this);
putText(*image,format("distance: %f m",*dist),Point(5,15),FONT_HERSHEY_PLAIN,1,Scalar(255));
putText(*image,format("Framerate: %f",cap->get(CV_CAP_PROP_FPS)),Point(5,30),FONT_HERSHEY_PLAIN,1,Scalar(255));
}
}
if(!einmalig)
{
*Ordner = ui->Speicherort->text();
Ordnerstring = Ordner->toStdString();
*writer = VideoWriter (Ordnerstring.data() ,
CV_FOURCC('D','I','V','X'),
30,
cv::Size(cap->get(CV_CAP_PROP_FRAME_WIDTH),cap->get(CV_CAP_PROP_FRAME_HEIGHT)));
einmalig = true;
}
//BGR abfangen und in RGB wandeln
if((image->type() == CV_8UC3) || (image->type() == CV_32FC3))
{
cvtColor(*image,*Hilf5,CV_BGR2RGB);
*image = *Hilf5;
}
//Wenn Bild in Grauwerten
if((image->type() == CV_8UC1) || (image->type() == CV_32FC1))
{
cvtColor(*image,*Hilf6,CV_GRAY2RGB);
*image = *Hilf6;
*qimage=QImage((uchar*)(image->data),image->cols,image->rows,QImage::Format_Indexed8);
}
if(Video_f)
{
cvtColor(*image,*Hilf7,CV_RGB2BGR);//Umwandlung muss erfolgen, da writer ein BGR Bild innerhalb seiner Klasse in ein RGB umwandelt
writer->write(*Hilf7);//write *image into the file
}
*qimage=QImage((uchar*)(image->data),image->cols,image->rows, QImage::Format_RGB888);//The image is stored using a 24-bit RGB format (8-8-8).
ui->lblshow->setPixmap(QPixmap::fromImage(*qimage,Qt::AutoColor));
ui->lblshow->resize(ui->lblshow->pixmap()->size());
ui->Info_Bil->setText(*Info_Bil);
ui->Info_Auf->setText(*Info_Auf);
ui->Info_Cam->setText(*Info_Cam);
ui->Info_Can->setText(*Info_Can);
ui->Info_Gaus->setText(*Info_Gau);
ui->Info_Grau->setText(*Info_Grau);
ui->Info_Med->setText(*Info_Med);
ui->Info_Sob->setText(*Info_Sob);
ui->Info_Tief->setText(*Info_Tief);
ui->Info_Adapt_Bil->setText(*Info_Adapt_Bil);//neu
ui->Info_Scharr->setText(*Info_Scharr);//neu
ui->Info_ZweiD->setText(*Info_zweiD);//neu
ui->Info_Tief_Farbe->setText(*Info_Tief_Farbe);//neu
}
答案 0 :(得分:1)
setMouseCallback想要一个静态函数,你给它一个非静态的类成员。
可能最好的方法是使用静态回调函数,重定向到类方法。
void mouseWrapper( int event, int x, int y, int flags, void* param ); // forward decl needed here
struct MainWindow
{
void onMouse( int event, int x, int y, int flags, void* param )
{
if( event == CV_EVENT_LBUTTONUP)
//....
}
void init()
{
setWindowTitle("Tiefe");
setMouseCallback("Tiefe",mouseWrapper,this);
}
};
void mouseWrapper( int event, int x, int y, int flags, void* param )
{
MainWindow * mainWin = (MainWindow *)(param);
mainWin->onMouse(event,x,y,flags,0);
}
答案 1 :(得分:0)
我也有同样的问题,我检查了github和stackoverflow,没有人解决这个问题。
所以我尝试将“ setWindowTitle(” Tiefe“)”更改为“ cv :: nameWindow(” Tiefe“)”,然后解决该错误。
也许这样可以帮助您解决问题