У меня странная проблема с OpenCV в Linux, в частности с Ubuntu 16.04. Если я использую обычный код для показа потока с веб-камеры, он работает нормально:
// 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);
}
В этом примере показан поток веб-камеры в одном окне imshow, а изображение краев Canny - во втором окне. Оба окна обновляются и показывают изображения, как и ожидалось, с очень незначительным, если вообще заметным, мерцанием.
Если вам интересно, почему я использую 1-ую камеру вместо обычной 0-й камеры, я запускаю ее на Jetson TX2, а 0-я камера является неотъемлемой частью платы разработки, и я бы предпочел используйте дополнительную внешнюю веб-камеру. По этой же причине я должен использовать Ubuntu 16.04, но я подозреваю, что результат будет таким же, как и в Ubuntu 18.04 (однако я этого не проверял).
Если вместо этого у меня есть функция, которая занимает значительную обработку вместо того, чтобы брать простые ребра Кэнни, т.е.
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.
Я должен упомянуть, что я явно объявляю окна с cv::namedWindow("imgOriginal");
перед циклом while, пытаясь не выпустить его из области видимости, но это, похоже, не помогает.
Конечно, я могу увеличить задержку, т.е.
charCheckForEscKey = cv::waitKey(1500);
Ожидать 1,5 секунды, но затем приложение перестает отвечать на запросы.
На основании этого поста c ++ opencv-изображение не отображается внутри потока наддува Я попытался объявить окно вне цикла 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()
?