Images

The Image component is used for adding images to the UI in several supported formats, including bitmap formats, such as PNG and JPEG, and vector graphics formats, such as SVG. To use any image files in your designs, you need to first add them to Assets:
- Select Assets >.
- Select the image file, and then select Open.
- Select the location where the image will be saved in the Add Resources dialog.
- Select OK.
Your image is now available in Assets.

When you drag-and-drop an image file from Assets to Navigator or the 2D view, Qt Design Studio automatically creates an instance of the Image component for you with the path to the image file set as the value of the Source field in Properties.
To load images from a URL using a supported URL scheme, specify the URL in the Source field.
You can use the Border Image component to display an image, such as a PNG file, as a border and a background. For more information about using border images to create buttons, see Creating Scalable Buttons and Borders.
If you need to display animated images, such as GIFs, use the Animated Image component.
Image Size

If the image Size is not specified, the size of the source image is used automatically.
By default, explicitly setting the width and height of the component causes the image to be scaled to that size. To change this behavior, set the value of the Fill mode field. Images can be stretched, tiled, or scaled uniformly to the specified size with or without cropping. The Pad option means that the image is not transformed.
Note: If the Clip check box is not selected, the component might paint outside its bounding rectangle even if the Fill mode is set to PreserveAspectCrop.
Select the Smooth check box to smoothly filter images when scaled or transformed. Smooth filtering gives better visual quality, but it may be slower on some hardware. If the image is displayed at its natural size, this property has no visual or performance effect.
Select the Mipmap check box to use mipmap filtering when scaling or transforming images. Mipmap filtering gives better visual quality when scaling down compared with smooth filtering, but it may come at a performance cost both when initializing the image and during rendering.
Select the Auto transform check box if the image should automatically apply image transformation metadata, such as EXIF orientation.
Source Size
The Source size property specifies the scaled width and height of the full-frame image. Unlike the value of the Size property, which scales the painting of the image, this property sets the maximum number of pixels stored for the loaded image so that large images do not use more memory than necessary. This ensures the image in memory is no larger than the set source size, regardless of its set size.
If the image’s actual size is larger than the source size, the image is scaled down. If only one dimension of the size is set to greater than 0, the other dimension is set in proportion to preserve the source image’s aspect ratio. The Fill mode is independent of this.
If both the source size width and height are set, the image is scaled down to fit within the specified size maintaining the image’s aspect ratio. However, if PreserveAspectCrop or PreserveAspectFit are used, the image is scaled to match the optimal size for cropping or fitting.
If the source is an intrinsically scalable image (such as SVG), source size determines the size of the loaded image regardless of intrinsic size. Avoid changing the source size property dynamically because rendering an SVG is slow compared with rendering other image formats.
If the source is a non-scalable image (such as JPEG), the loaded image will be no greater than the source size specifies. For some formats, the whole image will never actually be loaded into memory.
Note: Changing this property dynamically causes the image source to be reloaded, potentially even from the network, if it is not in the disk cache. Select the Cache check box to cache the image.
Image Alignment
You can align images horizontally and vertically in the Alignment H and Alignment V fields. By default, images are centered.
Select the Mirror check box to horizontally invert the image, effectively displaying a mirrored image.
Performance
By default, locally available images are loaded immediately, and the UI is blocked until loading is complete. If a large image is to be loaded, it may be preferable to load the image in a low priority thread, by selecting the Asynchronous check box. If the image is obtained from a network rather than a local resource, it is automatically loaded asynchronously.
Images are cached and shared internally, so if several images have the same Source, only one copy of the image will be loaded.
Note: Images are often the greatest user of memory in UIs. We recommended that you set the Source size of images that do not form a part of the UI. This is especially important for content that is loaded from external sources or provided by the user.
Border Image
The Border Image component extends the features of the Image component. It is used to create borders out of images by scaling or tiling parts of each image. A source image is broken into 9 regions that are scaled or tiled individually. The corner regions are not scaled at all, while the horizontal and vertical regions are scaled according to the values of the Tile mode H and Tile mode V field, or both.
The Stretch option scales the image to fit the available area. The Repeat option tiles the image until there is no more space. To ensure that the last image is not cropped, select the Round option that scales the images down when necessary.
Specify the regions of the image in the Border left, Border right, Border top, and Border bottom fields. The regions describe the distance from each edge of the source image to use as a border.

Note: You cannot change the Source size of a border image.
For examples of using border images, see the documentation of the BorderImage component.
Animated Image
The Animated Image component extends the features of the Image component, providing a way to play animations stored as images containing a series of frames, such as those stored in GIF files.
Set the speed of the animation in the Speed field. The speed is measured in percentage of the original animated image speed. The default speed is 1.0, which means the original speed.

To play the animation, select the Playing check box.
![]()
To pause the animation, select the (Paused) check box.
When the Cache check box is selected, every frame of the animation is cached. Deselect the check box if you are playing a long or large animation and you want to conserve memory.
If the image data comes from a sequential device (such as a socket), Animated Image can only loop if caching is enabled.
For more information, watch the following video:
Iso Icon
Note: The Iso Icon component is not available if you selected Qt 6 when creating the project.
The Iso Icon component specifies an icon from an ISO 7000 icon library as a Picture component. The icon to use for the type and its color can be specified.
To select an icon in the ISO Icon Browser in Qt Design Studio, select the ISO icon in the Navigator or 2D view, and then select Choose Icon in the context menu.
![]()
You can use the color picker in Properties to set the value of Icon color.
![]()
Summary of Images
The following table lists the components that you can use to add images. The Location column contains the tab name where you can find the component in Components. The MCU column indicates which components are supported on MCUs.
| Icon | Name | Location | MCU | Purpose |
|---|---|---|---|---|
| Animated Image | Default Components — Basic | An images that stores animations containing a series of frames, such as those stored in GIF files. | ||
| Border Image | Default Components — Basic | ![]() |
An image that is used as a border or background. | |
| Image | Default Components — Basic | ![]() |
An image in one of the supported formats, including bitmap formats such as PNG and JPEG and vector graphics formats such as SVG. | |
| Iso Icon | Qt Quick Studio Components | An icon from an ISO 7000 icon library specified as a Picture component. You can select the icon to use and its color. |
Note: This component is not supported on Qt 6.
Available under certain Qt licenses.
Find out more.
Qt Designer & Runtime Qt библиотеки на службе OpenCV разработчика, или тащим IplImage на QLabel
Как и большинства разработчиков Qt, использующих библиотеку OpenCV, меня заинтересовала тема представления изображения, полученного из web-камеры, как компонент визуального проектирования интерфейса для Qt Designer.
Перерыв кучу информации в сети, заметил, что большинство статей повторяют друг друга, и найти «изюминку» слишком трудно. Думаю, мой обыт создания визуальной компоненты по представлению изобравжения библиотеки OpenCV для Qt Designer будет полезен. К тому же, поделюсь информацией, как разделить библиотеки времени проектирования дизайна и времени выполнения кода. Подобный подход весьма удачно зарекомендовал себя в RAD Delphi для операционных систем семейства Windows.
Замечания
- Автор coffeesmoke не «разжёвывает» простые истины, методы и тонкости. Код понятен. Функции не превышают 20 строк.
- Проект и пример использования реализован на Qt Creator для ОС Linux. Разработчики Windows-приложений должны установить настройки в файлох .pro соответственно своей ОС
- Автор не пускается в дискуссии типа «а так было бы лучше». Нашли оптимальное решение, реализуйте.
- Автор не отвечает на вопросы настроек Qt Creator и/или Qt Designer. Поисковые системы вам в помощь!
- Пост несёт ознакомительный характер и служит обозначению направления движения ваших мыслей. Куда они пойдут, вам виднее.
Проектирование и выполнение
Выполнение
Оставим ненадолго библиотеку OpenCV работы с изображениями. Наша задача — универсальная runtime-библиотека (библиотека времени исполнения кода).
Возможно, то, что я сейчас покажу используется повсеместно. Однако, не встретил я на просторах сети по тематике построения плагинов под Qt Designer подобного подхода.
Задача состоит в том, чтобы не «тащить» библиотеку плагина Qt Designera в проект, а обойтись библиотекой времени исполнения. Очевидно, что runtime-библиотеку можно «обрамить» виджетом представления компонента на палитре Qt Dessigner
Дизайнер содержит простой компонент QLabel, способный передавать изображение свойством pixmap. Для наших целей этого достаточно. Обратимся к переводу документации Добавление модулей Qt Designer
и самому первоисточнику информации по ссылке Using Custom Widgets with Qt Designer.Самое полезное — информация о размещении пользовательских библиотек-плагинов! теперь нам известен путь назначения: $$QTDIR/plugin/designer
Оставим обвёртку нового компонента в стороне.Займёмся непосредственно компонентом runtime-библиотеки. Создадим динамически подгружаемую библиотеку с классом CQtOpenCVImage нашего нового виджета.
Заголовочный файл cqtopencvimage.h
#ifndef QTOPENCVIMAGE_H #define QTOPENCVIMAGE_H
#include #include #include #include "opencv2/opencv.hpp" #include /*----------------------------------------------------------------------------*/
class CQtOpenCVImagePrivate;
/*----------------------------------------------------------------------------*/ class #if defined(QDESIGNER_EXPORT_WIDGETS) QDESIGNER_WIDGET_EXPORT #else Q_DECL_EXPORT #endif
CQtOpenCVImage
: public QWidget < Q_OBJECT Q_PROPERTY(QUrl capture READ getCapture WRITE slot_setCapture) Q_PROPERTY(QString text READ getLabelText WRITE slot_setLabelText) Q_PROPERTY(QPixmap pixmap READ getPixmap WRITE slot_setPixmap) Q_PROPERTY(bool scaledContents READ hasScaledContents WRITE slot_setScaledContents) Q_PROPERTY(bool grayscale READ isGrayscale WRITE slot_setGrayscale) Q_PROPERTY(Qt::Alignment alignment READ getAlignment WRITE setAlignment) public: explicit CQtOpenCVImage(QWidget* parent = 0, Qt::WindowFlags f = 0); virtual ~CQtOpenCVImage(); QUrl& getCapture (); QString getLabelText () const; const QPixmap* getPixmap () const; const QImage* getImage () const; Qt::Alignment getAlignment() const; void setAlignment(Qt::Alignment); const QLabel* getQLabel () const; bool hasScaledContents() const; bool isGrayscale() const; public Q_SLOTS: void slot_setCapture ( const QUrl& ); void slot_setLabelText ( const QString& ); void slot_setPixmap ( const QPixmap& ); void slot_setImage ( const QImage& ); void slot_setQLabel ( const QLabel& ); void slot_setGrayscale(bool); void slot_setScaledContents(bool); Q_SIGNALS: void signal_Grayscale(bool); void signal_ImageChanged(); void signal_CaptureChanged(); void signal_PixmapChanged(); void signal_LabelChanged(); void signal_AlignmentChanged(); private: Q_DISABLE_COPY(CQtOpenCVImage) Q_DECLARE_PRIVATE(CQtOpenCVImage)
QScopedPointer d_ptr;
>; /*----------------------------------------------------------------------------*/ #endif // QTOPENCVIMAGE_H
-
Включение заголовочного файла QtDesigner/QDesignerExportWidget гарантирует подключение необходимого макроса QDESIGNER_WIDGET_EXPORT при использовании в файле проекта директивы
DEFINES += QDESIGNER_EXPORT_WIDGETS
QScopedPointer d_ptr;
- capture — URL устройства видеозахвата или номер web-камеры;
- text — текстовая надпись. Аналог свойства text QLabel;
- pixmap — указатель на объект типа QPixmap. Аналог свойства pixmap QLabel;
- scaledContents — масштабируемость изображения. Аналог свойства scaledContents QLabel;
- grayscale — булевый переключатель цветового режима вывода изображения, где значение true соответствует градациям серого, а false — цветное (RGB);
- alignment — выравнивание содержимого text и pixmap. Аналог свойства alignment QLabel;
Думаю, назначения методов класса описывать не имеет смысла: название говорят сами за себя.
Перейдём к коду реализации классов (файл cqtopencvimage.cpp).
Рассмотрим скрытый класс CQtOpenCVImagePrivate, его атрибуты и методы.
class CQtOpenCVImagePrivate < Q_DECLARE_PUBLIC(CQtOpenCVImage) public: CQtOpenCVImagePrivate(CQtOpenCVImage* owner); virtual ~CQtOpenCVImagePrivate(); CQtOpenCVImage* q_ptr; // указатель на экземпляр основного класса QGridLayout* f_grid_layout; // сетка выравнивания находящихся в ней компонент по всему периметру QLabel* f_label;// экземпляр типа QLabel для вывода изображения QUrl f_capture_path;// URL устройства видеозахвата или его номер QImage* p_qt_image; // Указател на экземпляр изображения типа QImage CvCapture* p_capture; // Указател на экземпляр устройства видеозахвата в рамках описания OpenCV IplImage* p_opencv_frame; // Указател на текущий фрем из p_capture uint f_grayscaled:1; // признак представления изобравжения в градациях серого void init (); // инициализация данных void close (); // корекктное закрытие всех указателей void free_qt_image (); // освобождение памяти экземпляра p_qt_image void new_qt_image ();// распределение памяти для экземпляра p_qt_image void free_capture (); // освобождение памяти экземпляра p_capture void new_capture (); // распределение памяти для экземпляра p_capture >;
Перейдём к реализации методов.
/*----------------------------------------------------------------------------*/ void CQtOpenCVImagePrivate::init () < Q_ASSERT(q_ptr); f_grid_layout = new QGridLayout(q_ptr); Q_ASSERT(f_grid_layout); f_label = new QLabel(q_ptr/*, Qt::WindowNoState*/); Q_ASSERT(f_label); f_grid_layout->addWidget (f_label); p_qt_image = 0, p_capture = 0, p_opencv_frame = 0, f_grayscaled = 0; > /*----------------------------------------------------------------------------*/ inline void CQtOpenCVImagePrivate::close () < free_qt_image (); free_capture (); >/*----------------------------------------------------------------------------*/ CQtOpenCVImagePrivate::CQtOpenCVImagePrivate(CQtOpenCVImage* owner) : q_ptr(owner) < init (); >/*----------------------------------------------------------------------------*/ CQtOpenCVImagePrivate::~CQtOpenCVImagePrivate () < close (); if(!(f_label->parent ())) delete f_label; if(!(f_grid_layout->parent ())) delete f_grid_layout; > /*----------------------------------------------------------------------------*/ inline void CQtOpenCVImagePrivate::free_qt_image () < if(p_qt_image) < delete p_qt_image; p_qt_image = 0; >> /*----------------------------------------------------------------------------*/ inline void CQtOpenCVImagePrivate::free_capture () < if(p_capture) < cvReleaseCapture(&p_capture); p_capture = 0; >>
Код понятен и читаем. Вопросов не должно возникнуть. Параметр CQtOpenCVImage* owner конструтора представляет указател на объект CQtOpenCVImage, содержащий экземпляр скрытого класса как переменную CQtOpenCVImage::d_ptr.
Как говорил доктор, герой Леонида Броневого, из фильма «Формула любви», — «Так, я продолжу. ».
Рассмотрим определение устройства захвата методом new_capture
/*----------------------------------------------------------------------------*/ void CQtOpenCVImagePrivate::new_capture () < free_capture ();//освобождение устройства захвата bool b_ok; int i_index = f_capture_path.toString ().toInt (&b_ok); // определение номера камеры, если это номер, а не URL /* информация к размышлению: перезахват устройства, если камера реализована как CGI для вебсервера, возвращающий по одному кадру if(b_ok) < p_capture = cvCreateCameraCapture(i_index); if(p_capture) if(!p_opencv_frame) p_opencv_frame = cvQueryFrame (p_capture); >else < while((p_capture =cvCaptureFromFile(f_capture_path.toString ().toStdString ().c_str ()))) < p_opencv_frame = cvQueryFrame (p_capture); new_qt_image (); cvWaitKey (1000); >> */ // да, ну его, этот перезахват. Перезахватим по запросу методами OpenCV. p_capture = b_ok ? cvCreateCameraCapture(i_index) : cvCaptureFromFile(f_capture_path.toString ().toStdString ().c_str ()); p_opencv_frame = p_capture ? cvQueryFrame (p_capture) : 0; // получение фрейма методом из OpenCV new_qt_image (); // формирование экземпляра QImage >
Для подробного знакомства с OpenCV читайте Оглавление
Формирование изображения типа QImage:
/*----------------------------------------------------------------------------*/ void CQtOpenCVImagePrivate::new_qt_image () < if(!p_capture) return; free_qt_image (); // освободим указатель на изображение if(p_opencv_frame) < // создадим OpenCV экземпляр изображения согласно параметру оттенка серого IplImage *_tmp = f_grayscaled ? cvCreateImage( cvSize( p_opencv_frame->width, p_opencv_frame->height ), IPL_DEPTH_8U, 1 ) : cvCloneImage (p_opencv_frame) ; try < // пребразование цвета в RGB или оттенки серого cvCvtColor( p_opencv_frame, _tmp, f_grayscaled ? CV_RGB2GRAY : CV_BGR2RGB ); // формирование изображения типа QImage p_qt_image = new QImage( (const uchar*)(_tmp->imageData), _tmp->width, _tmp->height, _tmp->widthStep, (f_grayscaled ? QImage::Format_Indexed8 : QImage::Format_RGB888) ); emit q_ptr->signal_ImageChanged (); // оповещение о готовности q_ptr->slot_setPixmap (QPixmap::fromImage (*p_qt_image)); // отрисовать изображение на QLabel > catch(. ) < // упс. Дрова -- в исходное, пельмени разлепить! close (); >// не забываем прибрать за собой! cvReleaseImage(&_tmp); > >
Думаю, с подводной частью айсберга всё понятно.
Реализация основного класса ещё проще. Даже, лень объяснять. Смотрите сами:
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/ CQtOpenCVImage::CQtOpenCVImage(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f), d_ptr(new CQtOpenCVImagePrivate(this)) < >/*----------------------------------------------------------------------------*/ CQtOpenCVImage::~CQtOpenCVImage() < >/*----------------------------------------------------------------------------*/ QUrl& CQtOpenCVImage::getCapture () < return (d_func ()->f_capture_path); > /*----------------------------------------------------------------------------*/ QString CQtOpenCVImage::getLabelText () const < return (d_func ()->f_label->text ()); > /*----------------------------------------------------------------------------*/ bool CQtOpenCVImage::hasScaledContents() const < return d_func ()->f_label->hasScaledContents (); > /*----------------------------------------------------------------------------*/ void CQtOpenCVImage::slot_setScaledContents(bool Value ) < d_func ()->f_label->setScaledContents (Value); > /*----------------------------------------------------------------------------*/ bool CQtOpenCVImage::isGrayscale() const < return d_func ()->f_grayscaled; > /*----------------------------------------------------------------------------*/ void CQtOpenCVImage::slot_setGrayscale( bool Value ) < if(d_func ()->f_grayscaled != Value) < d_func ()->f_grayscaled = Value; if(!(d_func ()->p_capture)) d_func ()->new_capture (); else d_func ()->new_qt_image (); emit signal_Grayscale (d_func ()->f_grayscaled); > > /*----------------------------------------------------------------------------*/ void CQtOpenCVImage::slot_setLabelText ( const QString& Value ) < d_func ()->f_label->setText (Value); > /*----------------------------------------------------------------------------*/ void CQtOpenCVImage::slot_setCapture ( const QUrl& Value ) < // Раскомментировать при необходимости исключения переинициализации захвата // if(getCapture ().toString () != Value.toString () || !d_func ()->p_opencv_frame) // < d_func ()->f_capture_path = Value.toString ().trimmed (); d_func ()->new_capture (); emit signal_CaptureChanged (); // > > /*----------------------------------------------------------------------------*/ const QPixmap* CQtOpenCVImage::getPixmap () const < return ((const QPixmap*)(d_func ()->f_label->pixmap ())); > /*----------------------------------------------------------------------------*/ void CQtOpenCVImage::slot_setPixmap ( const QPixmap& Value ) < d_func ()->f_label->setPixmap (Value); emit signal_PixmapChanged (); > /*----------------------------------------------------------------------------*/ const QImage* CQtOpenCVImage::getImage () const < return(d_func ()->p_qt_image); > /*----------------------------------------------------------------------------*/ void CQtOpenCVImage::slot_setImage ( const QImage& Value ) < d_func ()->free_qt_image (); d_func ()->p_qt_image = new QImage(Value); slot_setPixmap (QPixmap::fromImage (*(d_func ()->p_qt_image))); emit signal_ImageChanged (); > /*----------------------------------------------------------------------------*/ void CQtOpenCVImage::slot_setQLabel ( const QLabel& Value) < d_func ()->f_label->setText (Value.text ()); emit signal_LabelChanged (); > /*----------------------------------------------------------------------------*/ Qt::Alignment CQtOpenCVImage::getAlignment() const < return(d_func ()->f_label->alignment ()); > /*----------------------------------------------------------------------------*/ void CQtOpenCVImage::setAlignment(Qt::Alignment Value) < d_func ()->f_label->setAlignment (Value); emit signal_AlignmentChanged (); > /*----------------------------------------------------------------------------*/ const QLabel* CQtOpenCVImage::getQLabel () const < return ((const QLabel*)(d_func ()->f_label)); >
Формируем runtime-библиотеку. Опишем файл проекта images.pro:
TARGET = QtOpenCVImages TARGET = $$qtLibraryTarget($$TARGET) TEMPLATE = lib CONFIG += debug_and_release
Не забываем включить:
DEFINES += QDESIGNER_EXPORT_WIDGETS
Определим путь, куда попадут файлы библиотек:
unix:!symbian < target.path = $$PWD/../../../../lib DESTDIR = $$PWD/../../../../lib INSTALLS += target >
Добавим файлы класса:
SOURCES += \ cqtopencvimage.cpp HEADERS += \ cqtopencvimage.h
Определим пути заголовков файлов библиотек OpenCV и пути зависимостей проекта:
INCLUDEPATH += /usr/include/opencv2 DEPENDPATH += /usr/include/opencv2
Добавим библиотеку OpenCV (core и highgui) к нашему проекту:
#win32:CONFIG(release): LIBS += -L/usr/lib/ -lopencv_core #else:win32:CONFIG(debug, debug|release): LIBS += -L/usr/lib/ -lopencv_cored #else: unix: LIBS += -L/usr/lib/ -lopencv_core #win32:CONFIG(release, debug|release): LIBS += -L$$PWD/../../../../../../usr/lib/release/ -lopencv_highgui #else:win32:CONFIG(debug, debug|release): LIBS += -L$$PWD/../../../../../../usr/lib/debug/ -lopencv_highguid #win32:CONFIG(release): LIBS += -L/usr/lib/release/ -lopencv_highgui #else:symbian: LIBS += -lopencv_highgui #else: unix: LIBS += -L/usr/lib/ -lopencv_highgui
Уважаемые разработчики ОС Windows, я «соскочил» с иглы Microsoft давно и прошу прощения, что закомментировал пути библиотек для вашей ОС. Вы — народ неглупый, разберётесь.
*NIX-оиды, используйте команду ln -s, чтобы создать ссылки на ваши библиотеки из места расположения в каталог /usr/lib
Один раз создав ссылку, просто, пересобирайте проект, и всё будет работать нормально!
Итак, мы создали динамическую библиотеку Qt визуального компонента отображения рисунка, полученного из web-камеры средствами OpenCV.
Проектирование
Настало время подключить нашу runtime-библиотеку к оболочке класса-плагина для Qt Designer.
Создадим проект библиотеки-плагина:
TARGET = QtOpenCVWidgets TARGET = $$qtLibraryTarget($$TARGET) TEMPLATE = lib CONFIG += designer plugin release DEFINES += QDESIGNER_EXPORT_WIDGETS SOURCES += \ qtopencvimageplugin.cpp \ ../qtopencvwidgets.cpp HEADERS +=\ qtopencvimageplugin.h \ ../qtopencvwidgets.h \ ../runtime/images/cqtopencvimage.h RESOURCES += \ qtopencvimages.qrc unix:!symbian < target.path = $$PWD/../../../lib DESTDIR = $$PWD/../../../lib INSTALLS += target >INCLUDEPATH += /usr/include/opencv2 DEPENDPATH += /usr/include/opencv2 #win32:CONFIG(release, debug|release): LIBS += -L/usr/lib/ -lQtOpenCVImages #else:win32:CONFIG(debug, debug|release): LIBS += -L/usr/lib -lQtOpenCVImages #else:symbian: LIBS += -lQtOpenCVImages #else: unix: LIBS += -L/usr/lib -lQtOpenCVImages INCLUDEPATH += $$PWD/../runtime/images DEPENDPATH += $$PWD/../runtime/images
- Изменилось название библиотеки: TARGET = QtOpenCVWidgets;
- Параметр CONFIG += designer plugin release содержит тэги plugin и designer;
- Плагин реализован в двух файлах по одному на заголовок и реализацию qtopencvimageplugin.* qtopencvwidgets.*<.i>;
Всё так же присутствует зависимость от заголовков библиотеки OpenCV т.к. добавилась зависимость от включённого заголовка cqtopencvimage.h нашего виджета QtOpenCVImages;
Включена динамическая runtime библиотека libQtOpenCVImages по символьной ссылке из /usr/lib/libQtOpenCVImages.so , указывающей на её реальное расположение в каталоге проекта
#ifndef QTOPENCVIMAGEPLUGIN_H #define QTOPENCVIMAGEPLUGIN_H #include #include class QtOpenCVImagePlugin : public QObject, public QDesignerCustomWidgetInterface < Q_OBJECT Q_INTERFACES(QDesignerCustomWidgetInterface) public: explicit QtOpenCVImagePlugin(QObject *parent = 0); QString name() const; QString includeFile() const; QString group() const; QIcon icon() const; QString toolTip() const; QString whatsThis() const; bool isContainer() const; QWidget* createWidget(QWidget *parent); void initialize(QDesignerFormEditorInterface *core); bool isInitialized() const; QString domXml() const; signals: public slots: private: bool f_init; >; #endif // QTOPENCVIMAGEPLUGIN_H
Основная идея: объявить как Q_INTERFACE, наследуясь от QDesignerCustomWidgetInterface и перегрузить методы класса-интерфеса дизайнера согласно своим требованиям.
qtopencvimageplugin.cpp
#include "qtopencvimageplugin.h" #include "cqtopencvimage.h" QtOpenCVImagePlugin::QtOpenCVImagePlugin(QObject *parent) : QObject(parent), f_init(false) < >QString QtOpenCVImagePlugin::name() const < return "CQtOpenCVImage";// имя класса виджета >QString QtOpenCVImagePlugin::includeFile() const < return QLatin1String("cqtopencvimage.h"); // название включения в файл ui_*.h новой формы >QString QtOpenCVImagePlugin::group() const < return tr("OpenCV Widgets"); // название группы отображения на панели компонентов Qt Designer >QIcon QtOpenCVImagePlugin::icon() const < return QIcon(":QtOpenCVLogo.png"); // значок виджета >QString QtOpenCVImagePlugin::toolTip() const < return QString(); >QString QtOpenCVImagePlugin::whatsThis() const < return QString(); >bool QtOpenCVImagePlugin::isContainer() const < return false; >QWidget* QtOpenCVImagePlugin::createWidget(QWidget *parent) < return new CQtOpenCVImage(parent); // вот она, реализация экземпляра класса нашего виджета! >void QtOpenCVImagePlugin::initialize(QDesignerFormEditorInterface *core) < // установка признака инициализации при помещении на форму if (f_init) return; f_init = true; >bool QtOpenCVImagePlugin::isInitialized() const < return f_init; >QString QtOpenCVImagePlugin::domXml() const < // основные параметры для дизайнера return "\n" " \n" " \n" " \n" " 0 \n" " 0 \n" " 400 \n" " 200 \n" " \n" " \n" " \n" " "; >
Осталось совсем немного: создать общую обвёртку-контейнер для всех наших виджетов группы Qt OpenCV
qtopencvwidgets.h
#ifndef QTOPENCVWIDGETS_H #define QTOPENCVWIDGETS_H #include #include #include class QtOpenCVWidgets : public QObject, public QDesignerCustomWidgetCollectionInterface < Q_OBJECT Q_INTERFACES(QDesignerCustomWidgetCollectionInterface) public: explicit QtOpenCVWidgets(QObject *parent = 0); QListcustomWidgets() const < return f_plugins; >private: QList f_plugins; >; #endif // QTOPENCVWIDGETS_H
qtopencvwidgets.cpp
#include "qtopencvwidgets.h" #include "images/qtopencvimageplugin.h" QtOpenCVWidgets::QtOpenCVWidgets(QObject *parent) : QObject(parent) < f_plugins //Q_DECLARE_INTERFACE(QtOpenCVWidgets, "com.trolltech.Qt.Designer.QtOpenCV") Q_EXPORT_PLUGIN2(qtopencvwidgetsplugin, QtOpenCVWidgets)
Интерес представляет конструктор, а именно: f_plugins Plugin(this);
Применение
Открываем Qt Designer и ищем на палитре компонентов наш СQtOpenCVImage. Пмещаем его на новую форму. Меняем capture на нужный URL 192.168.0.20:8080/image.jpg . В данном случае, это Java-аплет сервера камеры, предоставляющий текущий запрашиваемый кадр
Поставим «галочку» на свойстве grayscale
Исходный код: Если скачали ранее, не переходите по ней.
Выводы
- Научились создавать библиотеку времени выполнения для реализации собственного класса на основе визуальных компонент Qt;
- Научились обрамлять runtime библиотеку в плагин Qt Designer, сделав приложения независимыми от плагина дизайнера на время выполнения;
Приложения
Простой тестовый пример
Создадим стандартное Qt GUI приложение, откроем основную форму окна, поместим с неё наш компонент, создадим немного сервисных управлений, соберём и запустим.
Меняем «Адрес. » на значение 0 (встроенная видеокамера) и смотрим на изменения изображения.
Что дальше?
- Оптимизация текущего проекта;
- Описание проверенного визуального компонента поиска границ изображения методом Кэнни (Canny): CQtOpenCVCannyWidget на основе класса CQtOpenCVCanny;
- Связь между QtOpenCVImage и QtOpenCVCanny
Подскажите пожалуйста есть ли возможность добавить собственное изображение в классификатор в формате png, jpg, jpeg, bmp?
Подскажите пожалуйста есть ли возможность добавить собственное изображение в классификатор в формате png, jpg, jpeg, bmp?
Администратор
Сообщений: 4050 Регистрация: 05.06.2008
13.06.2018 18:46:19
Все виды графических примитивов описаны в файле mapgdi.h.
Например:
#define IMG_GRAPHICMARK 165 // Знак из файла (ВМР, Metafile ) typedef struct IMGGRAPHICMARKEX // (165) ТОЧЕЧНЫЙ ЗНАК - ГРАФИЧЕСКОЕ ИЗОБРАЖЕНИЕ < // (size = 312) int Length; // Полная длина записи описания объекта int Ident; // Идентификатор считанного изображения = 0 char Name[256]; // Имя файла изображения int Type; // Тип файла (1 - BMP, 2 - JPEG, 3 - Metafile) int Height; // Габариты знака (высота, ширина) int Width; // int PosH; // Точка привязки знака по горизонтали int PosV; // и вертикали (от начала габаритов знака) int Shift; // Смещение тени IMGLINE Contour; // Параметры контура char ContourFlag; // Флаг наличия контура char ShadeFlag; // Флаг наличия тени char TransparentFlag; // Флаг прозрачности фонового цвета // (первый пиксел картинки - левый нижний угол BMP) char Reserve[13]; // Резерв >IMGGRAPHICMARKEX;
Для Linux пока реализована поддержка файла BMP, который должен размещаться рядом с файлом RSC.
Изменить параметры отображения в принтерном виде можно функцией:
// Установить принтерный вид объекта // hRsc - идентификатор классификатора карты // incode - порядковый номер объекта // length - длина параметров // number - номер функции отображения // param - указатель на параметры функции // При ошибке возвращает ноль , иначе порядковый номер объекта _MAPIMP long int _MAPAPI mapSetRscPrintObjectImage(HRSC hRsc, long int incode,long int length,long int number,char * param);
Для этого нужно объявить структуру IMGGRAPHICMARKEX, заполнить ее и передать ее адрес в функцию:
IMGGRAPHICMARKEX parm; . mapSetRscPrintObjectImage(hRsc, incode, sizeof(IMGGRAPHICMARKEX), IMG_GRAPHICMARK, (char *)&parm);
В поле Name структуры IMGGRAPHICMARKEX указывается имя файла без пути к файлу.
Параметр hRsc может быть получен при открытии классификатора.
Параметр incode может быть получен по классификационному коду объекта и локализации или по ключу объекта в классификаторе.
Пользователь
Сообщений: 127 Регистрация: 09.02.2015
14.06.2018 16:40:33
Подскажите пожалуйста, какими значениями мне заполнить структуру IMGGRAPHICMARKEX , с именем файла я поняла, а вот дальше не очень понятно и все ли поля являются обязательными в этой структуре?
| Цитата |
|---|
| Параметр incode может быть получен по классификационному коду объекта и локализации или по ключу объекта в классификаторе. |
Приведите пожалуйста пример, пока не понятно, как получить incode.
У меня же этого объекта еще нет в классификаторе, а как раз таки я его хочу добавить туда. Поясните пожалуйста.
Повторюсь, задача заключается в добавлении собственного изображения в классификатор (для последующего его использования).
Изменено: Анастаия - 14.06.2018 16:41:15
Администратор
Сообщений: 4050 Регистрация: 05.06.2008
14.06.2018 18:52:48
Если в структуре есть поле, то в нем всегда будет какое-то значение.
После объявления переменной типа структура ее можно обнулить (memset),
а затем установить значения в соответствии с назначением поля.
IMGGRAPHICMARKEX parm; memset((char*)&parm, 0, sizeof(parm)); parm.Length = sizeof(parm); strcpy(parm.Name, "example.bmp"); parm.Type = 1; parm.Height = 32; parm.Width = 32; parm.PosV = 16; parm.PosH = 16; . parm.TransparentFlag = 1;
Для создания в классификаторе нового объекта есть функция:
// Создать объект // RSCOBJECT - структура входных данных (см. maptype.h) // hRsc - идентификатор классификатора карты // При ошибке возвращает ноль , иначе порядковый номер объекта (с 1) _MAPIMP long int _MAPAPI mapAppendRscObject(HRSC hRsc, RSCOBJECT * object);
Возвращаемое функцией mapAppendRscObject значение и будет "incode" объекта.
Но прикладная программа, как правило, не создает и не редактирует классификатор, который должен создаваться заблаговременно средствами Редактора классификатора
на основании бумажного документа с кодами и изображениями знаков и описанием их атрибутов, утвержденного Заказчиком.
Удобнее это сделать в программе Панорама Мини.
Пользователь
Сообщений: 127 Регистрация: 09.02.2015
15.06.2018 14:34:23
Спасибо за ответ. Относительно Панорамы Мини мы учтем. Но на данный момент есть все же желание разобраться, как добавлять свое изображение в классификатор в программе.
Добавила объект из классификатора, а затем применила метод изменяющий его внешний вид. В результате ничего не изменилось.
HRSC myHrsc = mapGetRscIdent(hmap, hsite); std::cout Изменено: Анастаия - 15.06.2018 14:37:25 