moved Pastie so seperate repo
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
Pastie
|
||||
moc_*
|
||||
ui_*
|
119
Pastie.pro
Normal file
|
@ -0,0 +1,119 @@
|
|||
#-------------------------------------------------
|
||||
#
|
||||
# Project created by QtCreator 2014-09-12T15:39:17
|
||||
#
|
||||
#-------------------------------------------------
|
||||
|
||||
QT += core gui opengl multimedia
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
|
||||
TARGET = Pastie
|
||||
TEMPLATE = app
|
||||
|
||||
ICON = resources/Mr-potato.icns
|
||||
|
||||
SOURCES += main.cpp\
|
||||
mainwindow.cpp \
|
||||
camera.cpp \
|
||||
imagelist.cpp \
|
||||
image.cpp \
|
||||
viewer.cpp \
|
||||
debugstream.cpp \
|
||||
filterlist.cpp \
|
||||
source.cpp \
|
||||
tabcalibration.cpp \
|
||||
tabimages.cpp \
|
||||
tabcamera.cpp \
|
||||
tabfilters.cpp \
|
||||
tabpads.cpp \
|
||||
console.cpp \
|
||||
painter.cpp \
|
||||
filters/maxchannel.cpp \
|
||||
filters/normalize.cpp \
|
||||
filters/shapedetect.cpp \
|
||||
filters/setting.cpp \
|
||||
filters/result.cpp \
|
||||
filters/blur.cpp \
|
||||
filters/watershed.cpp
|
||||
|
||||
HEADERS += mainwindow.h \
|
||||
camera.h \
|
||||
imagelist.h \
|
||||
image.h \
|
||||
viewer.h \
|
||||
debugstream.h \
|
||||
filterlist.h \
|
||||
source.h \
|
||||
tabcalibration.h \
|
||||
tabimages.h \
|
||||
tabcamera.h \
|
||||
tabfilters.h \
|
||||
tabpads.h \
|
||||
console.h \
|
||||
cast.h \
|
||||
painter.h \
|
||||
filters.h \
|
||||
filters/maxchannel.h \
|
||||
filters/normalize.h \
|
||||
filters/shapedetect.h \
|
||||
filters/setting.h \
|
||||
filters/result.h \
|
||||
filters/blur.h \
|
||||
filters/watershed.h
|
||||
|
||||
SOURCES += filters/filter.cpp \
|
||||
filters/undistort.cpp \
|
||||
filters/threshold.cpp \
|
||||
filters/kmeans.cpp \
|
||||
filters/histequalize.cpp \
|
||||
filters/morph.cpp \
|
||||
filters/convert.cpp \
|
||||
filters/pattern.cpp \
|
||||
filters/padfilter.cpp \
|
||||
filters/edgedetect.cpp \
|
||||
filters/channel.cpp \
|
||||
filters/perspective.cpp
|
||||
|
||||
HEADERS += filters/filter.h \
|
||||
filters/kmeans.h \
|
||||
filters/threshold.h \
|
||||
filters/undistort.h \
|
||||
filters/histequalize.h \
|
||||
filters/morph.h \
|
||||
filters/convert.h \
|
||||
filters/pattern.h \
|
||||
filters/edgedetect.h \
|
||||
filters/channel.h \
|
||||
filters/perspective.h \
|
||||
filters/padfilter.h
|
||||
|
||||
FORMS += mainwindow.ui \
|
||||
about.ui \
|
||||
imagelist.ui \
|
||||
tabcalibration.ui \
|
||||
tabimages.ui \
|
||||
tabcamera.ui \
|
||||
tabfilters.ui \
|
||||
tabpads.ui
|
||||
|
||||
# OpenCV
|
||||
INCLUDEPATH += /usr/local/include
|
||||
|
||||
LIBS += -L/usr/local/lib
|
||||
LIBS += -lopencv_core \
|
||||
-lopencv_highgui \
|
||||
-lopencv_imgproc\
|
||||
-lopencv_imgcodecs \
|
||||
-lopencv_videoio \
|
||||
-lopencv_calib3d \
|
||||
-lopencv_features2d
|
||||
|
||||
RESOURCES += \
|
||||
images.qrc \
|
||||
texts.qrc
|
||||
|
||||
OTHER_FILES +=
|
||||
|
||||
CONFIG += c++11
|
||||
QMAKE_MAC_SDK = macosx10.10
|
263
Pastie.pro.user
Normal file
|
@ -0,0 +1,263 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 3.3.0, 2014-12-20T13:25:42. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
<value type="QByteArray">{8f80b8d2-0f3b-47b3-a327-f81ae0873a3f}</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||
<value type="int">0</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
|
||||
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
|
||||
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
|
||||
<value type="QString" key="language">Cpp</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">qt2</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<value type="int" key="EditorConfiguration.CodeStyle.Count">1</value>
|
||||
<value type="QByteArray" key="EditorConfiguration.Codec">UTF-8</value>
|
||||
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.IndentSize">4</value>
|
||||
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
|
||||
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
|
||||
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
|
||||
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
|
||||
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
|
||||
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
|
||||
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
|
||||
<value type="int" key="EditorConfiguration.TabSize">8</value>
|
||||
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
|
||||
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
|
||||
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanIndentation">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
|
||||
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.PluginSettings</variable>
|
||||
<valuemap type="QVariantMap"/>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Target.0</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop Qt 5.4.0 clang 64bit</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop Qt 5.4.0 clang 64bit</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">qt.54.clang_64_kit</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/Users/stv0g/workspace/rwth-dbv/code/build-Pastie-Desktop_Qt_5_4_0_clang_64bit-Debug</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibraryAuto">true</value>
|
||||
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
|
||||
<value type="QString">-w</value>
|
||||
<value type="QString">-r</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
|
||||
<value type="QString">-w</value>
|
||||
<value type="QString">-r</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Bereinigen</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Debug</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">2</value>
|
||||
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.1">
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/Users/stv0g/workspace/rwth-dbv/code/build-Pastie-Desktop_Qt_5_4_0_clang_64bit-Release</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">qmake</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">QtProjectManager.QMakeBuildStep</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibrary">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.LinkQmlDebuggingLibraryAuto">true</value>
|
||||
<value type="QString" key="QtProjectManager.QMakeBuildStep.QMakeArguments"></value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.QMakeForced">false</value>
|
||||
<value type="bool" key="QtProjectManager.QMakeBuildStep.UseQtQuickCompiler">false</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.1">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
|
||||
<value type="QString">-w</value>
|
||||
<value type="QString">-r</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">false</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments"></value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">2</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Make</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.MakeStep</value>
|
||||
<valuelist type="QVariantList" key="Qt4ProjectManager.MakeStep.AutomaticallyAddedMakeArguments">
|
||||
<value type="QString">-w</value>
|
||||
<value type="QString">-r</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="Qt4ProjectManager.MakeStep.Clean">true</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeArguments">clean</value>
|
||||
<value type="QString" key="Qt4ProjectManager.MakeStep.MakeCommand"></value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Bereinigen</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Release</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4BuildConfiguration</value>
|
||||
<value type="int" key="Qt4ProjectManager.Qt4BuildConfiguration.BuildConfiguration">0</value>
|
||||
<value type="bool" key="Qt4ProjectManager.Qt4BuildConfiguration.UseShadowBuild">true</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">2</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deployment</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Lokales Deployment</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.PluginSettings"/>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.AddedSuppressionFiles"/>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectBusEvents">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.CollectSystime">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableBranchSim">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableCacheSim">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Callgrind.EnableEventToolTips">true</value>
|
||||
<value type="double" key="Analyzer.Valgrind.Callgrind.MinimumCostRatio">0.01</value>
|
||||
<value type="double" key="Analyzer.Valgrind.Callgrind.VisualisationMinimumCostRatio">10</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.FilterExternalIssues">true</value>
|
||||
<value type="int" key="Analyzer.Valgrind.LeakCheckOnFinish">1</value>
|
||||
<value type="int" key="Analyzer.Valgrind.NumCallers">25</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.RemovedSuppressionFiles"/>
|
||||
<value type="int" key="Analyzer.Valgrind.SelfModifyingCodeDetection">1</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.ShowReachable">false</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.TrackOrigins">true</value>
|
||||
<value type="QString" key="Analyzer.Valgrind.ValgrindExecutable">valgrind</value>
|
||||
<valuelist type="QVariantList" key="Analyzer.Valgrind.VisibleErrorKinds">
|
||||
<value type="int">0</value>
|
||||
<value type="int">1</value>
|
||||
<value type="int">2</value>
|
||||
<value type="int">3</value>
|
||||
<value type="int">4</value>
|
||||
<value type="int">5</value>
|
||||
<value type="int">6</value>
|
||||
<value type="int">7</value>
|
||||
<value type="int">8</value>
|
||||
<value type="int">9</value>
|
||||
<value type="int">10</value>
|
||||
<value type="int">11</value>
|
||||
<value type="int">12</value>
|
||||
<value type="int">13</value>
|
||||
<value type="int">14</value>
|
||||
</valuelist>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Pastie</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">Qt4ProjectManager.Qt4RunConfiguration:/Users/stv0g/workspace/rwth-dbv/code/pastie/Pastie.pro</value>
|
||||
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.CommandLineArguments">google/*</value>
|
||||
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.ProFile">Pastie.pro</value>
|
||||
<value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseDyldImageSuffix">false</value>
|
||||
<value type="bool" key="Qt4ProjectManager.Qt4RunConfiguration.UseTerminal">false</value>
|
||||
<value type="QString" key="Qt4ProjectManager.Qt4RunConfiguration.UserWorkingDirectory">/Users/stv0g/workspace/rwth-dbv/data</value>
|
||||
<value type="uint" key="RunConfiguration.QmlDebugServerPort">3768</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseMultiProcess">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.TargetCount</variable>
|
||||
<value type="int">1</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
|
||||
<value type="int">18</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Version</variable>
|
||||
<value type="int">18</value>
|
||||
</data>
|
||||
</qtcreator>
|
143
about.ui
Normal file
|
@ -0,0 +1,143 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AboutDialog</class>
|
||||
<widget class="QDialog" name="AboutDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>585</width>
|
||||
<height>254</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>About</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="3" column="2">
|
||||
<widget class="QPushButton" name="pushButton">
|
||||
<property name="text">
|
||||
<string>Close</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QPlainTextEdit" name="plainTextEdit">
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="plainText">
|
||||
<string>Seminar Bildverarbeitung und Inhaltsanalyse
|
||||
Lehrstuhl für Bildverarbeitung
|
||||
RWTH Aachen
|
||||
|
||||
Steffen Vogel
|
||||
- Mail: steffen.vogel@rwth-aachen.de
|
||||
- Web: http:///www.steffenvogel.de
|
||||
|
||||
Wintersemester 2014/15</string>
|
||||
</property>
|
||||
<property name="backgroundVisible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>128</width>
|
||||
<height>128</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>192</width>
|
||||
<height>192</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="images.qrc">:/icons/resources/Mr-potato.png</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>10</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="images.qrc"/>
|
||||
</resources>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>pushButton</sender>
|
||||
<signal>clicked()</signal>
|
||||
<receiver>AboutDialog</receiver>
|
||||
<slot>close()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>400</x>
|
||||
<y>176</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>294</x>
|
||||
<y>186</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
76
camera.cpp
Normal file
|
@ -0,0 +1,76 @@
|
|||
#include <opencv2/calib3d.hpp>
|
||||
|
||||
#include <QtDebug>
|
||||
|
||||
#include "filters/pattern.h"
|
||||
#include "camera.h"
|
||||
#include "image.h"
|
||||
|
||||
Camera::Camera(Source *s) :
|
||||
source(s),
|
||||
calibrated(false)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
void Camera::reset()
|
||||
{
|
||||
calibrated = false;
|
||||
avgReprErr = 0;
|
||||
distCoeffs = Mat::zeros(8, 1, CV_32F);
|
||||
matrix = Mat::eye(3, 3, CV_32F);
|
||||
}
|
||||
|
||||
bool Camera::calibrate(list<Image *> imgs, Pattern *pattern)
|
||||
{
|
||||
vector<vector<Point2f>> imagePoints;
|
||||
vector<vector<Point3f>> objectPoints;
|
||||
vector<Mat> rvecs, tvecs;
|
||||
|
||||
if (calibrated) {
|
||||
qWarning() << "Camera is already calibrated. Reset first!";
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto img : imgs) {
|
||||
img->applyFilter(pattern);
|
||||
PatternResult *result = (PatternResult *) img->getResult(pattern);
|
||||
|
||||
if (result->isFound())
|
||||
imagePoints.push_back(result->getPoints());
|
||||
}
|
||||
|
||||
if (imagePoints.size() < 5) {
|
||||
qWarning() << "Only " << imagePoints.size() << " patterns detected. This is not enough!";
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Fill in vector of calibration rig points */
|
||||
std::vector<Point3f> planar = pattern->getPoints();
|
||||
for (unsigned i = 0; i < imagePoints.size(); i++)
|
||||
objectPoints.push_back(planar);
|
||||
|
||||
/* Calculate camera matrix and distortion coefficients */
|
||||
calibrateCamera(objectPoints, imagePoints, source->getSize(), matrix, distCoeffs, rvecs, tvecs);
|
||||
|
||||
/* Calculate average reprojection error */
|
||||
double totalErr = 0;
|
||||
int totalPoints = 0;
|
||||
|
||||
for (unsigned i = 0; i < imagePoints.size(); i++) {
|
||||
std::vector<Point2f> imagePoints2;
|
||||
|
||||
projectPoints(objectPoints[i], rvecs[i], tvecs[i], matrix, distCoeffs, imagePoints2);
|
||||
|
||||
totalErr += pow(norm(imagePoints[i], imagePoints2, NORM_L2), 2);
|
||||
totalPoints += objectPoints[i].size();
|
||||
}
|
||||
|
||||
avgReprErr = totalErr / totalPoints;
|
||||
calibrated = true;
|
||||
|
||||
qDebug() << "Calibration completed: Found " << imagePoints.size() << " patterns in " << imgs.size() << " images";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
41
camera.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
#ifndef CAMERA_H
|
||||
#define CAMERA_H
|
||||
|
||||
#include <opencv2/videoio.hpp>
|
||||
|
||||
#include <list>
|
||||
|
||||
#include "source.h"
|
||||
#include "filters/pattern.h"
|
||||
|
||||
using namespace cv;
|
||||
using namespace std;
|
||||
|
||||
class Image;
|
||||
|
||||
class Camera
|
||||
{
|
||||
public:
|
||||
Camera(Source *s);
|
||||
|
||||
bool calibrate(list<Image *> imgs, Pattern *pattern);
|
||||
|
||||
/* Getters */
|
||||
const Mat & getDistCoeffs() { return distCoeffs; }
|
||||
const Mat & getMatrix() { return matrix; }
|
||||
double getAvgReprErr() { return avgReprErr; }
|
||||
bool isCalibrated() { return calibrated; }
|
||||
|
||||
void reset();
|
||||
|
||||
Source *source;
|
||||
|
||||
protected:
|
||||
bool calibrated;
|
||||
double avgReprErr;
|
||||
|
||||
Mat matrix;
|
||||
Mat distCoeffs;
|
||||
};
|
||||
|
||||
#endif // CAMERA_H
|
58
cast.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
#ifndef CAST_H
|
||||
#define CAST_H
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
|
||||
#include <QtDebug>
|
||||
|
||||
#include <QTransform>
|
||||
#include <QSize>
|
||||
#include <QPoint>
|
||||
#include <QRect>
|
||||
#include <QImage>
|
||||
|
||||
using namespace cv;
|
||||
|
||||
inline QImage toQImage(const Mat &mat)
|
||||
{
|
||||
Mat *conv = new Mat;
|
||||
|
||||
|
||||
|
||||
switch (mat.channels()) {
|
||||
case 3: cvtColor(mat, *conv, COLOR_RGB2RGBA); break;
|
||||
case 1: cvtColor(mat, *conv, COLOR_GRAY2RGBA); break;
|
||||
}
|
||||
|
||||
return QImage((const unsigned char *) conv->data, conv->cols, conv->rows, conv->step,
|
||||
QImage::Format_RGB32, [] (void * data) { ((Mat *) data)->release(); }, conv);
|
||||
}
|
||||
|
||||
inline QTransform toQTransform(const Mat &m)
|
||||
{
|
||||
return QTransform(
|
||||
m.at<float>(0,0), m.at<float>(0,1), m.at<float>(0,2),
|
||||
m.at<float>(1,0), m.at<float>(1,1), m.at<float>(1,2),
|
||||
m.at<float>(2,0), m.at<float>(2,1), m.at<float>(2,2));
|
||||
}
|
||||
|
||||
inline QSize toQt(const Size2i &s) { return QSize (s.width, s.height); }
|
||||
inline QSizeF toQt(const Size2d &s) { return QSizeF(s.width, s.height); }
|
||||
|
||||
inline QPoint toQt(const Point2i &p) { return QPoint (p.x, p.y); }
|
||||
inline QPointF toQt(const Point2d &p) { return QPointF(p.x, p.y); }
|
||||
|
||||
inline QRect toQt(const Rect2i &r) { return QRect (r.x, r.y, r.width, r.height); }
|
||||
inline QRectF toQt(const Rect2d &r) { return QRectF(r.x, r.y, r.width, r.height); }
|
||||
|
||||
inline Size2i toCv(const QSize &s) { return Size2i(s.width(), s.height()); }
|
||||
inline Size2d toCv(const QSizeF &s) { return Size2d(s.width(), s.height()); }
|
||||
|
||||
inline Point2i toCv(const QPoint &p) { return Point2i(p.x(), p.y()); }
|
||||
inline Point2d toCv(const QPointF &p) { return Point2d(p.x(), p.y()); }
|
||||
|
||||
inline Rect2i toCv(const QRect &r) { return Rect2i(r.x(), r.y(), r.width(), r.height()); }
|
||||
inline Rect2d toCv(const QRectF &r) { return Rect2d(r.x(), r.y(), r.width(), r.height()); }
|
||||
|
||||
#endif // CAST_H
|
25
console.cpp
Normal file
|
@ -0,0 +1,25 @@
|
|||
#include <QtDebug>
|
||||
#include <QScrollBar>
|
||||
|
||||
#include "console.h"
|
||||
|
||||
Console::Console(QWidget *parent) :
|
||||
QPlainTextEdit(parent),
|
||||
qcout(std::cout, QtDebugMsg), /* redirect standard outputs to console */
|
||||
qcerr(std::cerr, QtCriticalMsg)
|
||||
{
|
||||
DebugStream::registerConsole(this);
|
||||
DebugStream::registerHandler();
|
||||
|
||||
|
||||
}
|
||||
|
||||
void Console::setup()
|
||||
{
|
||||
QFile intro(":/resources/intro.html");
|
||||
if (!intro.open(QFile::ReadOnly))
|
||||
qCritical() << "Failed to open intro.html resource";
|
||||
|
||||
appendHtml(intro.readAll());
|
||||
moveCursor(QTextCursor::Start);
|
||||
}
|
20
console.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
#ifndef CONSOLE_H
|
||||
#define CONSOLE_H
|
||||
|
||||
#include <QPlainTextEdit>
|
||||
|
||||
#include "debugstream.h"
|
||||
|
||||
class Console : public QPlainTextEdit
|
||||
{
|
||||
public:
|
||||
Console(QWidget *parent = 0);
|
||||
|
||||
void setup();
|
||||
|
||||
protected:
|
||||
DebugStream qcout;
|
||||
DebugStream qcerr;
|
||||
};
|
||||
|
||||
#endif // CONSOLE_H
|
98
debugstream.cpp
Normal file
|
@ -0,0 +1,98 @@
|
|||
#include <QtDebug>
|
||||
|
||||
#include "debugstream.h"
|
||||
|
||||
QPlainTextEdit *DebugStream::console;
|
||||
|
||||
DebugStream::DebugStream(std::ostream &s, QtMsgType t) :
|
||||
stream(s),
|
||||
type(t)
|
||||
{
|
||||
oldBuf = s.rdbuf();
|
||||
s.rdbuf(this);
|
||||
}
|
||||
|
||||
DebugStream::~DebugStream()
|
||||
{
|
||||
if (!string.empty())
|
||||
handler(type, QString::fromStdString(string));
|
||||
|
||||
stream.rdbuf(oldBuf);
|
||||
}
|
||||
|
||||
std::streamsize DebugStream::xsputn(const char *p, std::streamsize n)
|
||||
{
|
||||
string.append(p, p + n);
|
||||
|
||||
size_t pos = 0;
|
||||
while (pos != std::string::npos) {
|
||||
pos = string.find('\n');
|
||||
if (pos != std::string::npos) {
|
||||
std::string tmp(string.begin(), string.begin() + pos);
|
||||
handler(type, QString::fromStdString(tmp));
|
||||
string. erase(string.begin(), string.begin() + pos + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int DebugStream::overflow(int v)
|
||||
{
|
||||
if (v == '\n') {
|
||||
handler(type, QString::fromStdString(string));
|
||||
string.clear();
|
||||
}
|
||||
else
|
||||
string += v;
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
QString DebugStream::format(QString msg, QtMsgType type)
|
||||
{
|
||||
QString out("<pre><div style='font-weight: bold; color: %1'>[%2]</div> %3</pre>");
|
||||
|
||||
switch (type) {
|
||||
case QtDebugMsg: out = out.arg("Gray").arg("Debug "); break;
|
||||
case QtWarningMsg: out = out.arg("Orange").arg("Warning "); break;
|
||||
case QtCriticalMsg: out = out.arg("DarkRed").arg("Critical"); break;
|
||||
case QtFatalMsg: out = out.arg("Magenta").arg("Fatal "); break;
|
||||
}
|
||||
|
||||
return out.arg(msg);
|
||||
}
|
||||
|
||||
void DebugStream::registerHandler()
|
||||
{
|
||||
qInstallMessageHandler(DebugStream::handler);
|
||||
}
|
||||
|
||||
void DebugStream::registerConsole(QPlainTextEdit *pte)
|
||||
{
|
||||
console = pte;
|
||||
}
|
||||
|
||||
void DebugStream::handler(QtMsgType type, const QString &msg)
|
||||
{
|
||||
static int dropped;
|
||||
static int next = 1;
|
||||
if (msg == "Camera dropped frame!") {
|
||||
if (++dropped == next) {
|
||||
next = next + next*2;
|
||||
printf("Camera dropped %u frames! Next %u\n\n", dropped, next);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (console)
|
||||
console->appendHtml(format(msg, type));
|
||||
else
|
||||
printf("%s\n", (const char *) QByteArray(msg.toLocal8Bit().constData()));
|
||||
}
|
||||
|
||||
void DebugStream::handler(QtMsgType type, const QMessageLogContext &, const QString &msg)
|
||||
{
|
||||
handler(type, msg);
|
||||
}
|
36
debugstream.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
#ifndef DEBUGSTREAM_H
|
||||
#define DEBUGSTREAM_H
|
||||
|
||||
#include <QtGlobal>
|
||||
#include <QPlainTextEdit>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
class DebugStream : public std::basic_streambuf<char>
|
||||
{
|
||||
|
||||
public:
|
||||
DebugStream(std::ostream &stream, QtMsgType type);
|
||||
~DebugStream();
|
||||
|
||||
static QString format(QString msg, QtMsgType type = QtDebugMsg);
|
||||
static void registerConsole(QPlainTextEdit *);
|
||||
static void registerHandler();
|
||||
|
||||
protected:
|
||||
int overflow(int_type v);
|
||||
std::streamsize xsputn(const char *p, std::streamsize n);
|
||||
|
||||
private:
|
||||
std::ostream &stream;
|
||||
std::streambuf *oldBuf;
|
||||
std::string string;
|
||||
|
||||
QtMsgType type;
|
||||
|
||||
static void handler(QtMsgType type, const QString &msg);
|
||||
static void handler(QtMsgType type, const QMessageLogContext &, const QString &str);
|
||||
static QPlainTextEdit *console;
|
||||
};
|
||||
|
||||
#endif // DEBUGSTREAM_H
|
131
filterlist.cpp
Normal file
|
@ -0,0 +1,131 @@
|
|||
#include "mainwindow.h"
|
||||
|
||||
#include "filterlist.h"
|
||||
|
||||
FilterList::FilterList(QObject *parent) :
|
||||
QAbstractTableModel(parent),
|
||||
selection(this)
|
||||
{
|
||||
connect(&selection, &QItemSelectionModel::currentChanged, [&] (QModelIndex i, QModelIndex) {
|
||||
emit filterSelected(at(i.row()));
|
||||
});
|
||||
}
|
||||
|
||||
int FilterList::rowCount(const QModelIndex &) const
|
||||
{
|
||||
return size();
|
||||
}
|
||||
|
||||
int FilterList::columnCount(const QModelIndex &) const
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
|
||||
QVariant FilterList::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
Filter *filter = at(index.row());
|
||||
Result *result = filter->getLastResult();
|
||||
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
case Qt::EditRole:
|
||||
switch (index.column()) {
|
||||
case 2: return filter->getName();
|
||||
case 3: return (filter->isEnabled() && result) ? result->getResult() : QVariant();
|
||||
case 4: return (filter->isEnabled()) ? QString::number(filter->getTime() * 1e-6, 'g', 3) : QVariant();
|
||||
}
|
||||
break;
|
||||
|
||||
case Qt::CheckStateRole:
|
||||
switch (index.column()) {
|
||||
case 0: return (filter->isEnabled()) ? Qt::Checked: Qt::Unchecked;
|
||||
case 1: return (filter->isShown()) ? Qt::Checked: Qt::Unchecked;
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool FilterList::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
Filter *filter = at(index.row());
|
||||
|
||||
switch (role) {
|
||||
case Qt::CheckStateRole:
|
||||
switch (index.column()) {
|
||||
case 0: filter->setEnabled(value == Qt::Checked);
|
||||
case 1: filter->setShow(value == Qt::Checked); break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
emit filtersChanged();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariant FilterList::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (role == Qt::DisplayRole) {
|
||||
if (orientation == Qt::Horizontal) {
|
||||
switch (section) {
|
||||
case 0: return QString(tr("Enabled"));
|
||||
case 1: return QString(tr("Show"));
|
||||
case 2: return QString(tr("Filter"));
|
||||
case 3: return QString(tr("Result"));
|
||||
case 4: return QString(tr("Time [mSec]"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
Qt::ItemFlags FilterList::flags(const QModelIndex &index) const
|
||||
{
|
||||
Qt::ItemFlags flags = Qt::ItemIsEnabled;
|
||||
|
||||
switch (index.column()) {
|
||||
case 0:
|
||||
case 1: flags |= Qt::ItemIsUserCheckable; break;
|
||||
case 2: flags |= Qt::ItemIsSelectable; break;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
void FilterList::add(Filter *filter)
|
||||
{
|
||||
beginInsertRows(QModelIndex(), size(), size());
|
||||
push_back(filter);
|
||||
endInsertRows();
|
||||
|
||||
connect(filter, SIGNAL(filterChanged()), this, SIGNAL(filtersChanged()));
|
||||
|
||||
emit filterAdded(filter);
|
||||
}
|
||||
|
||||
void FilterList::execute(Image *img)
|
||||
{
|
||||
img->filtered = img->original.clone();
|
||||
|
||||
try {
|
||||
for (auto filter : *this) {
|
||||
img->applyFilter(filter);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
qCritical("%s", e.msg.c_str());
|
||||
}
|
||||
|
||||
/* Update times and results */
|
||||
emit dataChanged(
|
||||
createIndex(0, 4),
|
||||
createIndex(size(), 4)
|
||||
);
|
||||
}
|
||||
|
||||
void FilterList::reset()
|
||||
{
|
||||
for (Filter *filter : *this)
|
||||
filter->reset();
|
||||
}
|
41
filterlist.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
#ifndef FILTERLIST_H
|
||||
#define FILTERLIST_H
|
||||
|
||||
#include <QAbstractTableModel>
|
||||
#include <QItemSelection>
|
||||
|
||||
#include "filters/filter.h"
|
||||
|
||||
class FilterList :
|
||||
public QAbstractTableModel,
|
||||
public QList<Filter *>
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
FilterList(QObject *parent = 0);
|
||||
|
||||
int rowCount(const QModelIndex &) const;
|
||||
int columnCount(const QModelIndex &) const;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||
Qt::ItemFlags flags(const QModelIndex & index) const;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role);
|
||||
|
||||
void add(Filter *filt);
|
||||
void execute(Image *img);
|
||||
|
||||
QItemSelectionModel selection;
|
||||
|
||||
public slots:
|
||||
void reset();
|
||||
|
||||
signals:
|
||||
void filtersChanged();
|
||||
void filterSelected(Filter *filter);
|
||||
void filterAdded(Filter *filter);
|
||||
void filterRemoved(Filter *filter);
|
||||
};
|
||||
|
||||
#endif // FILTERLIST_H
|
22
filters.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
#ifndef FILTERS_H
|
||||
#define FILTERS_H
|
||||
|
||||
#include "filters/blur.h"
|
||||
#include "filters/channel.h"
|
||||
#include "filters/convert.h"
|
||||
#include "filters/edgedetect.h"
|
||||
#include "filters/fourier.h"
|
||||
#include "filters/histequalize.h"
|
||||
#include "filters/kmeans.h"
|
||||
#include "filters/maxchannel.h"
|
||||
#include "filters/morph.h"
|
||||
#include "filters/normalize.h"
|
||||
#include "filters/pattern.h"
|
||||
#include "filters/perspective.h"
|
||||
#include "filters/shapedetect.h"
|
||||
#include "filters/threshold.h"
|
||||
#include "filters/undistort.h"
|
||||
#include "filters/watershed.h"
|
||||
|
||||
#endif // FILTERS_H
|
||||
|
55
filters/blur.cpp
Normal file
|
@ -0,0 +1,55 @@
|
|||
#include <opencv2/imgproc.hpp>
|
||||
|
||||
#include "blur.h"
|
||||
|
||||
Blur::Blur(enum Type t, Size ks, double sp, double clr, double si, int bdr) :
|
||||
type(t),
|
||||
size(ks),
|
||||
border(bdr),
|
||||
sigma(si),
|
||||
color(clr),
|
||||
space(sp)
|
||||
{
|
||||
QMap<int, QString> mapType;
|
||||
QMap<int, QString> mapBorder;
|
||||
|
||||
mapType[BILATERAL] = "Bilateral";
|
||||
//mapType[BILATERAL_ADAPTIVE] = "Adaptive Bilateral";
|
||||
mapType[BOX] = "Box";
|
||||
mapType[BOX_NORMALIZED] = "Box Normalized";
|
||||
mapType[GAUSSIAN] = "Gaussian";
|
||||
mapType[MEDIAN] = "Median";
|
||||
|
||||
mapBorder[BORDER_DEFAULT] = "Default";
|
||||
//mapBorder[BORDER_CONSTANT] = "Constant";
|
||||
//mapBorder[BORDER_REPLICATE] = "Replicate";
|
||||
mapBorder[BORDER_ISOLATED] = "Isolated";
|
||||
mapBorder[BORDER_REFLECT] = "Reflect";
|
||||
mapBorder[BORDER_REFLECT_101] = "Reflect 101";
|
||||
mapBorder[BORDER_WRAP] = "Wrap";
|
||||
|
||||
settings["Type"] = new EnumSetting(this, (int&) type, mapType);
|
||||
settings["Border"] = new EnumSetting(this, (int&) border, mapBorder);
|
||||
settings["Kernel Size"] = new SizeSetting(this, size);
|
||||
settings["Space"] = new DoubleSetting(this, space);
|
||||
settings["Color"] = new DoubleSetting(this, color);
|
||||
settings["Sigma"] = new DoubleSetting(this, sigma);
|
||||
}
|
||||
|
||||
Result * Blur::applyInternal(Image *img)
|
||||
{
|
||||
Mat m = img->filtered.clone();
|
||||
Mat &n = img->filtered;
|
||||
|
||||
switch (type) {
|
||||
case BILATERAL: bilateralFilter(m, n, -1, space, color); break;
|
||||
case BILATERAL_ADAPTIVE: break; // FIXME adaptiveBilateralFilter(m, n, size, color, space); break;
|
||||
case BOX: boxFilter(m, n, -1, size, anchor, true, border); break;
|
||||
case BOX_NORMALIZED: blur(m, n, size, anchor, border); break;
|
||||
case GAUSSIAN: GaussianBlur(m, n, size, sigma, 0, border); break;
|
||||
case MEDIAN: medianBlur(m, n, size.width); break;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
36
filters/blur.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
#ifndef BLUR_H
|
||||
#define BLUR_H
|
||||
|
||||
#include "filter.h"
|
||||
|
||||
class Blur : public Filter
|
||||
{
|
||||
public:
|
||||
enum Type {
|
||||
BILATERAL,
|
||||
BILATERAL_ADAPTIVE,
|
||||
BOX,
|
||||
BOX_NORMALIZED,
|
||||
GAUSSIAN,
|
||||
MEDIAN
|
||||
};
|
||||
|
||||
Blur(enum Type t, Size ks, double sp = 10, double clr = 20, double sigma = 2, int bdr = BORDER_DEFAULT);
|
||||
|
||||
QString getName() const { return "Blur"; }
|
||||
|
||||
protected:
|
||||
Result * applyInternal(Image *img);
|
||||
|
||||
enum Blur::Type type;
|
||||
|
||||
Size size;
|
||||
Point anchor = Point(-1, -1);
|
||||
int border;
|
||||
|
||||
double sigma;
|
||||
double color;
|
||||
double space;
|
||||
};
|
||||
|
||||
#endif // BLUR_H
|
22
filters/channel.cpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
#include <opencv2/imgproc.hpp>
|
||||
|
||||
#include "channel.h"
|
||||
|
||||
using namespace cv;
|
||||
|
||||
Channel::Channel(int ch) :
|
||||
channel(ch)
|
||||
{
|
||||
settings["Channel"] = new IntegerSetting(this, channel);
|
||||
}
|
||||
|
||||
Result * Channel::applyInternal(Image *img)
|
||||
{
|
||||
Mat channels[3];
|
||||
split(img->filtered, channels);
|
||||
|
||||
img->filtered = channels[(int) channel];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
19
filters/channel.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
#ifndef CHANNEL_H
|
||||
#define CHANNEL_H
|
||||
|
||||
#include "filter.h"
|
||||
|
||||
class Channel : public Filter
|
||||
{
|
||||
public:
|
||||
Channel(int ch);
|
||||
|
||||
QString getName() const { return "Channel"; }
|
||||
|
||||
protected:
|
||||
Result * applyInternal(Image *img);
|
||||
|
||||
int channel;
|
||||
};
|
||||
|
||||
#endif // CHANNEL_H
|
28
filters/convert.cpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
#include "convert.h"
|
||||
|
||||
Convert::Convert(int c) :
|
||||
Filter(),
|
||||
code(c)
|
||||
{
|
||||
QMap<int, QString> mapCode;
|
||||
mapCode[COLOR_BGR2HSV] = "BGR to HSV";
|
||||
mapCode[COLOR_BGR2GRAY] = "BGR to Gray";
|
||||
mapCode[COLOR_BGR2Lab] = "BGR to Lab";
|
||||
mapCode[COLOR_BGR2Luv] = "BGR to Luv";
|
||||
mapCode[COLOR_BGR2HLS] = "BGR to HLS";
|
||||
mapCode[COLOR_BGR2YUV] = "BGR to YUV";
|
||||
mapCode[COLOR_BGR2YCrCb]= "BGR to YCrCb";
|
||||
// FIXME add more codes
|
||||
|
||||
settings["Code"] = new EnumSetting(this, code, mapCode);
|
||||
}
|
||||
|
||||
Result * Convert::applyInternal(Image *img)
|
||||
{
|
||||
Mat dest;
|
||||
cvtColor(img->filtered, dest, code);
|
||||
img->filtered = dest;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
19
filters/convert.h
Normal file
|
@ -0,0 +1,19 @@
|
|||
#ifndef CONVERT_H
|
||||
#define CONVERT_H
|
||||
|
||||
#include "filter.h"
|
||||
|
||||
class Convert : public Filter
|
||||
{
|
||||
public:
|
||||
Convert(int code);
|
||||
|
||||
QString getName() const { return "Convert"; }
|
||||
|
||||
protected:
|
||||
Result * applyInternal(Image *img);
|
||||
|
||||
int code;
|
||||
};
|
||||
|
||||
#endif // CONVERT_H
|
19
filters/edgedetect.cpp
Normal file
|
@ -0,0 +1,19 @@
|
|||
#include "edgedetect.h"
|
||||
|
||||
#include <opencv2/imgproc.hpp>
|
||||
|
||||
EdgeDetect::EdgeDetect(double t, double r) :
|
||||
threshold(t),
|
||||
ratio(r)
|
||||
{
|
||||
settings["Threshold"] = new DoubleSetting(this, threshold);
|
||||
settings["Ratio"] = new DoubleSetting(this, ratio);
|
||||
}
|
||||
|
||||
Result * EdgeDetect::applyInternal(Image *img)
|
||||
{
|
||||
Canny(img->filtered, img->filtered, threshold, threshold * ratio);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
20
filters/edgedetect.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
#ifndef EDGEDETECT_H
|
||||
#define EDGEDETECT_H
|
||||
|
||||
#include "filter.h"
|
||||
|
||||
class EdgeDetect : public Filter
|
||||
{
|
||||
public:
|
||||
EdgeDetect(double t, double r);
|
||||
|
||||
QString getName() const { return "EdgeDetect"; }
|
||||
|
||||
protected:
|
||||
Result * applyInternal(Image *img);
|
||||
|
||||
double threshold;
|
||||
double ratio;
|
||||
};
|
||||
|
||||
#endif // EDGEDETECT_H
|
40
filters/filter.cpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
#include <QElapsedTimer>
|
||||
#include <QFormLayout>
|
||||
|
||||
#include "cast.h"
|
||||
#include "filter.h"
|
||||
|
||||
using namespace cv;
|
||||
|
||||
Filter::~Filter()
|
||||
{
|
||||
delete widget;
|
||||
}
|
||||
|
||||
QWidget * Filter::getWidget(QWidget *parent)
|
||||
{
|
||||
if (!widget) {
|
||||
widget = new QWidget(parent);
|
||||
|
||||
QFormLayout *layout = new QFormLayout(widget);
|
||||
layout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
|
||||
|
||||
for (QString key : settings.keys())
|
||||
layout->addRow(key, settings[key]->getWidget(widget));
|
||||
}
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
Result * Filter::apply(Image *img)
|
||||
{
|
||||
QElapsedTimer timer;
|
||||
|
||||
if (enabled) {
|
||||
timer.start();
|
||||
result = applyInternal(img); /* Virtual call */
|
||||
time = timer.nsecsElapsed();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
57
filters/filter.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
#ifndef FILTER_H
|
||||
#define FILTER_H
|
||||
|
||||
#include <string>
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
#include <QVector>
|
||||
#include <QPainter>
|
||||
#include <QWidget>
|
||||
|
||||
#include "painter.h"
|
||||
#include "image.h"
|
||||
#include "result.h"
|
||||
#include "setting.h"
|
||||
|
||||
using namespace cv;
|
||||
|
||||
class Filter : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
virtual ~Filter();
|
||||
|
||||
Result * apply(Image *img);
|
||||
|
||||
QWidget * getWidget(QWidget *parent = 0);
|
||||
|
||||
/* Setter */
|
||||
void setEnabled(bool e) { enabled = e; }
|
||||
void setShow(bool s) { show = s; }
|
||||
|
||||
/* Getter */
|
||||
bool isEnabled() const { return enabled; }
|
||||
bool isShown() const { return show; }
|
||||
long getTime() const { return time; }
|
||||
Result * getLastResult() const { return result; }
|
||||
virtual QString getName() const = 0;
|
||||
|
||||
public slots:
|
||||
virtual void reset() { }
|
||||
|
||||
signals:
|
||||
void filterChanged();
|
||||
|
||||
protected:
|
||||
bool enabled = true;
|
||||
bool show = true;
|
||||
long time = 0; /* in uSecs */
|
||||
|
||||
Result *result = NULL;
|
||||
QWidget *widget = NULL;
|
||||
QMap<QString, Setting*> settings;
|
||||
virtual Result * applyInternal(Image *img) = 0;
|
||||
};
|
||||
|
||||
#endif // FILTER_H
|
14
filters/fourier.h
Normal file
|
@ -0,0 +1,14 @@
|
|||
#ifndef FOURIER_H
|
||||
#define FOURIER_H
|
||||
|
||||
#include "filter.h"
|
||||
|
||||
class Fourier : public Filter
|
||||
{
|
||||
public:
|
||||
void apply(Image *img);
|
||||
|
||||
QString getName() const { return "Fourier"; }
|
||||
};
|
||||
|
||||
#endif // FOURIER_H
|
8
filters/histequalize.cpp
Normal file
|
@ -0,0 +1,8 @@
|
|||
#include "histequalize.h"
|
||||
|
||||
Result * HistEqualize::applyInternal(Image *img)
|
||||
{
|
||||
equalizeHist(img->filtered, img->filtered);
|
||||
|
||||
return NULL;
|
||||
}
|
16
filters/histequalize.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#ifndef HISTEQUALIZE_H
|
||||
#define HISTEQUALIZE_H
|
||||
|
||||
#include "filter.h"
|
||||
|
||||
class HistEqualize : public Filter
|
||||
{
|
||||
public:
|
||||
QString getName() const { return "HistEqualize"; }
|
||||
|
||||
protected:
|
||||
Result * applyInternal(Image *img);
|
||||
|
||||
};
|
||||
|
||||
#endif // HISTEQUALIZE_H
|
60
filters/kmeans.cpp
Normal file
|
@ -0,0 +1,60 @@
|
|||
#include <QtDebug>
|
||||
|
||||
#include "kmeans.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
KMeans::KMeans(int km) :
|
||||
k(km),
|
||||
low(0),
|
||||
high(k)
|
||||
{
|
||||
settings["K"] = new IntegerSetting(this, k, 1, 2*k);
|
||||
settings["Low"] = new IntegerSetting(this, low, 0, 2*k-1,
|
||||
"Only set pixels with a label higher or equal to this value.");
|
||||
settings["High"] = new IntegerSetting(this, high, 0, 2*k,
|
||||
"Only set Pixels with a label lower or equal to this value.");
|
||||
}
|
||||
|
||||
void KMeans::reset()
|
||||
{
|
||||
labels.release();
|
||||
}
|
||||
|
||||
Result * KMeans::applyInternal(Image *img)
|
||||
{
|
||||
Mat m = img->filtered.clone();
|
||||
Mat reshaped_image, reshaped_image32f;
|
||||
Mat centers, centers_u8;
|
||||
int flags = KMEANS_RANDOM_CENTERS; //KMEANS_PP_CENTERS;
|
||||
|
||||
TermCriteria criteria = TermCriteria(TermCriteria::COUNT | TermCriteria::EPS, 4, 0.1);
|
||||
|
||||
reshaped_image = m.reshape(1, m.cols * m.rows);
|
||||
reshaped_image.convertTo(reshaped_image32f, CV_32FC1, 1.0 / 255.0);
|
||||
|
||||
if (labels.data)
|
||||
flags |= KMEANS_USE_INITIAL_LABELS;
|
||||
|
||||
kmeans(reshaped_image32f, k, labels, criteria, 1, flags, centers);
|
||||
|
||||
MatIterator_<Vec3b> first = img->filtered.begin<Vec3b>();
|
||||
MatIterator_<Vec3b> last = img->filtered.end<Vec3b>();
|
||||
MatConstIterator_<int> label = labels.begin<int>();
|
||||
|
||||
centers.convertTo(centers_u8, CV_8UC1, 255.0);
|
||||
Mat centers_u8c3 = centers_u8.reshape(3);
|
||||
|
||||
while (first != last) {
|
||||
if (*label >= low && *label <= high)
|
||||
*first = centers_u8c3.ptr<Vec3b>(*label)[0];
|
||||
else
|
||||
*first = Vec3b(0, 0, 0);
|
||||
|
||||
++first;
|
||||
++label;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
26
filters/kmeans.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
#ifndef KMEANS_H
|
||||
#define KMEANS_H
|
||||
|
||||
#include "filter.h"
|
||||
|
||||
class KMeans : public Filter
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
KMeans(int k);
|
||||
|
||||
QString getName() const { return "KMeans"; }
|
||||
|
||||
public slots:
|
||||
void reset();
|
||||
|
||||
protected:
|
||||
Result * applyInternal(Image *img);
|
||||
|
||||
int k;
|
||||
int low, high;
|
||||
Mat labels;
|
||||
};
|
||||
|
||||
#endif // KMEANS_H
|
20
filters/maxchannel.cpp
Normal file
|
@ -0,0 +1,20 @@
|
|||
#include "maxchannel.h"
|
||||
|
||||
Result * MaxChannel::applyInternal(Image *img)
|
||||
{
|
||||
Mat &m = img->filtered;
|
||||
|
||||
CV_Assert(m.type() == CV_8UC3);
|
||||
|
||||
for(int i = 0; i < m.rows; i++) {
|
||||
uchar *p = m.ptr<uchar>(i);
|
||||
for (int j = 0; j < 3*m.cols; j += 3) {
|
||||
p[j] = (p[j ] > p[j+1] && p[j ] > p[j+2]) ? 0xff : 0;
|
||||
p[j+1] = (p[j+1] > p[j ] && p[j+1] > p[j+2]) ? 0xff : 0;
|
||||
p[j+2] = (p[j+2] > p[j ] && p[j+2] > p[j+2]) ? 0xff : 0;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
15
filters/maxchannel.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
#ifndef MAXCHANNEL_H
|
||||
#define MAXCHANNEL_H
|
||||
|
||||
#include "filter.h"
|
||||
|
||||
class MaxChannel : public Filter
|
||||
{
|
||||
public:
|
||||
Result * applyInternal(Image *img);
|
||||
|
||||
QString getName() const { return "MaxChannel"; }
|
||||
|
||||
};
|
||||
|
||||
#endif // MAXCHANNEL_H
|
54
filters/morph.cpp
Normal file
|
@ -0,0 +1,54 @@
|
|||
#include "morph.h"
|
||||
|
||||
Morph::Morph(int o, int t, Size s, Point a, int i) :
|
||||
op(o),
|
||||
shape(t),
|
||||
iterations(i),
|
||||
size(s),
|
||||
anchor(a)
|
||||
{
|
||||
QMap<int, QString> mapOp;
|
||||
QMap<int, QString> mapShape;
|
||||
|
||||
mapOp[MORPH_OPEN] = "Open";
|
||||
mapOp[MORPH_CLOSE] = "Close";
|
||||
mapOp[MORPH_ERODE] = "Erode";
|
||||
mapOp[MORPH_DILATE] = "Dilate";
|
||||
mapOp[MORPH_BLACKHAT] = "Blackhat";
|
||||
mapOp[MORPH_GRADIENT] = "Gradient";
|
||||
|
||||
mapShape[MORPH_RECT] = "Rectangle";
|
||||
mapShape[MORPH_ELLIPSE] = "Ellipse";
|
||||
mapShape[MORPH_CROSS] = "Cross";
|
||||
|
||||
settings["Iterations"] = new IntegerSetting(this, iterations);
|
||||
settings["Operation"] = new EnumSetting(this, op, mapOp);
|
||||
settings["Shape"] = new EnumSetting(this, shape, mapShape);
|
||||
settings["Size"] = new SizeSetting(this, size, 1);
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
void Morph::reset()
|
||||
{
|
||||
kernel = getStructuringElement(shape, size);
|
||||
}
|
||||
|
||||
Result * Morph::applyInternal(Image *img)
|
||||
{
|
||||
Mat &m = img->filtered;
|
||||
|
||||
switch (op) {
|
||||
case MORPH_DILATE: dilate(m, m, kernel, anchor, iterations); break;
|
||||
case MORPH_ERODE: erode(m, m, kernel, anchor, iterations); break;
|
||||
case MORPH_OPEN:
|
||||
case MORPH_CLOSE:
|
||||
case MORPH_BLACKHAT:
|
||||
case MORPH_GRADIENT:
|
||||
morphologyEx(m, m, op, kernel, anchor, iterations); break;
|
||||
default:
|
||||
CV_Error(100, "Invalid morph operation");
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
27
filters/morph.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
#ifndef MORPH_H
|
||||
#define MORPH_H
|
||||
|
||||
#include "filter.h"
|
||||
|
||||
class Morph : public Filter
|
||||
{
|
||||
public:
|
||||
Morph(int op, int shape, Size size = Size(3, 3), Point anchor = Point(-1, -1), int iterations = 1);
|
||||
QString getName() const { return "Morph"; }
|
||||
|
||||
public slots:
|
||||
void reset();
|
||||
|
||||
protected:
|
||||
Result * applyInternal(Image *img);
|
||||
|
||||
Mat kernel;
|
||||
|
||||
int op;
|
||||
int shape;
|
||||
int iterations;
|
||||
Size size;
|
||||
Point anchor;
|
||||
};
|
||||
|
||||
#endif // MORPH_H
|
22
filters/normalize.cpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
#include "normalize.h"
|
||||
|
||||
Result * Normalize::applyInternal(Image *img)
|
||||
{
|
||||
Mat &m = img->filtered;
|
||||
|
||||
CV_Assert(m.type() == CV_8UC3);
|
||||
|
||||
for(int i = 0; i < m.rows; i++) {
|
||||
uchar *p = m.ptr<uchar>(i);
|
||||
for (int j = 0; j < 3*m.cols; j += 3) {
|
||||
|
||||
double s = 255.0 / (p[j] + p[j+1] + p[j+2]);
|
||||
|
||||
p[j] *= s;
|
||||
p[j+1] *= s;
|
||||
p[j+2] *= s;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
13
filters/normalize.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
#ifndef NORMALIZE_H
|
||||
#define NORMALIZE_H
|
||||
|
||||
#include "filter.h"
|
||||
|
||||
class Normalize : public Filter
|
||||
{
|
||||
public:
|
||||
Result * applyInternal(Image *img);
|
||||
QString getName() const { return "Normalize"; }
|
||||
};
|
||||
|
||||
#endif // NORMALIZE_H
|
7
filters/padfilter.cpp
Normal file
|
@ -0,0 +1,7 @@
|
|||
#include "padfilter.h"
|
||||
|
||||
Result * PadFilter::applyInternal(Image *)
|
||||
{
|
||||
|
||||
return NULL;
|
||||
}
|
16
filters/padfilter.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#ifndef PADFILTER_H
|
||||
#define PADFILTER_H
|
||||
|
||||
#include "filter.h"
|
||||
|
||||
class PadFilter : public Filter
|
||||
{
|
||||
public:
|
||||
QString getName() const { return "PadFilter"; };
|
||||
|
||||
protected:
|
||||
Result * applyInternal(Image *img);
|
||||
|
||||
};
|
||||
|
||||
#endif // PADFILTER_H
|
121
filters/pattern.cpp
Normal file
|
@ -0,0 +1,121 @@
|
|||
#include <opencv2/imgproc.hpp>
|
||||
|
||||
#include <QPainter>
|
||||
#include <QtDebug>
|
||||
|
||||
#include "cast.h"
|
||||
#include "pattern.h"
|
||||
#include "image.h"
|
||||
#include "convert.h"
|
||||
|
||||
Pattern::Pattern(Size si, double sp, Type t) :
|
||||
type(t),
|
||||
size(si),
|
||||
spacing(sp)
|
||||
{
|
||||
//QMap<int, QString> mapType
|
||||
|
||||
settings["Size"] = new SizeSetting(this, size, 1, 20);
|
||||
settings["Spacing"] = new DoubleSetting(this, spacing, 1e-3, 1e2);
|
||||
//settings["Type"] = new EnumSetting(this, type, mapType);
|
||||
|
||||
}
|
||||
|
||||
Result * Pattern::applyInternal(Image *img)
|
||||
{
|
||||
bool found;
|
||||
std::vector<Point2f> points;
|
||||
|
||||
Mat gray;
|
||||
if (img->original.channels() > 1)
|
||||
cvtColor(img->original, gray, COLOR_RGB2GRAY);
|
||||
else
|
||||
gray = img->original;
|
||||
|
||||
switch(type) {
|
||||
case CHESSBOARD:
|
||||
found = findChessboardCorners(gray, size, points, flags);
|
||||
if(found) {
|
||||
cornerSubPix(gray, points, Size(11, 11), Size(-1, -1),
|
||||
TermCriteria(TermCriteria::EPS + TermCriteria::MAX_ITER, 30, 0.1));
|
||||
}
|
||||
break;
|
||||
|
||||
case CIRCLES_GRID:
|
||||
found = findCirclesGrid(gray, size, points);
|
||||
break;
|
||||
|
||||
case ASYMMETRIC_CIRCLES_GRID:
|
||||
found = findCirclesGrid(gray, size, points, CALIB_CB_ASYMMETRIC_GRID);
|
||||
break;
|
||||
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return new PatternResult(found, points);
|
||||
}
|
||||
|
||||
|
||||
std::vector<Point3f> Pattern::getPoints() const
|
||||
{
|
||||
std::vector<Point3f> points;
|
||||
|
||||
switch(type) {
|
||||
case CHESSBOARD:
|
||||
case CIRCLES_GRID:
|
||||
for (int i = 0; i < size.height; ++i) {
|
||||
for (int j = 0; j < size.width; ++j)
|
||||
points.push_back(Point3f(j*spacing, i*spacing, 0));
|
||||
}
|
||||
break;
|
||||
|
||||
case ASYMMETRIC_CIRCLES_GRID:
|
||||
for (int i = 0; i < size.height; i++) {
|
||||
for (int j = 0; j < size.width; j++)
|
||||
points.push_back(Point3f((2*j+i%2)*spacing, i*spacing, 0));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return points;
|
||||
}
|
||||
|
||||
std::vector<int> Pattern::getCornerIndizes() const
|
||||
{
|
||||
return {
|
||||
0,
|
||||
size.width - 1,
|
||||
size.width * size.height - size.width,
|
||||
size.width * size.height - 1
|
||||
};
|
||||
}
|
||||
|
||||
PatternResult::PatternResult(bool f, std::vector<Point2f> p) :
|
||||
found(f),
|
||||
points(p)
|
||||
{ }
|
||||
|
||||
void PatternResult::draw(Painter *p) const
|
||||
{
|
||||
QPen pen = p->pen();
|
||||
|
||||
for (unsigned i = 0; i < points.size(); i++) {
|
||||
QColor clr = found ? QColor::fromHsl(360.0 / points.size() * i, 255, 128) : Qt::gray;
|
||||
|
||||
pen.setColor(clr);
|
||||
p->setPen(pen);
|
||||
p->drawMarker(toQt((Point2i) points[i]));
|
||||
|
||||
if (i != 0)
|
||||
p->drawLine(toQt((Point2i) points[i-1]), toQt((Point2i) points[i]));
|
||||
}
|
||||
}
|
||||
|
||||
QString PatternResult::getResult() const
|
||||
{
|
||||
return QString("found = %1, points = %2").arg(found).arg(points.size());
|
||||
}
|
57
filters/pattern.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
#ifndef PATTERN_H
|
||||
#define PATTERN_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/calib3d.hpp>
|
||||
|
||||
#include "filter.h"
|
||||
|
||||
using namespace cv;
|
||||
|
||||
class Image;
|
||||
class PatternResult;
|
||||
|
||||
class Pattern : public Filter
|
||||
{
|
||||
public:
|
||||
enum Type {
|
||||
CHESSBOARD,
|
||||
CIRCLES_GRID,
|
||||
ASYMMETRIC_CIRCLES_GRID
|
||||
} type;
|
||||
|
||||
Pattern(Size si, double sp, Type t = Type::CHESSBOARD);
|
||||
|
||||
Result * applyInternal(Image *img);
|
||||
|
||||
/* Getter */
|
||||
QString getName() const { return "Pattern"; }
|
||||
std::vector<int> getCornerIndizes() const;
|
||||
std::vector<Point3f> getPoints() const;
|
||||
|
||||
protected:
|
||||
Size size;
|
||||
int flags = CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE + CALIB_CB_FAST_CHECK;
|
||||
double spacing;
|
||||
};
|
||||
|
||||
class PatternResult : public Result
|
||||
{
|
||||
public:
|
||||
PatternResult(bool found, std::vector<Point2f> op);
|
||||
|
||||
void draw(Painter *p) const;
|
||||
QString getResult() const;
|
||||
|
||||
/* Getter */
|
||||
std::vector<Point2f> getPoints() const { return points; }
|
||||
bool isFound() const { return found; }
|
||||
|
||||
protected:
|
||||
bool found;
|
||||
std::vector<Point2f> points;
|
||||
};
|
||||
|
||||
#endif // PATTERN_H
|
42
filters/perspective.cpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
#include <opencv2/imgproc.hpp>
|
||||
|
||||
#include <QtDebug>
|
||||
|
||||
#include "cast.h"
|
||||
#include "perspective.h"
|
||||
|
||||
Perspective::Perspective(Camera *c, Pattern *p) :
|
||||
cam(c),
|
||||
pattern(p)
|
||||
{ }
|
||||
|
||||
Result * Perspective::applyInternal(Image *img)
|
||||
{
|
||||
Mat &m = img->filtered;
|
||||
PatternResult *presult = (PatternResult *) img->getResult(pattern);
|
||||
|
||||
if (presult->isFound()) {
|
||||
std::vector<Point2f> src, dest, tmp;
|
||||
std::vector<Point2f> srcPoints = presult->getPoints();
|
||||
std::vector<Point3f> destPoints = pattern->getPoints();
|
||||
|
||||
for (int i : pattern->getCornerIndizes()) {
|
||||
src.push_back(srcPoints[i]);
|
||||
tmp.push_back(Point2f(destPoints[i].x, destPoints[i].y));
|
||||
}
|
||||
|
||||
int destWidth = 0.75 * m.cols;
|
||||
int destHeight = tmp[2].y * (destWidth / tmp[1].x);
|
||||
|
||||
dest.push_back( Point2f((m.cols - destWidth) / 2, (m.rows - destHeight) / 2) );
|
||||
dest.push_back( dest[0] + Point2f(destWidth, 0) );
|
||||
dest.push_back( dest[0] + Point2f(0, destHeight) );
|
||||
dest.push_back( dest[0] + Point2f(destWidth, destHeight) );
|
||||
|
||||
map = getPerspectiveTransform(src, dest);
|
||||
warpPerspective(img->filtered, img->filtered, map, img->filtered.size());
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
22
filters/perspective.h
Normal file
|
@ -0,0 +1,22 @@
|
|||
#ifndef PERSPECTIVE_H
|
||||
#define PERSPECTIVE_H
|
||||
|
||||
#include "pattern.h"
|
||||
#include "filter.h"
|
||||
|
||||
class Perspective : public Filter
|
||||
{
|
||||
public:
|
||||
Perspective(Camera *cam, Pattern *p);
|
||||
|
||||
QString getName() const { return "Perspective"; }
|
||||
|
||||
protected:
|
||||
Result * applyInternal(Image *img);
|
||||
|
||||
Mat map;
|
||||
Camera *cam;
|
||||
Pattern *pattern;
|
||||
};
|
||||
|
||||
#endif // PERSPECTIVE_H
|
3
filters/result.cpp
Normal file
|
@ -0,0 +1,3 @@
|
|||
#include "result.h"
|
||||
|
||||
|
51
filters/result.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
#ifndef RESULT_H
|
||||
#define RESULT_H
|
||||
|
||||
#include <QString>
|
||||
|
||||
class Painter;
|
||||
|
||||
class Result
|
||||
{
|
||||
public:
|
||||
virtual ~Result() { };
|
||||
|
||||
virtual void draw(Painter *) const { };
|
||||
virtual QString getResult() const = 0;
|
||||
};
|
||||
|
||||
class IntegerResult : public Result
|
||||
{
|
||||
public:
|
||||
IntegerResult(QString n, int v) :
|
||||
name(n),
|
||||
value(v)
|
||||
{ }
|
||||
|
||||
QString getResult() const {
|
||||
return QString("%1 = %2").arg(name).arg(value);
|
||||
}
|
||||
|
||||
protected:
|
||||
QString name;
|
||||
int value;
|
||||
};
|
||||
|
||||
class DoubleResult : public Result
|
||||
{
|
||||
public:
|
||||
DoubleResult(QString n, double v) :
|
||||
name(n),
|
||||
value(v)
|
||||
{ }
|
||||
|
||||
QString getResult() const {
|
||||
return QString("%1 = %2").arg(name).arg(value);
|
||||
}
|
||||
|
||||
protected:
|
||||
QString name;
|
||||
double value;
|
||||
};
|
||||
|
||||
#endif // RESULT_H
|
150
filters/setting.cpp
Normal file
|
@ -0,0 +1,150 @@
|
|||
#include <QLayout>
|
||||
#include <QtDebug>
|
||||
#include <QLabel>
|
||||
|
||||
#include "ui_doublesetting.h"
|
||||
#include "setting.h"
|
||||
#include "viewer.h"
|
||||
#include "filter.h"
|
||||
|
||||
Setting::Setting(Filter *f, QString tip)
|
||||
: toolTip(tip)
|
||||
{
|
||||
connect(this, SIGNAL(valueChanged()), f, SIGNAL(filterChanged()));
|
||||
connect(this, SIGNAL(valueChanged()), f, SLOT(reset()));
|
||||
}
|
||||
|
||||
QWidget * Setting::getWidget(QWidget *parent)
|
||||
{
|
||||
if (!widget)
|
||||
widget = createWidget(parent);
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
QWidget * BooleanSetting::createWidget(QWidget *parent)
|
||||
{
|
||||
box = new QCheckBox(parent);
|
||||
|
||||
connect(box, static_cast<void (QCheckBox::*)(bool)>(&QCheckBox::clicked), [&](bool v) {
|
||||
value = v;
|
||||
emit valueChanged();
|
||||
});
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
QWidget * IntegerSetting::createWidget(QWidget *parent)
|
||||
{
|
||||
QWidget *widget = new QWidget(parent);
|
||||
QHBoxLayout *layout = new QHBoxLayout(widget);
|
||||
|
||||
slider = new QSlider(Qt::Horizontal, widget);
|
||||
spinner = new QSpinBox(widget);
|
||||
|
||||
widget->setToolTip(toolTip);
|
||||
layout->setMargin(0);
|
||||
layout->addWidget(slider);
|
||||
layout->addWidget(spinner);
|
||||
spinner->setValue(value);
|
||||
slider->setValue(value);
|
||||
slider->setMinimum(min);
|
||||
slider->setMaximum(max);
|
||||
slider->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||
|
||||
connect(slider, static_cast<void (QSlider::*)(int)>(&QSlider::valueChanged), [&](int v) {
|
||||
value = v;
|
||||
spinner->setValue(v);
|
||||
emit valueChanged();
|
||||
});
|
||||
connect(spinner, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [&](int v) {
|
||||
value = v;
|
||||
slider->setValue(value);
|
||||
emit valueChanged();
|
||||
});
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
QWidget * DoubleSetting::createWidget(QWidget *parent)
|
||||
{
|
||||
QWidget *widget = new QWidget(parent);
|
||||
QHBoxLayout *layout = new QHBoxLayout(widget);
|
||||
|
||||
slider = new QSlider(Qt::Horizontal, widget);
|
||||
spinner = new QDoubleSpinBox(widget);
|
||||
|
||||
widget->setToolTip(toolTip);
|
||||
layout->setMargin(0);
|
||||
layout->addWidget(slider);
|
||||
layout->addWidget(spinner);
|
||||
layout->setMargin(0);
|
||||
spinner->setValue(value);
|
||||
slider->setValue(value * SCALE);
|
||||
slider->setMinimum(min * SCALE);
|
||||
slider->setMaximum(max * SCALE);
|
||||
slider->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||
|
||||
connect(slider, static_cast<void (QSlider::*)(int)>(&QSlider::valueChanged), [&](int v) {
|
||||
value = (double) v / SCALE;
|
||||
spinner->setValue(value);
|
||||
emit valueChanged();
|
||||
});
|
||||
connect(spinner, static_cast<void (QDoubleSpinBox::*)(double)>(&QDoubleSpinBox::valueChanged), [&](double v) {
|
||||
value = v;
|
||||
slider->setValue(value * SCALE);
|
||||
emit valueChanged();
|
||||
});
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
QWidget * EnumSetting::createWidget(QWidget *parent)
|
||||
{
|
||||
QComboBox *combo = new QComboBox(parent);
|
||||
|
||||
for (int key : map.keys())
|
||||
combo->addItem(map.value(key), QVariant(key));
|
||||
|
||||
combo->setCurrentText(map[value]);
|
||||
combo->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||
|
||||
connect(combo, &QComboBox::currentTextChanged, [&](QString v) {
|
||||
value = map.key(v, map.keys().first());
|
||||
emit valueChanged();
|
||||
});
|
||||
|
||||
return combo;
|
||||
}
|
||||
|
||||
QWidget * SizeSetting::createWidget(QWidget *parent)
|
||||
{
|
||||
QWidget *widget = new QWidget(parent);
|
||||
QHBoxLayout *layout = new QHBoxLayout(widget);
|
||||
QLabel *lblX = new QLabel("x", widget);
|
||||
|
||||
spinnerH = new QSpinBox(widget);
|
||||
spinnerW = new QSpinBox(widget);
|
||||
|
||||
layout->setMargin(0);
|
||||
layout->addWidget(spinnerW);
|
||||
layout->addWidget(lblX);
|
||||
layout->addWidget(spinnerH);
|
||||
spinnerH->setValue(value.height);
|
||||
spinnerW->setValue(value.width);
|
||||
spinnerH->setMinimum(min);
|
||||
spinnerH->setMaximum(max);
|
||||
spinnerW->setMinimum(min);
|
||||
spinnerW->setMaximum(max);
|
||||
|
||||
connect(spinnerH, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [&](int v) {
|
||||
value.height = v;
|
||||
emit valueChanged();
|
||||
});
|
||||
connect(spinnerW, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [&](int v) {
|
||||
value.width = v;
|
||||
emit valueChanged();
|
||||
});
|
||||
|
||||
return widget;
|
||||
}
|
118
filters/setting.h
Normal file
|
@ -0,0 +1,118 @@
|
|||
#ifndef SETTING_H
|
||||
#define SETTING_H
|
||||
|
||||
#include <QSpinBox>
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QSlider>
|
||||
#include <QComboBox>
|
||||
#include <QCheckBox>
|
||||
#include <QMap>
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
using namespace cv;
|
||||
|
||||
class Filter;
|
||||
|
||||
class Setting : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Setting(Filter *f, QString tip);
|
||||
QWidget * getWidget(QWidget *parent);
|
||||
|
||||
signals:
|
||||
void valueChanged();
|
||||
|
||||
protected:
|
||||
virtual QWidget * createWidget(QWidget *parent) = 0;
|
||||
|
||||
Filter *filter;
|
||||
QWidget *widget = NULL;
|
||||
QString toolTip;
|
||||
};
|
||||
|
||||
class IntegerSetting : public Setting
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
IntegerSetting(Filter *f, int &v, int mi = 0, int ma = 100, QString tip = "") :
|
||||
Setting(f, tip), value(v), min(mi), max(ma) { }
|
||||
|
||||
protected:
|
||||
QWidget * createWidget(QWidget *parent = 0);
|
||||
|
||||
int &value, min, max;
|
||||
QSpinBox *spinner;
|
||||
QSlider *slider;
|
||||
};
|
||||
|
||||
class BooleanSetting : public Setting
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
BooleanSetting(Filter *f, bool &v, QString tip = "") :
|
||||
Setting(f, tip), value(v) { }
|
||||
|
||||
protected:
|
||||
QWidget *createWidget(QWidget *parent);
|
||||
|
||||
bool &value;
|
||||
QCheckBox *box;
|
||||
};
|
||||
|
||||
class DoubleSetting : public Setting
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
DoubleSetting(Filter *f, double &v, double mi = 0, double ma = 100, QString tip = "") :
|
||||
Setting(f, tip), value(v), min(mi), max(ma) { }
|
||||
|
||||
protected:
|
||||
static const int SCALE = 1000;
|
||||
|
||||
QWidget * createWidget(QWidget *parent = 0);
|
||||
|
||||
double &value, min, max;
|
||||
QDoubleSpinBox *spinner;
|
||||
QSlider *slider;
|
||||
};
|
||||
|
||||
class EnumSetting : public Setting
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
EnumSetting(Filter *f, int &v, QMap<int, QString> m, QString tip = "") :
|
||||
Setting(f, tip), value(v), map(m) { }
|
||||
|
||||
protected:
|
||||
QWidget * createWidget(QWidget *parent);
|
||||
|
||||
int &value;
|
||||
QMap<int, QString> map;
|
||||
QComboBox *combo;
|
||||
};
|
||||
|
||||
class SizeSetting : public Setting
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
SizeSetting(Filter *f, Size &v, int mi = 1, int ma = 100, QString tip = "") :
|
||||
Setting(f, tip), value(v), min(mi), max(ma) { }
|
||||
|
||||
protected:
|
||||
QWidget * createWidget(QWidget *parent);
|
||||
|
||||
Size &value;
|
||||
int min, max;
|
||||
|
||||
QSpinBox *spinnerH, *spinnerW;
|
||||
};
|
||||
|
||||
#endif // SETTING_H
|
113
filters/shapedetect.cpp
Normal file
|
@ -0,0 +1,113 @@
|
|||
#include "cast.h"
|
||||
#include "shapedetect.h"
|
||||
|
||||
static double angle(Point pt1, Point pt2, Point pt0)
|
||||
{
|
||||
double dx1 = pt1.x - pt0.x;
|
||||
double dy1 = pt1.y - pt0.y;
|
||||
double dx2 = pt2.x - pt0.x;
|
||||
double dy2 = pt2.y - pt0.y;
|
||||
|
||||
return (dx1*dx2 + dy1*dy2)/sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
|
||||
}
|
||||
|
||||
static double area(RotatedRect rect)
|
||||
{
|
||||
Point2f p[4];
|
||||
rect.points(p);
|
||||
|
||||
double dxa = p[0].x - p[1].x;
|
||||
double dya = p[0].y - p[1].y;
|
||||
double dxb = p[1].x - p[2].x;
|
||||
double dyb = p[2].y - p[2].y;
|
||||
|
||||
return sqrt( (dxa*dxa + dya*dya) * (dxb*dxb + dyb*dyb) );
|
||||
}
|
||||
|
||||
ShapeDetect::ShapeDetect(double e, double cos) :
|
||||
epsilon(e),
|
||||
cosine(cos)
|
||||
{
|
||||
QMap<int, QString> mapMode;
|
||||
mapMode[AREA] = "Area";
|
||||
mapMode[COSINE] = "Cosine";
|
||||
|
||||
settings["Mode"] = new EnumSetting(this, (int&) mode, mapMode);
|
||||
settings["Epsilon"] = new DoubleSetting(this, epsilon, 0, 1);
|
||||
settings["Cosine"] = new DoubleSetting(this, cosine, 0, 1);
|
||||
settings["Shape no"]= new IntegerSetting(this, shape, 0, 1000);
|
||||
}
|
||||
|
||||
Result * ShapeDetect::applyInternal(Image *img)
|
||||
{
|
||||
Mat &m = img->filtered;
|
||||
int i = 0;
|
||||
|
||||
std::vector<std::vector<Point>> contours;
|
||||
ShapeResult *result = new ShapeResult;
|
||||
|
||||
findContours(m.clone(), contours, RETR_LIST, CHAIN_APPROX_SIMPLE);
|
||||
|
||||
for (std::vector<Point> contour : contours) {
|
||||
//std::vector<Point> contour = contours[shape];
|
||||
|
||||
std::vector<Point> approx;
|
||||
bool closed = isContourConvex(contour);
|
||||
double arc = arcLength(contour, closed);
|
||||
|
||||
approxPolyDP(contour, approx, epsilon * arc, closed);
|
||||
|
||||
switch (approx.size()) {
|
||||
case 4:
|
||||
if (mode == ShapeDetect::COSINE) {
|
||||
double maxCosine = 0;
|
||||
|
||||
for (int j = 2; j < 5; j++) {
|
||||
double cosine = fabs(angle(approx[j%4], approx[j-2], approx[j-1]));
|
||||
maxCosine = std::max(maxCosine, cosine);
|
||||
}
|
||||
|
||||
if (maxCosine < cosine) {
|
||||
RotatedRect rect = minAreaRect(approx);
|
||||
//RotatedRect rect = minAreaRect(contour);
|
||||
if (i++ == shape)
|
||||
result->rects.push_back(rect);
|
||||
}
|
||||
}
|
||||
else if (mode == ShapeDetect::AREA) {
|
||||
RotatedRect rect = minAreaRect(contour);
|
||||
|
||||
double areaContour = contourArea(contour);
|
||||
double areaRect = area(rect);
|
||||
|
||||
if (areaContour / areaRect > epsilon) {
|
||||
if (i++ == shape)
|
||||
result->rects.push_back(rect);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void ShapeResult::draw(Painter *p) const
|
||||
{
|
||||
QPen pen = p->pen();
|
||||
pen.setWidth(2);
|
||||
p->setPen(pen);
|
||||
|
||||
for (auto rect : rects) {
|
||||
Point2f v[4];
|
||||
rect.points(v);
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
p->drawLine(toQt((Point2i) v[i]), toQt((Point2i) v[(i+1)%4]));
|
||||
}
|
||||
}
|
||||
|
||||
QString ShapeResult::getResult() const
|
||||
{
|
||||
return QString("rects = %1").arg(rects.size());
|
||||
}
|
40
filters/shapedetect.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
#ifndef SHAPEDETECT_H
|
||||
#define SHAPEDETECT_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "filter.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class ShapeDetect : public Filter
|
||||
{
|
||||
public:
|
||||
enum Mode {
|
||||
AREA,
|
||||
COSINE
|
||||
};
|
||||
|
||||
ShapeDetect(double epsilon = 1, double cosine = 0.3);
|
||||
QString getName() const { return "ShapeDetect"; };
|
||||
|
||||
protected:
|
||||
Result * applyInternal(Image *img);
|
||||
|
||||
double epsilon;
|
||||
double cosine;
|
||||
int shape = 0;
|
||||
enum Mode mode;
|
||||
};
|
||||
|
||||
class ShapeResult : public Result
|
||||
{
|
||||
public:
|
||||
void draw(Painter *p) const;
|
||||
|
||||
QString getResult() const;
|
||||
|
||||
QList<RotatedRect> rects;
|
||||
};
|
||||
|
||||
#endif // SHAPEDETECT_H
|
48
filters/threshold.cpp
Normal file
|
@ -0,0 +1,48 @@
|
|||
#include "threshold.h"
|
||||
|
||||
Threshold::Threshold(enum Threshold::Type t, double v, int sz, double d) :
|
||||
Filter(),
|
||||
type(t),
|
||||
size(sz),
|
||||
value(v),
|
||||
c(d)
|
||||
{
|
||||
QMap<int, QString> typeMap;
|
||||
typeMap[ADAPTIVE_GAUSS] = "Adaptive Gauss";
|
||||
typeMap[ADAPTIVE_MEAN] = "Adaptive Mean";
|
||||
typeMap[FIXED] = "Fixed";
|
||||
typeMap[OTSU] = "Otsu's method";
|
||||
typeMap[TRIANGLE] = "Triangle";
|
||||
|
||||
settings["Type"] = new EnumSetting(this, (int&) type, typeMap);
|
||||
settings["Threshold"] = new DoubleSetting(this, value, 0, 0xff);
|
||||
settings["C"] = new DoubleSetting(this, c, 0, 0xff);
|
||||
settings["Size"] = new IntegerSetting(this, size, 1, 100);
|
||||
settings["Inverted"] = new BooleanSetting(this, invert);
|
||||
}
|
||||
|
||||
Result * Threshold::applyInternal(Image *img)
|
||||
{
|
||||
Mat &m = img->filtered;
|
||||
|
||||
int mode = (invert) ? THRESH_BINARY_INV : THRESH_BINARY;
|
||||
|
||||
if (type == ADAPTIVE_GAUSS)
|
||||
adaptiveThreshold(m, m, 0xff, ADAPTIVE_THRESH_GAUSSIAN_C, mode, size, c);
|
||||
else if (type == ADAPTIVE_MEAN)
|
||||
adaptiveThreshold(m, m, 0xff, ADAPTIVE_THRESH_MEAN_C, mode, size, c);
|
||||
else {
|
||||
int method;
|
||||
|
||||
switch (type) {
|
||||
case OTSU: method = THRESH_OTSU; break;
|
||||
case TRIANGLE: method = THRESH_TRIANGLE; break;
|
||||
default: method = 0;
|
||||
}
|
||||
|
||||
double ret = threshold(img->filtered, img->filtered, value, 0xff, mode | method);
|
||||
return new DoubleResult("tresh", ret);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
32
filters/threshold.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
#ifndef THRESHOLD_H
|
||||
#define THRESHOLD_H
|
||||
|
||||
#include "filter.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class Threshold : public Filter
|
||||
{
|
||||
public:
|
||||
enum Type {
|
||||
ADAPTIVE_GAUSS,
|
||||
ADAPTIVE_MEAN,
|
||||
OTSU,
|
||||
TRIANGLE,
|
||||
FIXED
|
||||
};
|
||||
|
||||
Threshold(enum Threshold::Type t, double v = 0, int sz = 7, double c = 100);
|
||||
|
||||
QString getName() const { return "Threshold"; }
|
||||
|
||||
protected:
|
||||
Result * applyInternal(Image *img);
|
||||
|
||||
enum Threshold::Type type;
|
||||
bool invert = false;
|
||||
int size;
|
||||
double value, c;
|
||||
};
|
||||
|
||||
#endif // THRESHOLD_H
|
30
filters/undistort.cpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
#include "undistort.h"
|
||||
|
||||
Undistort::Undistort(Camera *c) :
|
||||
cam(c)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
void Undistort::reset()
|
||||
{
|
||||
Mat newCamMat = getOptimalNewCameraMatrix(cam->getMatrix(), cam->getDistCoeffs(), cam->source->getSize(), 1);
|
||||
|
||||
initUndistortRectifyMap(cam->getMatrix(), cam->getDistCoeffs(),
|
||||
Mat(), newCamMat, cam->source->getSize(), CV_16SC2, map1, map2);
|
||||
}
|
||||
|
||||
Result * Undistort::applyInternal(Image *img)
|
||||
{
|
||||
if (cam->isCalibrated()) {
|
||||
#if 1
|
||||
remap(img->filtered, img->filtered, map1, map2, INTER_LINEAR);
|
||||
#else
|
||||
Mat dest;
|
||||
undistort(mat, dest, cam->getMatrix(), cam->getDistCoeffs());
|
||||
mat = dest;
|
||||
#endif
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
24
filters/undistort.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
#ifndef UNDISTORT_H
|
||||
#define UNDISTORT_H
|
||||
|
||||
#include "filter.h"
|
||||
#include "camera.h"
|
||||
|
||||
class Undistort : public Filter
|
||||
{
|
||||
public:
|
||||
Undistort(Camera *c);
|
||||
void reset();
|
||||
|
||||
QString getName() const { return "Undistort"; }
|
||||
|
||||
protected:
|
||||
Result * applyInternal(Image *img);
|
||||
|
||||
Mat map1;
|
||||
Mat map2;
|
||||
|
||||
Camera *cam;
|
||||
};
|
||||
|
||||
#endif // UNDISTORT_H
|
22
filters/watershed.cpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
#include "watershed.h"
|
||||
|
||||
Watershed::Watershed()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Result * Watershed::applyInternal(Image *img)
|
||||
{
|
||||
Mat dist, dist_8u, &m = img->filtered;
|
||||
|
||||
CV_Assert(m.channels() == 1);
|
||||
|
||||
distanceTransform(m, dist, DIST_L2, 3);
|
||||
normalize(m, m, 0, 0xff, NORM_MINMAX);
|
||||
|
||||
dist.convertTo(dist_8u, CV_8U);
|
||||
m = dist_8u;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
18
filters/watershed.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
#ifndef WATERSHED_H
|
||||
#define WATERSHED_H
|
||||
|
||||
#include "filter.h"
|
||||
|
||||
class Watershed : public Filter
|
||||
{
|
||||
public:
|
||||
Watershed();
|
||||
|
||||
QString getName() const { return "Watershed"; }
|
||||
|
||||
protected:
|
||||
Result * applyInternal(Image *img);
|
||||
|
||||
};
|
||||
|
||||
#endif // WATERSHED_H
|
54
image.cpp
Normal file
|
@ -0,0 +1,54 @@
|
|||
#include <opencv2/highgui.hpp>
|
||||
|
||||
#include "image.h"
|
||||
#include "filters/filter.h"
|
||||
|
||||
using namespace cv;
|
||||
|
||||
Image::Image(Mat m, QString p) :
|
||||
path(p),
|
||||
original(m.clone()),
|
||||
loaded(false),
|
||||
saved(false)
|
||||
{ }
|
||||
|
||||
Image::Image(QString p) :
|
||||
path(p),
|
||||
saved(false)
|
||||
{
|
||||
load();
|
||||
}
|
||||
|
||||
Image::~Image()
|
||||
{
|
||||
qDeleteAll(results);
|
||||
results.clear();
|
||||
}
|
||||
|
||||
void Image::load(QString p)
|
||||
{
|
||||
if (p != "")
|
||||
path = p;
|
||||
|
||||
original = cv::imread(path.toStdString());
|
||||
loaded = (bool) original.data;
|
||||
}
|
||||
|
||||
void Image::save(QString p)
|
||||
{
|
||||
if (p != "")
|
||||
path = p;
|
||||
|
||||
saved = imwrite(path.toStdString(), original);
|
||||
}
|
||||
|
||||
void Image::applyFilter(Filter *filter)
|
||||
{
|
||||
// FIXME!
|
||||
// if (results.contains(filter))
|
||||
// delete results[filter];
|
||||
|
||||
Result *result = filter->apply(this);
|
||||
if (result)
|
||||
results[filter] = result;
|
||||
}
|
43
image.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
#ifndef IMAGE_H
|
||||
#define IMAGE_H
|
||||
|
||||
#include <QString>
|
||||
#include <QMap>
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
#include <opencv2/imgproc.hpp>
|
||||
|
||||
using namespace cv;
|
||||
|
||||
class Camera;
|
||||
class Filter;
|
||||
class Result;
|
||||
|
||||
class Image
|
||||
{
|
||||
public:
|
||||
Image(Mat mat = Mat(), QString path = "");
|
||||
Image(QString p);
|
||||
~Image();
|
||||
|
||||
void save(QString path = "");
|
||||
void load(QString path = "");
|
||||
|
||||
QString path;
|
||||
|
||||
Mat original;
|
||||
Mat filtered;
|
||||
|
||||
void applyFilter(Filter *filter);
|
||||
|
||||
/* Getter */
|
||||
Result * getResult(Filter *f) { return results[f]; }
|
||||
|
||||
protected:
|
||||
QMap<Filter*, Result*> results;
|
||||
|
||||
bool loaded;
|
||||
bool saved;
|
||||
};
|
||||
|
||||
#endif // IMAGE_H
|
158
imagelist.cpp
Normal file
|
@ -0,0 +1,158 @@
|
|||
#include <QFileDialog>
|
||||
#include <QDir>
|
||||
|
||||
#include "imagelist.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
extern MainWindow *mwindow;
|
||||
|
||||
ImageList::ImageList(QObject *parent) :
|
||||
QAbstractTableModel(parent),
|
||||
selection(this)
|
||||
{
|
||||
connect(&selection, &QItemSelectionModel::currentChanged, this, &ImageList::currentImage);
|
||||
}
|
||||
|
||||
ImageList::~ImageList()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
int ImageList::rowCount(const QModelIndex &) const {
|
||||
return count();
|
||||
};
|
||||
|
||||
int ImageList::columnCount(const QModelIndex &) const {
|
||||
return 6;
|
||||
};
|
||||
|
||||
QVariant ImageList::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
Image *img = at(index.row());
|
||||
QFileInfo fi = QFileInfo(img->path);
|
||||
|
||||
if (role == Qt::DisplayRole) {
|
||||
switch (index.column()) {
|
||||
case 0: return fi.baseName();
|
||||
case 1: return fi.suffix();
|
||||
case 2: return fi.size();
|
||||
case 3: return img->original.cols;
|
||||
case 4: return img->original.rows;
|
||||
case 5: return img->original.channels();
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant ImageList::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (role == Qt::DisplayRole) {
|
||||
if (orientation == Qt::Horizontal) {
|
||||
switch (section) {
|
||||
case 0: return QString(tr("Name"));
|
||||
case 1: return QString(tr("Typ"));
|
||||
case 2: return QString(tr("Size"));
|
||||
case 3: return QString(tr("Width"));
|
||||
case 4: return QString(tr("Height"));
|
||||
case 5: return QString(tr("Channels"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void ImageList::clear() {
|
||||
QList<Image *>::iterator it;
|
||||
|
||||
beginResetModel();
|
||||
for (Image *img : *this) {
|
||||
delete img;
|
||||
removeOne(img);
|
||||
}
|
||||
|
||||
endResetModel();
|
||||
}
|
||||
|
||||
QList<Image *> ImageList::selectedImages()
|
||||
{
|
||||
QList<Image *> sel;
|
||||
|
||||
for (QModelIndex index : selection.selectedRows())
|
||||
sel.append(at(index.row()));
|
||||
|
||||
return sel;
|
||||
}
|
||||
|
||||
Image * ImageList::currentImage()
|
||||
{
|
||||
current = at(selection.currentIndex().row());
|
||||
emit newImage(current);
|
||||
return current;
|
||||
}
|
||||
|
||||
Image * ImageList::nextImage()
|
||||
{
|
||||
QModelIndex oldIdx = selection.currentIndex();
|
||||
QModelIndex newIdx = index(oldIdx.row()-1, oldIdx.column());
|
||||
|
||||
if (newIdx.isValid()) {
|
||||
selection.setCurrentIndex(newIdx, QItemSelectionModel::Current);
|
||||
|
||||
current = at(newIdx.row());
|
||||
emit newImage(current);
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
Image * ImageList::prevImage()
|
||||
{
|
||||
QModelIndex oldIdx = selection.currentIndex();
|
||||
QModelIndex newIdx = index(oldIdx.row()+1, oldIdx.column());
|
||||
|
||||
if (newIdx.isValid()) {
|
||||
selection.setCurrentIndex(newIdx, QItemSelectionModel::Current);
|
||||
|
||||
current = at(newIdx.row());
|
||||
emit newImage(current);
|
||||
}
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
void ImageList::load(QStringList files)
|
||||
{
|
||||
for (QString file : files)
|
||||
add(new Image(file));
|
||||
|
||||
current = first();
|
||||
emit newImage(current);
|
||||
}
|
||||
|
||||
void ImageList::save(QString path)
|
||||
{
|
||||
currentImage()->save(path);
|
||||
}
|
||||
|
||||
void ImageList::loadFilePicker()
|
||||
{
|
||||
QStringList files = QFileDialog::getOpenFileNames(mwindow, tr("Open Image"), QDir::currentPath(),
|
||||
tr("Image Files (*.png *.jpg *.bmp)"));
|
||||
load(files);
|
||||
}
|
||||
|
||||
void ImageList::saveFilePicker()
|
||||
{
|
||||
QString path = QFileDialog::getSaveFileName(mwindow, tr("Save Image"), current->path,
|
||||
tr("Image Files (*.png *.jpg *.bmp)"));
|
||||
save(path);
|
||||
}
|
||||
|
||||
void ImageList::add(Image *img)
|
||||
{
|
||||
beginInsertRows(QModelIndex(), size(), size());
|
||||
push_back(img);
|
||||
endInsertRows();
|
||||
}
|
49
imagelist.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
#ifndef IMAGELIST_H
|
||||
#define IMAGELIST_H
|
||||
|
||||
#include <QList>
|
||||
#include <QAbstractTableModel>
|
||||
#include <QItemSelectionModel>
|
||||
|
||||
#include "image.h"
|
||||
|
||||
class ImageList :
|
||||
public QAbstractTableModel,
|
||||
protected QList<Image *>
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ImageList(QObject *parent = 0);
|
||||
~ImageList();
|
||||
|
||||
void add(Image *img);
|
||||
|
||||
|
||||
int rowCount(const QModelIndex &) const;
|
||||
int columnCount(const QModelIndex &) const;
|
||||
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||
|
||||
QItemSelectionModel selection;
|
||||
|
||||
signals:
|
||||
void newImage(Image *img);
|
||||
|
||||
public slots:
|
||||
void load(QStringList files);
|
||||
void save(QString path);
|
||||
void loadFilePicker();
|
||||
void saveFilePicker();
|
||||
void clear();
|
||||
|
||||
QList<Image *> selectedImages();
|
||||
Image * currentImage();
|
||||
Image * prevImage();
|
||||
Image * nextImage();
|
||||
|
||||
protected:
|
||||
Image *current;
|
||||
};
|
||||
|
||||
#endif // IMAGELIST_H
|
99
imagelist.ui
Normal file
|
@ -0,0 +1,99 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Form</class>
|
||||
<widget class="QWidget" name="Form">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QTableView" name="tblImages">
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="showGrid">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="gridStyle">
|
||||
<enum>Qt::DotLine</enum>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderCascadingSectionResizes">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="widget_3" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnClear">
|
||||
<property name="text">
|
||||
<string>Clear</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="images.qrc">
|
||||
<normaloff>:/icons/resources/edit-clear.png</normaloff>:/icons/resources/edit-clear.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnLoad">
|
||||
<property name="text">
|
||||
<string>Load</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="images.qrc">
|
||||
<normaloff>:/icons/resources/document-open.png</normaloff>:/icons/resources/document-open.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnSave">
|
||||
<property name="text">
|
||||
<string>Save</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="images.qrc">
|
||||
<normaloff>:/icons/resources/document-save.png</normaloff>:/icons/resources/document-save.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="images.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
35
images.qrc
Normal file
|
@ -0,0 +1,35 @@
|
|||
<RCC>
|
||||
<qresource prefix="/icons">
|
||||
<file>resources/Mr-potato.png</file>
|
||||
<file>resources/calibrate.png</file>
|
||||
<file>resources/chess.png</file>
|
||||
<file>resources/circ.png</file>
|
||||
<file>resources/acirc.png</file>
|
||||
<file>resources/Boris.png</file>
|
||||
<file>resources/camera-photo.png</file>
|
||||
<file>resources/cap5h.jpg</file>
|
||||
<file>resources/chess.svg</file>
|
||||
<file>resources/circ.svg</file>
|
||||
<file>resources/document-open.png</file>
|
||||
<file>resources/document-save.png</file>
|
||||
<file>resources/edit-clear.png</file>
|
||||
<file>resources/edit-undo.png</file>
|
||||
<file>resources/go-next.png</file>
|
||||
<file>resources/go-previous.png</file>
|
||||
<file>resources/image-x-generic.png</file>
|
||||
<file>resources/media-playback-start.png</file>
|
||||
<file>resources/system-log-out.png</file>
|
||||
<file>resources/media-playback-stop.png</file>
|
||||
<file>resources/perspective.png</file>
|
||||
<file>resources/list-add.png</file>
|
||||
<file>resources/list-remove.png</file>
|
||||
<file>resources/view-refresh.png</file>
|
||||
</qresource>
|
||||
<qresource prefix="/math">
|
||||
<file>resources/matbr_left.png</file>
|
||||
<file>resources/matbr_right.png</file>
|
||||
</qresource>
|
||||
<qresource prefix="/">
|
||||
<file>resources/Mr-potato.icns</file>
|
||||
</qresource>
|
||||
</RCC>
|
18
imglist.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
#ifndef IMGLIST_H
|
||||
#define IMGLIST_H
|
||||
|
||||
#include <QListWidget>
|
||||
|
||||
class ImgList : public QListWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ImgList(QWidget *parent = 0);
|
||||
|
||||
signals:
|
||||
|
||||
public slots:
|
||||
|
||||
};
|
||||
|
||||
#endif // IMGLIST_H
|
62
main.cpp
Normal file
|
@ -0,0 +1,62 @@
|
|||
#include "mainwindow.h"
|
||||
#include <QApplication>
|
||||
#include <QCameraInfo>
|
||||
|
||||
/* Filters */
|
||||
#include "filters.h"
|
||||
#include "imagelist.h"
|
||||
#include "filterlist.h"
|
||||
#include "source.h"
|
||||
#include "camera.h"
|
||||
|
||||
Source *source;
|
||||
Camera *cam;
|
||||
FilterList *filters;
|
||||
ImageList *images;
|
||||
MainWindow *mwindow;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
|
||||
QList<QCameraInfo> cameras = QCameraInfo::availableCameras();
|
||||
foreach (const QCameraInfo &cameraInfo, cameras)
|
||||
qDebug() << "Found Qt camera: " << cameraInfo.deviceName() << ": " << cameraInfo.description();
|
||||
|
||||
filters = new FilterList;
|
||||
images = new ImageList;
|
||||
source = new Source;
|
||||
cam = new Camera(source);
|
||||
mwindow = new MainWindow;
|
||||
|
||||
QStringList imgs = QCoreApplication::arguments();
|
||||
imgs.removeFirst();
|
||||
imgs.removeDuplicates();
|
||||
imgs.sort();
|
||||
images->load(imgs);
|
||||
|
||||
/* Setup pipeline */
|
||||
#if 1
|
||||
filters->add(new Blur(Blur::GAUSSIAN, Size(3, 3)));
|
||||
filters->add(new KMeans(4));
|
||||
filters->add(new Convert(COLOR_BGR2HSV));
|
||||
filters->add(new Channel(1));
|
||||
//filters->add(new Convert(COLOR_BGR2GRAY));
|
||||
//filters->add(new HistEqualize());
|
||||
filters->add(new Threshold(Threshold::OTSU));
|
||||
//filters->add(new EdgeDetect(80, 3));
|
||||
//filters->add(new Watershed());
|
||||
filters->add(new Morph(MORPH_CLOSE, MORPH_RECT));
|
||||
filters->add(new ShapeDetect());
|
||||
//filters->add(new MaxChannel());
|
||||
//filters->add(new Normalize());
|
||||
#else
|
||||
filters->add(new Undistort(cam));
|
||||
filters->add(new Pattern(Size(13, 9), 60));
|
||||
filters->add(new Perspective(cam, (Pattern *) filters->last()));
|
||||
#endif
|
||||
|
||||
mwindow->show();
|
||||
|
||||
return a.exec();
|
||||
}
|
64
mainwindow.cpp
Normal file
|
@ -0,0 +1,64 @@
|
|||
#include <opencv2/core.hpp>
|
||||
|
||||
#include <QDialog>
|
||||
#include <QtDebug>
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "ui_mainwindow.h"
|
||||
#include "ui_about.h"
|
||||
|
||||
using namespace cv;
|
||||
|
||||
extern FilterList *filters;
|
||||
extern ImageList *images;
|
||||
extern Camera *cam;
|
||||
extern Source *source;
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::MainWindow)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->logConsole->setup();
|
||||
ui->splitterH->setSizes({
|
||||
static_cast<int>(0.8 * ui->splitterH->width()),
|
||||
static_cast<int>(0.2 * ui->splitterH->width())
|
||||
});
|
||||
|
||||
/* Connect actions */
|
||||
connect(images, &ImageList::newImage, ui->viewer, &Viewer::showImage);
|
||||
connect(source, &Source::newImage, ui->viewer, &Viewer::showImage);
|
||||
connect(filters, &FilterList::filtersChanged,ui->viewer, &Viewer::updateImage);
|
||||
connect(ui->actionRedraw, &QAction::triggered, ui->viewer, &Viewer::updateImage);
|
||||
connect(ui->actionCalibrate, &QAction::triggered, ui->tabCalibration, &TabCalibration::doCalibration);
|
||||
connect(ui->actionSnapshot, &QAction::triggered, ui->tabCamera, &TabCamera::doSnapshot);
|
||||
connect(ui->actionAbout, &QAction::triggered, this, &MainWindow::showAbout);
|
||||
connect(ui->actionExit, &QAction::triggered, this, &MainWindow::close);
|
||||
connect(ui->actionClear, &QAction::triggered, images, &ImageList::clear);
|
||||
connect(ui->actionLoad, &QAction::triggered, images, &ImageList::loadFilePicker);
|
||||
connect(ui->actionSave, &QAction::triggered, images, &ImageList::saveFilePicker);
|
||||
connect(ui->actionNextImage, &QAction::triggered, images, &ImageList::nextImage);
|
||||
connect(ui->actionPrevImage, &QAction::triggered, images, &ImageList::prevImage);
|
||||
connect(ui->actionPlay, &QAction::triggered, source, &Source::play);
|
||||
connect(ui->actionTabImages, &QAction::triggered, [=]() { ui->tabWidget->setCurrentWidget(ui->tabImages); });
|
||||
connect(ui->actionTabFilters, &QAction::triggered, [=]() { ui->tabWidget->setCurrentWidget(ui->tabFilters); });
|
||||
connect(ui->actionTabCamera, &QAction::triggered, [=]() { ui->tabWidget->setCurrentWidget(ui->tabCamera); });
|
||||
connect(ui->actionTabCalibration,&QAction::triggered, [=]() { ui->tabWidget->setCurrentWidget(ui->tabCalibration); });
|
||||
|
||||
updateGeometry();
|
||||
showMaximized();
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void MainWindow::showAbout()
|
||||
{
|
||||
QDialog dialog(this);
|
||||
Ui::AboutDialog about;
|
||||
|
||||
about.setupUi(&dialog);
|
||||
dialog.exec();
|
||||
}
|
43
mainwindow.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <opencv2/opencv.hpp>
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QSignalMapper>
|
||||
|
||||
#include "tabcalibration.h"
|
||||
#include "tabcamera.h"
|
||||
#include "tabfilters.h"
|
||||
#include "tabimages.h"
|
||||
#include "tabpads.h"
|
||||
|
||||
#include "filterlist.h"
|
||||
#include "imagelist.h"
|
||||
#include "camera.h"
|
||||
|
||||
using namespace cv;
|
||||
|
||||
namespace Ui {
|
||||
class MainWindow;
|
||||
}
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MainWindow(QWidget *parent = 0);
|
||||
~MainWindow();
|
||||
|
||||
public slots:
|
||||
void showAbout();
|
||||
|
||||
protected:
|
||||
Ui::MainWindow *ui;
|
||||
|
||||
signals:
|
||||
void newImage(Image *img);
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
490
mainwindow.ui
Normal file
|
@ -0,0 +1,490 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1267</width>
|
||||
<height>903</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Pastie</string>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>32</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="tabShape">
|
||||
<enum>QTabWidget::Triangular</enum>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralWidget">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitterV">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<widget class="QSplitter" name="splitterH">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<widget class="Viewer" name="viewer" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>320</width>
|
||||
<height>240</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="contextMenuPolicy">
|
||||
<enum>Qt::DefaultContextMenu</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>400</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="tabShape">
|
||||
<enum>QTabWidget::Rounded</enum>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="TabImages" name="tabImages">
|
||||
<attribute name="title">
|
||||
<string>Images</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="TabFilters" name="tabFilters">
|
||||
<attribute name="title">
|
||||
<string>Filters</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="TabCamera" name="tabCamera">
|
||||
<attribute name="title">
|
||||
<string>Camera</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
<widget class="TabCalibration" name="tabCalibration">
|
||||
<attribute name="title">
|
||||
<string>Calibration</string>
|
||||
</attribute>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="Console" name="logConsole">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="undoRedoEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="plainText">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="centerOnScroll">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QToolBar" name="toolBar">
|
||||
<property name="windowTitle">
|
||||
<string>toolBar</string>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="movable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="floatable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="toolBarArea">
|
||||
<enum>LeftToolBarArea</enum>
|
||||
</attribute>
|
||||
<attribute name="toolBarBreak">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<addaction name="actionLoad"/>
|
||||
<addaction name="actionSave"/>
|
||||
<addaction name="actionClear"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionPlay"/>
|
||||
<addaction name="actionSnapshot"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionPrevImage"/>
|
||||
<addaction name="actionRedraw"/>
|
||||
<addaction name="actionNextImage"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionCalibrate"/>
|
||||
<addaction name="actionReset"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionExit"/>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menuBar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1267</width>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="nativeMenuBar">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
<property name="title">
|
||||
<string>Images</string>
|
||||
</property>
|
||||
<addaction name="actionLoad"/>
|
||||
<addaction name="actionClear"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionExit"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu">
|
||||
<property name="title">
|
||||
<string>?</string>
|
||||
</property>
|
||||
<addaction name="actionAbout"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuCamera">
|
||||
<property name="title">
|
||||
<string>Camera</string>
|
||||
</property>
|
||||
<addaction name="actionSnapshot"/>
|
||||
<addaction name="actionPlay"/>
|
||||
<addaction name="actionCalibrate"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuTabs">
|
||||
<property name="title">
|
||||
<string>Tabs</string>
|
||||
</property>
|
||||
<addaction name="actionTabImages"/>
|
||||
<addaction name="actionTabCamera"/>
|
||||
<addaction name="actionTabFilters"/>
|
||||
<addaction name="actionTabCalibration"/>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
<addaction name="menuCamera"/>
|
||||
<addaction name="menuTabs"/>
|
||||
<addaction name="menu"/>
|
||||
</widget>
|
||||
<action name="actionLoad">
|
||||
<property name="icon">
|
||||
<iconset theme="document-open" resource="images.qrc">
|
||||
<normaloff>:/icons/resources/document-open.png</normaloff>:/icons/resources/document-open.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Load</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Load images from files</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+O</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionExit">
|
||||
<property name="icon">
|
||||
<iconset resource="images.qrc">
|
||||
<normaloff>:/icons/resources/system-log-out.png</normaloff>:/icons/resources/system-log-out.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Exit</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Quit program</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+Q</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionAbout">
|
||||
<property name="text">
|
||||
<string>About</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionCalibrate">
|
||||
<property name="icon">
|
||||
<iconset resource="images.qrc">
|
||||
<normaloff>:/icons/resources/calibrate.png</normaloff>:/icons/resources/calibrate.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Calibrate</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+C</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionClear">
|
||||
<property name="icon">
|
||||
<iconset resource="images.qrc">
|
||||
<normaloff>:/icons/resources/edit-clear.png</normaloff>:/icons/resources/edit-clear.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Clear</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Remove all images from the list</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+P</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionPlay">
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="images.qrc">
|
||||
<normaloff>:/icons/resources/media-playback-start.png</normaloff>
|
||||
<normalon>:/icons/resources/media-playback-stop.png</normalon>:/icons/resources/media-playback-start.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Start / Stop</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Start / Stop the live preview</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+X</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSnapshot">
|
||||
<property name="icon">
|
||||
<iconset resource="images.qrc">
|
||||
<normaloff>:/icons/resources/camera-photo.png</normaloff>:/icons/resources/camera-photo.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Snapshot</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Take a snapshot of the current viewfinder</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+Y</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionPrevImage">
|
||||
<property name="icon">
|
||||
<iconset resource="images.qrc">
|
||||
<normaloff>:/icons/resources/go-previous.png</normaloff>:/icons/resources/go-previous.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Previous Image</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show previous image from list</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Down</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionNextImage">
|
||||
<property name="icon">
|
||||
<iconset resource="images.qrc">
|
||||
<normaloff>:/icons/resources/go-next.png</normaloff>:/icons/resources/go-next.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Next Image</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Show next image from list</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Up</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSave">
|
||||
<property name="icon">
|
||||
<iconset resource="images.qrc">
|
||||
<normaloff>:/icons/resources/document-save.png</normaloff>:/icons/resources/document-save.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Save the current image to a file</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+S</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionReset">
|
||||
<property name="icon">
|
||||
<iconset resource="images.qrc">
|
||||
<normaloff>:/icons/resources/edit-undo.png</normaloff>:/icons/resources/edit-undo.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Reset Calibration</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Reset camera matrix and distortion coefficients obtained through calibration</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Ctrl+R</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionTabImages">
|
||||
<property name="text">
|
||||
<string>Images</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>F1</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionTabFilters">
|
||||
<property name="text">
|
||||
<string>Filters</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>F2</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionTabCamera">
|
||||
<property name="text">
|
||||
<string>Camera</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>F3</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionTabCalibration">
|
||||
<property name="text">
|
||||
<string>Calibration</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>F4</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionRedraw">
|
||||
<property name="icon">
|
||||
<iconset resource="images.qrc">
|
||||
<normaloff>:/icons/resources/view-refresh.png</normaloff>:/icons/resources/view-refresh.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Redraw</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>F5</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Viewer</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>viewer.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>Console</class>
|
||||
<extends>QPlainTextEdit</extends>
|
||||
<header>console.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>TabImages</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>tabimages.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>TabFilters</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>tabfilters.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>TabCamera</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>tabcamera.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>TabCalibration</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>tabcalibration.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources>
|
||||
<include location="images.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
<slots>
|
||||
<slot>showAbout()</slot>
|
||||
</slots>
|
||||
</ui>
|
15
painter.cpp
Normal file
|
@ -0,0 +1,15 @@
|
|||
#include "painter.h"
|
||||
|
||||
Painter::Painter(QPaintDevice *device, double r) :
|
||||
QPainter(device),
|
||||
ratio(r)
|
||||
{ }
|
||||
|
||||
|
||||
void Painter::drawMarker(const QPoint ¢er, int r)
|
||||
{
|
||||
drawEllipse(center, r, r);
|
||||
drawLine(center + QPoint(+r, +r), center - QPoint(+r, +r));
|
||||
drawLine(center + QPoint(+r, -r), center - QPoint(+r, -r));
|
||||
}
|
||||
|
18
painter.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
#ifndef PAINTER_H
|
||||
#define PAINTER_H
|
||||
|
||||
#include <QPainter>
|
||||
|
||||
class Painter : public QPainter
|
||||
{
|
||||
public:
|
||||
Painter(QPaintDevice *device, double ratio = 1);
|
||||
|
||||
void drawMarker(const QPoint ¢er, int radius = 8);
|
||||
|
||||
protected:
|
||||
double ratio;
|
||||
|
||||
};
|
||||
|
||||
#endif // PAINTER_H
|
BIN
resources/Mr-potato.icns
Normal file
BIN
resources/Mr-potato.png
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
resources/acirc.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
resources/calibrate.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
resources/camera-photo.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
resources/cap5h.jpg
Normal file
After Width: | Height: | Size: 79 KiB |
BIN
resources/chess.png
Normal file
After Width: | Height: | Size: 953 B |
185
resources/chess.svg
Normal file
|
@ -0,0 +1,185 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="48"
|
||||
height="48"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.5 r10040"
|
||||
sodipodi:docname="circ.svg"
|
||||
inkscape:export-filename="/home/stv0g/workspace/dbvsem/code/pastie/resources/chess.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90">
|
||||
<defs
|
||||
id="defs4" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.7604167"
|
||||
inkscape:cx="30.786693"
|
||||
inkscape:cy="19.146453"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-page="true"
|
||||
inkscape:snap-global="true"
|
||||
inkscape:window-width="1278"
|
||||
inkscape:window-height="750"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="24"
|
||||
inkscape:window-maximized="0" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Ebene 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-1004.3622)">
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none"
|
||||
d="m 40.508388,1049.148 -5.892129,0 0,-10.459 10.556733,0 0,6.1626 z"
|
||||
id="rect3755-6"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccc" />
|
||||
<path
|
||||
style="fill:#000000;fill-opacity:1;stroke:none"
|
||||
d="m 13.502795,1049.148 -6.0148868,0 -4.541846,-4.2964 0,-6.1626 10.5567328,0 z"
|
||||
id="rect3755-0-2-7"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccc" />
|
||||
<path
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none"
|
||||
d="m 7.6106683,1007.3119 5.8921297,0 0,10.459 -10.5567333,0 0,-6.1626 z"
|
||||
id="rect3755"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccc" />
|
||||
<rect
|
||||
style="fill:#000000;fill-opacity:1;stroke:none"
|
||||
id="rect3755-0"
|
||||
width="10.556733"
|
||||
height="10.458986"
|
||||
x="13.502797"
|
||||
y="1007.3119" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none"
|
||||
id="rect3755-4"
|
||||
width="10.556733"
|
||||
height="10.458986"
|
||||
x="24.059528"
|
||||
y="1007.3119" />
|
||||
<path
|
||||
style="fill:#000000;fill-opacity:1;stroke:none"
|
||||
d="m 34.616261,1007.3119 6.014887,0 4.541846,4.2964 0,6.1626 -10.556733,0 z"
|
||||
id="rect3755-0-2"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccccc" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none"
|
||||
id="rect3755-2"
|
||||
width="10.556733"
|
||||
height="10.458986"
|
||||
x="-45.172997"
|
||||
y="1017.7709"
|
||||
transform="scale(-1,1)" />
|
||||
<rect
|
||||
style="fill:#000000;fill-opacity:1;stroke:none"
|
||||
id="rect3755-0-24"
|
||||
width="10.556733"
|
||||
height="10.458986"
|
||||
x="-34.616264"
|
||||
y="1017.7709"
|
||||
transform="scale(-1,1)" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none"
|
||||
id="rect3755-4-0"
|
||||
width="10.556733"
|
||||
height="10.458986"
|
||||
x="-24.059528"
|
||||
y="1017.7709"
|
||||
transform="scale(-1,1)" />
|
||||
<rect
|
||||
style="fill:#000000;fill-opacity:1;stroke:none"
|
||||
id="rect3755-0-2-8"
|
||||
width="10.556733"
|
||||
height="10.458986"
|
||||
x="-13.502797"
|
||||
y="1017.7709"
|
||||
transform="scale(-1,1)" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none"
|
||||
id="rect3755-1"
|
||||
width="10.556733"
|
||||
height="10.458986"
|
||||
x="2.9460647"
|
||||
y="1028.23" />
|
||||
<rect
|
||||
style="fill:#000000;fill-opacity:1;stroke:none"
|
||||
id="rect3755-0-0"
|
||||
width="10.556733"
|
||||
height="10.458986"
|
||||
x="13.502797"
|
||||
y="1028.23" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none"
|
||||
id="rect3755-4-6"
|
||||
width="10.556733"
|
||||
height="10.458986"
|
||||
x="24.059528"
|
||||
y="1028.23" />
|
||||
<rect
|
||||
style="fill:#000000;fill-opacity:1;stroke:none"
|
||||
id="rect3755-0-2-9"
|
||||
width="10.556733"
|
||||
height="10.458986"
|
||||
x="34.616261"
|
||||
y="1028.23" />
|
||||
<rect
|
||||
style="fill:#000000;fill-opacity:1;stroke:none"
|
||||
id="rect3755-0-24-5"
|
||||
width="10.556733"
|
||||
height="10.458986"
|
||||
x="-34.616264"
|
||||
y="1038.689"
|
||||
transform="scale(-1,1)" />
|
||||
<rect
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none"
|
||||
id="rect3755-4-0-5"
|
||||
width="10.556733"
|
||||
height="10.458986"
|
||||
x="-24.059528"
|
||||
y="1038.689"
|
||||
transform="scale(-1,1)" />
|
||||
<rect
|
||||
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:3.94646239000000021;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="rect2985"
|
||||
width="44.053532"
|
||||
height="44.053532"
|
||||
x="1.9732312"
|
||||
y="1006.3354"
|
||||
ry="10.36474" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 5.5 KiB |
BIN
resources/circ.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
187
resources/circ.svg
Normal file
|
@ -0,0 +1,187 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="48"
|
||||
height="48"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.5 r10040"
|
||||
sodipodi:docname="circ.svg"
|
||||
inkscape:export-filename="/home/stv0g/workspace/dbvsem/code/pastie/resources/chess.png"
|
||||
inkscape:export-xdpi="90"
|
||||
inkscape:export-ydpi="90">
|
||||
<defs
|
||||
id="defs4" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="5.7604167"
|
||||
inkscape:cx="8.479279"
|
||||
inkscape:cy="19.146453"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:snap-bbox="false"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-page="true"
|
||||
inkscape:snap-global="true"
|
||||
inkscape:window-width="1278"
|
||||
inkscape:window-height="750"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="24"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:object-paths="true"
|
||||
inkscape:object-nodes="false"
|
||||
inkscape:snap-intersection-paths="true"
|
||||
inkscape:snap-smooth-nodes="false"
|
||||
inkscape:snap-midpoints="false"
|
||||
inkscape:snap-nodes="true"
|
||||
inkscape:snap-object-midpoints="true" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Ebene 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-1004.3622)">
|
||||
<rect
|
||||
style="fill:none;stroke:#000000;stroke-width:3.94646239;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
id="rect2985"
|
||||
width="44.053532"
|
||||
height="44.053532"
|
||||
x="1.9732342"
|
||||
y="1006.3354"
|
||||
ry="10.36474" />
|
||||
<g
|
||||
id="g4780"
|
||||
transform="translate(-2.6303638e-6,-0.18770124)">
|
||||
<g
|
||||
transform="translate(-0.34719718,0)"
|
||||
id="g4716">
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:#000000;stroke:none"
|
||||
id="path3915"
|
||||
sodipodi:cx="-25.345388"
|
||||
sodipodi:cy="4.6003618"
|
||||
sodipodi:rx="4.687161"
|
||||
sodipodi:ry="4.687161"
|
||||
d="m -20.658227,4.6003618 c 0,2.5886475 -2.098514,4.687161 -4.687161,4.687161 -2.588648,0 -4.687161,-2.0985135 -4.687161,-4.687161 0,-2.5886475 2.098513,-4.68716094 4.687161,-4.68716094 2.588647,0 4.687161,2.09851344 4.687161,4.68716094 z"
|
||||
transform="matrix(0.93157895,0,0,0.93157895,36.267022,1012.5729)" />
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:#000000;stroke:none"
|
||||
id="path3915-2"
|
||||
sodipodi:cx="-25.345388"
|
||||
sodipodi:cy="4.6003618"
|
||||
sodipodi:rx="4.687161"
|
||||
sodipodi:ry="4.687161"
|
||||
d="m -20.658227,4.6003618 c 0,2.5886475 -2.098514,4.687161 -4.687161,4.687161 -2.588648,0 -4.687161,-2.0985135 -4.687161,-4.687161 0,-2.5886475 2.098513,-4.68716094 4.687161,-4.68716094 2.588647,0 4.687161,2.09851344 4.687161,4.68716094 z"
|
||||
transform="matrix(0.93157895,0,0,0.93157895,47.958425,1012.5729)" />
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:#000000;stroke:none"
|
||||
id="path3915-5"
|
||||
sodipodi:cx="-25.345388"
|
||||
sodipodi:cy="4.6003618"
|
||||
sodipodi:rx="4.687161"
|
||||
sodipodi:ry="4.687161"
|
||||
d="m -20.658227,4.6003618 c 0,2.5886475 -2.098514,4.687161 -4.687161,4.687161 -2.588648,0 -4.687161,-2.0985135 -4.687161,-4.687161 0,-2.5886475 2.098513,-4.68716094 4.687161,-4.68716094 2.588647,0 4.687161,2.09851344 4.687161,4.68716094 z"
|
||||
transform="matrix(0.93157895,0,0,0.93157895,59.649833,1012.5729)" />
|
||||
</g>
|
||||
<g
|
||||
id="g4774">
|
||||
<g
|
||||
id="g4716-2"
|
||||
transform="translate(-0.34719563,11.503652)">
|
||||
<path
|
||||
transform="matrix(0.93157895,0,0,0.93157895,36.267022,1012.5729)"
|
||||
d="m -20.658227,4.6003618 c 0,2.5886475 -2.098514,4.687161 -4.687161,4.687161 -2.588648,0 -4.687161,-2.0985135 -4.687161,-4.687161 0,-2.5886475 2.098513,-4.68716094 4.687161,-4.68716094 2.588647,0 4.687161,2.09851344 4.687161,4.68716094 z"
|
||||
sodipodi:ry="4.687161"
|
||||
sodipodi:rx="4.687161"
|
||||
sodipodi:cy="4.6003618"
|
||||
sodipodi:cx="-25.345388"
|
||||
id="path3915-6"
|
||||
style="fill:#000000;stroke:none"
|
||||
sodipodi:type="arc" />
|
||||
<path
|
||||
transform="matrix(0.93157895,0,0,0.93157895,47.958425,1012.5729)"
|
||||
d="m -20.658227,4.6003618 c 0,2.5886475 -2.098514,4.687161 -4.687161,4.687161 -2.588648,0 -4.687161,-2.0985135 -4.687161,-4.687161 0,-2.5886475 2.098513,-4.68716094 4.687161,-4.68716094 2.588647,0 4.687161,2.09851344 4.687161,4.68716094 z"
|
||||
sodipodi:ry="4.687161"
|
||||
sodipodi:rx="4.687161"
|
||||
sodipodi:cy="4.6003618"
|
||||
sodipodi:cx="-25.345388"
|
||||
id="path3915-2-5"
|
||||
style="fill:#000000;stroke:none"
|
||||
sodipodi:type="arc" />
|
||||
<path
|
||||
transform="matrix(0.93157895,0,0,0.93157895,59.649833,1012.5729)"
|
||||
d="m -20.658227,4.6003618 c 0,2.5886475 -2.098514,4.687161 -4.687161,4.687161 -2.588648,0 -4.687161,-2.0985135 -4.687161,-4.687161 0,-2.5886475 2.098513,-4.68716094 4.687161,-4.68716094 2.588647,0 4.687161,2.09851344 4.687161,4.68716094 z"
|
||||
sodipodi:ry="4.687161"
|
||||
sodipodi:rx="4.687161"
|
||||
sodipodi:cy="4.6003618"
|
||||
sodipodi:cx="-25.345388"
|
||||
id="path3915-5-5"
|
||||
style="fill:#000000;stroke:none"
|
||||
sodipodi:type="arc" />
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
transform="translate(-0.34719191,23.382802)"
|
||||
id="g4716-8">
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:#000000;stroke:none"
|
||||
id="path3915-71"
|
||||
sodipodi:cx="-25.345388"
|
||||
sodipodi:cy="4.6003618"
|
||||
sodipodi:rx="4.687161"
|
||||
sodipodi:ry="4.687161"
|
||||
d="m -20.658227,4.6003618 c 0,2.5886475 -2.098514,4.687161 -4.687161,4.687161 -2.588648,0 -4.687161,-2.0985135 -4.687161,-4.687161 0,-2.5886475 2.098513,-4.68716094 4.687161,-4.68716094 2.588647,0 4.687161,2.09851344 4.687161,4.68716094 z"
|
||||
transform="matrix(0.93157895,0,0,0.93157895,36.267022,1012.5729)" />
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:#000000;stroke:none"
|
||||
id="path3915-2-0"
|
||||
sodipodi:cx="-25.345388"
|
||||
sodipodi:cy="4.6003618"
|
||||
sodipodi:rx="4.687161"
|
||||
sodipodi:ry="4.687161"
|
||||
d="m -20.658227,4.6003618 c 0,2.5886475 -2.098514,4.687161 -4.687161,4.687161 -2.588648,0 -4.687161,-2.0985135 -4.687161,-4.687161 0,-2.5886475 2.098513,-4.68716094 4.687161,-4.68716094 2.588647,0 4.687161,2.09851344 4.687161,4.68716094 z"
|
||||
transform="matrix(0.93157895,0,0,0.93157895,47.958425,1012.5729)" />
|
||||
<path
|
||||
sodipodi:type="arc"
|
||||
style="fill:#000000;stroke:none"
|
||||
id="path3915-5-53"
|
||||
sodipodi:cx="-25.345388"
|
||||
sodipodi:cy="4.6003618"
|
||||
sodipodi:rx="4.687161"
|
||||
sodipodi:ry="4.687161"
|
||||
d="m -20.658227,4.6003618 c 0,2.5886475 -2.098514,4.687161 -4.687161,4.687161 -2.588648,0 -4.687161,-2.0985135 -4.687161,-4.687161 0,-2.5886475 2.098513,-4.68716094 4.687161,-4.68716094 2.588647,0 4.687161,2.09851344 4.687161,4.68716094 z"
|
||||
transform="matrix(0.93157895,0,0,0.93157895,59.649833,1012.5729)" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 8 KiB |
BIN
resources/document-open.png
Normal file
After Width: | Height: | Size: 1.5 KiB |
BIN
resources/document-save.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
resources/edit-clear.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
resources/edit-undo.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
resources/go-next.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
resources/go-previous.png
Normal file
After Width: | Height: | Size: 1.2 KiB |
BIN
resources/image-x-generic.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
15
resources/intro.html
Normal file
|
@ -0,0 +1,15 @@
|
|||
<h2>Welcome to Pastie 0.1</h2>
|
||||
<br/>
|
||||
|
||||
Seminar <b>Digital Image Processing and Content Analysis</b> WS 2014/15<br/>
|
||||
Institute of Imaging & Computer Vision (LfB)<br/>
|
||||
RWTH Aachen University<br/>
|
||||
<br>
|
||||
|
||||
Written by Steffen Vogel
|
||||
<ul>
|
||||
<li>Mail: <a href="mailto:steffen.vogel@rwth-aachen.de">steffen.vogel@rwth-aachen.de</a></li>
|
||||
<li>Web: <a href="http://www.steffenvogel.de">www.steffenvogel.de</a></li>
|
||||
</ul><br>
|
||||
|
||||
<em>This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version.</em><br/>
|
BIN
resources/list-add.png
Normal file
After Width: | Height: | Size: 601 B |
BIN
resources/list-remove.png
Normal file
After Width: | Height: | Size: 317 B |
64
resources/matbr.svg
Normal file
|
@ -0,0 +1,64 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="210mm"
|
||||
height="297mm"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.48.5 r10040"
|
||||
sodipodi:docname="Neues Dokument 1">
|
||||
<defs
|
||||
id="defs4" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="3.959798"
|
||||
inkscape:cx="111.80375"
|
||||
inkscape:cy="932.59156"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1278"
|
||||
inkscape:window-height="750"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="24"
|
||||
inkscape:window-maximized="0" />
|
||||
<metadata
|
||||
id="metadata7">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Ebene 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1">
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:2.4879477;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||
d="m 98.478771,74.270877 5.722049,0 0,64.924503 -5.722049,0"
|
||||
id="path2985"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cccc"
|
||||
inkscape:export-filename="/home/stv0g/workspace/rwth-dbv/code/pastie/resources/matbr_right.png"
|
||||
inkscape:export-xdpi="230"
|
||||
inkscape:export-ydpi="230" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2 KiB |
BIN
resources/matbr_left.png
Normal file
After Width: | Height: | Size: 245 B |
BIN
resources/matbr_right.png
Normal file
After Width: | Height: | Size: 260 B |
BIN
resources/media-playback-start.png
Normal file
After Width: | Height: | Size: 1 KiB |
BIN
resources/media-playback-stop.png
Normal file
After Width: | Height: | Size: 571 B |
BIN
resources/perspective.png
Normal file
After Width: | Height: | Size: 914 B |
BIN
resources/system-log-out.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
resources/view-refresh.png
Normal file
After Width: | Height: | Size: 2 KiB |
86
source.cpp
Normal file
|
@ -0,0 +1,86 @@
|
|||
#include <QDir>
|
||||
#include <QtDebug>
|
||||
|
||||
#include <opencv2/core.hpp>
|
||||
|
||||
#include "source.h"
|
||||
|
||||
using namespace cv;
|
||||
|
||||
Source::Source() :
|
||||
VideoCapture(CAP_ANY)
|
||||
{
|
||||
if (!isOpened())
|
||||
throw Exception();
|
||||
|
||||
setSize(Size(640, 480));
|
||||
setFPS(15);
|
||||
|
||||
connect(&tmr, SIGNAL(timeout()), this, SLOT(tick()));
|
||||
}
|
||||
|
||||
Size Source::getSize()
|
||||
{
|
||||
return Size(
|
||||
get(CAP_PROP_FRAME_WIDTH),
|
||||
get(CAP_PROP_FRAME_HEIGHT)
|
||||
);
|
||||
}
|
||||
|
||||
bool Source::setSize(const Size s)
|
||||
{
|
||||
set(CAP_PROP_FRAME_WIDTH, s.width);
|
||||
return set(CAP_PROP_FRAME_HEIGHT, s.height);
|
||||
}
|
||||
|
||||
double Source::getFPS()
|
||||
{
|
||||
return fps;
|
||||
}
|
||||
|
||||
bool Source::setFPS(double f)
|
||||
{
|
||||
fps = f;
|
||||
|
||||
if (tmr.isActive())
|
||||
tmr.start(1000.0 / fps);
|
||||
|
||||
return set(CAP_PROP_FPS, fps);
|
||||
}
|
||||
|
||||
Image * Source::getSnapshot()
|
||||
{
|
||||
static unsigned no;
|
||||
|
||||
Mat mat;
|
||||
QString fileName = QString("%1/snapshot_%2.png")
|
||||
.arg(QDir::tempPath()).arg(no++);
|
||||
|
||||
read(mat);
|
||||
|
||||
return new Image(mat, fileName);
|
||||
}
|
||||
|
||||
void Source::play(bool run)
|
||||
{
|
||||
if (run)
|
||||
tmr.start(1000.0 / fps);
|
||||
else
|
||||
tmr.stop();
|
||||
}
|
||||
|
||||
void Source::tick()
|
||||
{
|
||||
static bool running;
|
||||
|
||||
if (running)
|
||||
return;
|
||||
|
||||
running = true;
|
||||
|
||||
if (read(last.original))
|
||||
emit newImage(&last);
|
||||
|
||||
running = false;
|
||||
}
|
||||
|
46
source.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
#ifndef SOURCE_H
|
||||
#define SOURCE_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QTimer>
|
||||
|
||||
#include <opencv2/videoio.hpp>
|
||||
|
||||
#include "image.h"
|
||||
|
||||
using namespace cv;
|
||||
|
||||
class Source :
|
||||
public QObject,
|
||||
public VideoCapture
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Source();
|
||||
|
||||
Size getSize();
|
||||
bool setSize(const Size s);
|
||||
|
||||
double getFPS();
|
||||
bool setFPS(double f);
|
||||
|
||||
Image * getSnapshot();
|
||||
|
||||
public slots:
|
||||
void play(bool);
|
||||
|
||||
signals:
|
||||
void newImage(Image *img);
|
||||
|
||||
protected slots:
|
||||
void tick();
|
||||
|
||||
protected:
|
||||
Image last;
|
||||
QTimer tmr;
|
||||
|
||||
double fps;
|
||||
};
|
||||
|
||||
#endif // SOURCE_H
|
81
tabcalibration.cpp
Normal file
|
@ -0,0 +1,81 @@
|
|||
#include <opencv2/core.hpp>
|
||||
|
||||
#include "filters/pattern.h"
|
||||
#include "mainwindow.h"
|
||||
#include "imagelist.h"
|
||||
#include "tabcalibration.h"
|
||||
#include "ui_tabcalibration.h"
|
||||
|
||||
extern Camera *cam;
|
||||
extern ImageList *images;
|
||||
extern FilterList *filters;
|
||||
extern MainWindow *mwindow;
|
||||
|
||||
TabCalibration::TabCalibration(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::TabCalibration)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
connect(ui->btnCalibrate, &QPushButton::clicked, this, &TabCalibration::doCalibration);
|
||||
connect(ui->btnPerspective, &QPushButton::clicked, this, &TabCalibration::doPerspective);
|
||||
connect(ui->btnReset, &QPushButton::clicked, this, &TabCalibration::resetCalibration);
|
||||
}
|
||||
|
||||
TabCalibration::~TabCalibration()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void TabCalibration::doPerspective()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void TabCalibration::doCalibration()
|
||||
{
|
||||
int index = ui->cmbBoardPattern->currentIndex();
|
||||
float spacing = ui->spinBoardSpacing->value();
|
||||
|
||||
Size size = Size(ui->spinBoardSizeX->value(), ui->spinBoardSizeY->value());
|
||||
Pattern *pattern = new Pattern(size, spacing, Pattern::Type(index));
|
||||
|
||||
filters->add(pattern);
|
||||
|
||||
if (cam->calibrate(images->selectedImages().toStdList(), pattern))
|
||||
showResults();
|
||||
}
|
||||
|
||||
void TabCalibration::resetCalibration()
|
||||
{
|
||||
filters->reset();
|
||||
cam->reset();
|
||||
|
||||
showResults();
|
||||
}
|
||||
|
||||
void TabCalibration::showResults()
|
||||
{
|
||||
/* Reprojection Error */
|
||||
ui->lblAvgReprErr->setText(QString::number(cam->getAvgReprErr()));
|
||||
|
||||
/* Distortion coefficients */
|
||||
Mat mat = cam->getDistCoeffs();
|
||||
ui->lblDistCoeff_0->setText(QString::number(mat.at<float>(0), 'g', 4));
|
||||
ui->lblDistCoeff_1->setText(QString::number(mat.at<float>(1), 'g', 4));
|
||||
ui->lblDistCoeff_2->setText(QString::number(mat.at<float>(2), 'g', 4));
|
||||
ui->lblDistCoeff_3->setText(QString::number(mat.at<float>(3), 'g', 4));
|
||||
ui->lblDistCoeff_4->setText(QString::number(mat.at<float>(4), 'g', 4));
|
||||
|
||||
/* Camera Matrix */
|
||||
mat = cam->getMatrix();
|
||||
ui->lblMatrix_0_0->setText(QString::number(mat.at<float>(0, 0), 'g', 4));
|
||||
ui->lblMatrix_0_1->setText(QString::number(mat.at<float>(0, 1), 'g', 4));
|
||||
ui->lblMatrix_0_2->setText(QString::number(mat.at<float>(0, 2), 'g', 4));
|
||||
ui->lblMatrix_1_0->setText(QString::number(mat.at<float>(1, 0), 'g', 4));
|
||||
ui->lblMatrix_1_1->setText(QString::number(mat.at<float>(1, 1), 'g', 4));
|
||||
ui->lblMatrix_1_2->setText(QString::number(mat.at<float>(1, 2), 'g', 4));
|
||||
ui->lblMatrix_2_0->setText(QString::number(mat.at<float>(2, 0), 'g', 4));
|
||||
ui->lblMatrix_2_1->setText(QString::number(mat.at<float>(2, 1), 'g', 4));
|
||||
ui->lblMatrix_2_2->setText(QString::number(mat.at<float>(2, 2), 'g', 4));
|
||||
}
|
30
tabcalibration.h
Normal file
|
@ -0,0 +1,30 @@
|
|||
#ifndef TABCALIBRATION_H
|
||||
#define TABCALIBRATION_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "camera.h"
|
||||
|
||||
namespace Ui {
|
||||
class TabCalibration;
|
||||
}
|
||||
|
||||
class TabCalibration : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TabCalibration(QWidget *parent = 0);
|
||||
~TabCalibration();
|
||||
|
||||
public slots:
|
||||
void doCalibration();
|
||||
void doPerspective();
|
||||
void resetCalibration();
|
||||
void showResults();
|
||||
|
||||
private:
|
||||
Ui::TabCalibration *ui;
|
||||
};
|
||||
|
||||
#endif // TABCALIBRATION_H
|
870
tabcalibration.ui
Normal file
|
@ -0,0 +1,870 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TabCalibration</class>
|
||||
<widget class="QWidget" name="TabCalibration">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>532</width>
|
||||
<height>543</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>12</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QWidget" name="widget_9" native="true">
|
||||
<layout class="QFormLayout" name="formLayout_7">
|
||||
<property name="fieldGrowthPolicy">
|
||||
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
|
||||
</property>
|
||||
<property name="formAlignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing</set>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_32">
|
||||
<property name="text">
|
||||
<string>Pattern</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="cmbBoardPattern">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string comment="chess">Chessboard</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="images.qrc">
|
||||
<normaloff>:/icons/resources/chess.png</normaloff>:/icons/resources/chess.png</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string comment="circ">Circles Symmetric</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="images.qrc">
|
||||
<normaloff>:/icons/resources/circ.png</normaloff>:/icons/resources/circ.png</iconset>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string comment="circa">Circles Asymmetric</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="images.qrc">
|
||||
<normaloff>:/icons/resources/acirc.png</normaloff>:/icons/resources/acirc.png</iconset>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_29">
|
||||
<property name="text">
|
||||
<string>Board Size</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QWidget" name="widget_10" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_6">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinBoardSizeX">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>6</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_30">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>16</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>x</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinBoardSizeY">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>9</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_31">
|
||||
<property name="text">
|
||||
<string>Spacing</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QWidget" name="widget_11" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_7">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="spinBoardSpacing">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>114</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>156</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>25.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="widget_5" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnCalibrate">
|
||||
<property name="text">
|
||||
<string>Calibrate</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="images.qrc">
|
||||
<normaloff>:/icons/resources/calibrate.png</normaloff>:/icons/resources/calibrate.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnPerspective">
|
||||
<property name="text">
|
||||
<string>Perspective</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="images.qrc">
|
||||
<normaloff>:/icons/resources/perspective.png</normaloff>:/icons/resources/perspective.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnReset">
|
||||
<property name="text">
|
||||
<string>Reset</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="images.qrc">
|
||||
<normaloff>:/icons/resources/edit-undo.png</normaloff>:/icons/resources/edit-undo.png</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>124</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="grpResults">
|
||||
<property name="title">
|
||||
<string>Results</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<property name="leftMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QWidget" name="widget_12" native="true">
|
||||
<layout class="QFormLayout" name="formLayout_4">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_34">
|
||||
<property name="text">
|
||||
<string>Average Reprojection Error:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="lblAvgReprErr">
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Cam Matrix:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="matMatrix" native="true">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_24">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>5</width>
|
||||
<height>60</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="images.qrc">:/math/resources/matbr_left.png</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="widget_6" native="true">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="lblMatrix_0_1">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="lblMatrix_0_0">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>1</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLabel" name="lblMatrix_2_1">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="lblMatrix_1_0">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="lblMatrix_1_1">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>1</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="lblMatrix_2_0">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QLabel" name="lblMatrix_1_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QLabel" name="lblMatrix_2_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>1</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="lblMatrix_0_2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>25</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_25">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>5</width>
|
||||
<height>60</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="images.qrc">:/math/resources/matbr_right.png</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_33">
|
||||
<property name="text">
|
||||
<string>Distortion Coefficients:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="matDistCoeff" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_9">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_26">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>5</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="images.qrc">:/math/resources/matbr_left.png</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="widget_8" native="true">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_10">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="lblDistCoeff_2">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lblDistCoeff_0">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lblDistCoeff_3">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lblDistCoeff_1">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="lblDistCoeff_4">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_40">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>5</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="pixmap">
|
||||
<pixmap resource="images.qrc">:/math/resources/matbr_right.png</pixmap>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="widget_7" native="true">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="images.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
99
tabcamera.cpp
Normal file
|
@ -0,0 +1,99 @@
|
|||
#include <opencv2/videoio.hpp>
|
||||
|
||||
#include <QtDebug>
|
||||
#include <QComboBox>
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "camera.h"
|
||||
#include "source.h"
|
||||
#include "imagelist.h"
|
||||
|
||||
#include "tabcamera.h"
|
||||
#include "ui_tabcamera.h"
|
||||
|
||||
extern Source *source;
|
||||
extern Camera *cam;
|
||||
extern ImageList *images;
|
||||
extern FilterList *filters;
|
||||
|
||||
TabCamera::TabCamera(QWidget *parent) :
|
||||
QWidget(parent),
|
||||
ui(new Ui::TabCamera)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->cmbCamResolution->setCurrentText(
|
||||
QString("%1x%2").arg(source->getSize().width)
|
||||
.arg(source->getSize().height)
|
||||
);
|
||||
ui->cmbCamFPS->setCurrentText(
|
||||
QString::number(source->getFPS())
|
||||
);
|
||||
|
||||
connect(ui->sldCamBrightness, &QSlider::sliderReleased, this, &TabCamera::changeSetting);
|
||||
connect(ui->sldCamContrast, &QSlider::sliderReleased, this, &TabCamera::changeSetting);
|
||||
connect(ui->sldCamExposure, &QSlider::sliderReleased, this, &TabCamera::changeSetting);
|
||||
connect(ui->sldCamFocus, &QSlider::sliderReleased, this, &TabCamera::changeSetting);
|
||||
connect(ui->sldCamGain, &QSlider::sliderReleased, this, &TabCamera::changeSetting);
|
||||
connect(ui->sldCamGamma, &QSlider::sliderReleased, this, &TabCamera::changeSetting);
|
||||
connect(ui->sldCamHue, &QSlider::sliderReleased, this, &TabCamera::changeSetting);
|
||||
connect(ui->sldCamSharpness, &QSlider::sliderReleased, this, &TabCamera::changeSetting);
|
||||
|
||||
connect(ui->cmbCamFPS, &QComboBox::currentTextChanged, this, &TabCamera::changeFPS);
|
||||
connect(ui->cmbCamResolution, &QComboBox::currentTextChanged, this, &TabCamera::changeResolution);
|
||||
connect(ui->btnSnapshot, &QPushButton::clicked, this, &TabCamera::doSnapshot);
|
||||
connect(ui->btnPlay, &QPushButton::clicked, source, &Source::play);
|
||||
}
|
||||
|
||||
TabCamera::~TabCamera()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void TabCamera::changeResolution(QString resolution)
|
||||
{
|
||||
QStringList wh = resolution.split('x');
|
||||
|
||||
bool success = source->setSize(Size(wh[0].toInt(), wh[1].toInt()));
|
||||
if (!success)
|
||||
qWarning() << "Camera did not accept new resolution: " << resolution;
|
||||
|
||||
filters->reset();
|
||||
cam->reset();
|
||||
}
|
||||
|
||||
void TabCamera::changeFPS(QString fps)
|
||||
{
|
||||
bool success = source->setFPS(fps.toDouble());
|
||||
if (!success)
|
||||
qWarning() << "Camera did not accept new FPS: " << fps;
|
||||
}
|
||||
|
||||
void TabCamera::changeSetting()
|
||||
{
|
||||
QSlider *sld = qobject_cast<QSlider *>(sender());
|
||||
|
||||
int prop = getCVCap(sld);
|
||||
double value = (double) sld->value() / 1000;
|
||||
|
||||
bool success = source->set(prop, value);
|
||||
if (!success)
|
||||
qWarning() << "Camera did not accept property " << prop << " with value " << value;
|
||||
}
|
||||
|
||||
int TabCamera::getCVCap(QWidget *w)
|
||||
{
|
||||
if (w == ui->sldCamBrightness) return CAP_PROP_BRIGHTNESS;
|
||||
else if (w == ui->sldCamContrast) return CAP_PROP_CONTRAST;
|
||||
else if (w == ui->sldCamExposure) return CAP_PROP_EXPOSURE;
|
||||
else if (w == ui->sldCamFocus) return CAP_PROP_FOCUS;
|
||||
else if (w == ui->sldCamGain) return CAP_PROP_GAIN;
|
||||
else if (w == ui->sldCamGamma) return CAP_PROP_GAMMA;
|
||||
else if (w == ui->sldCamHue) return CAP_PROP_HUE;
|
||||
else if (w == ui->sldCamSharpness) return CAP_PROP_SHARPNESS;
|
||||
else return -1;
|
||||
}
|
||||
|
||||
void TabCamera::doSnapshot()
|
||||
{
|
||||
images->add(source->getSnapshot());
|
||||
}
|