感想上一篇答主baidu_30233079解答的:如何给回调函数传数据
如何给一个回调函数传数据?-编程语言-CSDN问答
CSDN问答为您找到如何给一个回调函数传数据?相关问题答案,如果想了解更多关于如何给一个回调函数传数据? c++、opencv 技术问题等相关问答,请访问CSDN问答。
https://ask.csdn.net/questions/7504028
问题大概是,在OpenCV的Canny边缘检测算法中,我想自己编写一个类去实现这个事情,做到如下这样
Mat img = imread(filename); // 读取图片
MyCanny myCanny(img);
myCanny.canny_process;
三行结束对一个图片的边缘检测,这样很方便以后用对吧
于是我写了个类
class MyCanny{
private:
Mat src, src_gray;
Mat dst, detected_edges; // input and output matrix
// int lowThreshold = 0;
const int max_lowThreshold = 100;
const int ratio = 3;
const int kernel_size = 3;
const char* window_name = "Edge Map"; // some parameters
MyCanny * canny_pointer = this;
public:
// int lowThreshold = 0;
explicit MyCanny(const Mat &img); // 构造函数,用于对类的对象赋值,由于数据是private的,只能通过此种方式赋值
Mat get_dst(); // 可以不需要通过static静态就获得dst矩阵
Mat get_src();
void canny_process(); // 用于进行主要的CannyEdge处理过程
static void canny_threshold(int pos, void* userdata);
};
以及类里面的函数,注意,canny_threshold
作为回调函数,是静态,由static
修饰的
void MyCanny::canny_process() {
cout << "canny_process is called..." << endl;
if (src.empty()){
cout << "Failed to load src..." << endl;
exit(100);
}
dst.create(src.size(), src.type());
cvtColor(src, src_gray, COLOR_BGR2GRAY);
namedWindow(window_name, WINDOW_AUTOSIZE); // 这一段代码必须有,是createTrackbar必须的
createTrackbar("Min Threshold:",
window_name,
&lowThreshold,
max_lowThreshold,
canny_threshold);
canny_threshold(0, this); // callback function 回调函数
// FIXME: 回调时,lowThreshold这个参数怎么传给Canny_threshold? 通过`pos`
waitKey(0);
}
void MyCanny::canny_threshold(int pos, void *userdata) {
// 可以把自己数据封装到结构体、或者类,用usrdata传进来。另外一个参数`pos`是当前trackbar的数值
// 实例化一个对象,然后通过对象访问非静态成员数据
auto * myCanny = (MyCanny *) userdata;
// 这几行代码测试是否被回调了
cout << "canny_threshold is called..." << endl;
cout << canny->ratio << endl;
cout << "pos=" << pos << endl;
cout << "lowThreshold=" <<lowThreshold << endl;
cout << "max_lowThreshold=" << myCanny->max_lowThreshold << endl;
// FIXME: 第二次调用时指针出问题
// 获取类的数据
Mat src = myCanny->src;
Mat dst = myCanny->dst;
Mat src_gray = myCanny->src_gray;
Mat detected_edges = myCanny->detected_edges;
// int lowThreshold = myCanny->lowThreshold;
int ratio = myCanny->ratio;
int kernel_size = myCanny->kernel_size;
// 更新lowThreshold
lowThreshold = pos;
// 此时这些参数都是用实例化的对象,通过类传过来的
blur(myCanny->src_gray, myCanny->detected_edges, Size(3, 3));
cout << "blur finished..." << endl;
Canny(myCanny->detected_edges,
myCanny->detected_edges,
lowThreshold,
lowThreshold * ratio,
kernel_size);
cout << "canny finished..." << endl;
myCanny->dst = Scalar::all(0);
src.copyTo(myCanny->dst, myCanny->detected_edges);
imshow(myCanny->window_name, myCanny->dst);
myCanny = nullptr;
userdata = nullptr;
// 重置指针,重置不了啊
}
我的主函数
void function2_1(){
// 实现Canny边缘检测,用类的方法
cout << "Canny Edge Detector" << endl;
Mat img = imread("../../images/learn_slam.jpg");
MyCanny mCanny(img);
mCanny.canny_process();
}
可以看到,在回调函数 canny_threshold
里面,写了几个cout
用来测试是不是回调了,发现第一个参数pos的传输始终是正常的,但是第二个参数userdata在第一次进行回调的时候,似乎由于实例化类指针的问题,不能再次访问类的数据
我觉得可能是实例化类指针的问题?