opencv/modules/highgui/test/test_gui.cpp
kozinove efa4d9176a
Merge pull request #25661 from itlab-vision:framebuffer
Highgui backend on top of Framebuffer #25661

### Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

- [ x] I agree to contribute to the project under Apache 2 License.
- [ x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
- [ x] The PR is proposed to the proper branch
- [ ] There is a reference to the original bug report and related work
- [ x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
      Patch to opencv_extra has the same branch name.
- [ x] The feature is well documented and sample code can be built with the project CMake

Environment variables used:
OPENCV_UI_BACKEND - you need to add the value “FB”
OPENCV_UI_PRIORITY_FB - requires priority indication
OPENCV_HIGHGUI_FB_MODE={FB|XVFB|EMU} - mode of using Framebuffer (default "FB")
- FB - Linux Framebuffer
- XVFB - virtual Framebuffer
- EMU - emulation (images are not displayed)
OPENCV_HIGHGUI_FB_DEVICE (FRAMEBUFFER) - path to the Framebuffer file (default "/dev/fb0").

Examples of using:

sudo OPENCV_UI_BACKEND=FB ./opencv_test_highgui
sudo OPENCV_UI_PRIORITY_FB=1111 ./opencv_test_highgui
OPENCV_UI_BACKEND=FB OPENCV_HIGHGUI_FB_MODE=EMU ./opencv_test_highgui
sudo OPENCV_UI_BACKEND=FB OPENCV_HIGHGUI_FB_MODE=FB ./opencv_test_highgui

export DISPLAY=:99
Xvfb $DISPLAY -screen 0 1024x768x24 -fbdir /tmp/ -f /tmp/user.xvfb.auth&
sudo -u sipeed XAUTHORITY=/tmp/user.xvfb.auth x11vnc -display $DISPLAY -listen localhost&
DISPLAY=:0 gvncviewer localhost&

FRAMEBUFFER=/tmp/Xvfb_screen0 OPENCV_UI_BACKEND=FB OPENCV_HIGHGUI_FB_MODE=XVFB ./opencv_test_highgui
2024-06-26 15:31:19 +03:00

259 lines
8.9 KiB
C++

/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "test_precomp.hpp"
namespace opencv_test { namespace {
inline void verify_size(const std::string &nm, const cv::Mat &img)
{
EXPECT_NO_THROW(imshow(nm, img));
EXPECT_EQ(-1, waitKey(200));
// see https://github.com/opencv/opencv/issues/25550
// Wayland backend is not supported getWindowImageRect().
string framework;
EXPECT_NO_THROW(framework = currentUIFramework());
if(framework == "WAYLAND")
{
return;
}
Rect rc;
EXPECT_NO_THROW(rc = getWindowImageRect(nm));
EXPECT_EQ(rc.size(), img.size());
}
#if (!defined(ENABLE_PLUGINS) \
&& !defined HAVE_GTK \
&& !defined HAVE_QT \
&& !defined HAVE_WIN32UI \
&& !defined HAVE_COCOA \
&& !defined HAVE_WAYLAND \
)
TEST(Highgui_GUI, DISABLED_regression)
#else
TEST(Highgui_GUI, regression)
#endif
{
const std::string window_name("opencv_highgui_test_window");
const cv::Size image_size(800, 600);
EXPECT_NO_THROW(destroyAllWindows());
ASSERT_NO_THROW(namedWindow(window_name));
const vector<int> channels = {1, 3, 4};
const vector<int> depths = {CV_8U, CV_8S, CV_16U, CV_16S, CV_32F, CV_64F};
for(int cn : channels)
{
SCOPED_TRACE(cn);
for(int depth : depths)
{
SCOPED_TRACE(depth);
double min_val = 0.;
double max_val = 256.;
switch(depth)
{
case CV_8S:
min_val = static_cast<double>(-0x7F);
max_val = static_cast<double>(0x7F + 1);
break;
case CV_16S:
min_val = static_cast<double>(-0x7FFF);
max_val = static_cast<double>(0x7FFF + 1);
break;
case CV_16U:
max_val = static_cast<double>(0xFFFF + 1);
break;
case CV_32F:
case CV_64F:
max_val = 1.0;
break;
}
Mat m = cvtest::randomMat(TS::ptr()->get_rng(), image_size, CV_MAKE_TYPE(depth, cn), min_val, max_val, false);
verify_size(window_name, m);
Mat bgr(image_size, CV_MAKE_TYPE(depth, cn));
int b_g = image_size.width / 3, g_r = b_g * 2;
if (cn > 1)
{
bgr.colRange(0, b_g).setTo(cv::Scalar(max_val, min_val, min_val));
bgr.colRange(b_g, g_r).setTo(cv::Scalar(min_val, max_val, min_val));
bgr.colRange(g_r, image_size.width).setTo(cv::Scalar(min_val, min_val, max_val));
}
else
{
bgr.colRange(0, b_g).setTo(cv::Scalar::all(min_val));
bgr.colRange(b_g, g_r).setTo(cv::Scalar::all((min_val + max_val) / 2));
bgr.colRange(g_r, image_size.width).setTo(cv::Scalar::all(max_val));
}
verify_size(window_name, bgr);
}
}
EXPECT_NO_THROW(destroyAllWindows());
}
//==================================================================================================
static void Foo(int, void* counter)
{
if (counter)
{
int *counter_int = static_cast<int*>(counter);
(*counter_int)++;
}
}
#if (!defined(ENABLE_PLUGINS) \
&& !defined HAVE_GTK \
&& !defined HAVE_QT \
&& !defined HAVE_WIN32UI \
&& !defined HAVE_WAYLAND \
) \
|| defined(__APPLE__) /* test fails on Mac (cocoa) */ \
|| defined HAVE_FRAMEBUFFER /* trackbar is not supported */
TEST(Highgui_GUI, DISABLED_trackbar_unsafe)
#else
TEST(Highgui_GUI, trackbar_unsafe)
#endif
{
int value = 50;
int callback_count = 0;
const std::string window_name("trackbar_test_window");
const std::string trackbar_name("trackbar");
EXPECT_NO_THROW(destroyAllWindows());
ASSERT_NO_THROW(namedWindow(window_name));
EXPECT_EQ((int)1, createTrackbar(trackbar_name, window_name, &value, 100, Foo, &callback_count));
EXPECT_EQ(value, getTrackbarPos(trackbar_name, window_name));
EXPECT_GE(callback_count, 0);
EXPECT_LE(callback_count, 1);
int callback_count_base = callback_count;
EXPECT_NO_THROW(setTrackbarPos(trackbar_name, window_name, 90));
EXPECT_EQ(callback_count_base + 1, callback_count);
EXPECT_EQ(90, value);
EXPECT_EQ(90, getTrackbarPos(trackbar_name, window_name));
EXPECT_NO_THROW(destroyAllWindows());
}
static
void testTrackbarCallback(int pos, void* param)
{
CV_Assert(param);
int* status = (int*)param;
status[0] = pos;
status[1]++;
}
#if (!defined(ENABLE_PLUGINS) \
&& !defined HAVE_GTK \
&& !defined HAVE_QT \
&& !defined HAVE_WIN32UI \
&& !defined HAVE_WAYLAND \
) \
|| defined(__APPLE__) /* test fails on Mac (cocoa) */ \
|| defined HAVE_FRAMEBUFFER /* trackbar is not supported */
TEST(Highgui_GUI, DISABLED_trackbar)
#else
TEST(Highgui_GUI, trackbar)
#endif
{
int status[2] = {-1, 0}; // pos, counter
const std::string window_name("trackbar_test_window");
const std::string trackbar_name("trackbar");
EXPECT_NO_THROW(destroyAllWindows());
ASSERT_NO_THROW(namedWindow(window_name));
EXPECT_EQ((int)1, createTrackbar(trackbar_name, window_name, NULL, 100, testTrackbarCallback, status));
EXPECT_EQ(0, getTrackbarPos(trackbar_name, window_name));
int callback_count = status[1];
EXPECT_GE(callback_count, 0);
EXPECT_LE(callback_count, 1);
int callback_count_base = callback_count;
EXPECT_NO_THROW(setTrackbarPos(trackbar_name, window_name, 90));
callback_count = status[1];
EXPECT_EQ(callback_count_base + 1, callback_count);
int value = status[0];
EXPECT_EQ(90, value);
EXPECT_EQ(90, getTrackbarPos(trackbar_name, window_name));
EXPECT_NO_THROW(destroyAllWindows());
}
// See https://github.com/opencv/opencv/issues/25560
#if (!defined(ENABLE_PLUGINS) \
&& !defined HAVE_GTK \
&& !defined HAVE_QT \
&& !defined HAVE_WIN32UI \
&& !defined HAVE_WAYLAND)
TEST(Highgui_GUI, DISABLED_small_width_image)
#else
TEST(Highgui_GUI, small_width_image)
#endif
{
const std::string window_name("trackbar_test_window");
cv::Mat src(1,1,CV_8UC3,cv::Scalar(0));
EXPECT_NO_THROW(destroyAllWindows());
ASSERT_NO_THROW(namedWindow(window_name));
ASSERT_NO_THROW(imshow(window_name, src));
EXPECT_NO_THROW(waitKey(10));
EXPECT_NO_THROW(destroyAllWindows());
}
TEST(Highgui_GUI, currentUIFramework)
{
auto framework = currentUIFramework();
std::cout << "UI framework: \"" << framework << "\"" << std::endl;
#if (!defined(ENABLE_PLUGINS) \
&& !defined HAVE_GTK \
&& !defined HAVE_QT \
&& !defined HAVE_WIN32UI \
&& !defined HAVE_COCOA \
&& !defined HAVE_WAYLAND \
)
EXPECT_TRUE(framework.empty());
#elif !defined(ENABLE_PLUGINS)
EXPECT_GT(framework.size(), 0); // builtin backends
#endif
}
}} // namespace