- Notifications
You must be signed in to change notification settings - Fork4
Graph-ICS is a tool for creating and visualizing image, video, and data streams.
License
Graph-ICS/Graph-ICS
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
A Node-Based Image, Video and Data Processing Tool
Graph-ICS is a tool for visualizing and creating image, video, and data streams. A stream always consists of an input and a series of filter nodes. Graph-ICS provides out-of-the-box usage of many filtering algorithms from the libraries ITK,OpenCV, andQt. Up to 10 different streams can be processed and displayed simultaneously. A core concept of Graph-ICS is to give its users the freedom to easily extend the available nodes for their desired use-case.
- Go to theReleases section and download the installer for your platform.
- You can find an installer forWindows,MacOS, andLinux.
- Extract the content and run the executable.
The linux binary for Graph-ICS was built and tested on Ubuntu 18.04 LTS. According tolinuxdeployqt the binary should also work on newer systems and different distributions.
I tried running the binary onEndeavourOS (Arch-based), but didnot get it to work.
The distributed mac binary was built on macOSX High Sierra 10.13.6 and cannot run on older systems.
If the Graph-ICS binary doesn't run on your system you can alwaysbuild from source!
If you encounter a problem anywhere in the process look upTroubleshooting! Maybe the problem has already been solved for you :)
Worth Mentioning:
The guide walks thorugh the steps on how to build Graph-ICS for theDebug configuration. You just need to replaceDebug withRelease in all following commands to produce theRelease configuration.
- Install Git
- Install Build Tools
- Install CMake
- Install Qt Library and QtCreator
- Build OpenCV
- Build ITK
- Build Graph-ICS
- Develop via QtCreator
- Plugins, Examples and Documentation (optional)
- Troubleshooting
- Download and install Git from theofficial website or via your package manager.
Windows:
- Download and install Visual Studio Community 2019 fromhere.
- Install Windows 10 SDK for C++ using the Visual Studio Installer.
- Make sure the compiler tools are in yourPATH.
- e.g.C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x64
Linux:
- Installgcc,g++ andmake packages.
e.g. onUbuntu use:
$ sudo apt install gcc g++ make
MacOS:
- Download and install XCode using the AppStore.
- Go to the officialCMake download website.
- Select the binary distributions of the latest relase for your platform.
- Make sure you have a CMake version greater than3.14 installed.
Note: On Linux you can also install CMake via your package manager.
Make surecmake runs from the commandline and check your version:
$ cmake --version
- Download theQt Online Installer for open-source.
- We needQt 5.15.2.
- Make sure to install the binaries for the compiler you use (e.g. on Windows using Visual Studio Community 2019:MSVC2019, on Linux/MacOS:Desktop gcc).
- Make sure to install all Qt Modules to have no dependency issues.
Windows:
- Additionally installQt Creator CDB Debugger Support andDebugging Tools for Windows.
- Open a commandline window.
- cd to a location where you want to store the library (e.g.C:/Libraries/) and execute the following commands.
- Pay close attention to the commands and execute them in the specified order!
Do not choose a path wich is too long! CMake paths are restricted to 50 characters by default.
$ mkdir opencv&&cd opencv$ git clone https://github.com/opencv/opencv.git src&&cd src$ git checkout tags/4.5.5 -b 4.5.5&&cd ..$ mkdir build-4.5.5&&cd build-4.5.5
In the following you will see the-j8 option. This is to speed up the build by a large factor. Replace8 with the number of threads your CPU supports.
Inside the/opencv/build-4.5.5 directory execute:
Windows:
$ cmake ../src -DWITH_FFMPEG=ON$ cmake --build. -j8 --config DebugLinux:
Before configuring OpenCV you need to make sure to have all needed packages installed.
To install the dependencies on Ubuntu run:
$ sudo apt install pkg-config ffmpeg libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libavresample-dev mesa-common-dev libglu1-mesa-dev
$ mkdir Debug&&cd Debug$ cmake ../../src -DCMAKE_BUILD_TYPE=Debug -DWITH_FFMPEG=ON
Make sure that OpenCV findsFFMPEG and the output in theVideo I/O section looks something like this:
Video I/O:-- DC1394: NO-- FFMPEG: YES-- avcodec: YES (57.107.100)-- avformat: YES (57.83.100)-- avutil: YES (55.78.100)-- swscale: YES (4.8.100)-- avresample: YES (3.7.0)
cmake --build. -j8MacOS:
$ mkdir Debug&&cd Debug$ cmake ../../src -DCMAKE_BUILD_TYPE=Debug$ cmake --build. -j8
- Only configure and start the build after OpenCV has finished.
- I know the build process takes long but you can grab a hot drink ☕ and enjoy some fresh air while waiting :)
- The next steps will seem familiar to you.
- Open a commandline window.
- cd to a location where you want to store the library and execute the following commands.
- Pay close attention to the commands and execute them in the specified order!
Do not choose a path wich is too long! CMake paths are restricted to 50 characters by default.
$ mkdir itk&&cd itk$ git clone https://github.com/InsightSoftwareConsortium/ITK.git src&&cd src$ git checkout tags/v5.2.1 -b v5.2.1&&cd ..$ mkdir build-v5.2.1&&cd build-v5.2.1
Make sure to adjust the path for theOpenCV_DIR option depending on your OpenCV build directory.
ITK has a known issue inv5.2.1 regarding theVideoBridgeOpenCV module and the testing of it. ITK will only compile successfully without testing so we need to specify the-DBUILD_TESTING=OFF option to build without errors.
Inside the/itk/build-v5.2.1 directory execute:
Windows:
$ cmake ../src -DOpenCV_DIR=<your path to>/opencv/build-4.5.5 -DModule_ITKVideoBridgeOpenCV=ON -DBUILD_TESTING=OFF$ cmake --build. -j8 --config Debug
Linux and MacOS:
$ mkdir Debug&&cd Debug$ cmake ../../src -DCMAKE_BUILD_TYPE=Debug -DOpenCV_DIR=<your path to>/opencv/build-4.5.5/Debug -DModule_ITKVideoBridgeOpenCV=ON -DBUILD_TESTING=OFF$ cmake --build. -j8
- Open a commandline window andcd to the directory where you want to store Graph-ICS.
$ git clone https://github.com/Graph-ICS/Graph-ICS.git&&cd Graph-ICS$ mkdir build&&cd build
Inside the/Graph-ICS/build directory execute:
$ mkdir Debug&&cd Debug
Make sure to adjust the path for theQt5_DIR andITK_DIR options depending on your Qt and ITK-build directories.
Windows:
We need to specify theCMAKE_BUILD_TYPE to automatically place shared libraries into the directory with the Graph-ICS executable. We also keepDebug andRelease build in seperate directories in contrast to building OpenCV and ITK (on Windows) to import the build easier into QtCreator.
$ cmake ../.. -DCMAKE_BUILD_TYPE=Debug -DQt5_DIR=<your path to>/Qt/5.15.2/<compiler>/lib/cmake/Qt5 -DITK_DIR=<your path to>/itk/build-v5.2.1$ cmake --build. -j8 --config Debug
Linux and MacOS:
$ cmake ../.. -DCMAKE_BUILD_TYPE=Debug -DQt5_DIR=<your path to>/Qt/5.15.2/<compiler>/lib/cmake/Qt5 -DITK_DIR=<your path to>/itk/build-v5.2.1/Debug$ cmake --build. -j8
- Start QtCreator and selectOpen Project.
- Find your Graph-ICS source code and select theCMakeLists.txt.
- Deselect all kits.
- SelectImport Build From, enter the location of yourDebug build and clickImport.
- ClickConfigure Project.
- Now you should be able to develop Graph-ICS using the QtCreator.
Many errors initkOpenCV...BridgeTest.cxx files?
- I had this issue on Linux and MacOS.
- Building ITK without testing worked for me.
- Append
-DBUILD_TESTING=OFFto the cmake configuration and rebuild.
CMake can't find Qt?
- Try deleting all Qt related CMake cache entries (or your whole build directory) and setting
Qt5_DIRcache variable to:your path to/Qt/5.15.2/your compiler/lib/cmake/Qt5
QtCreator shows errors in C++ code after importing the build but compiles without a problem?
- Try disabling the QtCreator pluginClangCodeModel (worked for me).
- I found the solution in thisstackoverflow post.
- UI Tour
- Adding Nodes
- Node Structure
- Tasks and Views
- Save your Configurations
- Customize your Favoritesbar
- Node Overview
1: Searchpanel
- Here you can find all available nodes and query them using the searchbar at the top.
- Drag & drop, doubleclick or use the context menu to create a node (more inAdding Nodes).
2: Tasks
- This area is used to control your defined tasks.
- Read more about Tasks inTasks and Views.
3: Messages
- Warnings and messages are shown in themessages-tab.
4: Canvas
- All created nodes will be placed inside the canvas.
- Here you can connect and arrange your nodes to your liking.
- You can use standard editing methods like copy, paste, remove using shortcuts or themenubar'sedit menu
5: Favoritesbar
- All your favorite nodes in one place, for quick-access.
6: Viewarea
- The output of a stream will be shown in one of the views.
- Connect the output of a node with the view where you want to display your stream.
- You can add and remove views using the buttons above (+) and below (-).
- More about views inTasks and Views.
There are several ways to create nodes in Graph-ICS. Nodes can be created in the same way using thesearchpanel or thefavoritesbar. You can create nodes via:
- Doubleclick
- Context menu
- Drag & drop
- Drag & drop a file
Input nodes (Image andVideo) canalso be created by dragging and dropping a file (e.g.jpg ormp4) from the file explorer (or desktop) into thecanvas.
A node can be either aninput or afilter. Available inputs areImage,Video orCamera.Image andVideo represent a file on your system.Camera represents a camera device on your system.
A node can have any number of input and output ports (not practical, but possible). Ports can be connected with each other to represent a data flow from one node to the other. Ports always indicate the transfered data with an icon (image or data).
Nodes have attributes to change the parameters of for example a filtering algorithm. You can change the values and check the processed result right after.
Tasks andViews take a special role in the processing of streams. A stream can only be processed if the output is connected to a view. That is when tasks come into play. A task gets created as soon as the output of a node is connected with a view. The type of the task depends on the input node of the stream. For example aVideo node as input will always lead to the creation of a video task. The same can be applied toCamera andImage nodes.
Each view-task relation can be identified by a color.
After defining your tasks you can control and start processing the stream. You can control your tasks using the global or task specific options. Additionally you can select a view and use theRun menu in themenubar or the context menu in theview to control your task.
Views can be added and removed using the buttons above (+) and below (-) theviewarea. The views to date arehighly inflexible andimpractical. This topic will be adressed in a future release!
Videos or camera recordings can be edited (cut, copy, paste) by clicking theedit button (pencil icon) at the right side of a video or camera task.
You can select a range to cut out using the range slider below and select a position to paste frames using the slider above the regular frame slider. Use the buttons at the top to execute or undo/redo your editing.
The context menu in aview can be used to save your image or video to a file. Also you will be asked to save your video if you recorded a camera stream or edited your video so you don't accidentally loose your progress.
A node setup with all attribute values and connections can be saved to a config file (.gconfig) to persist your configuration work. You can use standard keyboard shortcuts or thefile menu in themenubar to interact with a configuration.
To customize yourfavoritesbar you can use the context menu in thesearchpanel or a node. Also you canpress and hold an item in thesearchpanel and drag & drop into thefavoritesbar. Use the context menu orpress and hold an item in thefavoritesbar to move it. Remove nodes from the favorites using the context menu.
Input:
| Node | Output | Functionality | Attributes | Library |
|---|---|---|---|---|
| Camera | Camera frame | Grab a frame from the camera device | Device: Camera device numberFPS: Frames per second | OpenCV |
| Image | Image from file | Load the image from the specified file | Path: Path to image file | Qt |
| Video | Video frame | Grab a frame from the specified video file | Path: Path to video fileFPS: Frames per second | OpenCV |
Filter:
| Node | Input | Output | Functionality | Attributes | Library |
|---|---|---|---|---|---|
| CvDilation | Image | Dilated image | Dilate the input image | Element: Dilation ElementKernel Size: Size of dilation element (more dilation for larger values) | OpenCV |
| CvErosion | Image | Eroded image | Erode the input image | Element: Erosion ElementKernel Size: Size of erosion element (more erosion for larger values) | OpenCV |
| CvFourierTransformPSD | Image | PSD image | Calculate the phase spectrum density | Show Log Amplitude: Show the logarithmic phase spectrum density | OpenCV |
| CvHistogramCalculation | Image | Forwarded image, Histogram data | Calculate the histogram | OpenCV | |
| CvHistogramEqualization | Image | Equalized image | Stretch histogram data to use all values between 0 and 255 (enhance contrast) | OpenCV | |
| CvMedian | Image | Median blurred image | Blur the image using the median | Kernel Size: Size of median kernel (larger values for more blur), only odd numbers allowed | OpenCV |
| CvSobelOperator | Image | Image with detected edges | Apply the sobel operator on the image (edge detection) | x-Derivative: Edge detection in x-directiony-Derivative: Edge detection in y-directon Both values can't be 0 | OpenCV |
| CvTransformation | Image | Transformed image | Rotate and/or scale the image | OpenCV | |
| Dummy | Image | Image | Forward the input image | ||
| ItkBinaryMorphClosing | Image | Closed image | Closes parts of the image by executing a dilation and a erosion | Radius: Closing radius (smallest parts to close) | ITK |
| ItkBinaryMorphOpening | Image | Opened image | Opens parts of the image by executing a erosion and a dilation | Radius: Opening radius (smallest parts to open) | ITK |
| ItkCannyEdgeDetection | Image | Image with detected edges | Apply a gaussian blur and the canny edge detection algorithm | Variance: Intensity of the gaussian blurUpper Threshold: Largest accepted valueLower Threshold: Smallest accepted value | ITK |
| ItkDiscreteGaussian | Image | Blurred image | Apply a gaussian blur | Variance: Intensity of the blur | ITK |
| ItkMedian | Image | Median blurred image | Apply a median blur | x-Radius: Blur radius in x-directiony-Radius: Blur radius in y-direction | ITK |
| ItkSubtract | Image to be subtracted Image to subtract | Subtracted image | Subtract the smaller image from the larger image, second connected image gets subtracted from first connected image if they have same size | ITK | |
| QtBlackWhite | Image | Black white image | Transform to black white | Qt | |
| QtDarker | Image | Darker image | Darken the image | Factor: Darkening factor (values above 100 darken, below 100 lighten) | Qt |
| QtLighter | Image | Lighter image | Lighten the image | Factor: Lightening factor (values above 100 lighten, below 100 darken | Qt |
Every contribution is appreciated! Make sure to read thecontributing guide first.
This guide assumes you already have builtGraph-ICS from source.
Graph-ICS aims to keep an open and easy interface to add new filter nodes. The following guide shows the steps that need and also could be done to add a new filter node. The example shows the creation of theCvSobelOperator node with a custom front-end.
QtCreator quickly generates a nice starting point for filter development and saves you much time writing the class definition.
- Right-click onapp/src/model/opencv and selectAdd New... .
- SelectC++,C++ Class and click onchoose.
- Enter a class name, hereCvSobelOperator.
- AddNode as the custom base class and selectAdd Q_OBJECT.
- Clicknext, thenfinish.
- Right-click on the project root and selectRun CMake (or from the menuBuild/Run CMake)
Header File:
#ifndef CVSOBELOPERATOR_H#defineCVSOBELOPERATOR_H#include"node.h"// Add to the Graph-ICS NamespacenamespaceG {// Derive from NodeclassCvSobelOperator :publicNode{// Important Q_OBJECT Macro Q_OBJECTpublic:explicitCvSobelOperator();// Pure virtual function// Filter functionality needs to go in hereboolretrieveResult()override;// Virtual function// Define special behavior if an attribute value changedvoidonAttributeValueChanged(Attribute* attribute)override;private:// Declare your in- and out-ports// You can have as many as you want and need Port m_inPort; Port m_outPort;// Declare the attributes// CvSobelOperator has two attributes to specify the edge detection direction Attribute* m_xDerivative; Attribute* m_yDerivative;};}// namespace G#endif// CVSOBELOPERATOR_H
Source File:
#include"cvsobeloperator.h"#include<cv.h>#include<opencv2/imgproc/imgproc.hpp>// Wrap the definition into the namspace to avoid writing G::Foo everywherenamespaceG{CvSobelOperator::CvSobelOperator()// !!!Pass the classname to the Node constructor!!! : Node("CvSobelOperator")// Initialize the ports with a supported datatype (GIMAGE or GDATA) , m_inPort(Port::TYPE::GIMAGE) , m_outPort(Port::TYPE::GIMAGE)// The Attribute class is really generiy and can be customized to your liking// attributeFactory is a prototype factory for predefined Attribute instances// For simplicity we just use the predefined IntTextField-Attribute , m_xDerivative(attributeFactory.makeIntTextField(1,0,2,1,"x-Derivative")) , m_yDerivative(attributeFactory.makeIntTextField(0,0,2,1,"y-Derivative")){// Register your in-and out-ports to the port systemregisterPorts({&m_inPort}, {&m_outPort});// Register your attributes to the attribute systemregisterAttribute("xDerivative", m_xDerivative);registerAttribute("yDerivative", m_yDerivative);}boolCvSobelOperator::retrieveResult(){try {// We know that the in-port has an image when entering this function cv::Mat& cvImage = m_inPort.getGImage()->getCvMatImage();// We need to make sure the image has only one channelif (cvImage.channels() >1) {cv::cvtColor(cvImage, cvImage, CV_BGR2GRAY); }// Retrieve the values from the attributes to use them in the filteringint xDerivative = m_xDerivative->getValue().toInt();int yDerivative = m_yDerivative->getValue().toInt();// Do the filteringcv::Sobel(cvImage, cvImage, CV_8U, xDerivative, yDerivative);// Forward the result to the out-port m_outPort.getGImage()->setImage(cvImage); }catch (int e) {qDebug() <<"CvSobelOperator. Exception Nr." << e <<'\n';returnfalse; }returntrue;}voidCvSobelOperator::onAttributeValueChanged(Attribute* attribute){// Clear the cached data in the output stream// Because an attribute value changed and the result needs to be calculated againclearStreamCache();// The specification of the cv::Sobel function does not allow both parameters to be 0// This is why this function needs to make sure that the values are never both 0.if (attribute->getValue().toInt() ==0) { Attribute* other;if (attribute == m_xDerivative) { other = m_yDerivative; }else { other = m_xDerivative; }if (other->getValue().toInt() ==0) { other->setValue(1); } }}}// namespace G}
- OpenNodes.cmake located inGraph-ICS/app and add your newly created node to theOPENCV_NODES variable
set(OPENCV_NODES CvDilation CvErosion CvFourierTransformPSD CvHistogramCalculation CvHistogramEqualization CvMedian CvTransformation# Our newly added Filter CvSobelOperator)
Now you just need to run CMake and build Graph-ICS.
You also can customize the node front-end if you don't like the auto generated look or want additional features. As an example we add a button to the node to swap the attribute values.
- Add a new .qml file toapp/qml/node/custom
- The file needs to have the exact same name as the filter class (here: CvSobelOperator).
importQtQuick2.15importQtQuick.Layouts1.15// Import our ThemeimportTheme1.0import"../"import"../attribute"import"../../components"// Import the c++ modelimportModel.CvSobelOperator1.0// GNode provides a Component interface that can be used for customization// GNode provides all functionality and default ComponentsGNode { id: sobel// Instantiate the c++ model and assign it to the model property model: CvSobelOperatorModel {}// Override the background// Do not specitfy size or anchors of the Rectangle, as it will fit to the content background: Rectangle { color:Theme.primary radius:8border.width:3border.color: {if (isSelected) {returnTheme.secondary }if (isHovered) {returnTheme.secondaryLight }returnTheme.primaryDark } }// Override the content// Everything a sobel contains is inside of the content Component// e.g. Title and Attributes// Specify a size for this Component if no implicit size is available (e.g. Item)// You don't need to use Layouts (but they are convenient for sizing) content: ColumnLayout { spacing:Theme.smallSpaceing// Display the node name (id)Text {Layout.fillWidth:true text: id font:Theme.font.body2 color:Theme.onprimary topPadding:Theme.largeSpaceing leftPadding:Theme.largeSpaceing rightPadding:Theme.largeSpaceing bottomPadding:Theme.smallSpaceing verticalAlignment:Text.AlignVCenter horizontalAlignment:Text.AlignHCenter } RowLayout {Layout.leftMargin:Theme.largeSpaceingLayout.rightMargin:Theme.smallSpaceingLayout.fillHeight:true Item {Layout.preferredHeight:xDerivative.height+yDerivative.height+Theme.smallSpaceingLayout.minimumWidth:Math.max(xDerivative.width,yDerivative.width)// Specify the Attributes// Custom Attributes that derive from GAttribute can be used too TextFieldAttribute { id: xDerivative// make sure to use the exact same name as in registerAttribute(...) (c++) name:"xDerivative"// get the attribute model from the node model by the name node: sobel model:node.model.getAttribute(name)// Don't forget to add the Attributes to the attributes array// Otherwise saving and loading the node will not work properly// It is necessary to use the onCompleted function to push the// attribute into the array, because content is a Component// and the content object is only created during GNode's onCompleted functionComponent.onCompleted:attributes.push(xDerivative) } TextFieldAttribute { id: yDerivativeanchors.top:xDerivative.bottomanchors.topMargin:Theme.smallSpaceing name:"yDerivative" node: sobel model:node.model.getAttribute(name)Component.onCompleted:attributes.push(yDerivative) } }// Simple demonstration// swap the attribute values GIconButton {Layout.preferredHeight:Theme.baseHeightLayout.preferredWidth:Theme.baseHeight// Make sure that the attribute values can not be altered if the node is locked// Otherwise unexpected behavior may occur if the values are changed// while a stream is processing enabled:!isLockedicon.source:Theme.icon.swapVerticon.color: {if (hovered|| pressed) {returnTheme.primaryDark }returnTheme.onprimary } transparent:true onClicked: {let value=xDerivative.valuexDerivative.setValue(yDerivative.value)yDerivative.setValue(value) } } } }// If you just want to create your individual Attributes and don't want to override the content// you can just override the predefined attribute Components e.g.:// textFieldAttributeComponent: MyCustomTextFieldAttribute {}}
Special thanks ❤️ to all open-source projects making life easier for developers all over the world and especially:
About
Graph-ICS is a tool for creating and visualizing image, video, and data streams.
Topics
Resources
License
Contributing
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Uh oh!
There was an error while loading.Please reload this page.
Contributors2
Uh oh!
There was an error while loading.Please reload this page.











