Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenCV Fullscreen Windows on Multiple Monitors

Tags:

opencv

I have an OpenCV application that displays a fullscreen window, via:

cv::namedWindow("myWindow", CV_WINDOW_NORMAL)
cv::setWindowProperties("myWindow", CV_WND_PROP_FULLSCREEN, CV_WINDOW_FULLSCREEN)

It works fine, but when I have multiple monitors it always displays the fullscreen window on the First monitor. Is there any way to display on the 2nd monitor? I've tried setting X/Y and Width/Height, but they seem to be ignored once fullscreen is enabled.

like image 264
Yeraze Avatar asked Jul 02 '14 20:07

Yeraze


3 Answers

Edits:

Sometimes pure OpenCV code cannot do a fullscreen window on a dual display. Here is a Qt way of doing it:

#include <QApplication>
#include <QDesktopWidget>
#include <QLabel>

#include <opencv2/highgui/highgui.hpp>

using namespace cv;

int main(int argc, char *argv[]) 
{
    QApplication app(argc, argv);
    QDesktopWidget dw;
    QLabel myLabel;

    // define dimension of the second display
    int width_second  = 2560;
    int height_second = 1440;

    // define OpenCV Mat
    Mat img = Mat(Size(width_second, height_second), CV_8UC1);

    // move the widget to the second display
    QRect screenres = QApplication::desktop()->screenGeometry(1);
    myLabel.move(QPoint(screenres.x(), screenres.y()));

    // set full screen
    myLabel.showFullScreen();

    // set Qimg
    QImage Qimg((unsigned char*)img.data, img.cols, img.rows, QImage::Format_Indexed8);

    // set Qlabel
    myLabel.setPixmap(QPixmap::fromImage(Qimg));

    // show the image via Qt
    myLabel.show();

    return app.exec();
}

Don't forget to configure the .pro file as:

TEMPLATE = app
QT += widgets
TARGET = main
LIBS += -L/usr/local/lib -lopencv_core -lopencv_highgui

# Input
SOURCES += main.cpp

And in terminal compile your code as:

qmake
make

Original:

It is possible.

Here is a working demo code, to show a full-screen image on a second display. Hinted from How to display different windows in different monitors with OpenCV:

#include <opencv2/highgui/highgui.hpp>

using namespace cv;

int main ( int argc, char **argv )
{
    // define dimension of the main display
    int width_first  = 1920;
    int height_first = 1200;

    // define dimension of the second display
    int width_second  = 2560;
    int height_second = 1440;

    // move the window to the second display 
    // (assuming the two displays are top aligned)
    namedWindow("My Window", CV_WINDOW_NORMAL);
    moveWindow("My Window", width_first, height_first);
    setWindowProperty("My Window", CV_WND_PROP_FULLSCREEN, CV_WINDOW_FULLSCREEN);

    // create target image
    Mat img = Mat(Size(width_second, height_second), CV_8UC1);

    // show the image
    imshow("My Window", img);
    waitKey(0);

    return 0;
}
like image 79
WDC Avatar answered Oct 03 '22 13:10

WDC


I've tried different ways to make it working, but unfortunetely it seems that this is not possible using OpenCV. The only thing you can do is probably display one window on main(primary) screen just using your current code and handle second window manually - set window position, resize image, and just use imshow function to display it. Here is some example:

void showWindowAlmostFullscreen(cv::Mat img, std::string windowTitle, cv::Size screenSize, cv::Point screenZeroPoint)
{
    screenSize -= cv::Size(100, 100); //leave some place for window title bar etc
    double xScallingFactor = (float)screenSize.width / (float)img.size().width;
    double yScallingFactor = (float)screenSize.height / (float)img.size().height;
    double minFactor = std::min(xScallingFactor, yScallingFactor);
    cv::Mat temp;
    cv::resize(img, temp, cv::Size(), minFactor, minFactor);
    cv::moveWindow(windowTitle, screenZeroPoint.x, screenZeroPoint.y);
    cv::imshow(windowTitle, temp);
}

int _tmain(int argc, _TCHAR* argv[])
{
    cv::Mat img1 = cv::imread("D:\\temp\\test.png");
    cv::Mat img2;
    cv::bitwise_not(img1, img2);

    cv::namedWindow("img1", CV_WINDOW_AUTOSIZE);
    cv::setWindowProperty("img1", CV_WND_PROP_FULLSCREEN, CV_WINDOW_FULLSCREEN);

    cv::namedWindow("img2");

    while(cv::waitKey(1) != 'q')
    {
        cv::imshow("img1", img1);
        cv::setWindowProperty("img1", CV_WND_PROP_FULLSCREEN, CV_WINDOW_FULLSCREEN);
        showWindowAlmostFullscreen(img2, "img2", cv::Size(1366, 768), cv::Point(260, 1080));
    }
}

and the result:
enter image description here

Screen size and screen zero point (i don't know whether this is a correct name of this point - generally it's just a point in which there is screen (0,0) point) you can get using some other library or from windows control panel. Screen zero point will display when you will start moving screen:
enter image description here

like image 39
cyriel Avatar answered Oct 03 '22 13:10

cyriel


If you use QT for writing your code, you can possibly utilize QT5's "Widget".

Here is a tutorial that will show you how to display an OpenCV image in a QT Widget.

Once you have that working you can then use something like this:

QScreen *screen = QGuiApplication::screens()[1]; // specify which screen to use

SecondDisplay secondDisplay = new SecondDisplay(); // your widget

** Add your code to display opencv image in widget here **

secondDisplay->move(screen->geometry().x(), screen->geometry().y());
secondDisplay->resize(screen->geometry().width(), screen->geometry().height());
secondDisplay->showFullScreen();

(Code found here on another SO answer)

I have not tried this myself, so I can't guarantee it will work, however, but it seems likely (if not a little overkill)

Hope this helps.

like image 40
Aphire Avatar answered Oct 03 '22 15:10

Aphire