vendor: OpenCV 5.0.0 snapshot at 40738fb16ceddb5fb3fea747585f7ce6abb0605b

This commit is contained in:
Gitea Mirror Bot
2026-08-22 00:10:33 +08:00
commit f7f077da11
6933 changed files with 2335208 additions and 0 deletions
+181
View File
@@ -0,0 +1,181 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#include "precomp.hpp"
#include "backend.hpp"
#include <opencv2/core/utils/configuration.private.hpp>
#include <opencv2/core/utils/logger.defines.hpp>
#ifdef NDEBUG
#define CV_LOG_STRIP_LEVEL CV_LOG_LEVEL_DEBUG + 1
#else
#define CV_LOG_STRIP_LEVEL CV_LOG_LEVEL_VERBOSE + 1
#endif
#include <opencv2/core/utils/logger.hpp>
#include "registry.hpp"
#include "registry.impl.hpp"
#include "plugin_api.hpp"
#include "plugin_wrapper.impl.hpp"
namespace cv { namespace highgui_backend {
UIBackend::~UIBackend()
{
// nothing
}
UIWindowBase::~UIWindowBase()
{
// nothing
}
UIWindow::~UIWindow()
{
// nothing
}
UITrackbar::~UITrackbar()
{
// nothing
}
static
std::string& getUIBackendName()
{
static std::string g_backendName = toUpperCase(cv::utils::getConfigurationParameterString("OPENCV_UI_BACKEND", ""));
return g_backendName;
}
static bool g_initializedUIBackend = false;
static
std::shared_ptr<UIBackend> createUIBackend()
{
const std::string& name = getUIBackendName();
bool isKnown = false;
const auto& backends = getBackendsInfo();
if (!name.empty())
{
CV_LOG_INFO(NULL, "UI: requested backend name: " << name);
}
for (size_t i = 0; i < backends.size(); i++)
{
const auto& info = backends[i];
if (!name.empty())
{
if (name != info.name)
{
continue;
}
isKnown = true;
}
try
{
CV_LOG_DEBUG(NULL, "UI: trying backend: " << info.name << " (priority=" << info.priority << ")");
if (!info.backendFactory)
{
CV_LOG_DEBUG(NULL, "UI: factory is not available (plugins require filesystem support): " << info.name);
continue;
}
std::shared_ptr<UIBackend> backend = info.backendFactory->create();
if (!backend)
{
CV_LOG_VERBOSE(NULL, 0, "UI: not available: " << info.name);
continue;
}
CV_LOG_INFO(NULL, "UI: using backend: " << info.name << " (priority=" << info.priority << ")");
g_initializedUIBackend = true;
getUIBackendName() = info.name;
return backend;
}
catch (const std::exception& e)
{
CV_LOG_WARNING(NULL, "UI: can't initialize " << info.name << " backend: " << e.what());
}
catch (...)
{
CV_LOG_WARNING(NULL, "UI: can't initialize " << info.name << " backend: Unknown C++ exception");
}
}
if (name.empty())
{
CV_LOG_DEBUG(NULL, "UI: fallback on builtin code: " OPENCV_HIGHGUI_BUILTIN_BACKEND_STR);
}
else
{
if (!isKnown)
CV_LOG_INFO(NULL, "UI: unknown backend: " << name);
}
g_initializedUIBackend = true;
return std::shared_ptr<UIBackend>();
}
static inline
std::shared_ptr<UIBackend> createDefaultUIBackend()
{
CV_LOG_DEBUG(NULL, "UI: Initializing backend...");
return createUIBackend();
}
std::shared_ptr<UIBackend>& getCurrentUIBackend()
{
static std::shared_ptr<UIBackend> g_currentUIBackend = createDefaultUIBackend();
return g_currentUIBackend;
}
void setUIBackend(const std::shared_ptr<UIBackend>& api)
{
getCurrentUIBackend() = api;
}
bool setUIBackend(const std::string& backendName)
{
CV_TRACE_FUNCTION();
std::string backendName_u = toUpperCase(backendName);
if (g_initializedUIBackend)
{
// ... already initialized
if (getUIBackendName() == backendName_u)
{
CV_LOG_INFO(NULL, "UI: backend is already activated: " << (backendName.empty() ? "builtin(legacy)" : backendName));
return true;
}
else
{
// ... re-create new
CV_LOG_DEBUG(NULL, "UI: replacing backend...");
getUIBackendName() = backendName_u;
getCurrentUIBackend() = createUIBackend();
}
}
else
{
// ... no backend exists, just specify the name (initialization is triggered by getCurrentUIBackend() call)
getUIBackendName() = backendName_u;
}
std::shared_ptr<UIBackend> api = getCurrentUIBackend();
if (!api)
{
if (!backendName.empty())
{
CV_LOG_WARNING(NULL, "UI: backend is not available: " << backendName << " (using builtin legacy code)");
return false;
}
else
{
CV_LOG_WARNING(NULL, "UI: switched to builtin code (legacy)");
}
}
if (!backendName_u.empty())
{
CV_Assert(backendName_u == getUIBackendName()); // data race?
}
return true;
}
}} // namespace cv::highgui_backend
+140
View File
@@ -0,0 +1,140 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#ifndef OPENCV_HIGHGUI_BACKEND_HPP
#define OPENCV_HIGHGUI_BACKEND_HPP
#include <memory>
#include <map>
namespace cv { namespace highgui_backend {
class CV_EXPORTS UIWindowBase
{
public:
typedef std::shared_ptr<UIWindowBase> Ptr;
typedef std::weak_ptr<UIWindowBase> WeakPtr;
virtual ~UIWindowBase();
virtual const std::string& getID() const = 0; // internal name, used for logging
virtual bool isActive() const = 0;
virtual void destroy() = 0;
}; // UIWindowBase
class UITrackbar;
class CV_EXPORTS UIWindow : public UIWindowBase
{
public:
virtual ~UIWindow();
virtual void imshow(InputArray image) = 0;
virtual double getProperty(int prop) const = 0;
virtual bool setProperty(int prop, double value) = 0;
virtual void resize(int width, int height) = 0;
virtual void move(int x, int y) = 0;
virtual Rect getImageRect() const = 0;
virtual void setTitle(const std::string& title) = 0;
virtual void setMouseCallback(MouseCallback onMouse, void* userdata /*= 0*/) = 0;
//TODO: handle both keys and mouse events (both with mouse coordinates)
//virtual void setInputCallback(InputCallback onInputEvent, void* userdata /*= 0*/) = 0;
virtual std::shared_ptr<UITrackbar> createTrackbar(
const std::string& name,
int count,
TrackbarCallback onChange /*= 0*/,
void* userdata /*= 0*/
) = 0;
virtual std::shared_ptr<UITrackbar> findTrackbar(const std::string& name) = 0;
#if 0 // QT only
virtual void displayOverlay(const std::string& text, int delayms = 0) = 0;
virtual void displayStatusBar(const std::string& text, int delayms /*= 0*/) = 0;
virtual int createButton(
const std::string& bar_name, ButtonCallback on_change,
void* userdata = 0, int type /*= QT_PUSH_BUTTON*/,
bool initial_button_state /*= false*/
) = 0;
// addText, QtFont stuff
#endif
#if 0 // OpenGL
virtual void imshow(const ogl::Texture2D& tex) = 0;
virtual void setOpenGlDrawCallback(OpenGlDrawCallback onOpenGlDraw, void* userdata = 0) = 0;
virtual void setOpenGlContext() = 0;
virtual void updateWindow() = 0;
#endif
}; // UIWindow
class CV_EXPORTS UITrackbar : public UIWindowBase
{
public:
virtual ~UITrackbar();
virtual int getPos() const = 0;
virtual void setPos(int pos) = 0;
virtual cv::Range getRange() const = 0;
virtual void setRange(const cv::Range& range) = 0;
}; // UITrackbar
class CV_EXPORTS UIBackend
{
public:
virtual ~UIBackend();
virtual void destroyAllWindows() = 0;
// namedWindow
virtual std::shared_ptr<UIWindow> createWindow(
const std::string& winname,
int flags
) = 0;
virtual int waitKeyEx(int delay /*= 0*/) = 0;
virtual int pollKey() = 0;
virtual const std::string getName() const = 0;
};
std::shared_ptr<UIBackend>& getCurrentUIBackend();
void setUIBackend(const std::shared_ptr<UIBackend>& api);
bool setUIBackend(const std::string& backendName);
#ifndef BUILD_PLUGIN
#ifdef HAVE_WIN32UI
std::shared_ptr<UIBackend> createUIBackendWin32UI();
#endif
#ifdef HAVE_GTK
std::shared_ptr<UIBackend> createUIBackendGTK();
#endif
#if 0 // TODO: defined HAVE_QT
std::shared_ptr<UIBackend> createUIBackendQT();
#endif
#ifdef HAVE_FRAMEBUFFER
std::shared_ptr<UIBackend> createUIBackendFramebuffer();
#endif
#endif // BUILD_PLUGIN
} // namespace highgui_backend
} // namespace cv
#endif // OPENCV_HIGHGUI_BACKEND_HPP
+48
View File
@@ -0,0 +1,48 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#ifndef OPENCV_UI_FACTORY_HPP
#define OPENCV_UI_FACTORY_HPP
#include "backend.hpp"
namespace cv { namespace highgui_backend {
class IUIBackendFactory
{
public:
virtual ~IUIBackendFactory() {}
virtual std::shared_ptr<cv::highgui_backend::UIBackend> create() const = 0;
};
class StaticBackendFactory CV_FINAL: public IUIBackendFactory
{
protected:
std::function<std::shared_ptr<cv::highgui_backend::UIBackend>(void)> create_fn_;
public:
StaticBackendFactory(std::function<std::shared_ptr<cv::highgui_backend::UIBackend>(void)>&& create_fn)
: create_fn_(create_fn)
{
// nothing
}
~StaticBackendFactory() CV_OVERRIDE {}
std::shared_ptr<cv::highgui_backend::UIBackend> create() const CV_OVERRIDE
{
return create_fn_();
}
};
//
// PluginUIBackendFactory is implemented in plugin_wrapper
//
std::shared_ptr<IUIBackendFactory> createPluginUIBackendFactory(const std::string& baseName);
}} // namespace
#endif // OPENCV_UI_FACTORY_HPP
Binary file not shown.

After

Width:  |  Height:  |  Size: 832 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 799 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 522 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 531 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 561 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 761 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 536 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 688 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 579 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 914 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 674 B

@@ -0,0 +1,201 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
@@ -0,0 +1 @@
Icons for Google Material Design: https://github.com/google/material-design-icons/
+72
View File
@@ -0,0 +1,72 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#ifndef UI_PLUGIN_API_HPP
#define UI_PLUGIN_API_HPP
#include <opencv2/core/cvdef.h>
#include <opencv2/core/llapi/llapi.h>
#include "backend.hpp"
#if !defined(BUILD_PLUGIN)
/// increased for backward-compatible changes, e.g. add new function
/// Caller API <= Plugin API -> plugin is fully compatible
/// Caller API > Plugin API -> plugin is not fully compatible, caller should use extra checks to use plugins with older API
#define API_VERSION 0 // preview
/// increased for incompatible changes, e.g. remove function argument
/// Caller ABI == Plugin ABI -> plugin is compatible
/// Caller ABI > Plugin ABI -> plugin is not compatible, caller should use shim code to use old ABI plugins (caller may know how lower ABI works, so it is possible)
/// Caller ABI < Plugin ABI -> plugin can't be used (plugin should provide interface with lower ABI to handle that)
#define ABI_VERSION 0 // preview
#else // !defined(BUILD_PLUGIN)
#if !defined(ABI_VERSION) || !defined(API_VERSION)
#error "Plugin must define ABI_VERSION and API_VERSION before including plugin_api.hpp"
#endif
#endif // !defined(BUILD_PLUGIN)
typedef cv::highgui_backend::UIBackend* CvPluginUIBackend;
struct OpenCV_UI_Plugin_API_v0_0_api_entries
{
/** @brief Get backend API instance
@param[out] handle pointer on backend API handle
@note API-CALL 1, API-Version == 0
*/
CvResult (CV_API_CALL *getInstance)(CV_OUT CvPluginUIBackend* handle) CV_NOEXCEPT;
}; // OpenCV_UI_Plugin_API_v0_0_api_entries
typedef struct OpenCV_UI_Plugin_API_v0
{
OpenCV_API_Header api_header;
struct OpenCV_UI_Plugin_API_v0_0_api_entries v0;
} OpenCV_UI_Plugin_API_v0;
#if ABI_VERSION == 0 && API_VERSION == 0
typedef OpenCV_UI_Plugin_API_v0 OpenCV_UI_Plugin_API;
#else
#error "Not supported configuration: check ABI_VERSION/API_VERSION"
#endif
#ifdef BUILD_PLUGIN
extern "C" {
CV_PLUGIN_EXPORTS
const OpenCV_UI_Plugin_API* CV_API_CALL opencv_ui_plugin_init_v0
(int requested_abi_version, int requested_api_version, void* reserved /*NULL*/) CV_NOEXCEPT;
} // extern "C"
#else // BUILD_PLUGIN
typedef const OpenCV_UI_Plugin_API* (CV_API_CALL *FN_opencv_ui_plugin_init_t)
(int requested_abi_version, int requested_api_version, void* reserved /*NULL*/);
#endif // BUILD_PLUGIN
#endif // UI_PLUGIN_API_HPP
+294
View File
@@ -0,0 +1,294 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
// Not a standalone header, part of backend.cpp
//
//==================================================================================================
// Dynamic backend implementation
#include "opencv2/core/utils/plugin_loader.private.hpp"
namespace cv { namespace impl {
using namespace cv::highgui_backend;
#if OPENCV_HAVE_FILESYSTEM_SUPPORT && defined(ENABLE_PLUGINS)
using namespace cv::plugin::impl; // plugin_loader.hpp
class PluginUIBackend CV_FINAL: public std::enable_shared_from_this<PluginUIBackend>
{
protected:
void initPluginAPI()
{
const char* init_name = "opencv_ui_plugin_init_v0";
FN_opencv_ui_plugin_init_t fn_init = reinterpret_cast<FN_opencv_ui_plugin_init_t>(lib_->getSymbol(init_name));
if (fn_init)
{
CV_LOG_DEBUG(NULL, "Found entry: '" << init_name << "'");
for (int supported_api_version = API_VERSION; supported_api_version >= 0; supported_api_version--)
{
plugin_api_ = fn_init(ABI_VERSION, supported_api_version, NULL);
if (plugin_api_)
break;
}
if (!plugin_api_)
{
CV_LOG_INFO(NULL, "UI: plugin is incompatible (can't be initialized): " << lib_->getName());
return;
}
// NB: force strict minor version check (ABI is not preserved for now)
if (!checkCompatibility(plugin_api_->api_header, ABI_VERSION, API_VERSION, true))
{
plugin_api_ = NULL;
return;
}
CV_LOG_INFO(NULL, "UI: plugin is ready to use '" << plugin_api_->api_header.api_description << "'");
}
else
{
CV_LOG_INFO(NULL, "UI: plugin is incompatible, missing init function: '" << init_name << "', file: " << lib_->getName());
}
}
bool checkCompatibility(const OpenCV_API_Header& api_header, unsigned int abi_version, unsigned int api_version, bool checkMinorOpenCVVersion)
{
if (api_header.opencv_version_major != CV_VERSION_MAJOR)
{
CV_LOG_ERROR(NULL, "UI: wrong OpenCV major version used by plugin '" << api_header.api_description << "': " <<
cv::format("%d.%d, OpenCV version is '" CV_VERSION "'", api_header.opencv_version_major, api_header.opencv_version_minor))
return false;
}
if (!checkMinorOpenCVVersion)
{
// no checks for OpenCV minor version
}
else if (api_header.opencv_version_minor != CV_VERSION_MINOR)
{
CV_LOG_ERROR(NULL, "UI: wrong OpenCV minor version used by plugin '" << api_header.api_description << "': " <<
cv::format("%d.%d, OpenCV version is '" CV_VERSION "'", api_header.opencv_version_major, api_header.opencv_version_minor))
return false;
}
CV_LOG_DEBUG(NULL, "UI: initialized '" << api_header.api_description << "': built with "
<< cv::format("OpenCV %d.%d (ABI/API = %d/%d)",
api_header.opencv_version_major, api_header.opencv_version_minor,
api_header.min_api_version, api_header.api_version)
<< ", current OpenCV version is '" CV_VERSION "' (ABI/API = " << abi_version << "/" << api_version << ")"
);
if (api_header.min_api_version != abi_version) // future: range can be here
{
// actually this should never happen due to checks in plugin's init() function
CV_LOG_ERROR(NULL, "UI: plugin is not supported due to incompatible ABI = " << api_header.min_api_version);
return false;
}
if (api_header.api_version != api_version)
{
CV_LOG_INFO(NULL, "UI: NOTE: plugin is supported, but there is API version mismath: "
<< cv::format("plugin API level (%d) != OpenCV API level (%d)", api_header.api_version, api_version));
if (api_header.api_version < api_version)
{
CV_LOG_INFO(NULL, "UI: NOTE: some functionality may be unavailable due to lack of support by plugin implementation");
}
}
return true;
}
public:
std::shared_ptr<cv::plugin::impl::DynamicLib> lib_;
const OpenCV_UI_Plugin_API* plugin_api_;
PluginUIBackend(const std::shared_ptr<cv::plugin::impl::DynamicLib>& lib)
: lib_(lib)
, plugin_api_(NULL)
{
initPluginAPI();
}
std::shared_ptr<cv::highgui_backend::UIBackend> create() const
{
CV_Assert(plugin_api_);
CvPluginUIBackend instancePtr = NULL;
if (plugin_api_->v0.getInstance)
{
if (CV_ERROR_OK == plugin_api_->v0.getInstance(&instancePtr))
{
CV_Assert(instancePtr);
// TODO C++20 "aliasing constructor"
return std::shared_ptr<cv::highgui_backend::UIBackend>(instancePtr, [](cv::highgui_backend::UIBackend*){}); // empty deleter
}
}
return std::shared_ptr<cv::highgui_backend::UIBackend>();
}
};
class PluginUIBackendFactory CV_FINAL: public IUIBackendFactory
{
public:
std::string baseName_;
std::shared_ptr<PluginUIBackend> backend;
bool initialized;
public:
PluginUIBackendFactory(const std::string& baseName)
: baseName_(baseName)
, initialized(false)
{
// nothing, plugins are loaded on demand
}
std::shared_ptr<cv::highgui_backend::UIBackend> create() const CV_OVERRIDE
{
if (!initialized)
{
const_cast<PluginUIBackendFactory*>(this)->initBackend();
}
if (backend)
return backend->create();
return std::shared_ptr<cv::highgui_backend::UIBackend>();
}
protected:
void initBackend()
{
AutoLock lock(getInitializationMutex());
try
{
if (!initialized)
loadPlugin();
}
catch (...)
{
CV_LOG_INFO(NULL, "UI: exception during plugin loading: " << baseName_ << ". SKIP");
}
initialized = true;
}
void loadPlugin();
};
static
std::vector<FileSystemPath_t> getPluginCandidates(const std::string& baseName)
{
using namespace cv::utils;
using namespace cv::utils::fs;
const std::string baseName_l = toLowerCase(baseName);
const std::string baseName_u = toUpperCase(baseName);
const FileSystemPath_t baseName_l_fs = toFileSystemPath(baseName_l);
std::vector<FileSystemPath_t> paths;
// TODO OPENCV_PLUGIN_PATH
const std::vector<std::string> paths_ = getConfigurationParameterPaths("OPENCV_CORE_PLUGIN_PATH", std::vector<std::string>());
if (paths_.size() != 0)
{
for (size_t i = 0; i < paths_.size(); i++)
{
paths.push_back(toFileSystemPath(paths_[i]));
}
}
else
{
FileSystemPath_t binaryLocation;
if (getBinLocation(binaryLocation))
{
binaryLocation = getParent(binaryLocation);
#ifndef CV_UI_PLUGIN_SUBDIRECTORY
paths.push_back(binaryLocation);
#else
paths.push_back(binaryLocation + toFileSystemPath("/") + toFileSystemPath(CV_UI_PLUGIN_SUBDIRECTORY_STR));
#endif
}
}
const std::string default_expr = libraryPrefix() + "opencv_highgui_" + baseName_l + "*" + librarySuffix();
const std::string plugin_expr = getConfigurationParameterString((std::string("OPENCV_UI_PLUGIN_") + baseName_u).c_str(), default_expr.c_str());
std::vector<FileSystemPath_t> results;
#ifdef _WIN32
FileSystemPath_t moduleName = toFileSystemPath(libraryPrefix() + "opencv_highgui_" + baseName_l + librarySuffix());
if (plugin_expr != default_expr)
{
moduleName = toFileSystemPath(plugin_expr);
results.push_back(moduleName);
}
for (const FileSystemPath_t& path : paths)
{
results.push_back(path + L"\\" + moduleName);
}
results.push_back(moduleName);
#else
CV_LOG_DEBUG(NULL, "UI: " << baseName << " plugin's glob is '" << plugin_expr << "', " << paths.size() << " location(s)");
for (const std::string& path : paths)
{
if (path.empty())
continue;
std::vector<std::string> candidates;
cv::glob(utils::fs::join(path, plugin_expr), candidates);
// Prefer candisates with higher versions
// TODO: implemented accurate versions-based comparator
std::sort(candidates.begin(), candidates.end(), std::greater<std::string>());
CV_LOG_DEBUG(NULL, " - " << path << ": " << candidates.size());
copy(candidates.begin(), candidates.end(), back_inserter(results));
}
#endif
CV_LOG_DEBUG(NULL, "Found " << results.size() << " plugin(s) for " << baseName);
return results;
}
#ifdef HAVE_OPENCV_IMGCODECS // NB: require loading of imgcodecs module
static void* g_imwrite = (void*)imwrite;
#endif
void PluginUIBackendFactory::loadPlugin()
{
#ifdef HAVE_OPENCV_IMGCODECS
CV_Assert(g_imwrite);
#endif
for (const FileSystemPath_t& plugin : getPluginCandidates(baseName_))
{
auto lib = std::make_shared<cv::plugin::impl::DynamicLib>(plugin);
if (!lib->isLoaded())
{
continue;
}
try
{
auto pluginBackend = std::make_shared<PluginUIBackend>(lib);
if (!pluginBackend)
{
continue;
}
if (pluginBackend->plugin_api_ == NULL)
{
CV_LOG_ERROR(NULL, "UI: no compatible plugin API for backend: " << baseName_ << " in " << toPrintablePath(plugin));
continue;
}
// NB: we are going to use UI backend, so prevent automatic library unloading
lib->disableAutomaticLibraryUnloading();
backend = pluginBackend;
return;
}
catch (...)
{
CV_LOG_WARNING(NULL, "UI: exception during plugin initialization: " << toPrintablePath(plugin) << ". SKIP");
}
}
}
#endif // OPENCV_HAVE_FILESYSTEM_SUPPORT && defined(ENABLE_PLUGINS)
} // namespace
namespace highgui_backend {
std::shared_ptr<IUIBackendFactory> createPluginUIBackendFactory(const std::string& baseName)
{
#if OPENCV_HAVE_FILESYSTEM_SUPPORT && defined(ENABLE_PLUGINS)
return std::make_shared<impl::PluginUIBackendFactory>(baseName);
#else
CV_UNUSED(baseName);
return std::shared_ptr<IUIBackendFactory>();
#endif
}
}} // namespace
+214
View File
@@ -0,0 +1,214 @@
/*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.
//
//
// Intel License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000, Intel Corporation, 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 Intel Corporation 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*/
#ifndef __HIGHGUI_H_
#define __HIGHGUI_H_
#if defined(__OPENCV_BUILD) && defined(BUILD_PLUGIN)
#undef __OPENCV_BUILD // allow public API only
#endif
#include "opencv2/core.hpp"
#include "opencv2/highgui.hpp"
#if !defined(BUILD_PLUGIN)
#include "opencv_highgui_config.hpp" // generated by CMake
#endif
#include "opencv2/core/utility.hpp"
#if defined(__OPENCV_BUILD)
#include "opencv2/core/private.hpp"
#include "opencv2/core/utils/configuration.private.hpp"
#endif
#include "opencv2/imgproc.hpp"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <ctype.h>
#if defined _WIN32 || defined WINCE
#include <windows.h>
#undef small
#undef min
#undef max
#undef abs
#endif
/* Errors */
#define HG_OK 0 /* Don't bet on it! */
#define HG_BADNAME -1 /* Bad window or file name */
#define HG_INITFAILED -2 /* Can't initialize HigHGUI */
#define HG_WCFAILED -3 /* Can't create a window */
#define HG_NULLPTR -4 /* The null pointer where it should not appear */
#define HG_BADPARAM -5
#define __BEGIN__ __CV_BEGIN__
#define __END__ __CV_END__
#define EXIT __CV_EXIT__
#define CV_WINDOW_MAGIC_VAL 0x00420042
#define CV_TRACKBAR_MAGIC_VAL 0x00420043
// Obsolete but widely used types and functions hidden here
typedef void (CV_CDECL *CvTrackbarCallback)(int pos);
int namedWindowImpl(const char* name, int flags = cv::WINDOW_AUTOSIZE);
void showImageImpl( const char* name, cv::InputArray img);
void resizeWindowImpl( const char* name, int width, int height );
void moveWindowImpl( const char* name, int x, int y );
void destroyWindowImpl(const char* name);
void destroyAllWindowsImpl(void);
int waitKeyImpl(int delay);
int getTrackbarPosImpl( const char* trackbar_name, const char* window_name );
void setTrackbarPosImpl( const char* trackbar_name, const char* window_name, int pos );
void setTrackbarMaxImpl(const char* trackbar_name, const char* window_name, int maxval);
void setTrackbarMinImpl(const char* trackbar_name, const char* window_name, int minval);
typedef void (CV_CDECL *CvTrackbarCallback2)(int pos, void* userdata);
int createTrackbar2Impl( const char* trackbar_name, const char* window_name,
int* value, int count, CvTrackbarCallback2 on_change,
void* userdata);
typedef void (CV_CDECL *CvMouseCallback )(int event, int x, int y, int flags, void* param);
void setMouseCallbackImpl( const char* window_name, CvMouseCallback on_mouse, void* param);
typedef void (CV_CDECL *CvOpenGlDrawCallback)(void* userdata);
void setOpenGLDrawCallbackImpl(const char* window_name, CvOpenGlDrawCallback callback, void* userdata);
void setOpenGLContextImpl(const char* window_name);
void updateWindowImpl(const char* window_name);
//Yannick Verdie 2010, Max Kostin 2015
void cvSetModeWindow_W32(const char* name, double prop_value);
void cvSetModeWindow_GTK(const char* name, double prop_value);
void cvSetModeWindow_COCOA(const char* name, double prop_value);
cv::Rect cvGetWindowRect_W32(const char* name);
cv::Rect cvGetWindowRect_GTK(const char* name);
cv::Rect cvGetWindowRect_COCOA(const char* name);
cv::Rect cvGetWindowRect_WAYLAND(const char* name);
double cvGetModeWindow_W32(const char* name);
double cvGetModeWindow_GTK(const char* name);
double cvGetModeWindow_COCOA(const char* name);
double cvGetPropWindowAutoSize_W32(const char* name);
double cvGetPropWindowAutoSize_GTK(const char* name);
double cvGetRatioWindow_W32(const char* name);
double cvGetRatioWindow_GTK(const char* name);
double cvGetOpenGlProp_W32(const char* name);
double cvGetOpenGlProp_GTK(const char* name);
double cvGetPropVisible_W32(const char* name);
double cvGetPropVisible_COCOA(const char* name);
double cvGetPropTopmost_W32(const char* name);
double cvGetPropTopmost_COCOA(const char* name);
void cvSetPropTopmost_W32(const char* name, const bool topmost);
void cvSetPropTopmost_COCOA(const char* name, const bool topmost);
double cvGetPropVsync_W32(const char* name);
void cvSetPropVsync_W32(const char* name, const bool enabled);
void setWindowTitle_W32(const cv::String& name, const cv::String& title);
void setWindowTitle_GTK(const cv::String& name, const cv::String& title);
void setWindowTitle_QT(const cv::String& name, const cv::String& title);
void setWindowTitle_COCOA(const cv::String& name, const cv::String& title);
void setWindowTitle_WAYLAND(const cv::String& name, const cv::String& title);
int pollKey_W32();
//for QT
#if defined (HAVE_QT)
cv::Rect cvGetWindowRect_QT(const char* name);
double cvGetModeWindow_QT(const char* name);
void cvSetModeWindow_QT(const char* name, double prop_value);
double cvGetPropWindow_QT(const char* name);
void cvSetPropWindow_QT(const char* name,double prop_value);
double cvGetRatioWindow_QT(const char* name);
void cvSetRatioWindow_QT(const char* name,double prop_value);
double cvGetOpenGlProp_QT(const char* name);
double cvGetPropVisible_QT(const char* name);
#endif
inline void convertToShow(const cv::Mat &src, cv::Mat &dst, bool toRGB = true)
{
const int src_depth = src.depth();
CV_Assert(src_depth != CV_16F && src_depth != CV_32S);
cv::Mat tmp;
switch(src_depth)
{
case CV_8U:
tmp = src;
break;
case CV_8S:
cv::convertScaleAbs(src, tmp, 1, 127);
break;
case CV_16S:
cv::convertScaleAbs(src, tmp, 1/255., 127);
break;
case CV_16U:
cv::convertScaleAbs(src, tmp, 1/255.);
break;
case CV_32F:
case CV_64F: // assuming image has values in range [0, 1)
src.convertTo(tmp, CV_8U, 255., 0.);
break;
}
cv::cvtColor(tmp, dst, toRGB ? cv::COLOR_BGR2RGB : cv::COLOR_BGRA2BGR, dst.channels());
}
namespace cv {
CV_EXPORTS Mutex& getWindowMutex();
static inline Mutex& getInitializationMutex() { return getWindowMutex(); }
} // namespace
#endif /* __HIGHGUI_H_ */
+25
View File
@@ -0,0 +1,25 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#ifndef OPENCV_HIGHGUI_REGISTRY_HPP
#define OPENCV_HIGHGUI_REGISTRY_HPP
#include "factory.hpp"
namespace cv { namespace highgui_backend {
struct BackendInfo
{
int priority; // 1000-<index*10> - default builtin priority
// 0 - disabled (OPENCV_UI_PRIORITY_<name> = 0)
// >10000 - prioritized list (OPENCV_UI_PRIORITY_LIST)
std::string name;
std::shared_ptr<IUIBackendFactory> backendFactory;
};
const std::vector<BackendInfo>& getBackendsInfo();
}} // namespace
#endif // OPENCV_HIGHGUI_REGISTRY_HPP
+198
View File
@@ -0,0 +1,198 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
//
// Not a standalone header, part of backend.cpp
//
#include "opencv2/core/utils/filesystem.private.hpp" // OPENCV_HAVE_FILESYSTEM_SUPPORT
namespace cv { namespace highgui_backend {
#if OPENCV_HAVE_FILESYSTEM_SUPPORT && defined(ENABLE_PLUGINS)
#define DECLARE_DYNAMIC_BACKEND(name) \
BackendInfo { \
1000, name, createPluginUIBackendFactory(name) \
},
#else
#define DECLARE_DYNAMIC_BACKEND(name) /* nothing */
#endif
#define DECLARE_STATIC_BACKEND(name, createBackendAPI) \
BackendInfo { \
1000, name, std::make_shared<cv::highgui_backend::StaticBackendFactory>([=] () -> std::shared_ptr<cv::highgui_backend::UIBackend> { return createBackendAPI(); }) \
},
static
std::vector<BackendInfo>& getBuiltinBackendsInfo()
{
static std::vector<BackendInfo> g_backends
{
#ifdef HAVE_GTK
DECLARE_STATIC_BACKEND("GTK", createUIBackendGTK)
#if defined(HAVE_GTK3)
DECLARE_STATIC_BACKEND("GTK3", createUIBackendGTK)
#elif defined(HAVE_GTK2)
DECLARE_STATIC_BACKEND("GTK2", createUIBackendGTK)
#else
#warning "HAVE_GTK definition issue. Register new GTK backend"
#endif
#elif defined(ENABLE_PLUGINS)
DECLARE_DYNAMIC_BACKEND("GTK")
DECLARE_DYNAMIC_BACKEND("GTK3")
DECLARE_DYNAMIC_BACKEND("GTK2")
#endif
#ifdef HAVE_FRAMEBUFFER
DECLARE_STATIC_BACKEND("FB", createUIBackendFramebuffer)
#endif
#if 0 // TODO
#ifdef HAVE_QT
DECLARE_STATIC_BACKEND("QT", createUIBackendQT)
#elif defined(ENABLE_PLUGINS)
DECLARE_DYNAMIC_BACKEND("QT")
#endif
#endif
#ifdef _WIN32
#ifdef HAVE_WIN32UI
DECLARE_STATIC_BACKEND("WIN32", createUIBackendWin32UI)
#elif defined(ENABLE_PLUGINS)
DECLARE_DYNAMIC_BACKEND("WIN32")
#endif
#endif
};
return g_backends;
}
static
bool sortByPriority(const BackendInfo &lhs, const BackendInfo &rhs)
{
return lhs.priority > rhs.priority;
}
/** @brief Manages list of enabled backends
*/
class UIBackendRegistry
{
protected:
std::vector<BackendInfo> enabledBackends;
UIBackendRegistry()
{
enabledBackends = getBuiltinBackendsInfo();
int N = (int)enabledBackends.size();
for (int i = 0; i < N; i++)
{
BackendInfo& info = enabledBackends[i];
info.priority = 1000 - i * 10;
}
CV_LOG_DEBUG(NULL, "UI: Builtin backends(" << N << "): " << dumpBackends());
if (readPrioritySettings())
{
CV_LOG_INFO(NULL, "UI: Updated backends priorities: " << dumpBackends());
N = (int)enabledBackends.size();
}
int enabled = 0;
for (int i = 0; i < N; i++)
{
BackendInfo& info = enabledBackends[enabled];
if (enabled != i)
info = enabledBackends[i];
size_t param_priority = utils::getConfigurationParameterSizeT(cv::format("OPENCV_UI_PRIORITY_%s", info.name.c_str()).c_str(), (size_t)info.priority);
CV_Assert(param_priority == (size_t)(int)param_priority); // overflow check
if (param_priority > 0)
{
info.priority = (int)param_priority;
enabled++;
}
else
{
CV_LOG_INFO(NULL, "UI: Disable backend: " << info.name);
}
}
enabledBackends.resize(enabled);
CV_LOG_DEBUG(NULL, "UI: Available backends(" << enabled << "): " << dumpBackends());
std::sort(enabledBackends.begin(), enabledBackends.end(), sortByPriority);
CV_LOG_INFO(NULL, "UI: Enabled backends(" << enabled << ", sorted by priority): " << (enabledBackends.empty() ? std::string("N/A") : dumpBackends()));
}
static std::vector<std::string> tokenize_string(const std::string& input, char token)
{
std::vector<std::string> result;
std::string::size_type prev_pos = 0, pos = 0;
while((pos = input.find(token, pos)) != std::string::npos)
{
result.push_back(input.substr(prev_pos, pos-prev_pos));
prev_pos = ++pos;
}
result.push_back(input.substr(prev_pos));
return result;
}
bool readPrioritySettings()
{
bool hasChanges = false;
cv::String prioritized_backends = utils::getConfigurationParameterString("OPENCV_UI_PRIORITY_LIST");
if (prioritized_backends.empty())
return hasChanges;
CV_LOG_INFO(NULL, "UI: Configured priority list (OPENCV_UI_PRIORITY_LIST): " << prioritized_backends);
const std::vector<std::string> names = tokenize_string(prioritized_backends, ',');
for (size_t i = 0; i < names.size(); i++)
{
const std::string& name = names[i];
int priority = (int)(100000 + (names.size() - i) * 1000);
bool found = false;
for (size_t k = 0; k < enabledBackends.size(); k++)
{
BackendInfo& info = enabledBackends[k];
if (name == info.name)
{
info.priority = priority;
CV_LOG_DEBUG(NULL, "UI: New backend priority: '" << name << "' => " << info.priority);
found = true;
hasChanges = true;
break;
}
}
if (!found)
{
CV_LOG_INFO(NULL, "UI: Adding backend (plugin): '" << name << "'");
enabledBackends.push_back(BackendInfo{priority, name, createPluginUIBackendFactory(name)});
hasChanges = true;
}
}
return hasChanges;
}
public:
std::string dumpBackends() const
{
std::ostringstream os;
for (size_t i = 0; i < enabledBackends.size(); i++)
{
if (i > 0) os << "; ";
const BackendInfo& info = enabledBackends[i];
os << info.name << '(' << info.priority << ')';
}
#if !defined(OPENCV_HIGHGUI_WITHOUT_BUILTIN_BACKEND)
os << " + BUILTIN(" OPENCV_HIGHGUI_BUILTIN_BACKEND_STR ")";
#endif
return os.str();
}
static UIBackendRegistry& getInstance()
{
static UIBackendRegistry g_instance;
return g_instance;
}
inline const std::vector<BackendInfo>& getEnabledBackends() const { return enabledBackends; }
};
const std::vector<BackendInfo>& getBackendsInfo()
{
return cv::highgui_backend::UIBackendRegistry::getInstance().getEnabledBackends();
}
}} // namespace
+221
View File
@@ -0,0 +1,221 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#include "precomp.hpp"
#include <opencv2/imgproc.hpp>
#include <algorithm>
using namespace cv;
namespace
{
class ROISelector
{
public:
Rect select(const String &windowName, Mat img, bool showCrossair = true, bool fromCenter = true, bool printNotice = true)
{
if(printNotice)
{
// show notice to user
printf("Select a ROI and then press SPACE or ENTER button!\n");
printf("Cancel the selection process by pressing c button!\n");
}
key = 0;
imageSize = img.size();
// set the drawing mode
selectorParams.drawFromCenter = fromCenter;
// show the image and give feedback to user
imshow(windowName, img);
// copy the data, rectangle should be drawn in the fresh image
selectorParams.image = img.clone();
// select the object
setMouseCallback(windowName, mouseHandler, (void*)this);
// end selection process on SPACE (32) ESC (27) or ENTER (13)
while (!(key == 32 || key == 27 || key == 13))
{
// draw the selected object
rectangle(selectorParams.image, selectorParams.box, Scalar(255, 0, 0), 2, 1);
// draw cross air in the middle of bounding box
if (showCrossair)
{
// horizontal line
line(selectorParams.image,
Point((int)selectorParams.box.x,
(int)(selectorParams.box.y + selectorParams.box.height / 2)),
Point((int)(selectorParams.box.x + selectorParams.box.width),
(int)(selectorParams.box.y + selectorParams.box.height / 2)),
Scalar(255, 0, 0), 2, 1);
// vertical line
line(selectorParams.image,
Point((int)(selectorParams.box.x + selectorParams.box.width / 2),
(int)selectorParams.box.y),
Point((int)(selectorParams.box.x + selectorParams.box.width / 2),
(int)(selectorParams.box.y + selectorParams.box.height)),
Scalar(255, 0, 0), 2, 1);
}
// show the image bounding box
imshow(windowName, selectorParams.image);
// reset the image
selectorParams.image = img.clone();
// get keyboard event
key = waitKey(30);
if (key == 'c' || key == 'C')//cancel selection
{
selectorParams.box = Rect();
break;
}
}
//cleanup callback
setMouseCallback(windowName, emptyMouseHandler, NULL);
return selectorParams.box;
}
void select(const String &windowName, Mat img, std::vector<Rect> &boundingBoxes,
bool showCrosshair = true, bool fromCenter = true, bool printNotice = true)
{
if(printNotice)
{
printf("Finish the selection process by pressing ESC button!\n");
}
boundingBoxes.clear();
key = 0;
// while key is not ESC (27)
for (;;)
{
Rect temp = select(windowName, img, showCrosshair, fromCenter, printNotice);
if (key == 27)
break;
if (temp.width > 0 && temp.height > 0)
boundingBoxes.push_back(temp);
}
}
struct handlerT
{
// basic parameters
bool isDrawing;
Rect2d box;
Mat image;
Point2f startPos;
// parameters for drawing from the center
bool drawFromCenter;
// initializer list
handlerT() : isDrawing(false), drawFromCenter(true){}
} selectorParams;
private:
static void emptyMouseHandler(int, int, int, int, void*)
{
}
static void mouseHandler(int event, int x, int y, int flags, void *param)
{
ROISelector *self = static_cast<ROISelector *>(param);
self->opencv_mouse_callback(event, x, y, flags);
}
void opencv_mouse_callback(int event, int x, int y, int)
{
switch (event)
{
// update the selected bounding box
case EVENT_MOUSEMOVE:
if (selectorParams.isDrawing)
{
if (selectorParams.drawFromCenter)
{
// limit half extends to imageSize
float halfWidth = std::min(std::min(
std::abs(x - selectorParams.startPos.x),
selectorParams.startPos.x),
imageSize.width - selectorParams.startPos.x);
float halfHeight = std::min(std::min(
std::abs(y - selectorParams.startPos.y),
selectorParams.startPos.y),
imageSize.height - selectorParams.startPos.y);
selectorParams.box.width = halfWidth * 2;
selectorParams.box.height = halfHeight * 2;
selectorParams.box.x = selectorParams.startPos.x - halfWidth;
selectorParams.box.y = selectorParams.startPos.y - halfHeight;
}
else
{
// limit x and y to imageSize
int lx = std::min(std::max(x, 0), imageSize.width);
int by = std::min(std::max(y, 0), imageSize.height);
selectorParams.box.width = std::abs(lx - selectorParams.startPos.x);
selectorParams.box.height = std::abs(by - selectorParams.startPos.y);
selectorParams.box.x = std::min((float)lx, selectorParams.startPos.x);
selectorParams.box.y = std::min((float)by, selectorParams.startPos.y);
}
}
break;
// start to select the bounding box
case EVENT_LBUTTONDOWN:
selectorParams.isDrawing = true;
selectorParams.box = Rect2d(x, y, 0, 0);
selectorParams.startPos = Point2f((float)x, (float)y);
break;
// cleaning up the selected bounding box
case EVENT_LBUTTONUP:
selectorParams.isDrawing = false;
if (selectorParams.box.width < 0)
{
selectorParams.box.x += selectorParams.box.width;
selectorParams.box.width *= -1;
}
if (selectorParams.box.height < 0)
{
selectorParams.box.y += selectorParams.box.height;
selectorParams.box.height *= -1;
}
break;
}
}
// save the keypressed character
int key;
Size imageSize;
};
}
Rect cv::selectROI(InputArray img, bool showCrosshair, bool fromCenter, bool printNotice)
{
ROISelector selector;
return selector.select("ROI selector", img.getMat(), showCrosshair, fromCenter, printNotice);
}
Rect cv::selectROI(const String& windowName, InputArray img, bool showCrosshair, bool fromCenter, bool printNotice)
{
ROISelector selector;
return selector.select(windowName, img.getMat(), showCrosshair, fromCenter, printNotice);
}
void cv::selectROIs(const String& windowName, InputArray img,
std::vector<Rect>& boundingBox, bool showCrosshair, bool fromCenter, bool printNotice)
{
ROISelector selector;
selector.select(windowName, img.getMat(), boundingBox, showCrosshair, fromCenter, printNotice);
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+591
View File
@@ -0,0 +1,591 @@
//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) 2008-2010, 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.
//--------------------Google Code 2010 -- Yannick Verdie--------------------//
#ifndef __OPENCV_HIGHGUI_QT_H__
#define __OPENCV_HIGHGUI_QT_H__
#include "precomp.hpp"
#ifndef _DEBUG
#define QT_NO_DEBUG_OUTPUT
#endif
#if defined( HAVE_QT_OPENGL )
#include <QtOpenGL>
// QGLWidget deprecated and no longer functions with Qt6, use QOpenGLWidget instead
#ifdef HAVE_QT6
#include <QOpenGLWidget>
#else
#include <QGLWidget>
#endif
#endif
#include <QAbstractEventDispatcher>
#include <QApplication>
#include <QFile>
#include <QPushButton>
#include <QGraphicsView>
#include <QSizePolicy>
#include <QInputDialog>
#include <QBoxLayout>
#include <QSettings>
#include <qtimer.h>
#include <QtConcurrentRun>
#include <QWaitCondition>
#include <QKeyEvent>
#include <QMetaObject>
#include <QPointer>
#include <QSlider>
#include <QLabel>
#include <QIODevice>
#include <QShortcut>
#include <QStatusBar>
#include <QVarLengthArray>
#include <QFileInfo>
#include <QDate>
#include <QFileDialog>
#include <QToolBar>
#include <QClipboard>
#include <QAction>
#include <QCheckBox>
#include <QRadioButton>
#include <QButtonGroup>
#include <QMenu>
#include <QTest>
//start private enum
enum { CV_MODE_NORMAL = 0, CV_MODE_OPENGL = 1 };
//we can change the keyboard shortcuts from here !
enum { shortcut_zoom_normal = Qt::CTRL + Qt::Key_Z,
shortcut_zoom_imgRegion = Qt::CTRL + Qt::Key_X,
shortcut_save_img = Qt::CTRL + Qt::Key_S,
shortcut_copy_clipbrd = Qt::CTRL + Qt::Key_C,
shortcut_properties_win = Qt::CTRL + Qt::Key_P,
shortcut_zoom_in = Qt::CTRL + Qt::Key_Plus,//QKeySequence(QKeySequence::ZoomIn),
shortcut_zoom_out = Qt::CTRL + Qt::Key_Minus,//QKeySequence(QKeySequence::ZoomOut),
shortcut_panning_left = Qt::CTRL + Qt::Key_Left,
shortcut_panning_right = Qt::CTRL + Qt::Key_Right,
shortcut_panning_up = Qt::CTRL + Qt::Key_Up,
shortcut_panning_down = Qt::CTRL + Qt::Key_Down
};
//end enum
class CvWindow;
class ViewPort;
class GuiReceiver : public QObject
{
Q_OBJECT
public:
GuiReceiver();
~GuiReceiver();
int start();
void isLastWindow();
bool bTimeOut;
QTimer* timer;
public slots:
void createWindow( QString name, int flags = 0 );
void destroyWindow(QString name);
void destroyAllWindow();
void addSlider(QString trackbar_name, QString window_name, void* value, int count, void* on_change);
void addSlider2(QString trackbar_name, QString window_name, void* value, int count, void* on_change, void *userdata);
void moveWindow(QString name, int x, int y);
void resizeWindow(QString name, int width, int height);
void showImage(QString name, cv::_InputArray arr);
void displayInfo( QString name, QString text, int delayms );
void displayStatusBar( QString name, QString text, int delayms );
void timeOut();
void toggleFullScreen(QString name, double flags );
cv::Rect getWindowRect(QString name);
double isFullScreen(QString name);
double getPropWindow(QString name);
void setPropWindow(QString name, double flags );
void setWindowTitle(QString name, QString title);
double getWindowVisible(QString name);
double getRatioWindow(QString name);
void setRatioWindow(QString name, double arg2 );
void saveWindowParameters(QString name);
void loadWindowParameters(QString name);
void putText(cv::Mat& img, QString text, QPoint org, void* font);
void addButton(QString button_name, int button_type, int initial_button_state , void* on_change, void* userdata);
void enablePropertiesButtonEachWindow();
void setOpenGlDrawCallback(QString name, void* callback, void* userdata);
void setOpenGlContext(QString name);
void updateWindow(QString name);
double isOpenGl(QString name);
private:
int nb_windows;
bool doesExternalQAppExist;
};
enum typeBar { type_CvTrackbar = 0, type_CvButtonbar = 1 };
class CvBar : public QHBoxLayout
{
public:
typeBar type;
QString name_bar;
QPointer<QWidget> myparent;
};
class CvButtonbar : public CvBar
{
Q_OBJECT
public:
CvButtonbar(QWidget* arg, QString bar_name);
void addButton(QString button_name, cv::ButtonCallback call, void* userdata, int button_type, int initial_button_state);
private:
void setLabel();
QPointer<QLabel> label;
QPointer<QButtonGroup> group_button;
};
class CvPushButton : public QPushButton
{
Q_OBJECT
public:
CvPushButton(CvButtonbar* par, QString button_name, cv::ButtonCallback call, void* userdata);
private:
CvButtonbar* myparent;
QString button_name ;
cv::ButtonCallback callback;
void* userdata;
private slots:
void callCallBack(bool);
};
class CvCheckBox : public QCheckBox
{
Q_OBJECT
public:
CvCheckBox(CvButtonbar* par, QString button_name, cv::ButtonCallback call, void* userdata, int initial_button_state);
private:
CvButtonbar* myparent;
QString button_name ;
cv::ButtonCallback callback;
void* userdata;
private slots:
void callCallBack(bool);
};
class CvRadioButton : public QRadioButton
{
Q_OBJECT
public:
CvRadioButton(CvButtonbar* par, QString button_name, cv::ButtonCallback call, void* userdata, int initial_button_state);
private:
CvButtonbar* myparent;
QString button_name ;
cv::ButtonCallback callback;
void* userdata;
private slots:
void callCallBack(bool);
};
class CvTrackbar : public CvBar
{
Q_OBJECT
public:
CvTrackbar(CvWindow* parent, QString name, int* value, int count, CvTrackbarCallback on_change);
CvTrackbar(CvWindow* parent, QString name, int* value, int count, CvTrackbarCallback2 on_change, void* data);
QPointer<QSlider> slider;
private slots:
void createDialog();
void update(int myvalue);
private:
void setLabel(int myvalue);
void create(CvWindow* arg, QString name, int* value, int count);
QString createLabel();
QPointer<QPushButton > label;
CvTrackbarCallback callback;
CvTrackbarCallback2 callback2;//look like it is use by python binding
int* dataSlider; // deprecated
void* userdata;
};
//Both are top level window, so that a way to differentiate them.
//if (obj->metaObject ()->className () == "CvWindow") does not give me robust result
enum typeWindow { type_CvWindow = 1, type_CvWinProperties = 2 };
class CvWinModel : public QWidget
{
public:
typeWindow type;
};
class CvWinProperties : public CvWinModel
{
Q_OBJECT
public:
CvWinProperties(QString name, QObject* parent);
~CvWinProperties();
QPointer<QBoxLayout> myLayout;
private:
void closeEvent ( QCloseEvent * e ) CV_OVERRIDE;
void showEvent ( QShowEvent * event ) CV_OVERRIDE;
void hideEvent ( QHideEvent * event ) CV_OVERRIDE;
};
class CvWindow : public CvWinModel
{
Q_OBJECT
public:
CvWindow(QString arg2, int flag = cv::WINDOW_NORMAL);
~CvWindow();
void setMouseCallBack(CvMouseCallback m, void* param);
void writeSettings();
void readSettings();
double getRatio();
void setRatio(int flags);
cv::Rect getWindowRect();
int getPropWindow();
void setPropWindow(int flags);
void toggleFullScreen(int flags);
void updateImage(cv::InputArray);
void displayInfo(QString text, int delayms);
void displayStatusBar(QString text, int delayms);
void enablePropertiesButton();
static CvButtonbar* createButtonBar(QString bar_name);
static void addSlider(CvWindow* w, QString name, int* value, int count, CvTrackbarCallback on_change);
static void addSlider2(CvWindow* w, QString name, int* value, int count, CvTrackbarCallback2 on_change, void* userdata);
void setOpenGlDrawCallback(CvOpenGlDrawCallback callback, void* userdata);
void makeCurrentOpenGlContext();
void updateGl();
bool isOpenGl();
void setViewportSize(QSize size);
//parameters (will be save/load)
int param_flags;
int param_gui_mode;
int param_ratio_mode;
QPointer<QBoxLayout> myGlobalLayout; //All the widget (toolbar, view, LayoutBar, ...) are attached to it
QPointer<QBoxLayout> myBarLayout;
QVector<QAction*> vect_QActions;
QPointer<QStatusBar> myStatusBar;
QPointer<QToolBar> myToolBar;
QPointer<QLabel> myStatusBar_msg;
protected:
virtual void keyPressEvent(QKeyEvent* event) CV_OVERRIDE;
virtual void closeEvent(QCloseEvent* event) CV_OVERRIDE;
private:
int mode_display; //opengl or native
ViewPort* myView;
QVector<QShortcut*> vect_QShortcuts;
void icvLoadTrackbars(QSettings *settings);
void icvSaveTrackbars(QSettings *settings);
void icvLoadControlPanel();
void icvSaveControlPanel();
void icvLoadButtonbar(CvButtonbar* t,QSettings *settings);
void icvSaveButtonbar(CvButtonbar* t,QSettings *settings);
void createActions();
void createShortcuts();
void createToolBar();
void createView();
void createStatusBar();
void createGlobalLayout();
void createBarLayout();
CvWinProperties* createParameterWindow();
void hideTools();
void showTools();
QSize getAvailableSize();
private slots:
void displayPropertiesWin();
};
enum type_mouse_event { mouse_up = 0, mouse_down = 1, mouse_dbclick = 2, mouse_move = 3, mouse_wheel = 4 };
static const int tableMouseButtons[][3]={
{cv::EVENT_LBUTTONUP, cv::EVENT_RBUTTONUP, cv::EVENT_MBUTTONUP}, //mouse_up
{cv::EVENT_LBUTTONDOWN, cv::EVENT_RBUTTONDOWN, cv::EVENT_MBUTTONDOWN}, //mouse_down
{cv::EVENT_LBUTTONDBLCLK, cv::EVENT_RBUTTONDBLCLK, cv::EVENT_MBUTTONDBLCLK}, //mouse_dbclick
{cv::EVENT_MOUSEMOVE, cv::EVENT_MOUSEMOVE, cv::EVENT_MOUSEMOVE}, //mouse_move
{0, 0, 0} //mouse_wheel, to prevent exceptions in code
};
class ViewPort
{
public:
virtual ~ViewPort() {}
virtual QWidget* getWidget() = 0;
virtual void setMouseCallBack(CvMouseCallback callback, void* param) = 0;
virtual void writeSettings(QSettings& settings) = 0;
virtual void readSettings(QSettings& settings) = 0;
virtual double getRatio() = 0;
virtual void setRatio(int flags) = 0;
virtual void updateImage(cv::InputArray) = 0;
virtual void startDisplayInfo(QString text, int delayms) = 0;
virtual void setOpenGlDrawCallback(CvOpenGlDrawCallback callback, void* userdata) = 0;
virtual void makeCurrentOpenGlContext() = 0;
virtual void updateGl() = 0;
virtual void setSize(QSize size_) = 0;
};
class OCVViewPort : public ViewPort
{
public:
explicit OCVViewPort();
~OCVViewPort() CV_OVERRIDE {};
void setMouseCallBack(CvMouseCallback callback, void* param) CV_OVERRIDE;
protected:
void icvmouseEvent(QMouseEvent* event, type_mouse_event category);
void icvmouseHandler(QMouseEvent* event, type_mouse_event category, int& cv_event, int& flags);
virtual void icvmouseProcessing(QPointF pt, int cv_event, int flags);
CvMouseCallback mouseCallback;
void* mouseData;
};
#ifdef HAVE_QT_OPENGL
// Use QOpenGLWidget for Qt6 (QGLWidget is deprecated)
#ifdef HAVE_QT6
typedef QOpenGLWidget OpenCVQtWidgetBase;
#else
typedef QGLWidget OpenCVQtWidgetBase;
#endif
class OpenGlViewPort : public OpenCVQtWidgetBase, public OCVViewPort
{
public:
explicit OpenGlViewPort(QWidget* parent);
~OpenGlViewPort() CV_OVERRIDE;
QWidget* getWidget() CV_OVERRIDE;
void writeSettings(QSettings& settings) CV_OVERRIDE;
void readSettings(QSettings& settings) CV_OVERRIDE;
double getRatio() CV_OVERRIDE;
void setRatio(int flags) CV_OVERRIDE;
void updateImage(cv::InputArray arr) CV_OVERRIDE;
void startDisplayInfo(QString text, int delayms) CV_OVERRIDE;
void setOpenGlDrawCallback(CvOpenGlDrawCallback callback, void* userdata) CV_OVERRIDE;
void makeCurrentOpenGlContext() CV_OVERRIDE;
void updateGl() CV_OVERRIDE;
void setSize(QSize size_) CV_OVERRIDE;
protected:
void initializeGL() CV_OVERRIDE;
void resizeGL(int w, int h) CV_OVERRIDE;
void paintGL() CV_OVERRIDE;
void wheelEvent(QWheelEvent* event) CV_OVERRIDE;
void mouseMoveEvent(QMouseEvent* event) CV_OVERRIDE;
void mousePressEvent(QMouseEvent* event) CV_OVERRIDE;
void mouseReleaseEvent(QMouseEvent* event) CV_OVERRIDE;
void mouseDoubleClickEvent(QMouseEvent* event) CV_OVERRIDE;
QSize sizeHint() const CV_OVERRIDE;
private:
QSize size;
CvOpenGlDrawCallback glDrawCallback;
void* glDrawData;
};
#endif // HAVE_QT_OPENGL
class DefaultViewPort : public QGraphicsView, public OCVViewPort
{
Q_OBJECT
public:
DefaultViewPort(CvWindow* centralWidget, int arg2);
~DefaultViewPort() CV_OVERRIDE;
QWidget* getWidget() CV_OVERRIDE;
void writeSettings(QSettings& settings) CV_OVERRIDE;
void readSettings(QSettings& settings) CV_OVERRIDE;
double getRatio() CV_OVERRIDE;
void setRatio(int flags) CV_OVERRIDE;
void updateImage(cv::InputArray) CV_OVERRIDE;
void startDisplayInfo(QString text, int delayms) CV_OVERRIDE;
void setOpenGlDrawCallback(CvOpenGlDrawCallback callback, void* userdata) CV_OVERRIDE;
void makeCurrentOpenGlContext() CV_OVERRIDE;
void updateGl() CV_OVERRIDE;
void setSize(QSize size_) CV_OVERRIDE;
public slots:
//reference:
//http://www.qtcentre.org/wiki/index.php?title=QGraphicsView:_Smooth_Panning_and_Zooming
//http://doc.qt.nokia.com/4.6/gestures-imagegestures-imagewidget-cpp.html
void siftWindowOnLeft();
void siftWindowOnRight();
void siftWindowOnUp() ;
void siftWindowOnDown();
void resetZoom();
void imgRegion();
void ZoomIn();
void ZoomOut();
void saveView();
void copy2Clipbrd();
protected:
void contextMenuEvent(QContextMenuEvent* event) CV_OVERRIDE;
void resizeEvent(QResizeEvent* event) CV_OVERRIDE;
void paintEvent(QPaintEvent* paintEventInfo) CV_OVERRIDE;
void wheelEvent(QWheelEvent* event) CV_OVERRIDE;
void mouseMoveEvent(QMouseEvent* event) CV_OVERRIDE;
void mousePressEvent(QMouseEvent* event) CV_OVERRIDE;
void mouseReleaseEvent(QMouseEvent* event) CV_OVERRIDE;
void mouseDoubleClickEvent(QMouseEvent* event) CV_OVERRIDE;
private:
int param_keepRatio;
//parameters (will be save/load)
QTransform param_matrixWorld;
cv::Mat image2Draw_mat;
QImage image2Draw_qt;
int nbChannelOriginImage;
void scaleView(qreal scaleFactor, QPointF center);
void moveView(QPointF delta);
QPoint mouseCoordinate;
QPointF positionGrabbing;
QRect positionCorners;
QTransform matrixWorld_inv;
float ratioX, ratioY;
QSize sizeHint() const CV_OVERRIDE;
QPointer<CvWindow> centralWidget;
QPointer<QTimer> timerDisplay;
bool drawInfo;
QString infoText;
QRectF target;
void drawInstructions(QPainter *painter);
void drawViewOverview(QPainter *painter);
void drawImgRegion(QPainter *painter);
void draw2D(QPainter *painter);
void drawStatusBar();
void controlImagePosition();
void icvmouseProcessing(QPointF pt, int cv_event, int flags) CV_OVERRIDE;
private slots:
void stopDisplayInfo();
};
#endif
+15
View File
@@ -0,0 +1,15 @@
<RCC>
<qresource prefix="/">
<file alias="left-icon">files_Qt/Material/28.png</file>
<file alias="right-icon">files_Qt/Material/23.png</file>
<file alias="up-icon">files_Qt/Material/19.png</file>
<file alias="down-icon">files_Qt/Material/24.png</file>
<file alias="zoom_x1-icon">files_Qt/Material/27.png</file>
<file alias="imgRegion-icon">files_Qt/Material/61.png</file>
<file alias="zoom_in-icon">files_Qt/Material/106.png</file>
<file alias="zoom_out-icon">files_Qt/Material/107.png</file>
<file alias="save-icon">files_Qt/Material/7.png</file>
<file alias="copy_clipbrd-icon">files_Qt/Material/43.png</file>
<file alias="properties-icon">files_Qt/Material/38.png</file>
</qresource>
</RCC>
File diff suppressed because it is too large Load Diff
+798
View File
@@ -0,0 +1,798 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#include "precomp.hpp"
#include "window_framebuffer.hpp"
#include <opencv2/core/utils/configuration.private.hpp>
#include <opencv2/core/utils/logger.defines.hpp>
#ifdef NDEBUG
#define CV_LOG_STRIP_LEVEL CV_LOG_LEVEL_DEBUG + 1
#else
#define CV_LOG_STRIP_LEVEL CV_LOG_LEVEL_VERBOSE + 1
#endif
#include <opencv2/core/utils/logger.hpp>
#include <unistd.h>
#include <stdio.h>
#include <termios.h>
#include <fcntl.h>
#include <stdlib.h>
#include <linux/fb.h>
#include <linux/input.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include "opencv2/imgproc.hpp"
#ifdef HAVE_FRAMEBUFFER_XVFB
#include <X11/XWDFile.h>
#include <X11/X.h>
#define C32INT(ptr) ((((unsigned char*)ptr)[0] << 24) | (((unsigned char*)ptr)[1] << 16) | \
(((unsigned char*)ptr)[2] << 8) | (((unsigned char*)ptr)[3] << 0))
#endif
namespace cv {
namespace highgui_backend {
std::shared_ptr<UIBackend> createUIBackendFramebuffer()
{
return std::make_shared<FramebufferBackend>();
}
static std::string& getFBMode()
{
static std::string fbModeOpenCV =
cv::utils::getConfigurationParameterString("OPENCV_HIGHGUI_FB_MODE", "FB");
return fbModeOpenCV;
}
static std::string& getFBFileName()
{
static std::string fbFileNameFB =
cv::utils::getConfigurationParameterString("FRAMEBUFFER", "/dev/fb0");
static std::string fbFileNameOpenCV =
cv::utils::getConfigurationParameterString("OPENCV_HIGHGUI_FB_DEVICE", "");
if (!fbFileNameOpenCV.empty()) return fbFileNameOpenCV;
return fbFileNameFB;
}
FramebufferWindow::FramebufferWindow(FramebufferBackend &_backend, int _flags):
backend(_backend), flags(_flags)
{
CV_LOG_DEBUG(NULL, "UI: FramebufferWindow::FramebufferWindow()");
FB_ID = "FramebufferWindow";
windowRect = Rect(0,0, backend.getFBWidth(), backend.getFBHeight());
}
FramebufferWindow::~FramebufferWindow()
{
CV_LOG_DEBUG(NULL, "UI: FramebufferWindow::~FramebufferWindow()");
}
void FramebufferWindow::imshow(InputArray image)
{
CV_LOG_DEBUG(NULL, "UI: FramebufferWindow::imshow(InputArray image)");
currentImg = image.getMat().clone();
CV_LOG_INFO(NULL, "UI: InputArray image: "
<< cv::typeToString(image.type()) << " size " << image.size());
if (currentImg.empty())
{
CV_LOG_WARNING(NULL, "UI: image is empty");
return;
}
CV_CheckEQ(currentImg.dims, 2, "UI: dims != 2");
Mat img = image.getMat();
switch (img.channels())
{
case 1:
{
Mat tmp;
switch(img.type())
{
case CV_8U:
tmp = img;
break;
case CV_8S:
cv::convertScaleAbs(img, tmp, 1, 127);
break;
case CV_16S:
cv::convertScaleAbs(img, tmp, 1/255., 127);
break;
case CV_16U:
cv::convertScaleAbs(img, tmp, 1/255.);
break;
case CV_32F:
case CV_64F: // assuming image has values in range [0, 1)
img.convertTo(tmp, CV_8U, 255., 0.);
break;
}
Mat rgb(img.rows, img.cols, CV_8UC3);
cvtColor(tmp, rgb, COLOR_GRAY2RGB);
img = rgb;
}
break;
case 3:
case 4:
{
Mat tmp(img.rows, img.cols, CV_8UC3);
convertToShow(img, tmp, true);
img = tmp;
}
break;
default:
CV_Error(cv::Error::StsBadArg, "Bad image: wrong number of channels");
}
{
Mat bgra(img.rows, img.cols, CV_8UC4);
cvtColor(img, bgra, COLOR_RGB2BGRA, bgra.channels());
img = bgra;
}
int newWidth = windowRect.width;
int newHeight = windowRect.height;
int cntChannel = img.channels();
cv::Size imgSize = currentImg.size();
if (flags & WINDOW_AUTOSIZE)
{
windowRect.width = imgSize.width;
windowRect.height = imgSize.height;
newWidth = windowRect.width;
newHeight = windowRect.height;
}
if (flags & WINDOW_FREERATIO)
{
newWidth = windowRect.width;
newHeight = windowRect.height;
}
else //WINDOW_KEEPRATIO
{
double aspect_ratio = ((double)img.cols) / img.rows;
newWidth = windowRect.width;
newHeight = (int)(windowRect.width / aspect_ratio);
if (newHeight > windowRect.height)
{
newWidth = (int)(windowRect.height * aspect_ratio);
newHeight = windowRect.height;
}
}
if ((newWidth != img.cols) && (newHeight != img.rows))
{
Mat imResize;
cv::resize(img, imResize, cv::Size(newWidth, newHeight), INTER_LINEAR);
img = imResize;
}
CV_LOG_INFO(NULL, "UI: Formated image: "
<< cv::typeToString(img.type()) << " size " << img.size());
if (backend.getMode() == FB_MODE_EMU)
{
CV_LOG_WARNING(NULL, "UI: FramebufferWindow::imshow is used in EMU mode");
return;
}
if (backend.getFBPointer() == MAP_FAILED)
{
CV_LOG_ERROR(NULL, "UI: Framebuffer is not mapped");
return;
}
int xOffset = backend.getFBXOffset();
int yOffset = backend.getFBYOffset();
int fbHeight = backend.getFBHeight();
int fbWidth = backend.getFBWidth();
int lineLength = backend.getFBLineLength();
int img_start_x;
int img_start_y;
int img_end_x;
int img_end_y;
int fb_start_x;
int fb_start_y;
if (windowRect.y - yOffset < 0)
{
img_start_y = - (windowRect.y - yOffset);
}
else
{
img_start_y = 0;
}
if (windowRect.x - xOffset < 0)
{
img_start_x = - (windowRect.x - xOffset);
}
else
{
img_start_x = 0;
}
if (windowRect.y + yOffset + img.rows > fbHeight)
{
img_end_y = fbHeight - windowRect.y - yOffset;
}
else
{
img_end_y = img.rows;
}
if (windowRect.x + xOffset + img.cols > fbWidth)
{
img_end_x = fbWidth - windowRect.x - xOffset;
}
else
{
img_end_x = img.cols;
}
if (windowRect.y + yOffset >= 0)
{
fb_start_y = windowRect.y + yOffset;
}
else
{
fb_start_y = 0;
}
if (windowRect.x + xOffset >= 0)
{
fb_start_x = windowRect.x + xOffset;
}
else
{
fb_start_x = 0;
}
for (int y = img_start_y; y < img_end_y; y++)
{
std::memcpy(backend.getFBPointer() +
(fb_start_y + y - img_start_y) * lineLength + fb_start_x * cntChannel,
img.ptr<unsigned char>(y) + img_start_x * cntChannel,
(img_end_x - img_start_x) * cntChannel);
}
}
double FramebufferWindow::getProperty(int /*prop*/) const
{
CV_LOG_WARNING(NULL, "UI: getProperty (not supported)");
return 0.0;
}
bool FramebufferWindow::setProperty(int /*prop*/, double /*value*/)
{
CV_LOG_WARNING(NULL, "UI: setProperty (not supported)");
return false;
}
void FramebufferWindow::resize(int width, int height)
{
CV_LOG_DEBUG(NULL, "UI: FramebufferWindow::resize(int width "
<< width <<", height " << height << ")");
CV_Assert(width > 0);
CV_Assert(height > 0);
if (!(flags & WINDOW_AUTOSIZE))
{
windowRect.width = width;
windowRect.height = height;
if (!currentImg.empty())
{
imshow(currentImg);
}
}
}
void FramebufferWindow::move(int x, int y)
{
CV_LOG_DEBUG(NULL, "UI: FramebufferWindow::move(int x " << x << ", y " << y <<")");
windowRect.x = x;
windowRect.y = y;
if (!currentImg.empty())
{
imshow(currentImg);
}
}
Rect FramebufferWindow::getImageRect() const
{
CV_LOG_DEBUG(NULL, "UI: FramebufferWindow::getImageRect()");
return windowRect;
}
void FramebufferWindow::setTitle(const std::string& /*title*/)
{
CV_LOG_WARNING(NULL, "UI: setTitle (not supported)");
}
void FramebufferWindow::setMouseCallback(MouseCallback /*onMouse*/, void* /*userdata*/)
{
CV_LOG_WARNING(NULL, "UI: setMouseCallback (not supported)");
}
std::shared_ptr<UITrackbar> FramebufferWindow::createTrackbar(
const std::string& /*name*/,
int /*count*/,
TrackbarCallback /*onChange*/,
void* /*userdata*/)
{
CV_LOG_WARNING(NULL, "UI: createTrackbar (not supported)");
return nullptr;
}
std::shared_ptr<UITrackbar> FramebufferWindow::findTrackbar(const std::string& /*name*/)
{
CV_LOG_WARNING(NULL, "UI: findTrackbar (not supported)");
return nullptr;
}
const std::string& FramebufferWindow::getID() const
{
CV_LOG_DEBUG(NULL, "UI: FramebufferWindow::getID()");
return FB_ID;
}
bool FramebufferWindow::isActive() const
{
CV_LOG_DEBUG(NULL, "UI: FramebufferWindow::isActive()");
return true;
}
void FramebufferWindow::destroy()
{
CV_LOG_DEBUG(NULL, "UI: FramebufferWindow::destroy()");
}
int FramebufferBackend::fbOpenAndGetInfo()
{
std::string fbFileName = getFBFileName();
CV_LOG_INFO(NULL, "UI: FramebufferWindow::The following is used as a framebuffer file: \n"
<< fbFileName);
int fb_fd = open(fbFileName.c_str(), O_RDWR);
if (fb_fd == -1)
{
CV_LOG_ERROR(NULL, "UI: can't open framebuffer");
return -1;
}
if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &fixInfo))
{
CV_LOG_ERROR(NULL, "UI: can't read fix info for framebuffer");
return -1;
}
if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &varInfo))
{
CV_LOG_ERROR(NULL, "UI: can't read var info for framebuffer");
return -1;
}
CV_LOG_INFO(NULL, "UI: framebuffer info: \n"
<< " red offset " << varInfo.red.offset << " length " << varInfo.red.length << "\n"
<< " green offset " << varInfo.green.offset << " length " << varInfo.green.length << "\n"
<< " blue offset " << varInfo.blue.offset << " length " << varInfo.blue.length << "\n"
<< "transp offset " << varInfo.transp.offset << " length " <<varInfo.transp.length << "\n"
<< "bits_per_pixel " << varInfo.bits_per_pixel);
if ((varInfo.red.offset != 16) && (varInfo.red.length != 8) &&
(varInfo.green.offset != 8) && (varInfo.green.length != 8) &&
(varInfo.blue.offset != 0) && (varInfo.blue.length != 8) &&
(varInfo.bits_per_pixel != 32) )
{
close(fb_fd);
CV_LOG_ERROR(NULL, "UI: Framebuffer format is not supported "
<< "(use BGRA format with bits_per_pixel = 32)");
return -1;
}
fbWidth = varInfo.xres;
fbHeight = varInfo.yres;
fbXOffset = varInfo.xoffset;
fbYOffset = varInfo.yoffset;
fbBitsPerPixel = varInfo.bits_per_pixel;
fbLineLength = fixInfo.line_length;
fbScreenSize = max(varInfo.xres, varInfo.xres_virtual) *
max(varInfo.yres, varInfo.yres_virtual) *
fbBitsPerPixel / 8;
fbPointer = (unsigned char*)
mmap(0, fbScreenSize, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0);
if (fbPointer == MAP_FAILED)
{
CV_LOG_ERROR(NULL, "UI: can't mmap framebuffer");
return -1;
}
return fb_fd;
}
int FramebufferBackend::XvfbOpenAndGetInfo()
{
int fb_fd = -1;
#ifdef HAVE_FRAMEBUFFER_XVFB
std::string fbFileName = getFBFileName();
CV_LOG_INFO(NULL, "UI: FramebufferWindow::The following is used as a framebuffer file: \n"
<< fbFileName);
fb_fd = open(fbFileName.c_str(), O_RDWR);
if (fb_fd == -1)
{
CV_LOG_ERROR(NULL, "UI: can't open framebuffer");
return -1;
}
XWDFileHeader *xwd_header;
xwd_header = (XWDFileHeader*)
mmap(NULL, sizeof(XWDFileHeader), PROT_READ, MAP_SHARED, fb_fd, 0);
if (xwd_header == MAP_FAILED)
{
CV_LOG_ERROR(NULL, "UI: can't mmap xwd header");
return -1;
}
if (C32INT(&(xwd_header->pixmap_format)) != ZPixmap)
{
CV_LOG_ERROR(NULL, "Unsupported pixmap format: " << xwd_header->pixmap_format);
return -1;
}
if (xwd_header->xoffset != 0)
{
CV_LOG_ERROR(NULL, "UI: Unsupported xoffset value: " << xwd_header->xoffset );
return -1;
}
unsigned int r = C32INT(&(xwd_header->red_mask));
unsigned int g = C32INT(&(xwd_header->green_mask));
unsigned int b = C32INT(&(xwd_header->blue_mask));
fbWidth = C32INT(&(xwd_header->pixmap_width));
fbHeight = C32INT(&(xwd_header->pixmap_height));
fbXOffset = 0;
fbYOffset = 0;
fbLineLength = C32INT(&(xwd_header->bytes_per_line));
fbBitsPerPixel = C32INT(&(xwd_header->bits_per_pixel));
CV_LOG_INFO(NULL, "UI: XVFB info: \n"
<< " red_mask " << r << "\n"
<< " green_mask " << g << "\n"
<< " blue_mask " << b << "\n"
<< "bits_per_pixel " << fbBitsPerPixel);
if ((r != 16711680 ) && (g != 65280 ) && (b != 255 ) &&
(fbBitsPerPixel != 32))
{
CV_LOG_ERROR(NULL, "UI: Framebuffer format is not supported "
<< "(use BGRA format with bits_per_pixel = 32)");
return -1;
}
xvfb_len_header = C32INT(&(xwd_header->header_size));
xvfb_len_colors = sizeof(XWDColor) * C32INT(&(xwd_header->ncolors));
xvfb_len_pixmap = C32INT(&(xwd_header->bytes_per_line)) *
C32INT(&(xwd_header->pixmap_height));
munmap(xwd_header, sizeof(XWDFileHeader));
fbScreenSize = xvfb_len_header + xvfb_len_colors + xvfb_len_pixmap;
xwd_header = (XWDFileHeader*)
mmap(NULL, fbScreenSize, PROT_READ | PROT_WRITE, MAP_SHARED, fb_fd, 0);
fbPointer = (unsigned char*)xwd_header;
fbPointer_dist = xvfb_len_header + xvfb_len_colors;
#else
CV_LOG_WARNING(NULL, "UI: To use virtual framebuffer, "
<< "compile OpenCV with the WITH_FRAMEBUFFER_XVFB=ON");
#endif
return fb_fd;
}
fb_var_screeninfo &FramebufferBackend::getVarInfo()
{
return varInfo;
}
fb_fix_screeninfo &FramebufferBackend::getFixInfo()
{
return fixInfo;
}
int FramebufferBackend::getFramebufferID()
{
return fbID;
}
int FramebufferBackend::getFBWidth()
{
return fbWidth;
}
int FramebufferBackend::getFBHeight()
{
return fbHeight;
}
int FramebufferBackend::getFBXOffset()
{
return fbXOffset;
}
int FramebufferBackend::getFBYOffset()
{
return fbYOffset;
}
int FramebufferBackend::getFBBitsPerPixel()
{
return fbBitsPerPixel;
}
int FramebufferBackend::getFBLineLength()
{
return fbLineLength;
}
unsigned char* FramebufferBackend::getFBPointer()
{
return fbPointer + fbPointer_dist;
}
Mat& FramebufferBackend::getBackgroundBuff()
{
return backgroundBuff;
}
OpenCVFBMode FramebufferBackend::getMode()
{
return mode;
}
FramebufferBackend::FramebufferBackend():mode(FB_MODE_FB), fbPointer_dist(0)
{
CV_LOG_DEBUG(NULL, "UI: FramebufferWindow::FramebufferBackend()");
std::string fbModeStr = getFBMode();
if (fbModeStr == "EMU")
{
mode = FB_MODE_EMU;
CV_LOG_WARNING(NULL, "UI: FramebufferWindow is trying to use EMU mode");
}
if (fbModeStr == "FB")
{
mode = FB_MODE_FB;
CV_LOG_WARNING(NULL, "UI: FramebufferWindow is trying to use FB mode");
}
if (fbModeStr == "XVFB")
{
mode = FB_MODE_XVFB;
CV_LOG_WARNING(NULL, "UI: FramebufferWindow is trying to use XVFB mode");
}
fbID = -1;
if (mode == FB_MODE_FB)
{
fbID = fbOpenAndGetInfo();
}
if (mode == FB_MODE_XVFB)
{
fbID = XvfbOpenAndGetInfo();
}
CV_LOG_INFO(NULL, "UI: FramebufferWindow::fbID " << fbID);
if (fbID == -1)
{
mode = FB_MODE_EMU;
fbWidth = 640;
fbHeight = 480;
fbXOffset = 0;
fbYOffset = 0;
fbBitsPerPixel = 0;
fbLineLength = 0;
CV_LOG_WARNING(NULL, "UI: FramebufferWindow is used in EMU mode");
return;
}
CV_LOG_INFO(NULL, "UI: Framebuffer's width, height, bits per pix: "
<< fbWidth << " " << fbHeight << " " << fbBitsPerPixel);
CV_LOG_INFO(NULL, "UI: Framebuffer's offsets (x, y), line length: "
<< fbXOffset << " " << fbYOffset << " " << fbLineLength);
backgroundBuff = Mat(fbHeight, fbWidth, CV_8UC4);
int cntChannel = 4;
for (int y = fbYOffset; y < backgroundBuff.rows + fbYOffset; y++)
{
std::memcpy(backgroundBuff.ptr<unsigned char>(y - fbYOffset),
getFBPointer() + y * fbLineLength + fbXOffset * cntChannel,
backgroundBuff.cols * cntChannel);
}
}
FramebufferBackend::~FramebufferBackend()
{
CV_LOG_DEBUG(NULL, "UI: FramebufferBackend::~FramebufferBackend()");
if(fbID == -1) return;
if (fbPointer != MAP_FAILED)
{
int cntChannel = 4;
for (int y = fbYOffset; y < backgroundBuff.rows + fbYOffset; y++)
{
std::memcpy(getFBPointer() + y * fbLineLength + fbXOffset * cntChannel,
backgroundBuff.ptr<cv::Vec4b>(y - fbYOffset),
backgroundBuff.cols * cntChannel);
}
munmap(fbPointer, fbScreenSize);
}
close(fbID);
}
void FramebufferBackend::destroyAllWindows() {
CV_LOG_DEBUG(NULL, "UI: FramebufferBackend::destroyAllWindows()");
}
// namedWindow
std::shared_ptr<UIWindow> FramebufferBackend::createWindow(
const std::string& winname,
int flags)
{
CV_LOG_DEBUG(NULL, "UI: FramebufferBackend::createWindow("
<< winname << ", " << flags << ")");
return std::make_shared<FramebufferWindow>(*this, flags);
}
void FramebufferBackend::initTermios(int echo, int wait)
{
tcgetattr(0, &old);
current = old;
current.c_lflag &= ~ICANON;
current.c_lflag &= ~ISIG;
current.c_cc[VMIN] = wait;
if (echo)
{
current.c_lflag |= ECHO;
}
else
{
current.c_lflag &= ~ECHO;
}
tcsetattr(0, TCSANOW, &current);
}
void FramebufferBackend::resetTermios(void)
{
tcsetattr(0, TCSANOW, &old);
}
int FramebufferBackend::getch_(int echo, int wait)
{
int ch;
initTermios(echo, wait);
ch = getchar();
if (ch < 0)
{
rewind(stdin);
}
resetTermios();
return ch;
}
bool FramebufferBackend::kbhit()
{
int byteswaiting = 0;
initTermios(0, 1);
if (ioctl(0, FIONREAD, &byteswaiting) < 0)
{
CV_LOG_ERROR(NULL, "UI: Framebuffer ERR byteswaiting" );
}
resetTermios();
return byteswaiting > 0;
}
int FramebufferBackend::waitKeyEx(int delay)
{
CV_LOG_DEBUG(NULL, "UI: FramebufferBackend::waitKeyEx(int delay = " << delay << ")");
int code = -1;
if (delay <= 0)
{
int ch = getch_(0, 1);
CV_LOG_INFO(NULL, "UI: FramebufferBackend::getch_() take value = " << (int)ch);
code = ch;
while ((ch = getch_(0, 0)) >= 0)
{
CV_LOG_INFO(NULL, "UI: FramebufferBackend::getch_() take value = "
<< (int)ch << " (additional code on <stdin>)");
code = ch;
}
}
else
{
bool f_kbhit = false;
while (!(f_kbhit = kbhit()) && (delay > 0))
{
delay -= 1;
usleep(1000);
}
if (f_kbhit)
{
CV_LOG_INFO(NULL, "UI: FramebufferBackend kbhit is True ");
int ch = getch_(0, 1);
CV_LOG_INFO(NULL, "UI: FramebufferBackend::getch_() take value = " << (int)ch);
code = ch;
while ((ch = getch_(0, 0)) >= 0)
{
CV_LOG_INFO(NULL, "UI: FramebufferBackend::getch_() take value = "
<< (int)ch << " (additional code on <stdin>)");
code = ch;
}
}
}
CV_LOG_INFO(NULL, "UI: FramebufferBackend::waitKeyEx() result code = " << code);
return code;
}
int FramebufferBackend::pollKey()
{
CV_LOG_DEBUG(NULL, "UI: FramebufferBackend::pollKey()");
int code = -1;
bool f_kbhit = false;
f_kbhit = kbhit();
if (f_kbhit)
{
CV_LOG_INFO(NULL, "UI: FramebufferBackend kbhit is True ");
int ch = getch_(0, 1);
CV_LOG_INFO(NULL, "UI: FramebufferBackend::getch_() take value = " << (int)ch);
code = ch;
while ((ch = getch_(0, 0)) >= 0)
{
CV_LOG_INFO(NULL, "UI: FramebufferBackend::getch_() take value = "
<< (int)ch << " (additional code on <stdin>)");
code = ch;
}
}
return code;
}
const std::string FramebufferBackend::getName() const
{
return "FB";
}
}} // cv::highgui_backend::
+135
View File
@@ -0,0 +1,135 @@
// This file is part of OpenCV project.
// It is subject to the license terms in the LICENSE file found in the top-level directory
// of this distribution and at http://opencv.org/license.html.
#ifndef OPENCV_HIGHGUI_WINDOWS_FRAMEBUFFER_HPP
#define OPENCV_HIGHGUI_WINDOWS_FRAMEBUFFER_HPP
#include "backend.hpp"
#include <linux/fb.h>
#include <linux/input.h>
#include <termios.h>
namespace cv {
namespace highgui_backend {
enum OpenCVFBMode{
FB_MODE_EMU,
FB_MODE_FB,
FB_MODE_XVFB
};
class FramebufferBackend;
class FramebufferWindow : public UIWindow
{
FramebufferBackend &backend;
std::string FB_ID;
Rect windowRect;
int flags;
Mat currentImg;
public:
FramebufferWindow(FramebufferBackend &backend, int flags);
virtual ~FramebufferWindow();
virtual void imshow(InputArray image) override;
virtual double getProperty(int prop) const override;
virtual bool setProperty(int prop, double value) override;
virtual void resize(int width, int height) override;
virtual void move(int x, int y) override;
virtual Rect getImageRect() const override;
virtual void setTitle(const std::string& title) override;
virtual void setMouseCallback(MouseCallback onMouse, void* userdata /*= 0*/) override;
virtual std::shared_ptr<UITrackbar> createTrackbar(
const std::string& name,
int count,
TrackbarCallback onChange /*= 0*/,
void* userdata /*= 0*/
) override;
virtual std::shared_ptr<UITrackbar> findTrackbar(const std::string& name) override;
virtual const std::string& getID() const override;
virtual bool isActive() const override;
virtual void destroy() override;
}; // FramebufferWindow
class FramebufferBackend: public UIBackend
{
OpenCVFBMode mode;
struct termios old, current;
void initTermios(int echo, int wait);
void resetTermios(void);
int getch_(int echo, int wait);
bool kbhit();
fb_var_screeninfo varInfo;
fb_fix_screeninfo fixInfo;
int fbWidth;
int fbHeight;
int fbXOffset;
int fbYOffset;
int fbBitsPerPixel;
int fbLineLength;
long int fbScreenSize;
unsigned char* fbPointer;
unsigned int fbPointer_dist;
Mat backgroundBuff;
int fbOpenAndGetInfo();
int fbID;
unsigned int xvfb_len_header;
unsigned int xvfb_len_colors;
unsigned int xvfb_len_pixmap;
int XvfbOpenAndGetInfo();
public:
fb_var_screeninfo &getVarInfo();
fb_fix_screeninfo &getFixInfo();
int getFramebufferID();
int getFBWidth();
int getFBHeight();
int getFBXOffset();
int getFBYOffset();
int getFBBitsPerPixel();
int getFBLineLength();
unsigned char* getFBPointer();
Mat& getBackgroundBuff();
OpenCVFBMode getMode();
FramebufferBackend();
virtual ~FramebufferBackend();
virtual void destroyAllWindows()override;
// namedWindow
virtual std::shared_ptr<UIWindow> createWindow(
const std::string& winname,
int flags
)override;
virtual int waitKeyEx(int delay /*= 0*/)override;
virtual int pollKey() override;
virtual const std::string getName() const override;
};
}} // cv::highgui_backend::
#endif
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff