When we use OpenCV from command line process, sometimes OpenCV will print internal logging messages such as:
[ INFO:0] global .\opencv-master\sources\modules\core\src\parallel\registry_parallel.impl.hpp (90) cv::parallel::ParallelBackendRegistry::ParallelBackendRegistry core(parallel): Enabled backends(2, sorted by priority): TBB(1000); OPENMP(990) [ INFO:0] global .\opencv-master\sources\modules\core\include\opencv2/core/parallel/backend/parallel_for.tbb.hpp (54) cv::parallel::tbb::ParallelForBackend::ParallelForBackend Initializing TBB parallel backend: TBB_INTERFACE_VERSION=12010 [ INFO:0] global .\opencv-master\sources\modules\core\src\parallel\parallel.cpp (73) cv::parallel::createParallelForAPI core(parallel): using backend: TBB (priority=1000)
This might be useful while debugging OpenCV problems but it is a noise if we want to print our own messages to the console. In this case, it is desirable to disable the internal OpenCV logging using the following code:
#include "opencv2/core/utils/logger.hpp" int main() { cv::utils::logging::setLogLevel(cv::utils::logging::LogLevel::LOG_LEVEL_SILENT); return 1; }
Product | Release date | C++ version | _MSC_VER |
Visual Studio 2019 16.11 | 10-Aug-21 | 14.29 | 1929 |
Visual Studio 2019 16.10 | 25-May-21 | 14.29 | 1929 |
Visual Studio 2019 16.9 | 02-Mar-21 | 14.28 | 1928 |
Visual Studio 2019 16.9 | 10-Nov-20 | 14.28 | 1928 |
Visual Studio 2019 16.7 | 05-Aug-20 | 14.27 | 1927 |
Visual Studio 2019 16.6 | 19-May-20 | 14.26 | 1926 |
Visual Studio 2019 16.5 | 16-Mar-20 | 14.25 | 1925 |
Visual Studio 2019 16.4 | 03-Dec-19 | 14.24 | 1924 |
Visual Studio 2019 16.3 | 23-Sep-19 | 14.23 | 1923 |
Visual Studio 2019 16.2 | 24-Jul-19 | 14.22 | 1922 |
Visual Studio 2019 16.1 | 21-May-19 | 14.21 | 1921 |
Visual Studio 2019 16.0 | 02-Apr-19 | 14.2 | 1920 |
Visual Studio 2017 15.9 | 13-Nov-18 | 14.16 | 1916 |
Visual Studio 2017 15.8 | 14-Aug-18 | 14.15 | 1915 |
Visual Studio 2017 15.7 | 07-May-18 | 14.14 | 1914 |
Visual Studio 2017 15.6 | 05-Mar-18 | 14.13 | 1913 |
Visual Studio 2017 15.5 | 04-Dec-17 | 14.12 | 1912 |
Visual Studio 2017 15.4 | 09-Oct-17 | 14.11 | 1911 |
Visual Studio 2017 15.3 | 14-Aug-17 | 14.11 | 1911 |
Visual Studio 2017 15.2 | 10-May-17 | 14.1 | 1910 |
Visual Studio 2017 15.1 | 05-Apr-17 | 14.1 | 1910 |
Visual Studio 2017 | 07-Mar-17 | 14.1 | 1910 |
Visual Studio 2015 | 20-Jul-15 | 14 | 1900 |
Visual Studio 2013 | 17-Oct-13 | 12 | 1800 |
Visual Studio 2012 | 15-Aug-12 | 11 | 1700 |
Visual Studio 2010 | 02-Jul-05 | 10 | 1600 |
Visual Studio 2008 | 30-Jun-05 | 9 | 1500 |
Visual Studio 2005 | 27-Jun-05 | 8 | 1400 |
# Set name and email you want attached to your commit transactions git config --global user.name "[name]" git config --global user.email "[email address]" # Enables helpful colorization of command line output git config --global color.ui auto # Configure kdiff3 as the merge tool on Windows. git config --global merge.tool kdiff3 git config --global mergetool.kdiff3.path "C:/Program Files/KDiff3/kdiff3.exe" git config --global mergetool.kdiff3.trustExitCode false
git branch -d localBranchName # Delete branch locally git push origin --delete remoteBranchName # Delete branch remotely git remote prune origin # Delete all local branches not on remote git push --set-upstream origin BRANCH_NAME # Push local branch to remote; will create a pull request. git branch --sort=-committerdate # Print branches ordered by the commit dates. git branch -vv # Show the last local and remote commit on each branch.
git checkout @{-N} # Go back N branches. git checkout - # Go to the last branch (shorthand to for the previous command)
git diff # changed but not staged. git diff --staged # staged and ignore local changes. git diff --cached # same as staged. git difftool # use external diff tool. git diff $startCommit..$endCommit -- FILE # Compare changes in one file from startCommit to endCommit. git diff $startCommit..$endCommit # Compare two commits.
git commit # open external editor for commit message git commit -m "message" git commit -a -m "message" # ignore staging and commit all modified files git commit --amend # Fix last commit message. # Add a file missed in the last commit. git add missed_file.txt git commit --amend # Remove a file after committing: git reset --soft HEAD~1 git reset accidently_added_file.jpg rm accidently_added_file.jpg git commit
git stash # Store the current changes in stash. git stash pop # Apply the stashed changes and then drop it. git stash drop # Remove the stashed changes. git stash apply # Apply the stashed changes and leave them in the stash.
git log git log -p -2 (--patch) git log --stat git log --pretty=oneline git log --pretty=format:"%h - %an, %ar : %s"
git reset --hard HEAD # Reset all files to the HEAD of the branch: git checkout HEAD -- FILE # reset a single file git reset --soft HEAD~1 # Revert committed changes.
The rules for the patterns you can put in the .gitignore file are as follows:
Qt comes with a QTreeWidget
class which can be used to show data in a tree view. It can be used to show hierarchical data using either Model/View framework or by manually creating the hierarchy. The QTreeWidget
supports multi-columns for each row and also allows editing of the individual cells. However, sometimes we need to present a QWidget
in a cell to allow user to interact with data. For example, we might want a user to choose a Boolean value for a cell and instead of asking the user to type Yes/No or True/False, we can present the user with a checkbox. This eliminates human errors in type the values. Often, there is also a need to embed a QPushButton within a cell to allow user to run some action.
Let’s dig in a single example on how to embed a QWidget
in a cell of a QTreeWidget
.
// Create a tree widget with three columns. QTreeWidget* treeWidget = new QTreeWidget(); treeWidget->setColumnCount(3); QStringList columnNames; columnNames << "Column 1" << "Column 2" << "Column 3"; treeWidget->setHeaderLabels(columnNames); // Add a top level tree widget item. QTreeWidgetItem* item = new QTreeWidgetItem(); treeWidget->addTopLevelItem(item); // Add a check box to the second column. QCheckBox* checkBox = new QCheckBox("Click Me!"); treeWidget->setItemWidget(item, 1, checkBox1); // Add tree widget to the parent widgets layout. this->setLayout(new QVBoxLayout()); this->setContentsMargins(0, 0, 0, 0); this->layout()->addWidget(treeWidget);
The above code produces the output as shown in the below image. The check box is left aligned and QTreeWidget
does not offer a way to center or right align it out of the box. A standard solution offered online is to inherit from QTreeWidgetItem
and take control of painting the item directly.
Inheriting from QTreeWidgetItem
is unnecessarily complicated and there is no need to do it. A simpler way is to put the checkbox in another widget and use a horizontal layout with stretch before and after the checkbox! This trick can be used to right align as well by omitting the stretch before the checkbox. Here is the code:
// Create a check box. QCheckBox* checkBox = new QCheckBox("Click Me!"); // Put the check box in a wrapping widget with appropriate layout. QWidget* checkBoxWrapper = new QWidget; QHBoxLayout* layout = new QHBoxLayout(); layout->addStretch(); layout->addWidget(checkBox); layout->addStretch(); layout->setContentsMargins(0, 0, 0, 0); checkBoxWrapper->setLayout(layout); // Add it to the tree widget. mTreeWidget->setItemWidget(item, 1, checkBoxWrapper);
This code is going to produce the following output:
The complete Visual Studio 2019 solution for this demo can be downloaded here.
In the last post, I discussed how to get started with VTK on Python. In this post, I will show how to add support to show frames per second (FPS). The idea to calculate FPS is straight forward: keep track of the number of frames (N) that were rendered in last T seconds. Then fps defined a N/T fps.
To calculate FPS we will add an observer to the EndEvent
command of the vtkRenderer
. In the callback function, we will count the number of frames rendered in the last T seconds and calculate FPS. Here is the complete code of the FpsObserver
:
import vtk from timeit import default_timer as timer class FpsObserver: def __init__(self, renderer, x=0, y=0): self.mRenderer = renderer self.mRenderer.AddObserver(vtk.vtkCommand.EndEvent, self) self.ActorPosX = x self.ActorPosY = y self.mFrameCount = 0 # Number of frames collected since last FPS was calculated. self.mStartTime = timer() # The last time FPS was calculated. self.mFpsUpdateRate = 1 # How often to update FPS in seconds. self._createFpsTextActor() def setPosition(self, x, y): self.ActorPosX = x self.ActorPosY = y self.mFpsActor.SetPosition(self.ActorPosX, self.ActorPosY) def __call__(self, caller, event): if event == "EndEvent": self.mFrameCount = self.mFrameCount + 1 if timer() - self.mStartTime > self.mFpsUpdateRate: _currentTime = timer() _duration = _currentTime - self.mStartTime _fps = self.mFrameCount/_duration print("fps={:.3f}".format(_fps)) self.mFpsActor.SetInput("FPS: {:.2f}".format(_fps)) self.mStartTime = _currentTime self.mFrameCount = 0 def _createFpsTextActor(self): self.mFpsActor = vtk.vtkTextActor() self.mFpsActor.GetTextProperty().SetFontFamilyAsString("Georgia") self.mFpsActor.GetTextProperty().SetFontSize(20) self.mFpsActor.GetTextProperty().SetColor([1, 1, 1]) self.mFpsActor.SetPosition(self.ActorPosX, self.ActorPosY) self.mRenderer.AddActor(self.mFpsActor)
To use FpsObserver
, we just need to initialize it as self.mFpsObserver = FpsObserver.FpsObserver(self.mRenderer)
. That’s it, this will display the FPS for last one seconds!
The visualization toolkit (VTK) is a open source library displaying scientific data. VTK is maintained by Kitware, the same company which gave us CMake. VTK is written in C/C++ but it comes with Python bindings and can be installed from https://pypi.org/project/vtk/. In this post, I am going to show how to start using VTK from Python using PyQt5.
Qt has two package for using with Python: PySide2 and PyQt5. PySide2 is the official module for Python but for a long time there was no official module and only PyQt5 was available. You can refer to https://www.learnpyqt.com/blog/pyqt5-vs-pyside2/ to understand the differences (they are mostly same) between two modules. I am going to use PyQt5 but the VTK module itself supports both Qt modules.
VTK provides a
class which inherits from QVTKRenderWindowInteractor
QWidget
, QGLWidget, or any other custom class inherited from QWidget
. We will add QVTKRenderWindowInteractor
to a QMainWindow
and use vtkRenderer
to render a Hello, World sphere. To decouple user interface (Qt) and rendering (VTK) I will create a VtkWindow
class and use it from a MainWindow
which is purely for VTK.
Lets first create the MainWindow:
from PyQt5 import QtCore, QtWidgets import sys import VtkWindow class MainWindow(QtWidgets.QMainWindow): def __init__(self, parent=None): super(MainWindow, self).__init__(parent) self.setWindowState(QtCore.Qt.WindowMaximized) self.mVtkWindow = VtkWindow.VtkWindow() self.setCentralWidget(self.mVtkWindow) if __name__ == '__main__': app = QtWidgets.QApplication(sys.argv) window = MainWindow() window.show() app.exec_()
If we comment lines 10 and 11 and run the MainWindow.py, it will display a blank Qt Window. Now lets see how to add VTK support to it by adding a VtkWindow
class:
from PyQt5 import QtWidgets import vtk import vtkmodules.qt vtkmodules.qt.QVTKRWIBase = "QGLWidget" from vtk.qt.QVTKRenderWindowInteractor import QVTKRenderWindowInteractor # VtkWindow must be derived from QFrame: https://vtk.org/Wiki/VTK/Examples/Python/Widgets/EmbedPyQt class VtkWindow(QtWidgets.QFrame): def __init__(self, parent=None): super(QtWidgets.QWidget, self).__init__(parent) # Create a VTK widget and add it to the QFrame. self.setLayout(QtWidgets.QVBoxLayout()) self.mVtkWidget = QVTKRenderWindowInteractor(self) self.layout().addWidget(self.mVtkWidget) self.layout().setContentsMargins(0, 0, 0, 0) # Get the render window and set an interactor. self.mRenderWindow = self.mVtkWidget.GetRenderWindow() self.mInteractor = self.mRenderWindow.GetInteractor() self.mInteractor.SetInteractorStyle(vtk.vtkInteractorStyleTrackballCamera()) self.mInteractor.Initialize() # Create a new renderer and set the background color. self.mRenderer = vtk.vtkRenderer() self.setBackgroundColor([0.5, 0.5, 0.5]) self.mRenderWindow.AddRenderer(self.mRenderer) # Set the Vtk Window title. self.mTitleActor = None self.setTitle("pyVtkLib Demo") # Called when QFrame is resized. def resizeEvent(self, newSize): textSize = [0, 0] self.mTitleActor.GetSize(self.mRenderer, textSize) width = int( (self.width() - textSize[0]) / 2.0) height = self.height() - textSize[1] self.mTitleActor.SetPosition(width, height - 10) def setBackgroundColor(self, color): self.mRenderer.SetBackground(color) def setTitle(self, title): if not self.mTitleActor: self.mTitleActor = vtk.vtkTextActor() self.mTitleActor.GetTextProperty().SetFontFamilyAsString("Georgia") self.mTitleActor.GetTextProperty().SetFontSize(30) self.mTitleActor.GetTextProperty().SetColor([1, 0, 0]) self.mTitleActor.SetInput(title) self.mTitleActor.SetPosition(0, 0) self.mRenderer.AddActor(self.mTitleActor) else: self.mTitleActor.SetInput(title)
VTK module for Python comes with a QVTKRenderWindowInteractor
class which by default inherits from QWidget
for PyQt5. In lines 4-5, we first change it to to use QGLWidget
so that rendering will be done using OpenGL instead of software renderer. Next, we create a class called VtkWindow
which inherits from QWidget
so that it can be use from Qt UI. Note, that it is recommended to inherit from QFrame
and not QWidget
as QVTKRenderWindowInteractor
cannot be reparented. More discussion on this topic can be found at EmbedPyQt example on VTK website. Next, we create an instance of QVTKRenderWindowInteractor
and add it to VtkWindow
class through a QVBoxLayout
.
After that it is usual VTK stuff of creating a vtkRenderingWindow
, vtkRenderWindowInteractor
, and vtkRenderer
. I prefer to use vtkInteractorStyleTrackballCamera
which I find far more intuitive than the default vtkInteractorStyleJoystickCamera
.
I render scene title at the top-middle of the screen and in order to place it here I listen to QFrame::resizeEvent to determine te current width and height of the QFrame.
Run the MainWindow.py from a terminal and it will display a windows with text pyVtkLib Demo printed in the middle-center of the window. In the next tutorial I will show how to measure and show frames per second to the VtkWindow
.
The code from this tutorial and any other future enhancements I will do will be available from saurabhg17/pyVtkLib repository at GitHub.
SLogLib is a flexible logging library written in C++. It comes with three logging devices: console, file, and memory but often there is a need to show log directly on the user interface. I heavily use Qt for all projects requiring user interface, so I wrote a logging device for QWidget
. It is available in SLogLib
repository in the Contrib/QWidgetLogger
folder.
Here is how to use the QWidgetLogger:
QWidgetLogger* logger = new QWidgetLogger(new HtmlFormatter(), "WidgetLogger"); SLogLib::addLoggingDevice(logger);
Once above code is added, any of the SLOGLIB_LOG_MSG_*
logging macros will write to the QWidgetLogger
as well as any other loggers added to SLogLib. QWidgetLogger
internally uses SLogTextEdit
class derived from QTextEdit
. Instance of SLogTextEdit
used by QWidgetLogger
can be retrieved by QWidgetLogger::widget() function. This instance should be added to the UI to show the logging messages. QDockWidget
is a good choice to show logging widget with QMainWindow
.
SLogTextEdit
sets a monospace 10 point font and it can be changed using style sheet. The color and style of the messages logged can also be changed using the Formatter
. The HtmlFormatter
used in the example above define different colors for different types of logging messages using HTML codes.
In Qt, UI elements can only be updated from the main thread but the logging messages might come from any thread. So SLogTextEdit
checks if the message was posted from the main thread or some other worker thread. If the message was posted from a worker thread, SLogTextEdit
emits a signal to only of its own private slot and updates itself in the slot. In Qt slots always run in the context of the main thread. This method works well but signal and slot mechanism is slow and update to widget lags while logging too many messages in a short period of time.
Recently, I worked on a project which made heavy use of C++ threads. To use SLogLib in this project I added multi-threaded support in SLogLib with the help of c++ 11 std::mutex
and std::lock_guard
. Over the last few months multi-threaded support in SLogLib has been extensively tested and there are no known bugs.
All threading support is located in LoggingManager.cpp. The functions which modify internal state in LoggingManager are protected by std::mutex. There is a support for building call stack through the use of SLOGLIB_ADD_TO_CALLSTACK
macro. In the latest build, there is a separate callstack for each thread.
Checkout the latest commit from https://github.com/saurabhg17/SLogLib.
If you received “Object arrays cannot be loaded when allow_pickle=False” while loading a numpy array using numpy.load()
it is because numpy has changed the default loading behaviour since version 1.16.3. If you are using numpy version newer than this, at many places on internet it is advised to simply downgrade the numpy version. This is not the correct solution at all. From the numpy documentation:
allow_pickle : bool, optional
Allow loading pickled object arrays stored in npy files. Reasons for disallowing pickles include security, as loading pickled data can execute arbitrary code. If pickles are disallowed, loading object arrays will fail. Default: False
Changed in version 1.16.3: Made default False in response to CVE-2019-6446.
Thus, the correct solution is to pass allow_pickle=True
to the numpy.load
function. However, this should be used carefully and ideally only with the files you have previously saved yourself since picking in python can execute arbitrary code thereby compromising the system security.
Some time back, I developed a data entry application in Qt5. One of the requirements was to let the user select a single string from a predefined list of string. I developed a custom widget called SStringSelector
for this purpose. SStringSelector
has two views: display and selection. The display view presents the currently selected string (blank if no string is selected), and a push button. To select a string, the user clicks on the button which presents the user with the selection dialog. The selection dialog consists of a list of string in an QListWidget and the user can select one of them by double-clicking a string. If the list of strings are long, the user can filter them using a filter QLineEdit present above the QListWidget.
SStringSelector
is distributed as a part of QtUtils repository hosted on Github. The SStringSelector
widget is really simple to use. Simple add the SStringSelector.h and SStringSelector.cpp files in your project and add an instance of SStringSelector in the layout of your app.
Below are some screenshots of the widget under Windows: