使用OpenCv在电影上绘制可调节网格

时间:2014-08-11 09:57:27

标签: c++ opencv overlay

我有一个我自己无法解决的问题。关于我的编程技巧,我是初学者,我希望你能帮助我解决我的问题! 我正在使用OS X 10.9.4和Xcode 5.1.1

运行Mac

首先,我编写了一个程序来在图像上绘制网格。通过更改变量n,可以使用Opencv GUI滑块调整网格密度。 然后我尝试在电影而不是图片上获得同样的东西。 不幸的是,我没有成功完成这项任务。为了获得电影的帧,我在网上找到了一段代码。图片的帧在无限循环内捕获:while(1)

当我在while(1)循环之外放置绘制循环(用于绘制网格线)和on_trackbar函数(用于调用滑块)时,我的印象是程序被困在我的无限循环中并且它从不调用轨迹栏功能。 当我将我的函数放在无限循环中时,电影正在出现但没有滑块和网格出现。 不幸的是我无法创建透明图像(标量(255,255,255,255)),然后将两个图像相加。 输入参数的大小不匹配(我相信不同的通道数量?)

这是我的代码:

//program to draw a nxn grid on a movie
//variable n can be adjusted with the Opencv GUI slider


#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "opencv2/opencv.hpp"
#include <iostream>


using namespace cv;
using namespace std;

/// Global Variables
const int n_slider_max = 9; ///highest density grid will be max+1/max+1 = 10/10
int n_slider;

/// Function header
void MyLine( Mat img, Point start, Point end );
void on_trackbar(int, void*);

int main( void ){

/// Initialize values
  n_slider = 0;

/// 2. Create Trackbar
  char TrackbarName[100];
  sprintf( TrackbarName, "N range [1,10]");

  createTrackbar( TrackbarName, "Myvideo", &n_slider, n_slider_max, on_trackbar );

/// Show some stuff
 on_trackbar( n_slider, 0 );

  waitKey( 0 );
  return(0);
}

/// Function Declaration

/**
 * @function MyLine
 * @brief Draw a simple line
 */
void MyLine( Mat img, Point start, Point end )
{
  int thickness = 2;
  int lineType = 8;
  line( img,
    start,
    end,
    Scalar( 0, 0, 255 ),
    thickness,
    lineType );
}

/**
 * @function on_trackbar
 * @brief Callback for trackbar
 */
void on_trackbar( int, void* )
{


  VideoCapture cap("movie.avi");

    //get width and height of movie frames
    int frame_width = cap.get(CV_CAP_PROP_FRAME_WIDTH);
    int frame_height = cap.get(CV_CAP_PROP_FRAME_HEIGHT);


  namedWindow("MyVideo",CV_WINDOW_AUTOSIZE); //create a window called "MyVideo"



    // Movie Loop: loop to read video frames and display them in a window
loop:while(1)
    {
        Mat frame;

        bool bSuccess = cap.read(frame); // read a new frame from video

        if (!bSuccess) //if not success, break loop
        {
            cout << "Cannot read the frame from video file" << endl;
            break;
        }

        /// Create an empty black image with the dimensions of the frame
        // when I try to create an transparent image with Scalar (255,255,255,255)
        // I get an error message telling me that the size of the input arguments do not match.
        Mat grid_image = zeros( frame_height, frame_width, CV_8UC3 );

        //Draw loop
        for(int i=1; i<n_slider+1; ++i)
        {//vertical lines
            MyLine( grid_image, Point( grid_image.cols*i/(n_slider+1), 0 ), Point(grid_image.cols*i/(n_slider+1), grid_image.rows ) );

            //horizontal lines
            MyLine( grid_image, Point( 0, grid_image.rows*i/(n_slider+1) ), Point( grid_image.cols,grid_image.rows*i/(n_slider+1) ) );
        }

        //Create a new image for mixing
        Mat mixed_image;


        addWeighted(grid_image,0.2,frame,0.8,0.0, mixed_image);
        imshow("MyVideo", mixed_image); //show the frame in "MyVideo" window


        if(waitKey(30) == 27) //wait for 'esc' key press for 30 ms. If 'esc' key is pressed, break loop
        {
            cout << "esc key is pressed by user" << endl;
            break;
        }

    }



}

感谢您阅读我的帖子,希望您能帮助我。

干杯

Krunch

2 个答案:

答案 0 :(得分:0)

on_trackbar()函数是一个回调函数。只有在对轨迹栏位置进行更改时才会调用它。因此,根据您的代码,一旦您进行了更改,它就永远不会退出回调。

您的代码部分应该是:

void on_trackbar()
{

//modify the value of n (possibly global)

}


int main()
{

  VideoCapture cap(..);
  createTrackbar(..);

  while(1)

  ..

}

答案 1 :(得分:0)

非常感谢你的帮助。

我根据您的建议重新构建了我的代码。我的程序现在正在运行! 代码更简洁。该程序现在直接将网格线绘制到相机框架上,而不是对图像进行叠加。

这是新代码:

//Program to draw a nxn grid on a movie
//The grid density can adjusted with the Opencv GUI slider


#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "opencv2/opencv.hpp"
#include <iostream>


using namespace cv;
using namespace std;

/// Global Variables
const int n_slider_max = 9; ///highest density grid will be max+1/max+1 = 10/10
int n_slider;

/// Function header
void MyLine( Mat img, Point start, Point end );
void on_trackbar(int, void*);

int main( int argc, char** argv ){

    /// Initialize values
    n_slider = 0;


    //Capture the movie given as a command line argument
    VideoCapture cap(argv[1]);


    //create a window called "Video"
    namedWindow("Video",CV_WINDOW_AUTOSIZE);

    /// 2. Create Trackbar
    char TrackbarName[100];
    sprintf( TrackbarName, "N range [1,10]");

    createTrackbar( TrackbarName, "Video", &n_slider, n_slider_max, on_trackbar );


    // Movie Loop: loop to read video frames and display them in a window
    while(1)
    {
        Mat frame;

        bool bSuccess = cap.read(frame); // read a new frame from video

        if (!bSuccess) //if not success, break loop
        {
            cout << "Cannot read the frame from video file" << endl;
            break;
        }


        //Draw loop
        for(int i=1; i<n_slider+1; ++i)
        {//vertical lines
            MyLine( frame, Point( frame.cols*i/(n_slider+1), 0 ), Point(frame.cols*i/(n_slider+1), frame.rows ) );

            //horizontal lines
            MyLine( frame, Point( 0, frame.rows*i/(n_slider+1) ), Point( frame.cols,frame.rows*i/(n_slider+1) ) );
        }


        //Show the movie
        imshow("Video", frame);


        if(waitKey(30) == 27) //wait for 'esc' key press for 30 ms. If 'esc' key is pressed, break loop
        {
            cout << "esc key is pressed by user" << endl;
            break;
        }

    }

    waitKey( 0 );
    return(0);

}

/// Function Declaration

/**
 * @function MyLine
 * @brief Draw a simple line
 */
void MyLine( Mat img, Point start, Point end )
{
    int thickness = 1;
    int lineType = 8;
    line( img,
         start,
         end,
         Scalar( 0, 0, 255 ),
         thickness,
         lineType );
}

/**
 * @function on_trackbar
 * @brief Callback for trackbar
 */
void on_trackbar( int, void* )
{

}