Как нарисовать линию на кадре из живого видео в opencv c ++ - PullRequest
1 голос
/ 11 июня 2019

Я хочу нарисовать линию на фрейме opencv в c ++.Для этого у меня есть код ниже, где я использую setMouseCallback(winName, onMouse, NULL);.В приведенном ниже коде я использую изображение:

Mat src;
const char* winName = "Image";
int start_x = 0;
int start_y = 0;
bool run_once = false;

void onMouse(int event, int x, int y, int f, void*) 
{

    if (cv::EVENT_LBUTTONDOWN)
    {
        if (f == 1)
        {
            if (run_once == false)
            {
                start_x = x;
                start_y = y;
                cout << "start x,y is : " << x << y << endl;
                run_once = true;

            }
        }
        if (f == 3)
        {
            cout << "start x,y is : " << start_x << start_y << endl;
            int end_x = x;
            int end_y = y;
            cout << "end x,y  is : " << end_x << end_y << endl;
            cv::line(src, cv::Point(start_x, start_y), cv::Point(end_x, end_y), Scalar(255), 2, 8, 0);
            imshow(winName, src);
            run_once = false;
        }


    }
}

int main()
{
    src = imread(<img path>, 1);

    namedWindow(winName, WINDOW_NORMAL);
    setMouseCallback(winName, onMouse, NULL);
    imshow(winName, src);
    while(1)
    {


    }

}

Используя приведенный выше код, если я щелкну левой кнопкой мыши на рамке, он записывает start_x start_y.Я перетаскиваю свою мышь влево / вправо, а затем щелкаю правой кнопкой мыши, и она записывает end_x end_y, просто рисует линию и отображает ее.Это прекрасно работает, но я хочу добиться этой функциональности в кадре живого видео.

Проблема, с которой я сталкиваюсь в кадре живого видео, заключается в том, что в канале живого видео мы постоянно отображаем кадр в цикле while(1), таким образомнарисованная линия удаляется в следующем кадре

void onMouse(int event, int x, int y, int f, void*)
{
   /*
    * SAME AS ABOVE
    */
}

int main(int, char**)
{
    VideoCapture cap(1); // open the default camera
    if (!cap.isOpened())  // check if we succeeded
        return -1;
    namedWindow(winName, WINDOW_NORMAL);
    setMouseCallback(winName, onMouse, NULL);


    for (;;)
    {

        cap >> src; // get a new frame from camera
        imshow(winName, src);
        if (waitKey(30) >= 0) break;
    }
    // the camera will be deinitialized automatically in VideoCapture destructor
    return 0;
}

В вышеприведенном коде у нас есть функция onMouse, где мы используем imshow, чтобы показать линию, нарисованную на кадре, но у нас также есть imshow in while(1), поэтому нарисованная линия не отображается.

Можно ли в любом случае нарисовать линию на кадре прямой трансляции видео.Пожалуйста помоги.Спасибо

1 Ответ

1 голос
/ 11 июня 2019

Как предложил @Sunreef, вы можете создать отдельный cv::Mat, чтобы сохранить изображение только со строками и отображать src в сочетании с этим изображением

// #0 NEW - add declaration of lines here so this Mat is visible in both onMouse and main scope
cv::Mat src, lines;

void onMouse(int event, int x, int y, int f, void*)
{        
    if (f == 3)
    {
        cout << "start x,y is : " << start_x << start_y << endl;
        int end_x = x;
        int end_y = y;
        cout << "end x,y  is : " << end_x << end_y << endl;

        // #1 NEW - draw line into lines instead of src
        cv::line(lines, cv::Point(start_x, start_y), cv::Point(end_x, end_y), Scalar(255), 2, 8, 0);

        // #2 NEW - remove unnecessary imshow here

        run_once = false;
     }
}

int main(int, char**)
{
    for (;;)
    {
        cap >> src; 

        // #3 NEW - init lines once, to be the same size, same type as src filled with zeros
        if(lines.empty()) lines = cv::Mat::zeros(src.size(), src.type());

        // #4 NEW - show lines combined with lines            
        imshow(winName, lines + src);

        if (waitKey(30) >= 0) break;
    }
    return 0;
}

Таким образом только lines изображение обновляется в onMouse (# 1).Нет необходимости показывать его в событии onMouse (# 2), так как оно все равно будет отображаться в основном цикле (# 4).Но перед тем, как вы действительно отобразите строки, вы накладываете (добавляете) их на изображение src.Единственная сложная задача - инициализировать lines, как только вы узнаете размер и тип src (# 3).И не забудьте сначала объявить lines (# 0), чтобы изображение было видимым глобально, точно так же, как src.

Я также предлагаю ознакомиться с:

...