在OpenCV处理期间如何保持窗口打开?

时间:2019-01-24 21:45:57

标签: c++ linux opencv ubuntu boost

我在Linux上遇到了一个奇怪的问题,特别是Ubuntu 16.04上的OpenCV。如果我使用通常的代码来显示这样的网络摄像头流,则效果很好:

// WebcamTest.cpp

#include <opencv2/opencv.hpp>

#include <iostream>

int main()
{
  // declare a VideoCapture object and associate to webcam, 1 => use 2nd webcam, the 0th webcam is the one integral to the TX2 development board
  cv::VideoCapture capWebcam(1);

  // check if VideoCapture object was associated to webcam successfully, if not, show error message and bail
  if (capWebcam.isOpened() == false)
  {
    std::cout << "error: capWebcam not accessed successfully\n\n";
    return (0);
  }

  cv::Mat imgOriginal;        // input image
  cv::Mat imgGrayscale;       // grayscale of input image
  cv::Mat imgBlurred;         // intermediate blured image
  cv::Mat imgCanny;           // Canny edge image

  char charCheckForEscKey = 0;

  // while the Esc key has not been pressed and the webcam connection is not lost . . .
  while (charCheckForEscKey != 27 && capWebcam.isOpened())
  {
    bool blnFrameReadSuccessfully = capWebcam.read(imgOriginal);            // get next frame

    // if frame was not read successfully, print error message and jump out of while loop
    if (!blnFrameReadSuccessfully || imgOriginal.empty())
    {
      std::cout << "error: frame not read from webcam\n";
      break;
    }

    // convert to grayscale
    cv::cvtColor(imgOriginal, imgGrayscale, CV_BGR2GRAY);

    // blur image
    cv::GaussianBlur(imgGrayscale, imgBlurred, cv::Size(5, 5), 0);

    // get Canny edges
    cv::Canny(imgBlurred, imgCanny, 75, 150);

    cv::imshow("imgOriginal", imgOriginal);
    cv::imshow("imgCanny", imgCanny);

    charCheckForEscKey = cv::waitKey(1);        // delay (in ms) and get key press, if any
  }  // end while

  return (0);
}

此示例在一个显示窗口中显示网络摄像头流,在第二个窗口中显示Canny边缘图像。两个窗口都会更新并按预期显示图像,并且几乎没有可见的闪烁。

如果您想知道为什么我使用第1个摄像头而不是通常的第0个摄像头,请在Jetson TX2上运行,第0个摄像头是开发板不可或缺的一个,我更喜欢使用其他外部网络摄像头。出于同样的原因,我必须使用Ubuntu 16.04,但是我怀疑结果与Ubuntu 18.04相同(但是尚未测试)。

如果相反,我有一个需要大量处理而不是简单的Canny边缘的函数,即:

int main(void)
{
  .
  .
  .
  // declare a VideoCapture object and associate to webcam, 1 => use 2nd webcam, the 0th webcam is the one integral to the TX2 development board
  cv::VideoCapture capWebcam(1);

  // check if VideoCapture object was associated to webcam successfully, if not, show error message and bail
  if (capWebcam.isOpened() == false)
  {
    std::cout << "error: capWebcam not accessed successfully\n\n";
    return (0);
  }

  cv::namedWindow("imgOriginal");

  cv::Mat imgOriginal;
  char charCheckForEscKey = 0;

  // while the Esc key has not been pressed and the webcam connection is not lost . . .
  while (charCheckForEscKey != 27 && capWebcam.isOpened())
  {    
    bool blnFrameReadSuccessfully = capWebcam.read(imgOriginal);            // get next frame

    // if frame was not read successfully, print error message and jump out of while loop
    if (!blnFrameReadSuccessfully || imgOriginal.empty())
    {
      std::cout << "error: frame not read from webcam\n";
      break;
    }

    detectLicensePlate(imgOriginal);

    cv::imshow("imgOriginal", imgOriginal);

    charCheckForEscKey = cv::waitKey(1);        // delay (in ms) and get key press, if any

  }  // end while
  .
  .
  .
  return (0);
}

detectLicensePlate()函数大约需要运行一秒钟。

我遇到的问题是,在运行该程序时,窗口仅出现最短的时间,通常时间不足以至于无法察觉,也没有足够长的时间才能真正看到结果。

奇怪的是,窗口消失了,然后detectLicensePlate()进行工作的第二天左右,然后窗口再次出现了很短的时间,然后又消失了,依此类推。就像在cv::imshow("imgOriginal", imgOriginal);之后,cv::destroyAllWindows();被隐式调用一样。

我试图实现的行为是使窗口保持打开状态,并在处理下一个结果时继续显示上一个结果。我记得这是Windows上的默认行为。

我应该提到的是,我在while循环之前用cv::namedWindow("imgOriginal");明确声明了Windows,以免使其超出范围,但这似乎无济于事。

我当然可以延长延迟时间,即

charCheckForEscKey = cv::waitKey(1500);

要等待1.5秒,但应用程序将变得非常无响应。

基于本文c++ opencv image not display inside the boost thread,我尝试在while循环之外声明窗口,并将detectLicensePlate()cv::imshow()放在单独的线程中,如下所示:

  .
  .
  .
  cv::namedWindow("imgOriginal");

  boost::thread myThread;

  // while the Esc key has not been pressed and the webcam connection is not lost . . .
  while (charCheckForEscKey != 27 && capWebcam.isOpened())
  {

    // if frame was not read successfully, print error message and jump out of while loop
    if (!blnFrameReadSuccessfully || imgOriginal.empty())
    {
      std::cout << "error: frame not read from webcam\n";
      break;
    }

    myThread = boost::thread(&preDetectLicensePlate, imgOriginal);
    myThread.join();
    .
    .
    .
  } // end while


// separate function
void preDetectLicensePlate(cv::Mat &imgOriginal)
{
  detectLicensePlate(imgOriginal);
  cv::imshow("imgOriginal", imgOriginal);
}

我什至尝试将detectLicensePlate()放在一个单独的线程上,而不是cv::imshow()上,反之,结果仍然相同。无论我如何更改顺序或使用线程,在进行下一轮处理时,都无法使窗口保持打开状态。

我意识到我可以使用完全不同的窗口环境,例如Qt或其他方式,但这可能会解决问题,也可能无法解决问题,但出于各种原因,我真的希望避免这种情况。

是否有人有其他建议来使OpenCV imshow窗口保持打开状态,直到下一次更新该窗口或显式调用cv::destroyAllWindows()为止?

0 个答案:

没有答案