这个opencv函数是如何在c++中解释的

How this opencv function explained in c++

本文关键字:c++ 解释 opencv 函数 这个      更新时间:2023-10-16

我确实需要了解这个函数是如何工作的,尤其是在文档中的所有函数中。以下是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);

现在我的问题是:

  1. 有6个论点,为什么那个家伙只写了5个论点
  2. 文档一开始说int,为什么createTrackbar没有int
  3. &const String & trackbarname中的意思是什么,我可以理解"H_MIN"是一个常量字符串,它是一个trackbarname,但&是什么意思,为什么不把&也写在代码中呢
  4. 同样的问题也出现在const String & winname中,即&是均值吗
  5. 在第三个参数int * value中,指向int的值指针,并在全局变量中声明,为什么写起来如此复杂?我们不能只写int H_MIN = 0(如果我是对的),H_MAX = 256
  6. 关于第四个参数int count,那个代码到底在哪里
  7. 第五个论点,TrackbarCallback onChange = 0,我不明白
  8. 最后一个论点,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 <opencvhighgui.h>
#include <opencvcv.h>
#include <opencv2opencv.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) &显示了通过引用传递。这意味着传递函数的变量可以在函数执行期间进行修改。请参阅此处以获取更多信息。

4) 与上述相同

5) 这不一定是全球性的。这里发生的事情是,您将一个整数的内存地址传递给函数。这将允许函数取消引用该内存地址处的内容。如果你不熟悉c和c++如何处理指针/引用/内存,你应该考虑对它进行一些研究,因为它是c编程不可或缺的概念。一个好的起点是这里。就这个变量的作用而言,本质上,它是一个变量的地址,你可以引用它,它会随着滑块的位置而更新,这样,如果你只是从滑块中获取值,你就不需要每次都调用滑块函数。

6) 计数是滑块上的最大位置。这在文档中很清楚。

7) 这个onchange方法是对一个函数的回调,该函数可以在轨迹条位置发生变化时执行。它默认为0,这意味着如果在轨迹条移动时不指定要调用的函数,则不会调用任何函数。如果你只是想获得轨迹条的值,看看我为第5点写了什么,然后使用value参数。

8) 这不是userdata参数。编译器能够看到,由于on_trackbar的类型,它实际上是onchange的参数。因此,他实际上将用户数据默认为0,并在轨迹条移动时具有功能。有关这方面的更多信息,您应该阅读c中的编译器时间多态性。关于它的好文章这里

看起来你还没有很好地掌握你的C和C++基础知识。我建议你读一本关于C或C++的书,因为你可以用你谈论的一些概念做一些非常强大的东西。祝你好运!