opencv:理解cvsetcaptureproperty函数和参数

opencv: understanding cvsetcaptureproperty function and argument

本文关键字:参数 函数 cvsetcaptureproperty 理解 opencv      更新时间:2023-10-16

我开始学习openCv,但我在理解函数的最后一个参数(双值)时遇到了一些困难

int cvSetCaptureProperty(CvCapture* capture, int property_id, double value)

我知道这是c++中使用的一个命题,但它在下面的代码中是如何工作的?

void onTrackSlide(int pos)
{
    cvSetCaptureProperty(cap, CV_CAP_PROP_POS_FRAMES, pos);
}

然后在主程序中调用它,如下所示:

cvCreateTrackbar("position", "example3", &slider, frames, onTrackSlide);

我不明白为什么在onTrackSlide函数的参数中从来没有填充或使用pos。

这是完整的程序:

#include<opencvcv.h>
#include<opencvhighgui.h>
#include "opencv2/opencv.hpp"
//#include <iostream>
using namespace cv;
int slider=0;
CvCapture* cap = NULL;
void onTrackSlide(int pos)
{
    cvSetCaptureProperty(cap, CV_CAP_PROP_POS_FRAMES, pos);
}

int main(int argc, char ** argv)
{
    cvNamedWindow("example3", CV_WINDOW_AUTOSIZE);
    cap = cvCreateFileCapture(argv[1]);
    int frames = (int)cvGetCaptureProperty(cap, CV_CAP_PROP_FRAME_COUNT);
    if (frames != 0)
    {
        cvCreateTrackbar("position", "example3", &slider, frames, onTrackSlide);
    }
    IplImage* frame;
    while (1)
    {
        frame = cvQueryFrame(cap);
        if (!frame)break;
        cvShowImage("example3", frame);
        char c = cvWaitKey(33);
        if (c == 27)  break;
    }
    cvReleaseCapture(&cap);
    cvDestroyWindow("example3");

}
createTrackbar是OpenCV用户界面(Highgui)的一个函数,它接受回调函数onChange:

C++:int createTrackbar(常量字符串和trackbarname,常量字符串和winname,int*值,int计数,TrackbarCallback onChange=0,void*userdata=0)

C:int cvCreateTrackbar(const char*trackbar_name,const char*window_name,int*value,int count,CvTrackbarCallback on_change=NULL

其中

onChange–指向每次滑块更改位置时要调用的函数的指针。此函数应原型化为void Foo(int,void*);,其中第一个参数是跟踪条位置

您定义的回调onChange类似于:

void onTrackSlide(int pos)
{ 
    // pos is the current trackbar position
    ...
}

由CCD_ 5内部回叫系统调用。每次移动轨迹条时,都会使用新的pos值调用回调。


从注释中,您定义了一个回调函数,如:

void onTrackSlide() 
{ 
    int pos; 
    cvSetCaptureProperty(cap, CV_CAP_PROP_POS_FRAMES, pos); 
}

并且这个不会工作,因为变量pos永远不会被初始化。


您也可以使用getTrackbarPos来获取轨迹条的当前值。

此代码使用跟踪条读取视频文件,跟踪条遵循读取过程。

#include <opencv2/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/videoio/videoio_c.h>
#include <iostream>
using namespace cv;

//First we defi ne a global variable for the slider position.
int g_slider_position = 0;

/*
    cv::VideoCapture::VideoCapture  (   const String &  filename    )
    Open video file or a capturing device or a IP video stream for video capturing with API Preference.
    Parameters: filename    it can be:
    1- name of video file (eg. video.avi)
    2- or image sequence (eg. img_%02d.jpg, which will read samples like img_00.jpg, img_01.jpg, img_02.jpg, ...)
    3- or URL of video stream (eg. protocol://host:port/script_name?script_params|auth)
    4- or GStreamer pipeline string in gst-launch tool format in case if GStreamer is used as backend Note that each video stream
       or IP camera feed has its own URL scheme. Please refer to the documentation of source stream to know the right URL.
*/
VideoCapture capture("../../videos/Mahrez.mp4"); //put your own video path.
Mat img;
/*
Now we defi ne a callback routine to be used when the user pokes the slider.
function to be called every time the slider changes position.This function should be prototyped as void Foo(int, void*);, 
where the first parameter is the trackbar position and the second parameter is the user data.
*/
void onTrackbarSlide(int position, void* data)
{
    /*
    CV_CAP_PROP_POS_FRAMES indicates that we would like to set the read position
    in units of frames. (We can use AVI_RATIO instead of FRAMES if we want to set the position as a fraction of the overall video length).
    Finally, we pass in the new value of the position.
    */
    capture.set(CAP_PROP_POS_FRAMES, position);
}
int main()
{
    namedWindow("Video_Slider", WINDOW_AUTOSIZE);
    
    /*
    cv::VideoCapture::get (int propId)  In this case, we want to find out how many frames are in the video
    so that we can calibrate the slider (in the next step).
    */
    int frames = (int) capture.get(CAP_PROP_FRAME_COUNT);
    if (frames != 0)
    {
        createTrackbar("Trackbar", "Video_Slider", &g_slider_position, frames, onTrackbarSlide);
    }
    while (true)
    {
        /*
        We then wait for 25 ms.* If the user hits a key, then c will be set to the ASCII value of that key;
        if not, then it will be set to –1. If the user hits the Esc key (ASCII 27), then we will exit the read loop.
        Otherwise, 25 ms will pass and we will just execute the loop again.
        We can control the speed of the video by adjusting the waitKey(25). It waits 25 ms to read the next frame.
        */
        char c = waitKey(25);
        if (c == 27) break;
        bool bSuccess = capture.read(img); // read a new frame from video 
        //Breaking the while loop at the end of the video
        if (bSuccess == false) break;
        /*
         The imshow() function requires that a named window already exist(created by cvNamedWindow()).
         */
        imshow("Video_Slider", img);
        /*
        void cv::setTrackbarPos (const String & trackbarname, const String & winname, int position) 
        This function sets the position of the specified trackbar in the specified window.
        */
        setTrackbarPos("Trackbar", "Video_Slider", g_slider_position);
        // Increment the slider position after reading each frame.
        g_slider_position++;
    }
    capture.release();
    destroyAllWindows();
    return 0;
}