提出问题
我对回调函数的概念只有一个模糊的理解,我一直以为我不能很好地解释它们,但是我最近在学习OpenCV时偶然遇到了它们,所以我想我’这次一定要尝试一下。
首先附上OpenCV相关的代码。
#include iostream#include opencv2/core/core.hpp#include opencv2/highgui/highgui.hpp#include imgproc.hppusing namespace std;using namespace cv; //TrackBar 改变回调函数void onChangeTrackBar(int pos, void* userdata); //主函数int main(){ //Trackbar值int posTrackBar=0; //Trackbar最大值int maxValue=255; //读取图像并转换为灰度格式Mat img Read image=imread(‘D:/code /repos/2.jpg’, 0); //创建一个名为Window的新窗口(‘binarized’); imshow(‘binarized’, img); //创建一个trackbar并将img数据添加到回调函数createTrackbar中(‘pos’, ‘binary’, posTrackBar, maxValue, onChangeTrackBar, img); return 0;} //回调函数void onChangeTrackBar(int pos, void * usrdata ){ //strong制Mat src=*(Mat*)(usrdata ); Mat dst; //二值化阈值(src, dst, pos, 255, 0); 与此相关的程序,请参阅这篇文章。 https://mp.toutiao.com/profile_v4/graphic/preview?pgc_id=6880767810209841677
查找资料
没有条件,但是不懂也没关系。 搜索了各大网站关于回调函数的文章,结合自己的理解。我了解了一些关于回调函数的知识。对于一个新的想法,来说一下我对回调函数的看法。
回调函数是通过函数指针调用的函数。当你将一个函数指针(地址)作为参数传递给另一个函数并使用这个指针来调用所指向的函数时,它被称为回调函数。回调函数不是由函数的实现者直接调用,而是由另一方在发生特定事件或条件时调用并响应该事件或条件。
以上解释来自百度百科,但是读完之后,你可能会想知道它在说什么。这。你能好好说话吗?事实上,如果你阅读了其中许多概念的官方答案,你会觉得它们甚至没有得到解释,你根本不理解它们。
没关系,我也是,可能大多数人也是。
所以我寻找其他答案。
你去商店买东西,你想要的东西恰好缺货,所以你把你的电话号码留给店员,几天后商店就有货了,店员给你打电话。我接到电话并去商店取货。在这个例子中,当你把电话号码留给店员时,称为回调函数,当产品稍后到达商店时,称为回调函数。接到店员打来的电话称为回调函数,去商店取货时响应回调事件称为回调函数。
作者:常西岭链接:https://www.zhihu.com/question/19801131/answer/13005983
啊?我感觉我开始明白一些东西了,但是如果实际的程序代码有问题怎么办?
我们在这里整理一下思路。
需要一个回调函数。我需要一个调用回调函数的函数。那么,从上面的相关步骤,我们知道回调函数是一个通过函数指针调用的函数。简单来说,这只是一个函数,你不需要做任何其他事情。
void on_callbackBJ(){ printf(‘I from beijing.\n’);}void on_callbackSH(){ printf(‘I from shanghai.\n’);}接下来,我们需要一个调用回调函数的函数。这也是一个函数,但是有什么区别我们可以称之为中间函数吗?它是通过形式参数调用的,而不是在函数体内调用。被调用的函数是另一个函数的地址。该函数将是一个回调函数。
void wherecallback(void *name()){ printf(‘你来自哪里?\n’);}
好了,现在你明白了,但是这个函数到底是做什么的呢?要了解这个函数的奥秘,首先问自己三个问题。
什么是回调函数?如何开发和使用回调函数?回调函数的作用是什么?以及在什么情况下应该使用它呢?我打开百度搜了很多资料如下:
第一个问题:
事实上,回调就是使用函数指针进行函数调用的过程。
为什么要使用回调呢?比如我想创建一个子模块来接收来自远程套接字的命令,当接收到命令时,它需要调用主模块中的函数来做相应的处理。我不知道我想用什么函数来处理这个命令以及主模块是什么。这意味着您不必担心主模块中如何处理它。我应该关心该函数的作用吗?我该怎么做?
使用回调!
自己创建回调函数。我需要调用另一个函数。该函数的参数之一是回调函数的名称。这样,系统就可以根据需要调用您创建的回调函数,并完成您希望回调函数执行的任何操作。
由于我阅读了这么多信息,我将用一句话总结每个定义。回调函数是函数指针的一种用法。
第二个问题:
我实现了一个非常简单的回调函数。
#include stdio.hvoid on_callbackBJ(){ printf(‘我来自北京。\n’);}void on_callbackSH(){ printf(‘我来自上海。\n’);}void wherecallback(void* name () ){ printf(‘你来自哪里?\n’); name();}int main(){ wherecallback(on_callbackSH);
用过STL的人都知道,它的很多算法和程序都是使用回调函数来实现策略的。你可以使用我的公式,只要它们是符合我的标准的函数或计算。您可以实现各种回调函数,只要它们符合我的格式即可。
只要函数的格式遵循clllback 的第二个参数的格式,上面的程序在烹饪食物或铺床时就可以正常工作。这就是回调的用途,将回调实现留给其他人。
概括
根据上面的答案,我对回调函数及其作用的理解是:我自己写了函数B来实现一个特定的功能。这是你的回调函数。当您调用API 函数时,该函数的某些参数需要指向该函数的指针或回调函数。你不需要关心API函数说什么,你只需要知道它实现了什么。在理解了函数和各个参数的含义后,你还可以将你创建的用于实现特定功能的函数B作为参数传递。当然,你也可以传递函数C或函数D来满足你的需求。
回归正题
现在,回到主题。如何理解OpenCV 中的回调函数。如上所述,我们需要调用OpenCV的API函数creatTrackbar()及其函数原型。
int createTrackbar(conststring trackbarname, conststring winname, int* value, int count, TrackbarCallback onChange=0, void* userdata=0); 您不需要知道这个函数的内部结构是什么。每一个都有它自己的意义。参数:
第一个参数trackbarname,类型为const string,表示轨迹栏的名称,用于表示你创建的轨迹栏。
第二个参数winname 为const string 类型,输入窗口的名称并指示该跟踪栏附加到哪个窗口。这对应于nameWindow() 创建窗口时输入的特定窗口名称。
第三个参数是int* 类型,是一个指向指示滑块位置的整数的指针。此外,创建滑块时的初始位置是变量的当前值。
第四个参数(int类型的count)表示滑块可以到达的最大位置值。 PS:滑块最小位置值始终为0。
首先要注意的是第五个参数,即TrackbarCallback 类型的onChange,其默认值为0。这是一个指向回调函数的指针,每当滑块的位置发生变化时就会调用该回调函数。该函数的原型必须是void XXXX(int,void*)。第一个参数是轨迹栏位置,第二个参数是用户数据(见下面的第6个参数)。如果回调是NULL指针,则表示没有调用回调函数,仅更改了第三个参数值。
第六个参数,void*类型的userdata,默认值也是0。该参数是用户传递给回调函数的数据,用于处理轨迹栏事件。如果使用的第三个参数值(实际参数)是全局变量,则可以完全忽略userdata 参数。
以及它的作用:
createTrackbar 函数创建具有特定名称和范围的轨迹栏(轨迹栏或滑块范围控制工具),并指定与轨迹栏位置同步的变量。您还必须指定一个回调函数onChange(第五个参数),当轨迹栏位置发生变化时将调用该函数。然后您将看到创建的轨迹栏将显示在指定winname(第二个参数)代表的窗口中。
剩下的就是在回调函数中处理。只需编写您最喜欢的函数并通过它即可。如果您想实现二进制处理,请执行此操作。
void onChangeTrackBar(int pos, void* usrdata){ //strong制类型转换Mat src=*(Mat*)(usrdata); //二值化阈值(src, dst, pos, ‘二值化’, dst);} 结果:
如果您想混合两个图像并调整其透明度,请执行以下操作:
void on_Trackbar(int , void* ){ alphaVal=(double)alphaValSlider/maxAlphaVal; betaVal=(1.0 – alphaVal); addWeighted(src1, alphaVal, src2, betaVal, 0.0, dst);
原创文章,作者:小条,如若转载,请注明出处:https://www.sudun.com/ask/87185.html