moved Pastie so seperate repo

This commit is contained in:
Steffen Vogel 2014-12-20 14:07:15 +01:00
commit a1893e4917
114 changed files with 6459 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
Pastie
moc_*
ui_*

119
Pastie.pro Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

@ -0,0 +1,7 @@
#include "padfilter.h"
Result * PadFilter::applyInternal(Image *)
{
return NULL;
}

16
filters/padfilter.h Normal file
View 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
View 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
View 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
View 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
View 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
View File

@ -0,0 +1,3 @@
#include "result.h"

51
filters/result.h Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

@ -0,0 +1,15 @@
#include "painter.h"
Painter::Painter(QPaintDevice *device, double r) :
QPainter(device),
ratio(r)
{ }
void Painter::drawMarker(const QPoint &center, 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
View 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 &center, int radius = 8);
protected:
double ratio;
};
#endif // PAINTER_H

BIN
resources/Mr-potato.icns Normal file

Binary file not shown.

BIN
resources/Mr-potato.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

BIN
resources/acirc.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

BIN
resources/calibrate.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
resources/camera-photo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
resources/cap5h.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

BIN
resources/chess.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 953 B

185
resources/chess.svg Normal file
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

187
resources/circ.svg Normal file
View 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.0 KiB

BIN
resources/document-open.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

BIN
resources/document-save.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
resources/edit-clear.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
resources/edit-undo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
resources/go-next.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
resources/go-previous.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

15
resources/intro.html Normal file
View 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 &amp; 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 601 B

BIN
resources/list-remove.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 317 B

64
resources/matbr.svg Normal file
View 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.0 KiB

BIN
resources/matbr_left.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 B

BIN
resources/matbr_right.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 260 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 571 B

BIN
resources/perspective.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 914 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
resources/view-refresh.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

86
source.cpp Normal file
View 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
View 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
View 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
View 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
View 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
View 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());
}

Some files were not shown because too many files have changed in this diff Show More