- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我真的需要特别了解这个功能是如何工作的,也许在所有功能中也可以从文档中了解。这是来自 opencv 函数的文档:这只是其中之一。
int cv::createTrackbar (const String & trackbarname, const String & winname,
int * value, int count, TrackbarCallback onChange = 0,void * userdata = 0)
这是某人编写的有效代码:
createTrackbar("H_MIN", trackbarWindowName, &H_MIN, H_MAX, on_trackbar);
createTrackbar("H_MAX", trackbarWindowName, &H_MAX, H_MAX, on_trackbar);
createTrackbar("S_MIN", trackbarWindowName, &S_MIN, S_MAX, on_trackbar);
createTrackbar("S_MAX", trackbarWindowName, &S_MAX, S_MAX, on_trackbar);
createTrackbar("V_MIN", trackbarWindowName, &V_MIN, V_MAX, on_trackbar);
createTrackbar("V_MAX", trackbarWindowName, &V_MAX, V_MAX, on_trackbar);
现在我的问题是:
int
,为什么 createTrackbar
没有 int ?&
在 const String & trackbarname
中是什么意思,我可以理解 "H_MIN"
是一个常量字符串,它是一个 trackbarname ,但是 &
是什么意思,为什么不在该代码中也写 &
呢?const String & winname
中,也就是说&
是什么意思?int * value
,value指针指向一个int,声明在全局变量中,为什么写起来这么复杂?我们不能只写 int H_MIN = 0
(如果我是对的),H_MAX = 256
吗?int count
,那个代码到底在哪里?TrackbarCallback onChange = 0
,我不明白这个void * userdata = 0
他编写了一个名为 on_trackbar
的函数,其中只有这个:void on_trackbar(int, void*){}
我也不明白这个很抱歉问了太多,我只需要真正了解我将如何正确或自定义地从文档中编写函数。
这里是所有的代码:
//objectTrackingTutorial.cpp
//Written by Kyle Hounslow 2013
//Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software")
//, to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
//and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
//IN THE SOFTWARE.
#include <sstream>
#include <string>
#include <iostream>
#include <opencv\highgui.h>
#include <opencv\cv.h>
#include <opencv2\opencv.hpp>
#include <vector>
using namespace cv;
using namespace std;
//initial min and max HSV filter values.
//these will be changed using trackbars
int H_MIN = 0;
int H_MAX = 256;
int S_MIN = 0;
int S_MAX = 256;
int V_MIN = 0;
int V_MAX = 256;
//default capture width and height
const int FRAME_WIDTH = 640;
const int FRAME_HEIGHT = 480;
//max number of objects to be detected in frame
const int MAX_NUM_OBJECTS = 50;
//minimum and maximum object area
const int MIN_OBJECT_AREA = 20 * 20;
const int MAX_OBJECT_AREA = FRAME_HEIGHT*FRAME_WIDTH / 1.5;
//names that will appear at the top of each window
const string windowName = "Original Image";
const string windowName1 = "HSV Image";
const string windowName2 = "Thresholded Image";
const string windowName3 = "After Morphological Operations";
const string trackbarWindowName = "Trackbars";
void on_trackbar(int, void*)
{//This function gets called whenever a
// trackbar position is changed
}
string intToString(int number){
std::stringstream ss;
ss << number;
return ss.str();
}
void createTrackbars(){
//create window for trackbars
namedWindow(trackbarWindowName, 0);
//create memory to store trackbar name on window
char TrackbarName[50];
sprintf_s(TrackbarName, "H_MIN", H_MIN);
sprintf_s(TrackbarName, "H_MAX", H_MAX);
sprintf_s(TrackbarName, "S_MIN", S_MIN);
sprintf_s(TrackbarName, "S_MAX", S_MAX);
sprintf_s(TrackbarName, "V_MIN", V_MIN);
sprintf_s(TrackbarName, "V_MAX", V_MAX);
//create trackbars and insert them into window
//3 parameters are: the address of the variable that is changing when the trackbar is moved(eg.H_LOW),
//the max value the trackbar can move (eg. H_HIGH),
//and the function that is called whenever the trackbar is moved(eg. on_trackbar)
// ----> ----> ---->
createTrackbar("H_MIN", trackbarWindowName, &H_MIN, H_MAX, on_trackbar);
createTrackbar("H_MAX", trackbarWindowName, &H_MAX, H_MAX, on_trackbar);
createTrackbar("S_MIN", trackbarWindowName, &S_MIN, S_MAX, on_trackbar);
createTrackbar("S_MAX", trackbarWindowName, &S_MAX, S_MAX, on_trackbar);
createTrackbar("V_MIN", trackbarWindowName, &V_MIN, V_MAX, on_trackbar);
createTrackbar("V_MAX", trackbarWindowName, &V_MAX, V_MAX, on_trackbar);
}
void drawObject(int x, int y, Mat &frame){
//use some of the openCV drawing functions to draw crosshairs
//on your tracked image!
//UPDATE:JUNE 18TH, 2013
//added 'if' and 'else' statements to prevent
//memory errors from writing off the screen (ie. (-25,-25) is not within the window!)
circle(frame, Point(x, y), 20, Scalar(0, 255, 0), 2);
if (y - 25>0)
line(frame, Point(x, y), Point(x, y - 25), Scalar(0, 255, 0), 2);
else line(frame, Point(x, y), Point(x, 0), Scalar(0, 255, 0), 2);
if (y + 25<FRAME_HEIGHT)
line(frame, Point(x, y), Point(x, y + 25), Scalar(0, 255, 0), 2);
else line(frame, Point(x, y), Point(x, FRAME_HEIGHT), Scalar(0, 255, 0), 2);
if (x - 25>0)
line(frame, Point(x, y), Point(x - 25, y), Scalar(0, 255, 0), 2);
else line(frame, Point(x, y), Point(0, y), Scalar(0, 255, 0), 2);
if (x + 25<FRAME_WIDTH)
line(frame, Point(x, y), Point(x + 25, y), Scalar(0, 255, 0), 2);
else line(frame, Point(x, y), Point(FRAME_WIDTH, y), Scalar(0, 255, 0), 2);
putText(frame, intToString(x) + "," + intToString(y), Point(x, y + 30), 1, 1, Scalar(0, 255, 0), 2);
}
void morphOps(Mat &thresh){
//create structuring element that will be used to "dilate" and "erode" image.
//the element chosen here is a 3px by 3px rectangle
Mat erodeElement = getStructuringElement(MORPH_RECT, Size(3, 3));
//dilate with larger element so make sure object is nicely visible
Mat dilateElement = getStructuringElement(MORPH_RECT, Size(8, 8));
erode(thresh, thresh, erodeElement);
erode(thresh, thresh, erodeElement);
dilate(thresh, thresh, dilateElement);
dilate(thresh, thresh, dilateElement);
}
void trackFilteredObject(int &x, int &y, Mat threshold, Mat &cameraFeed){
Mat temp;
threshold.copyTo(temp);
//these two vectors needed for output of findContours
vector< vector<Point> > contours;
vector<Vec4i> hierarchy;
//find contours of filtered image using openCV findContours function
findContours(temp, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
//use moments method to find our filtered object
double refArea = 0;
bool objectFound = false;
if (hierarchy.size() > 0) {
int numObjects = hierarchy.size();
//if number of objects greater than MAX_NUM_OBJECTS we have a noisy filter
if (numObjects<10){
for (int index = 0; index >= 0; index = hierarchy[index][0]) {
Moments moment = moments((cv::Mat)contours[index]);
double area = moment.m00;
//if the area is less than 20 px by 20px then it is probably just noise
//if the area is the same as the 3/2 of the image size, probably just a bad filter
//we only want the object with the largest area so we safe a reference area each
//iteration and compare it to the area in the next iteration.
if (area>400 && area<FRAME_HEIGHT*FRAME_WIDTH/1.5 && area>refArea){
printf("%f \n", area);
x = moment.m10 / area;
y = moment.m01 / area;
objectFound = true;
refArea = area;
}
else objectFound = false;
}
//let user know you found an object
if (objectFound == true){
putText(cameraFeed, "Tracking Object", Point(0, 50), 2, 1, Scalar(0, 255, 0), 2);
//draw object location on screen
drawObject(x, y, cameraFeed);
}
}
else putText(cameraFeed, "TOO MUCH NOISE! ADJUST FILTER", Point(0, 50), 1, 2, Scalar(0, 0, 255), 2);
}
}
int main(int argc, char* argv[])
{
//some boolean variables for different functionality within this
//program
bool trackObjects = true;
bool useMorphOps = true;
//Matrix to store each frame of the webcam feed
Mat cameraFeed;
//matrix storage for HSV image
Mat HSV;
//matrix storage for binary threshold image
Mat threshold;
//x and y values for the location of the object
int x = 0, y = 0;
//create slider bars for HSV filtering
createTrackbars();
//video capture object to acquire webcam feed
VideoCapture capture;
//open capture object at location zero (default location for webcam)
capture.open(0);
//set height and width of capture frame
capture.set(CV_CAP_PROP_FRAME_WIDTH, FRAME_WIDTH);
capture.set(CV_CAP_PROP_FRAME_HEIGHT, FRAME_HEIGHT);
//start an infinite loop where webcam feed is copied to cameraFeed matrix
//all of our operations will be performed within this loop
while (1){
//store image to matrix
capture.read(cameraFeed);
//convert frame from BGR to HSV colorspace
cvtColor(cameraFeed, HSV, COLOR_BGR2HSV);
//filter HSV image between values and store filtered image to
//threshold matrix
inRange(HSV, Scalar(H_MIN, S_MIN, V_MIN), Scalar(H_MAX, S_MAX, V_MAX), threshold);
//perform morphological operations on thresholded image to eliminate noise
//and emphasize the filtered object(s)
if (useMorphOps)
morphOps(threshold);
//pass in thresholded frame to our object tracking function
//this function will return the x and y coordinates of the
//filtered object
if (trackObjects)
trackFilteredObject(x, y, threshold, cameraFeed);
//show frames
imshow(windowName2, threshold);
imshow(windowName, cameraFeed);
imshow(windowName1, HSV);
//delay 30ms so that screen can refresh.
//image will not appear without this waitKey() command
waitKey(30);
}
return 0;
}
最佳答案
按顺序:
1) 最后一个参数 userdata 是默认的,从函数签名中的 =0 可以看出。这意味着如果您没有为参数指定值,它将被设置为默认值 0。
2) createTrackbar 的返回类型为 int,但是,您通过不将 createTrackbar 设置为变量来忽略此数据,这在您的情况下很好。
3) & 表示按引用传递。这意味着您传递给函数的变量可以在函数执行期间被修改。参见 here 了解更多信息。
4)同上
5) 这不一定是全局的。这里发生的是您将整数的内存地址传递给函数。这将允许该函数取消引用该内存地址中的内容。如果您不熟悉 c 和 c++ 如何处理指针/引用/内存,您应该考虑对其进行一些研究,因为它是 c 编程不可或缺的概念。一个好的起点是 here .就这个变量的作用而言,本质上,它是一个你可以引用的变量的地址,它随着 slider 的位置而更新,这样你就不需要每次都调用 slider 函数,如果你只是捕获来自 slider 的值。
6) 计数是 slider 上的最大位置。这在文档中很清楚。
7) 这个 onchange 方法是对一个函数的回调,只要轨迹栏位置发生变化就可以执行该函数。它默认为 0,这意味着如果您不指定要在轨迹栏移动时调用的函数,则不会调用任何函数。如果您只是想获取轨迹栏的值,请参阅我为第 5 点编写的内容并改用值参数。
8)这不是用户数据参数。由于其类型,编译器能够看到 on_trackbar 实际上是 onchange 的参数。因此,他实际上是将userdata默认为0,并且在trackbar移动时具有功能。有关这方面的更多信息,您应该阅读 c 中的编译器时多态性。关于它的好帖子 here
看来您还没有完全掌握 C 和 C++ 基础知识。我建议您通读一本关于 C 或 C++ 的书,因为您可以使用您谈到的一些概念来做一些非常强大的事情。祝你好运!
关于c++ - 这个 opencv 函数如何在 C++ 中解释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36674106/
#include using namespace std; class C{ private: int value; public: C(){ value = 0;
这个问题已经有答案了: What is the difference between char a[] = ?string?; and char *p = ?string?;? (8 个回答) 已关闭
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 7 年前。 此帖子已于 8 个月
除了调试之外,是否有任何针对 c、c++ 或 c# 的测试工具,其工作原理类似于将独立函数复制粘贴到某个文本框,然后在其他文本框中输入参数? 最佳答案 也许您会考虑单元测试。我推荐你谷歌测试和谷歌模拟
我想在第二台显示器中移动一个窗口 (HWND)。问题是我尝试了很多方法,例如将分辨率加倍或输入负值,但它永远无法将窗口放在我的第二台显示器上。 关于如何在 C/C++/c# 中执行此操作的任何线索 最
我正在寻找 C/C++/C## 中不同类型 DES 的现有实现。我的运行平台是Windows XP/Vista/7。 我正在尝试编写一个 C# 程序,它将使用 DES 算法进行加密和解密。我需要一些实
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
有没有办法强制将另一个 窗口置于顶部? 不是应用程序的窗口,而是另一个已经在系统上运行的窗口。 (Windows, C/C++/C#) 最佳答案 SetWindowPos(that_window_ha
假设您可以在 C/C++ 或 Csharp 之间做出选择,并且您打算在 Windows 和 Linux 服务器上运行同一服务器的多个实例,那么构建套接字服务器应用程序的最明智选择是什么? 最佳答案 如
你们能告诉我它们之间的区别吗? 顺便问一下,有什么叫C++库或C库的吗? 最佳答案 C++ 标准库 和 C 标准库 是 C++ 和 C 标准定义的库,提供给 C++ 和 C 程序使用。那是那些词的共同
下面的测试代码,我将输出信息放在注释中。我使用的是 gcc 4.8.5 和 Centos 7.2。 #include #include class C { public:
很难说出这里问的是什么。这个问题是含糊的、模糊的、不完整的、过于宽泛的或修辞性的,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开它,visit the help center 。 已关
我的客户将使用名为 annoucement 的结构/类与客户通信。我想我会用 C++ 编写服务器。会有很多不同的类继承annoucement。我的问题是通过网络将这些类发送给客户端 我想也许我应该使用
我在 C# 中有以下函数: public Matrix ConcatDescriptors(IList> descriptors) { int cols = descriptors[0].Co
我有一个项目要编写一个函数来对某些数据执行某些操作。我可以用 C/C++ 编写代码,但我不想与雇主共享该函数的代码。相反,我只想让他有权在他自己的代码中调用该函数。是否可以?我想到了这两种方法 - 在
我使用的是编写糟糕的第 3 方 (C/C++) Api。我从托管代码(C++/CLI)中使用它。有时会出现“访问冲突错误”。这使整个应用程序崩溃。我知道我无法处理这些错误[如果指针访问非法内存位置等,
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
我有一些 C 代码,将使用 P/Invoke 从 C# 调用。我正在尝试为这个 C 函数定义一个 C# 等效项。 SomeData* DoSomething(); struct SomeData {
这个问题已经有答案了: Why are these constructs using pre and post-increment undefined behavior? (14 个回答) 已关闭 6
我是一名优秀的程序员,十分优秀!