Compare commits
54 Commits
Author | SHA1 | Date | |
---|---|---|---|
4bd1ba84c3 | |||
019b42c738 | |||
30648b6df1 | |||
d3c26c12b4 | |||
915187816f | |||
70e9111474 | |||
7982e786e6 | |||
96014b329d | |||
79fb40b8c9 | |||
cc23a58866 | |||
8542ea8de5 | |||
74b260a33e | |||
0d7df37f74 | |||
0eea7cc4d8 | |||
2ab103016e | |||
f8743b9d97 | |||
97cdfa9838 | |||
2f2051273d | |||
257b470083 | |||
e857052715 | |||
e2cba423e2 | |||
296aa65c9a | |||
d67397c1d3 | |||
7d68f939e4 | |||
5ec478c8cd | |||
ccadb06314 | |||
5543b732e9 | |||
044b3c1d2f | |||
c2afd241fc | |||
1bbe0db68d | |||
2f5b6668e6 | |||
e2632e48f7 | |||
08af2286be | |||
8620cecd47 | |||
963b774c0a | |||
1a2017a65f | |||
67c4c99cc5 | |||
2e176aae47 | |||
b0151e85e9 | |||
ea33f1e725 | |||
8d13493c2a | |||
caa0631004 | |||
51183a2cf1 | |||
e5b9bd681b | |||
31dd89f30e | |||
f04c5806d1 | |||
a3431937d0 | |||
729b21400c | |||
c29f36a997 | |||
784b14c9e9 | |||
b3d678f078 | |||
249e6e30a4 | |||
453c3a36e5 | |||
5c92d603d2 |
81
.cproject
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
|
||||||
|
<storageModule moduleId="org.eclipse.cdt.core.settings">
|
||||||
|
<cconfiguration id="0.1353761552">
|
||||||
|
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="0.1353761552" moduleId="org.eclipse.cdt.core.settings" name="Default">
|
||||||
|
<externalSettings/>
|
||||||
|
<extensions>
|
||||||
|
<extension id="org.eclipse.cdt.core.VCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||||
|
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||||
|
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||||
|
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||||
|
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||||
|
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||||
|
</extensions>
|
||||||
|
</storageModule>
|
||||||
|
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||||
|
<configuration artifactName="${ProjName}" buildProperties="" description="" id="0.1353761552" name="Default" parent="org.eclipse.cdt.build.core.prefbase.cfg">
|
||||||
|
<folderInfo id="0.1353761552." name="/" resourcePath="">
|
||||||
|
<toolChain id="org.eclipse.cdt.build.core.prefbase.toolchain.1359385240" name="No ToolChain" resourceTypeBasedDiscovery="false" superClass="org.eclipse.cdt.build.core.prefbase.toolchain">
|
||||||
|
<targetPlatform id="org.eclipse.cdt.build.core.prefbase.toolchain.1359385240.2064614940" name=""/>
|
||||||
|
<builder command="${NDKROOT}/ndk-build.cmd" enableAutoBuild="true" enableCleanBuild="true" id="org.eclipse.cdt.build.core.settings.default.builder.1504609501" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Gnu Make Builder" superClass="org.eclipse.cdt.build.core.settings.default.builder">
|
||||||
|
<outputEntries>
|
||||||
|
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="outputPath" name=""/>
|
||||||
|
</outputEntries>
|
||||||
|
</builder>
|
||||||
|
<tool id="org.eclipse.cdt.build.core.settings.holder.libs.979977589" name="holder for library settings" superClass="org.eclipse.cdt.build.core.settings.holder.libs"/>
|
||||||
|
<tool id="org.eclipse.cdt.build.core.settings.holder.743530782" name="Assembly" superClass="org.eclipse.cdt.build.core.settings.holder">
|
||||||
|
<option id="org.eclipse.cdt.build.core.settings.holder.incpaths.1231978083" name="Include Paths" superClass="org.eclipse.cdt.build.core.settings.holder.incpaths" valueType="includePath">
|
||||||
|
<listOptionValue builtIn="false" value=""${NDKROOT}\platforms\android-9\arch-arm\usr\include""/>
|
||||||
|
<listOptionValue builtIn="false" value=""${NDKROOT}\sources\cxx-stl\gnu-libstdc++\4.6\include""/>
|
||||||
|
<listOptionValue builtIn="false" value=""${NDKROOT}\sources\cxx-stl\gnu-libstdc++\4.6\libs\armeabi-v7a\include""/>
|
||||||
|
<listOptionValue builtIn="false" value=""C:\Users\miguel.astor\Documents\OpenCV-2.4.8-android-sdk\sdk\native\jni\include""/>
|
||||||
|
<listOptionValue builtIn="false" value=""C:\android-ndk-r9c\toolchains\arm-linux-androideabi-4.8\prebuilt\windows\lib\gcc\arm-linux-androideabi\4.8\include""/>
|
||||||
|
</option>
|
||||||
|
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.1450614296" languageId="org.eclipse.cdt.core.assembly" languageName="Assembly" sourceContentType="org.eclipse.cdt.core.asmSource" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
|
||||||
|
</tool>
|
||||||
|
<tool id="org.eclipse.cdt.build.core.settings.holder.2086329912" name="GNU C++" superClass="org.eclipse.cdt.build.core.settings.holder">
|
||||||
|
<option id="org.eclipse.cdt.build.core.settings.holder.incpaths.915443128" name="Include Paths" superClass="org.eclipse.cdt.build.core.settings.holder.incpaths" valueType="includePath">
|
||||||
|
<listOptionValue builtIn="false" value=""${NDKROOT}\platforms\android-9\arch-arm\usr\include""/>
|
||||||
|
<listOptionValue builtIn="false" value=""${NDKROOT}\sources\cxx-stl\gnu-libstdc++\4.6\include""/>
|
||||||
|
<listOptionValue builtIn="false" value=""${NDKROOT}\sources\cxx-stl\gnu-libstdc++\4.6\libs\armeabi-v7a\include""/>
|
||||||
|
<listOptionValue builtIn="false" value=""C:\Users\miguel.astor\Documents\OpenCV-2.4.8-android-sdk\sdk\native\jni\include""/>
|
||||||
|
<listOptionValue builtIn="false" value=""C:\android-ndk-r9c\toolchains\arm-linux-androideabi-4.8\prebuilt\windows\lib\gcc\arm-linux-androideabi\4.8\include""/>
|
||||||
|
</option>
|
||||||
|
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.1750170923" languageId="org.eclipse.cdt.core.g++" languageName="GNU C++" sourceContentType="org.eclipse.cdt.core.cxxSource,org.eclipse.cdt.core.cxxHeader" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
|
||||||
|
</tool>
|
||||||
|
<tool id="org.eclipse.cdt.build.core.settings.holder.1705205854" name="GNU C" superClass="org.eclipse.cdt.build.core.settings.holder">
|
||||||
|
<option id="org.eclipse.cdt.build.core.settings.holder.incpaths.1859743695" name="Include Paths" superClass="org.eclipse.cdt.build.core.settings.holder.incpaths" valueType="includePath">
|
||||||
|
<listOptionValue builtIn="false" value=""${NDKROOT}\platforms\android-9\arch-arm\usr\include""/>
|
||||||
|
<listOptionValue builtIn="false" value=""${NDKROOT}\sources\cxx-stl\gnu-libstdc++\4.6\include""/>
|
||||||
|
<listOptionValue builtIn="false" value=""${NDKROOT}\sources\cxx-stl\gnu-libstdc++\4.6\libs\armeabi-v7a\include""/>
|
||||||
|
<listOptionValue builtIn="false" value=""C:\Users\miguel.astor\Documents\OpenCV-2.4.8-android-sdk\sdk\native\jni\include""/>
|
||||||
|
<listOptionValue builtIn="false" value=""C:\android-ndk-r9c\toolchains\arm-linux-androideabi-4.8\prebuilt\windows\lib\gcc\arm-linux-androideabi\4.8\include""/>
|
||||||
|
</option>
|
||||||
|
<inputType id="org.eclipse.cdt.build.core.settings.holder.inType.343342792" languageId="org.eclipse.cdt.core.gcc" languageName="GNU C" sourceContentType="org.eclipse.cdt.core.cSource,org.eclipse.cdt.core.cHeader" superClass="org.eclipse.cdt.build.core.settings.holder.inType"/>
|
||||||
|
</tool>
|
||||||
|
</toolChain>
|
||||||
|
</folderInfo>
|
||||||
|
</configuration>
|
||||||
|
</storageModule>
|
||||||
|
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
||||||
|
</cconfiguration>
|
||||||
|
</storageModule>
|
||||||
|
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||||
|
<project id="NxtAR-android.null.1875632970" name="NxtAR-android"/>
|
||||||
|
</storageModule>
|
||||||
|
<storageModule moduleId="scannerConfiguration">
|
||||||
|
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||||
|
<scannerConfigBuildInfo instanceId="0.1353761552">
|
||||||
|
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||||
|
</scannerConfigBuildInfo>
|
||||||
|
</storageModule>
|
||||||
|
<storageModule moduleId="org.eclipse.cdt.core.pathentry"/>
|
||||||
|
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
|
||||||
|
<storageModule moduleId="refreshScope" versionNumber="2">
|
||||||
|
<configuration configurationName="Default">
|
||||||
|
<resource resourceType="PROJECT" workspacePath="/NxtAR-android"/>
|
||||||
|
</configuration>
|
||||||
|
</storageModule>
|
||||||
|
<storageModule moduleId="org.eclipse.cdt.internal.ui.text.commentOwnerProjectMappings"/>
|
||||||
|
</cproject>
|
67
.settings/org.eclipse.cdt.codan.core.prefs
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
eclipse.preferences.version=1
|
||||||
|
org.eclipse.cdt.codan.checkers.errnoreturn=Warning
|
||||||
|
org.eclipse.cdt.codan.checkers.errnoreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},implicit\=>false}
|
||||||
|
org.eclipse.cdt.codan.checkers.errreturnvalue=Error
|
||||||
|
org.eclipse.cdt.codan.checkers.errreturnvalue.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
|
||||||
|
org.eclipse.cdt.codan.checkers.noreturn=Error
|
||||||
|
org.eclipse.cdt.codan.checkers.noreturn.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},implicit\=>false}
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation=Error
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.AbstractClassCreation.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem=Error
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.AmbiguousProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem=Warning
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.AssignmentInConditionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem=Error
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.AssignmentToItselfProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem=Warning
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.CaseBreakProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},no_break_comment\=>"no break",last_case_param\=>false,empty_case_param\=>false}
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.CatchByReference=Warning
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.CatchByReference.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},unknown\=>false,exceptions\=>()}
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem=Error
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.CircularReferenceProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization=Warning
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.ClassMembersInitialization.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},skip\=>true}
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem=Error
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.FieldResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem=Error
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.FunctionResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.InvalidArguments=Error
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.InvalidArguments.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem=Error
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.InvalidTemplateArgumentsProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem=Error
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.LabelStatementNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem=Error
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.MemberDeclarationNotFoundProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem=Error
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.MethodResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker=-Info
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.NamingConventionFunctionChecker.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},pattern\=>"^[a-z]",macro\=>true,exceptions\=>()}
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem=Warning
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.NonVirtualDestructorProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.OverloadProblem=Error
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.OverloadProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem=Error
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.RedeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem=Error
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.RedefinitionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem=-Warning
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.ReturnStyleProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem=-Warning
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.ScanfFormatStringSecurityProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem=Warning
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.StatementHasNoEffectProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true,exceptions\=>()}
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem=Warning
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.SuggestedParenthesisProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},paramNot\=>false}
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem=Warning
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.SuspiciousSemicolonProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},else\=>false,afterelse\=>false}
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem=Error
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.TypeResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem=Warning
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.UnusedFunctionDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true}
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem=Warning
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.UnusedStaticFunctionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true}
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem=Warning
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.UnusedVariableDeclarationProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true},macro\=>true,exceptions\=>("@(\#)","$Id")}
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem=Error
|
||||||
|
org.eclipse.cdt.codan.internal.checkers.VariableResolutionProblem.params={launchModes\=>{RUN_ON_FULL_BUILD\=>true,RUN_ON_INC_BUILD\=>true,RUN_ON_FILE_OPEN\=>false,RUN_ON_FILE_SAVE\=>false,RUN_AS_YOU_TYPE\=>true,RUN_ON_DEMAND\=>true}}
|
@@ -14,11 +14,10 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
-->
|
-->
|
||||||
<!-- android:screenOrientation="portrait" -->
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="ve.ucv.ciens.ccg.nxtar"
|
package="ve.ucv.ciens.ccg.nxtar"
|
||||||
android:versionCode="140404"
|
android:versionCode="140716"
|
||||||
android:versionName="14.04.04" >
|
android:versionName="14.07.16" >
|
||||||
|
|
||||||
<uses-sdk android:minSdkVersion="12" android:targetSdkVersion="19" />
|
<uses-sdk android:minSdkVersion="12" android:targetSdkVersion="19" />
|
||||||
|
|
||||||
@@ -33,7 +32,7 @@
|
|||||||
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
|
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:icon="@drawable/ic_launcher"
|
android:icon="@drawable/ic_nxtar_core_launcher"
|
||||||
android:label="@string/app_name" android:allowBackup="true">
|
android:label="@string/app_name" android:allowBackup="true">
|
||||||
<activity
|
<activity
|
||||||
android:name=".MainActivity"
|
android:name=".MainActivity"
|
||||||
|
45
README.md
@@ -1,4 +1,43 @@
|
|||||||
NxtAR-android
|
NxtAR: A generic software architecture for Augmented Reality based mobile robot control.
|
||||||
=============
|
========================================================================================
|
||||||
|
|
||||||
Modulo 2 de mi trabajo especial de grado.
|
Android backend module
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
### Abstract ###
|
||||||
|
|
||||||
|
NxtAR is a generic software architecture for the development of Augmented Reality games
|
||||||
|
and applications centered around mobile robot control. This is a reference implementation
|
||||||
|
with support for [LEGO Mindstorms NXT][1] mobile robots.
|
||||||
|
|
||||||
|
### Module description ###
|
||||||
|
|
||||||
|
The Android backend module is a concrete [LibGDX][2] application that implements the operating
|
||||||
|
system dependent parts of the NxtAR reference implementation. It is based around the [OpenCV][3]
|
||||||
|
Computer Vision and Machine Learning library. Currently this module supports Android (>= 3.1)
|
||||||
|
devices though it has been tested only on Android (>= 4.0). The module includes direct support for
|
||||||
|
the [OUYA][4] gaming console and other devices using OUYA gamepads.
|
||||||
|
|
||||||
|
### Module installation and usage. ###
|
||||||
|
|
||||||
|
Install the NxtAR-core_XXXXXX.apk file on your device. To use you need additionally an Android (>= 3.0)
|
||||||
|
phone and a LEGO Mindstorms NXT robot with the [LejOS][5] firmware installed. The [NxtAR-cam][6] module must be
|
||||||
|
installed on the device and the [NxtAR-bot][7] module must be installed on the robot. Then, to start the compiled
|
||||||
|
scenario follow these steps:
|
||||||
|
|
||||||
|
* Start the NxtAR-core application.
|
||||||
|
* Start the NxtAR-bot program on the robot.
|
||||||
|
* Calibrate the robot's light sensor following the on-screen instructions.
|
||||||
|
* When the robot displays *"Waiting for connection"* start the NxtAR-cam application and connect it with the robot.
|
||||||
|
* Press the *"Start video streaming"* button on the NxtAR-cam application.
|
||||||
|
* Press the *"Calibrate camera"* button on the NxtAR-core application and point the camera of the device running NxtAR-cam to an OpenCV checkerboard camera calibration pattern.
|
||||||
|
|
||||||
|
The camera calibration step can be repeated if needed.
|
||||||
|
|
||||||
|
[1]: http://www.lego.com/en-us/mindstorms/?domainredir=mindstorms.lego.com
|
||||||
|
[2]: http://libgdx.badlogicgames.com/
|
||||||
|
[3]: http://opencv.org/
|
||||||
|
[4]: https://www.ouya.tv/
|
||||||
|
[5]: http://www.lejos.org/nxj.php
|
||||||
|
[6]: https://github.com/sagge-miky/NxtAR-cam
|
||||||
|
[7]: https://github.com/sagge-miky/NxtAR-bot
|
||||||
|
BIN
assets/data/gfx/bomb_game/Anonymous_heart_1.png
Normal file
After Width: | Height: | Size: 30 KiB |
BIN
assets/data/gfx/bomb_game/comb_bomb.png
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
assets/data/gfx/bomb_game/incl_bomb.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
assets/data/gfx/bomb_game/wire_bomb.png
Normal file
After Width: | Height: | Size: 6.0 KiB |
BIN
assets/data/gfx/gui/Anonymous_Button_Cyan.png
Normal file
After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 7.3 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 6.8 KiB |
BIN
assets/data/gfx/gui/arm.png
Normal file
After Width: | Height: | Size: 58 KiB |
BIN
assets/data/gfx/gui/down_button.png
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
assets/data/gfx/gui/help.png
Normal file
After Width: | Height: | Size: 42 KiB |
BIN
assets/data/gfx/gui/left_button.png
Normal file
After Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 4.3 KiB |
BIN
assets/data/gfx/gui/right_button.png
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
assets/data/gfx/gui/slider_black.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
assets/data/gfx/gui/up_button.png
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
assets/data/gfx/gui/wheel.png
Normal file
After Width: | Height: | Size: 20 KiB |
3542
assets/models/Bomb_test_1.g3dj
Normal file
BIN
assets/models/Bomb_test_2.g3db
Normal file
3542
assets/models/Bomb_test_2.g3dj
Normal file
BIN
assets/models/collision_models/bomb_game/big_btn_col.g3db
Normal file
BIN
assets/models/collision_models/bomb_game/bomb_1_body_col.g3db
Normal file
BIN
assets/models/collision_models/bomb_game/bomb_2_body_col.g3db
Normal file
BIN
assets/models/collision_models/bomb_game/bomb_3_body_col.g3db
Normal file
BIN
assets/models/collision_models/bomb_game/bomb_3_btn_1_col.g3db
Normal file
BIN
assets/models/collision_models/bomb_game/bomb_3_btn_2_col.g3db
Normal file
BIN
assets/models/collision_models/bomb_game/bomb_3_btn_3_col.g3db
Normal file
BIN
assets/models/collision_models/bomb_game/bomb_3_btn_4_col.g3db
Normal file
BIN
assets/models/collision_models/bomb_game/cable_1_col.g3db
Normal file
BIN
assets/models/collision_models/bomb_game/cable_2_col.g3db
Normal file
BIN
assets/models/collision_models/bomb_game/cable_3_col.g3db
Normal file
BIN
assets/models/collision_models/bomb_game/door_col.g3db
Normal file
BIN
assets/models/collision_models/bomb_game/door_frame1_col.g3db
Normal file
BIN
assets/models/collision_models/bomb_game/robot_arm_col.g3db
Normal file
1101
assets/models/cube.g3dj
Normal file
BIN
assets/models/render_models/bomb_game/big_btn.g3db
Normal file
BIN
assets/models/render_models/bomb_game/bomb_1_body.g3db
Normal file
BIN
assets/models/render_models/bomb_game/bomb_2_body.g3db
Normal file
BIN
assets/models/render_models/bomb_game/bomb_3_body.g3db
Normal file
BIN
assets/models/render_models/bomb_game/bomb_3_btn_1.g3db
Normal file
BIN
assets/models/render_models/bomb_game/bomb_3_btn_2.g3db
Normal file
BIN
assets/models/render_models/bomb_game/bomb_3_btn_3.g3db
Normal file
BIN
assets/models/render_models/bomb_game/bomb_3_btn_4.g3db
Normal file
BIN
assets/models/render_models/bomb_game/cable_1.g3db
Normal file
BIN
assets/models/render_models/bomb_game/cable_2.g3db
Normal file
BIN
assets/models/render_models/bomb_game/cable_3.g3db
Normal file
BIN
assets/models/render_models/bomb_game/door.g3db
Normal file
BIN
assets/models/render_models/bomb_game/door_frame1.g3db
Normal file
BIN
assets/models/render_models/bomb_game/monkey.g3db
Normal file
BIN
assets/models/render_models/bomb_game/robot_arm.g3db
Normal file
29
assets/shaders/alphaSprite/alpha_frag.glsl
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 Miguel Angel Astor Romero
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
#ifdef GL_ES
|
||||||
|
precision mediump float;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uniform sampler2D u_texture;
|
||||||
|
|
||||||
|
varying vec2 v_texCoords;
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
vec4 texColor = texture2D(u_texture, v_texCoords);
|
||||||
|
if(texColor.a > 0.0)
|
||||||
|
texColor.a = 0.5;
|
||||||
|
gl_FragColor = texColor;
|
||||||
|
}
|
26
assets/shaders/alphaSprite/alpha_vert.glsl
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 Miguel Angel Astor Romero
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
uniform mat4 u_projTrans;
|
||||||
|
|
||||||
|
attribute vec4 a_position;
|
||||||
|
attribute vec2 a_texCoord0;
|
||||||
|
|
||||||
|
varying vec2 v_texCoords;
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
v_texCoords = a_texCoord0;
|
||||||
|
gl_Position = u_projTrans * a_position;
|
||||||
|
}
|
@@ -1,12 +0,0 @@
|
|||||||
#ifdef GL_ES
|
|
||||||
precision mediump float;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uniform sampler2D u_texture;
|
|
||||||
uniform vec2 u_scaling;
|
|
||||||
|
|
||||||
varying vec2 v_texCoords;
|
|
||||||
|
|
||||||
void main(){
|
|
||||||
gl_FragColor = texture2D(u_texture, v_texCoords * u_scaling);
|
|
||||||
}
|
|
@@ -1,11 +0,0 @@
|
|||||||
uniform mat4 u_projTrans;
|
|
||||||
|
|
||||||
attribute vec4 a_position;
|
|
||||||
attribute vec2 a_texCoord0;
|
|
||||||
|
|
||||||
varying vec2 v_texCoords;
|
|
||||||
|
|
||||||
void main(){
|
|
||||||
v_texCoords = a_texCoord0;
|
|
||||||
gl_Position = u_projTrans * a_position;
|
|
||||||
}
|
|
27
assets/shaders/bckg/bckg_frag.glsl
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 Miguel Angel Astor Romero
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
#ifdef GL_ES
|
||||||
|
precision mediump float;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uniform sampler2D u_texture;
|
||||||
|
uniform vec2 u_scaling;
|
||||||
|
|
||||||
|
varying vec2 v_texCoords;
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
gl_FragColor = texture2D(u_texture, v_texCoords * u_scaling);
|
||||||
|
}
|
26
assets/shaders/bckg/bckg_vert.glsl
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 Miguel Angel Astor Romero
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
uniform mat4 u_projTrans;
|
||||||
|
|
||||||
|
attribute vec4 a_position;
|
||||||
|
attribute vec2 a_texCoord0;
|
||||||
|
|
||||||
|
varying vec2 v_texCoords;
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
v_texCoords = a_texCoord0;
|
||||||
|
gl_Position = u_projTrans * a_position;
|
||||||
|
}
|
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 Miguel Angel Astor Romero
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef GL_ES
|
||||||
|
precision mediump float;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Ambient light color.
|
||||||
|
uniform vec4 u_ambient;
|
||||||
|
|
||||||
|
// Specular light color.
|
||||||
|
uniform vec4 u_specular;
|
||||||
|
|
||||||
|
// Shininess.
|
||||||
|
uniform float u_shiny;
|
||||||
|
|
||||||
|
// Fragment normal.
|
||||||
|
varying vec3 v_normal;
|
||||||
|
|
||||||
|
// Fragment shaded diffuse color.
|
||||||
|
varying vec4 v_diffuse;
|
||||||
|
|
||||||
|
// Vector from the fragment to the camera.
|
||||||
|
varying vec3 v_eyeVector;
|
||||||
|
|
||||||
|
// The light vector reflected around the fragment normal.
|
||||||
|
varying vec3 v_reflectedVector;
|
||||||
|
|
||||||
|
// The clamped dot product between the normal and the light vector.
|
||||||
|
varying float v_nDotL;
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
// Normalize the input varyings.
|
||||||
|
vec3 normal = normalize(v_normal);
|
||||||
|
vec3 eyeVector = normalize(v_eyeVector);
|
||||||
|
vec3 reflectedVector = normalize(v_reflectedVector);
|
||||||
|
|
||||||
|
// Specular Term.
|
||||||
|
vec4 specular = vec4(0.0, 0.0, 0.0, 1.0);
|
||||||
|
if(v_nDotL > 0.0){
|
||||||
|
specular = u_specular * pow(max(dot(reflectedVector, eyeVector), 0.0), u_shiny);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aggregate light color.
|
||||||
|
vec4 finalColor = clamp(vec4(/*u_ambient.rgb*/ + v_diffuse.rgb + specular.rgb, 1.0), 0.0, 1.0);
|
||||||
|
|
||||||
|
// Final color.
|
||||||
|
gl_FragColor = finalColor;
|
||||||
|
}
|
@@ -0,0 +1,160 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 Miguel Angel Astor Romero
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Model-view matrix.
|
||||||
|
uniform mat4 u_projTrans;
|
||||||
|
|
||||||
|
// The world space geometric transformation to apply to this vertex.
|
||||||
|
uniform mat4 u_geomTrans;
|
||||||
|
|
||||||
|
// The inverse transpose of the geometric transformation matrix.
|
||||||
|
uniform mat4 u_normalMatrix;
|
||||||
|
|
||||||
|
// Light source position
|
||||||
|
uniform vec3 u_lightPos;
|
||||||
|
|
||||||
|
// Diffuse light color.
|
||||||
|
uniform vec4 u_lightDiffuse;
|
||||||
|
|
||||||
|
// Camera world space position.
|
||||||
|
uniform vec3 u_cameraPos;
|
||||||
|
|
||||||
|
// Vertex color.
|
||||||
|
uniform vec4 u_materialDiffuse;
|
||||||
|
|
||||||
|
#ifdef SKINNING
|
||||||
|
// The model's bones.
|
||||||
|
uniform mat4 u_bone0;
|
||||||
|
uniform mat4 u_bone1;
|
||||||
|
uniform mat4 u_bone2;
|
||||||
|
uniform mat4 u_bone3;
|
||||||
|
#endif // SKINNING
|
||||||
|
|
||||||
|
// Vertex position in world coordinates.
|
||||||
|
attribute vec4 a_position;
|
||||||
|
|
||||||
|
// Vertex normal.
|
||||||
|
attribute vec4 a_normal;
|
||||||
|
|
||||||
|
#ifdef SKINNING
|
||||||
|
// The weight of each bone.
|
||||||
|
attribute vec2 a_boneWeight0;
|
||||||
|
attribute vec2 a_boneWeight1;
|
||||||
|
attribute vec2 a_boneWeight2;
|
||||||
|
attribute vec2 a_boneWeight3;
|
||||||
|
#endif // SKINNING
|
||||||
|
|
||||||
|
// Fragment normal.
|
||||||
|
varying vec3 v_normal;
|
||||||
|
|
||||||
|
// Diffuse shaded color.
|
||||||
|
varying vec4 v_diffuse;
|
||||||
|
|
||||||
|
// The vector from the vertex to the camera.
|
||||||
|
varying vec3 v_eyeVector;
|
||||||
|
|
||||||
|
// The light vector reflected around the vertex normal.
|
||||||
|
varying vec3 v_reflectedVector;
|
||||||
|
|
||||||
|
// The clamped dot product between the normal and the light vector.
|
||||||
|
varying float v_nDotL;
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
vec4 transformedPosition;
|
||||||
|
|
||||||
|
vec3 lightVector = normalize(u_lightPos.xyz);
|
||||||
|
vec3 invLightVector = -lightVector;
|
||||||
|
|
||||||
|
#ifdef SKINNING
|
||||||
|
// Do the skinning.
|
||||||
|
mat4 bones0;
|
||||||
|
mat4 bones1;
|
||||||
|
mat4 bones2;
|
||||||
|
mat4 bones3;
|
||||||
|
bones0 = u_bone0;
|
||||||
|
bones1 = u_bone1;
|
||||||
|
bones2 = u_bone2;
|
||||||
|
bones3 = u_bone3;
|
||||||
|
|
||||||
|
int index;
|
||||||
|
mat4 skinning = mat4(0.0);
|
||||||
|
|
||||||
|
index = int(a_boneWeight0.x);
|
||||||
|
if(index == 0){
|
||||||
|
skinning += (a_boneWeight0.y) * bones0;
|
||||||
|
}else if(index == 1){
|
||||||
|
skinning += (a_boneWeight0.y) * bones1;
|
||||||
|
}else if(index == 2){
|
||||||
|
skinning += (a_boneWeight0.y) * bones2;
|
||||||
|
}else if(index == 3){
|
||||||
|
skinning += (a_boneWeight0.y) * bones3;
|
||||||
|
}
|
||||||
|
|
||||||
|
index = int(a_boneWeight1.x);
|
||||||
|
if(index == 0){
|
||||||
|
skinning += (a_boneWeight1.y) * bones0;
|
||||||
|
}else if(index == 1){
|
||||||
|
skinning += (a_boneWeight1.y) * bones1;
|
||||||
|
}else if(index == 2){
|
||||||
|
skinning += (a_boneWeight1.y) * bones2;
|
||||||
|
}else if(index == 3){
|
||||||
|
skinning += (a_boneWeight1.y) * bones3;
|
||||||
|
}
|
||||||
|
|
||||||
|
index = int(a_boneWeight2.x);
|
||||||
|
if(index == 0){
|
||||||
|
skinning += (a_boneWeight2.y) * bones0;
|
||||||
|
}else if(index == 1){
|
||||||
|
skinning += (a_boneWeight2.y) * bones1;
|
||||||
|
}else if(index == 2){
|
||||||
|
skinning += (a_boneWeight2.y) * bones2;
|
||||||
|
}else if(index == 3){
|
||||||
|
skinning += (a_boneWeight2.y) * bones3;
|
||||||
|
}
|
||||||
|
|
||||||
|
index = int(a_boneWeight3.x);
|
||||||
|
if(index == 0){
|
||||||
|
skinning += (a_boneWeight3.y) * bones0;
|
||||||
|
}else if(index == 1){
|
||||||
|
skinning += (a_boneWeight3.y) * bones1;
|
||||||
|
}else if(index == 2){
|
||||||
|
skinning += (a_boneWeight3.y) * bones2;
|
||||||
|
}else if(index == 3){
|
||||||
|
skinning += (a_boneWeight3.y) * bones3;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transform the model.
|
||||||
|
transformedPosition = u_geomTrans * skinning * a_position;
|
||||||
|
#else
|
||||||
|
transformedPosition = u_geomTrans * a_position;
|
||||||
|
#endif // SKINNING
|
||||||
|
|
||||||
|
// Set the varyings.
|
||||||
|
#ifdef SKINNING
|
||||||
|
v_normal = normalize(vec4(u_normalMatrix * skinning * a_normal).xyz);
|
||||||
|
#else
|
||||||
|
v_normal = normalize(vec4(u_normalMatrix * a_normal).xyz);
|
||||||
|
#endif // SKINNING
|
||||||
|
v_eyeVector = normalize(u_cameraPos.xyz - transformedPosition.xyz);
|
||||||
|
v_reflectedVector = normalize(reflect(invLightVector, v_normal));
|
||||||
|
|
||||||
|
// Diffuse Term.
|
||||||
|
float invNDotL = max(dot(v_normal.xyz, invLightVector), 0.0);
|
||||||
|
v_nDotL = max(dot(v_normal.xyz, lightVector), 0.0);
|
||||||
|
v_diffuse = (u_lightDiffuse * u_materialDiffuse * v_nDotL) + (vec4(0.1, 0.1, 0.2, 1.0) * u_materialDiffuse * invNDotL);
|
||||||
|
|
||||||
|
gl_Position = u_projTrans * transformedPosition;
|
||||||
|
}
|
27
assets/shaders/movingBckg/movingBckg_frag.glsl
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 Miguel Angel Astor Romero
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
#ifdef GL_ES
|
||||||
|
precision mediump float;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uniform sampler2D u_texture;
|
||||||
|
uniform vec2 u_scaling;
|
||||||
|
|
||||||
|
varying vec2 v_texCoords;
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
gl_FragColor = texture2D(u_texture, v_texCoords * u_scaling);
|
||||||
|
}
|
27
assets/shaders/movingBckg/movingBckg_vert.glsl
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 Miguel Angel Astor Romero
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
uniform mat4 u_projTrans;
|
||||||
|
uniform float u_displacement;
|
||||||
|
|
||||||
|
attribute vec4 a_position;
|
||||||
|
attribute vec2 a_texCoord0;
|
||||||
|
|
||||||
|
varying vec2 v_texCoords;
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
v_texCoords = a_texCoord0 + u_displacement;
|
||||||
|
gl_Position = u_projTrans * a_position;
|
||||||
|
}
|
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 Miguel Angel Astor Romero
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef GL_ES
|
||||||
|
precision mediump float;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Ambient light color.
|
||||||
|
uniform vec4 u_ambient;
|
||||||
|
|
||||||
|
// Specular light color.
|
||||||
|
uniform vec4 u_specular;
|
||||||
|
|
||||||
|
// Shininess.
|
||||||
|
uniform float u_shiny;
|
||||||
|
|
||||||
|
// Fragment position.
|
||||||
|
varying vec4 v_position;
|
||||||
|
|
||||||
|
// Fragment normal.
|
||||||
|
varying vec3 v_normal;
|
||||||
|
|
||||||
|
// Fragment color received from the vertex shader.
|
||||||
|
varying vec4 v_color;
|
||||||
|
|
||||||
|
// Fragment shaded diffuse color.
|
||||||
|
varying vec4 v_diffuse;
|
||||||
|
|
||||||
|
varying vec3 v_lightVector;
|
||||||
|
varying vec3 v_eyeVector;
|
||||||
|
varying vec3 v_reflectedVector;
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
// Normalize the input varyings.
|
||||||
|
vec3 lightVector = normalize(v_lightVector);
|
||||||
|
vec3 eyeVector = normalize(v_eyeVector);
|
||||||
|
vec3 reflectedVector = normalize(v_reflectedVector);
|
||||||
|
|
||||||
|
// Specular Term:
|
||||||
|
vec4 specular = u_specular * pow(max(dot(reflectedVector, eyeVector), 0.0), 0.3 * u_shiny);
|
||||||
|
|
||||||
|
// Aggregate light color.
|
||||||
|
vec4 lightColor = clamp(vec4(u_ambient.rgb + v_diffuse.rgb + specular.rgb, 1.0), 0.0, 1.0);
|
||||||
|
|
||||||
|
// Final color.
|
||||||
|
gl_FragColor = clamp(lightColor, 0.0, 1.0);
|
||||||
|
}
|
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2014 Miguel Angel Astor Romero
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Model-view matrix.
|
||||||
|
uniform mat4 u_projTrans;
|
||||||
|
|
||||||
|
// The world space geometric transformation to apply to this vertex.
|
||||||
|
uniform mat4 u_geomTrans;
|
||||||
|
|
||||||
|
// Light source position
|
||||||
|
uniform vec4 u_lightPos;
|
||||||
|
|
||||||
|
// Diffuse light color.
|
||||||
|
uniform vec4 u_lightDiffuse;
|
||||||
|
|
||||||
|
// Camera world space position.
|
||||||
|
uniform vec3 u_cameraPos;
|
||||||
|
|
||||||
|
// Vertex position in world coordinates.
|
||||||
|
attribute vec4 a_position;
|
||||||
|
|
||||||
|
// Vertex normal.
|
||||||
|
attribute vec4 a_normal;
|
||||||
|
|
||||||
|
// Vertex color.
|
||||||
|
attribute vec4 a_color;
|
||||||
|
|
||||||
|
// Vertex color to pass to the fragment shader.
|
||||||
|
varying vec4 v_color;
|
||||||
|
|
||||||
|
// Diffuse shaded color to pass to the fragment shader.
|
||||||
|
varying vec4 v_diffuse;
|
||||||
|
|
||||||
|
// The vector from the vertex to the light source.
|
||||||
|
varying vec3 v_lightVector;
|
||||||
|
|
||||||
|
// The vector from the vertex to the camera.
|
||||||
|
varying vec3 v_eyeVector;
|
||||||
|
|
||||||
|
// The light vector reflected around the vertex normal.
|
||||||
|
varying vec3 v_reflectedVector;
|
||||||
|
|
||||||
|
void main(){
|
||||||
|
// Apply the geometric transformation to the original position of the vertex.
|
||||||
|
vec4 transformedPosition = u_geomTrans * a_position;
|
||||||
|
|
||||||
|
// Set the varyings.
|
||||||
|
v_lightVector = normalize(u_lightPos.xyz - transformedPosition.xyz);
|
||||||
|
v_eyeVector = normalize(u_cameraPos.xyz - transformedPosition.xyz);
|
||||||
|
v_reflectedVector = normalize(-reflect(v_lightVector, a_normal.xyz));
|
||||||
|
v_color = a_color;
|
||||||
|
|
||||||
|
// Diffuse Term.
|
||||||
|
v_diffuse = u_lightDiffuse * vec4(1.0) * max(dot(a_normal.xyz, v_lightVector), 0.0);
|
||||||
|
|
||||||
|
gl_Position = u_projTrans * transformedPosition;
|
||||||
|
}
|
BIN
ic_nxtar_core_launcher-web.png
Normal file
After Width: | Height: | Size: 21 KiB |
@@ -3,7 +3,7 @@ LOCAL_PATH := $(call my-dir)
|
|||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
OPENCV_CAMERA_MODULES:=off
|
OPENCV_CAMERA_MODULES:=off
|
||||||
OPENCV_LIB_TYPE:=STATIC
|
OPENCV_LIB_TYPE:=STATIC #SHARED
|
||||||
include C:\Users\miguel.astor\Documents\OpenCV-2.4.8-android-sdk\sdk\native\jni\OpenCV.mk
|
include C:\Users\miguel.astor\Documents\OpenCV-2.4.8-android-sdk\sdk\native\jni\OpenCV.mk
|
||||||
|
|
||||||
LOCAL_MODULE := cvproc
|
LOCAL_MODULE := cvproc
|
||||||
@@ -25,4 +25,67 @@ include $(CLEAR_VARS)
|
|||||||
LOCAL_MODULE := gdx-freetype
|
LOCAL_MODULE := gdx-freetype
|
||||||
LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libgdx-freetype.so
|
LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libgdx-freetype.so
|
||||||
|
|
||||||
include $(PREBUILT_SHARED_LIBRARY)
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_MODULE := ocv_tegra_java
|
||||||
|
LOCAL_SRC_FILES := C:\\Users\\miguel.astor\\Documents\\OpenCV-2.4.8-android-sdk\\sdk\\native\\libs\\armeabi-v7a\\libopencv_java.so
|
||||||
|
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_MODULE := ocv_tegra_info
|
||||||
|
LOCAL_SRC_FILES := C:\\Users\\miguel.astor\\Documents\\OpenCV-2.4.8-android-sdk\\sdk\\native\\libs\\armeabi-v7a\\libopencv_info.so
|
||||||
|
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_MODULE := ocv_tegra_native_camera_220
|
||||||
|
LOCAL_SRC_FILES := C:\\Users\\miguel.astor\\Documents\\OpenCV-2.4.8-android-sdk\\sdk\\native\\libs\\armeabi-v7a\\libnative_camera_r2.2.0.so
|
||||||
|
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_MODULE := ocv_tegra_native_camera_233
|
||||||
|
LOCAL_SRC_FILES := C:\\Users\\miguel.astor\\Documents\\OpenCV-2.4.8-android-sdk\\sdk\\native\\libs\\armeabi-v7a\\libnative_camera_r2.3.3.so
|
||||||
|
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_MODULE := ocv_tegra_native_camera_301
|
||||||
|
LOCAL_SRC_FILES := C:\\Users\\miguel.astor\\Documents\\OpenCV-2.4.8-android-sdk\\sdk\\native\\libs\\armeabi-v7a\\libnative_camera_r3.0.1.so
|
||||||
|
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_MODULE := ocv_tegra_native_camera_400
|
||||||
|
LOCAL_SRC_FILES := C:\\Users\\miguel.astor\\Documents\\OpenCV-2.4.8-android-sdk\\sdk\\native\\libs\\armeabi-v7a\\libnative_camera_r4.0.0.so
|
||||||
|
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_MODULE := ocv_tegra_native_camera_403
|
||||||
|
LOCAL_SRC_FILES := C:\\Users\\miguel.astor\\Documents\\OpenCV-2.4.8-android-sdk\\sdk\\native\\libs\\armeabi-v7a\\libnative_camera_r4.0.3.so
|
||||||
|
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_MODULE := ocv_tegra_native_camera_411
|
||||||
|
LOCAL_SRC_FILES := C:\\Users\\miguel.astor\\Documents\\OpenCV-2.4.8-android-sdk\\sdk\\native\\libs\\armeabi-v7a\\libnative_camera_r4.1.1.so
|
||||||
|
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
|
||||||
|
include $(CLEAR_VARS)
|
||||||
|
|
||||||
|
LOCAL_MODULE := ocv_tegra_native_camera_420
|
||||||
|
LOCAL_SRC_FILES := C:\\Users\\miguel.astor\\Documents\\OpenCV-2.4.8-android-sdk\\sdk\\native\\libs\\armeabi-v7a\\libnative_camera_r4.2.0.so
|
||||||
|
|
||||||
|
include $(PREBUILT_SHARED_LIBRARY)
|
||||||
|
191
jni/cv_proc.cpp
@@ -16,56 +16,171 @@
|
|||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
#include <android/log.h>
|
#include <android/log.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
#include "marker.hpp"
|
#include "marker.hpp"
|
||||||
|
|
||||||
//#define CAN_LOG
|
//#define LOG_ENABLED
|
||||||
|
#define MAX_MARKERS 5
|
||||||
extern "C"{
|
#define TRANSLATION_VECTOR_POINTS 3
|
||||||
#ifdef CAN_LOG
|
#define ROTATION_MATRIX_SIZE 9
|
||||||
|
#define POINTS_PER_CALIBRATION_SAMPLE 54
|
||||||
|
#define CALIBRATION_SAMPLES 10
|
||||||
|
|
||||||
|
#ifdef LOG_ENABLED
|
||||||
#define log(TAG, MSG) (__android_log_write(ANDROID_LOG_DEBUG, TAG, MSG))
|
#define log(TAG, MSG) (__android_log_write(ANDROID_LOG_DEBUG, TAG, MSG))
|
||||||
|
#else
|
||||||
|
#define log(TAG, MSG) ;
|
||||||
|
#endif
|
||||||
|
|
||||||
const char * TAG = "CVPROC_NATIVE";
|
const char * TAG = "CVPROC_NATIVE";
|
||||||
|
|
||||||
#else
|
extern "C"{
|
||||||
|
|
||||||
#define log(TAG, MSG) (1 + 1)
|
/**
|
||||||
|
* JNI wrapper around the nxtar::getAllMarkers() method.
|
||||||
|
*/
|
||||||
|
JNIEXPORT void JNICALL Java_ve_ucv_ciens_ccg_nxtar_MainActivity_getMarkerCodesAndLocations(JNIEnv* env, jobject jobj, jlong addrMatIn, jlong addrMatOut, jintArray codes, jlong camMat, jlong distMat, jfloatArray translations, jfloatArray rotations){
|
||||||
|
char codeMsg[128];
|
||||||
|
std::vector<int> vCodes;
|
||||||
|
nxtar::markers_vector vMarkers;
|
||||||
|
cv::Mat temp;
|
||||||
|
|
||||||
#endif
|
// Get the native object addresses.
|
||||||
|
log(TAG, "getMarkerCodesAndLocations(): Requesting native data.");
|
||||||
|
cv::Mat& myuv = *(cv::Mat*)addrMatIn;
|
||||||
|
cv::Mat& mbgr = *(cv::Mat*)addrMatOut;
|
||||||
|
cv::Mat& mCam = *(cv::Mat*)camMat;
|
||||||
|
cv::Mat& mDist = *(cv::Mat*)distMat;
|
||||||
|
jint * _codes = env->GetIntArrayElements(codes, 0);
|
||||||
|
jfloat * _tr = env->GetFloatArrayElements(translations, 0);
|
||||||
|
jfloat * _rt = env->GetFloatArrayElements(rotations, 0);
|
||||||
|
|
||||||
JNIEXPORT void JNICALL Java_ve_ucv_ciens_ccg_nxtar_MainActivity_getMarkerCodesAndLocations(
|
// Convert the input image to the BGR color space.
|
||||||
JNIEnv* env,
|
log(TAG, "getMarkerCodesAndLocations(): Converting color space before processing.");
|
||||||
jobject jobj,
|
cv::cvtColor(myuv, temp, CV_RGB2BGR);
|
||||||
jlong addrMatIn,
|
|
||||||
jlong addrMatOut,
|
|
||||||
jintArray codes
|
|
||||||
){
|
|
||||||
char codeMsg[128];
|
|
||||||
std::vector<int> vCodes;
|
|
||||||
|
|
||||||
log(TAG, "Requesting native data.");
|
// Find all markers in the input image.
|
||||||
|
log(TAG, "getMarkerCodesAndLocations(): Finding markers.");
|
||||||
|
nxtar::getAllMarkers(vMarkers, temp);
|
||||||
|
nxtar::estimateMarkerPosition(vMarkers, mCam, mDist);
|
||||||
|
|
||||||
cv::Mat& myuv = *(cv::Mat*)addrMatIn;
|
// Copy the marker codes to the output vector.
|
||||||
cv::Mat& mbgr = *(cv::Mat*)addrMatOut;
|
log(TAG, "getMarkerCodesAndLocations(): Copying marker codes.");
|
||||||
jint * _codes = env->GetIntArrayElements(codes, 0);
|
for(size_t i = 0; i < vMarkers.size() && i < MAX_MARKERS; i++){
|
||||||
|
_codes[i] = (jint)vMarkers[i].code;
|
||||||
log(TAG, "Converting color space before processing.");
|
|
||||||
cv::cvtColor(myuv, mbgr, CV_RGB2BGR);
|
|
||||||
|
|
||||||
log(TAG, "Finding markers.");
|
|
||||||
nxtar::getAllMarkers(vCodes, mbgr);
|
|
||||||
|
|
||||||
log(TAG, "Copying marker codes.");
|
|
||||||
for(int i = 0; i < vCodes.size() && i < 15; i++){
|
|
||||||
_codes[i] = vCodes[i];
|
|
||||||
sprintf(codeMsg, "Code [%d] = %d", i, vCodes[i]);
|
|
||||||
log(TAG, codeMsg);
|
|
||||||
}
|
|
||||||
vCodes.clear();
|
|
||||||
|
|
||||||
log(TAG, "Releasing native data.");
|
|
||||||
|
|
||||||
env->ReleaseIntArrayElements(codes, _codes, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copy the geometric transformations to the output vectors.
|
||||||
|
for(int i = 0, p = 0; i < vMarkers.size(); i++, p += 3){
|
||||||
|
_tr[p ] = vMarkers[i].translation.at<jfloat>(0);
|
||||||
|
_tr[p + 1] = vMarkers[i].translation.at<jfloat>(1);
|
||||||
|
_tr[p + 2] = vMarkers[i].translation.at<jfloat>(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int k = 0; k < vMarkers.size(); k++){
|
||||||
|
for(int row = 0; row < 3; row++){
|
||||||
|
for(int col = 0; col < 3; col++){
|
||||||
|
_rt[col + (row * 3) + (9 * k)] = vMarkers[k].rotation.at<jfloat>(row, col);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear marker memory.
|
||||||
|
vMarkers.clear();
|
||||||
|
|
||||||
|
// Convert the output image back to the RGB color space.
|
||||||
|
cv::cvtColor(temp, mbgr, CV_BGR2RGB);
|
||||||
|
|
||||||
|
// Release native data.
|
||||||
|
log(TAG, "getMarkerCodesAndLocations(): Releasing native data.");
|
||||||
|
env->ReleaseIntArrayElements(codes, _codes, 0);
|
||||||
|
env->ReleaseFloatArrayElements(translations, _tr, 0);
|
||||||
|
env->ReleaseFloatArrayElements(rotations, _rt, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JNI wrapper around the nxtar::findCalibrationPattern() method.
|
||||||
|
*/
|
||||||
|
JNIEXPORT jboolean JNICALL Java_ve_ucv_ciens_ccg_nxtar_MainActivity_findCalibrationPattern(JNIEnv* env, jobject jobj, jlong addrMatIn, jlong addrMatOut, jfloatArray points){
|
||||||
|
nxtar::points_vector v_points;
|
||||||
|
bool found;
|
||||||
|
cv::Mat temp;
|
||||||
|
|
||||||
|
// Get the native object addresses.
|
||||||
|
log(TAG, "findCalibrationPattern(): Requesting native data.");
|
||||||
|
cv::Mat& myuv = *(cv::Mat*)addrMatIn;
|
||||||
|
cv::Mat& mbgr = *(cv::Mat*)addrMatOut;
|
||||||
|
jfloat * _points = env->GetFloatArrayElements(points, 0);
|
||||||
|
|
||||||
|
// Convert the input image to the BGR color space.
|
||||||
|
log(TAG, "findCalibrationPattern(): Converting color space before processing.");
|
||||||
|
cv::cvtColor(myuv, temp, CV_RGB2BGR);
|
||||||
|
|
||||||
|
// Find the calibration points in the input image.
|
||||||
|
log(TAG, "findCalibrationPattern(): Finding calibration pattern.");
|
||||||
|
found = nxtar::findCalibrationPattern(v_points, temp);
|
||||||
|
|
||||||
|
// If the points were found then save them to the output array.
|
||||||
|
if(found){
|
||||||
|
log(TAG, "findCalibrationPattern(): Copying calibration points.");
|
||||||
|
for(size_t i = 0, p = 0; i < v_points.size(); i++, p += 2){
|
||||||
|
_points[p ] = (jfloat)v_points[i].x;
|
||||||
|
_points[p + 1] = (jfloat)v_points[i].y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the output image back to the RGB color space.
|
||||||
|
cv::cvtColor(temp, mbgr, CV_BGR2RGB);
|
||||||
|
|
||||||
|
// Release native data.
|
||||||
|
log(TAG, "findCalibrationPattern(): Releasing native data.");
|
||||||
|
env->ReleaseFloatArrayElements(points, _points, 0);
|
||||||
|
|
||||||
|
return (jboolean)found;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JNI wrapper around the nxtar::getCameraParameters() method.
|
||||||
|
*/
|
||||||
|
JNIEXPORT jdouble JNICALL Java_ve_ucv_ciens_ccg_nxtar_MainActivity_calibrateCameraParameters(JNIEnv* env, jobject jobj, jlong addrMatIn, jlong addrMatOut, jlong addrMatFrame, jfloatArray points){
|
||||||
|
double error;
|
||||||
|
std::vector<nxtar::points_vector> imagePoints;
|
||||||
|
|
||||||
|
// Get native object addresses.
|
||||||
|
log(TAG, "calibrateCameraParameters(): Requesting native data.");
|
||||||
|
cv::Mat& mIn = *(cv::Mat*)addrMatIn;
|
||||||
|
cv::Mat& mOut = *(cv::Mat*)addrMatOut;
|
||||||
|
cv::Mat& mFrame = *(cv::Mat*)addrMatFrame;
|
||||||
|
jfloat * _points = env->GetFloatArrayElements(points, 0);
|
||||||
|
|
||||||
|
// Prepare the image points data structure.
|
||||||
|
log(TAG, "calibrateCameraParameters(): Preparing image points.");
|
||||||
|
for(int i = 0; i < CALIBRATION_SAMPLES; i++){
|
||||||
|
nxtar::points_vector tempVector;
|
||||||
|
for(int j = 0, p = 0; j < POINTS_PER_CALIBRATION_SAMPLE; j++, p += 2){
|
||||||
|
tempVector.push_back(cv::Point2f(_points[p], _points[p + 1]));
|
||||||
|
}
|
||||||
|
imagePoints.push_back(tempVector);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the camera parameters.
|
||||||
|
log(TAG, "calibrateCameraParameters(): Getting camera parameters.");
|
||||||
|
error = nxtar::getCameraParameters(mIn, mOut, imagePoints, mFrame.size());
|
||||||
|
|
||||||
|
// Clear the image points.
|
||||||
|
log(TAG, "calibrateCameraParameters(): Clearing memory.");
|
||||||
|
for(int i = 0; i < imagePoints.size(); i++){
|
||||||
|
imagePoints[i].clear();
|
||||||
|
}
|
||||||
|
imagePoints.clear();
|
||||||
|
|
||||||
|
// Release native memory.
|
||||||
|
log(TAG, "calibrateCameraParameters(): Releasing native data.");
|
||||||
|
env->ReleaseFloatArrayElements(points, _points, 0);
|
||||||
|
|
||||||
|
// Return the calibration error as calculated by OpenCV.
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // extern "C"
|
||||||
|
898
jni/marker.cpp
@@ -16,383 +16,541 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <stddef.h>
|
||||||
|
#ifdef DESKTOP
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "marker.hpp"
|
#include "marker.hpp"
|
||||||
|
|
||||||
#define MIN_CONTOUR_LENGTH 0.1
|
|
||||||
|
|
||||||
namespace nxtar{
|
namespace nxtar{
|
||||||
|
|
||||||
static const cv::Scalar COLOR = cv::Scalar(255, 255, 255);
|
typedef std::vector<cv::Point3f> points_vector_3D;
|
||||||
|
typedef std::vector<std::vector<cv::Point> > contours_vector;
|
||||||
|
|
||||||
class Marker;
|
/******************************************************************************
|
||||||
|
* PRIVATE CONSTANTS *
|
||||||
typedef std::vector<std::vector<cv::Point> > contours_vector;
|
******************************************************************************/
|
||||||
typedef std::vector<cv::Point2f> points_vector;
|
|
||||||
typedef std::vector<Marker> markers_vector;
|
/**
|
||||||
|
* Minimal number of points in a contour.
|
||||||
|
*/
|
||||||
|
static const int MIN_POINTS = 40;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of a square cell in the calibration pattern.
|
||||||
|
*/
|
||||||
|
static const float SQUARE_SIZE = 1.0f;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Minimal lenght of a contour to be considered as a marker candidate.
|
||||||
|
*/
|
||||||
|
static const float MIN_CONTOUR_LENGTH = 0.1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flags for the calibration pattern detecion function.
|
||||||
|
*/
|
||||||
|
static const int PATTERN_DETECTION_FLAGS = cv::CALIB_CB_ADAPTIVE_THRESH + cv::CALIB_CB_NORMALIZE_IMAGE + cv::CALIB_CB_FAST_CHECK;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Color for rendering the marker outlines.
|
||||||
|
*/
|
||||||
|
static const cv::Scalar COLOR = cv::Scalar(255, 255, 255);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of the chessboard pattern image (columns, rows).
|
||||||
|
*/
|
||||||
|
static const cv::Size CHESSBOARD_PATTERN_SIZE(6, 9);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Termination criteria for OpenCV's iterative algorithms.
|
||||||
|
*/
|
||||||
|
static const cv::TermCriteria TERM_CRITERIA = cv::TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1);
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* PRIVATE FUNCTION PROTOTYPES *
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
float perimeter(points_vector &);
|
||||||
|
|
||||||
|
int hammDistMarker(cv::Mat);
|
||||||
|
|
||||||
|
cv::Mat rotate(cv::Mat);
|
||||||
|
|
||||||
|
int decodeMarker(cv::Mat &, int &);
|
||||||
|
|
||||||
|
void renderMarkers(markers_vector &, cv::Mat &);
|
||||||
|
|
||||||
|
void isolateMarkers(const contours_vector &, markers_vector &);
|
||||||
|
|
||||||
|
void findContours(cv::Mat &, contours_vector &, int);
|
||||||
|
|
||||||
|
void warpMarker(Marker &, cv::Mat &, cv::Mat &);
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* PUBLIC API *
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
void getAllMarkers(markers_vector & valid_markers, cv::Mat & img){
|
||||||
|
int rotations = 0;
|
||||||
|
cv::Mat gray, thresh, cont, mark;
|
||||||
|
contours_vector contours;
|
||||||
|
markers_vector markers;
|
||||||
|
cv::Point2f point;
|
||||||
|
#ifdef DESKTOP
|
||||||
|
std::ostringstream oss;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
valid_markers.clear();
|
||||||
|
|
||||||
|
// Find all marker candidates in the input image.
|
||||||
|
// 1) First, convert the image to grayscale.
|
||||||
|
// 2) Then, binarize the grayscale image.
|
||||||
|
// 3) Finally indentify all 4 sided figures in the binarized image.
|
||||||
|
cv::cvtColor(img, gray, CV_BGR2GRAY);
|
||||||
|
cv::adaptiveThreshold(gray, thresh, 255, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY_INV, 7, 7);
|
||||||
|
findContours(thresh, contours, MIN_POINTS);
|
||||||
|
isolateMarkers(contours, markers);
|
||||||
|
|
||||||
|
// Remove the perspective distortion from the detected marker candidates.
|
||||||
|
// Then attempt to decode them and push the valid ones into the valid
|
||||||
|
// markers vector.
|
||||||
|
for(int i = 0; i < markers.size(); i++){
|
||||||
|
warpMarker(markers[i], gray, mark);
|
||||||
|
|
||||||
|
int code = decodeMarker(mark, rotations);
|
||||||
|
|
||||||
|
if(code != -1){
|
||||||
|
markers[i].code = code;
|
||||||
|
|
||||||
|
// If the decoder detected the marker is rotated then reorder the points
|
||||||
|
// so that the orientation calculations always use the correct top of the marker.
|
||||||
|
if(rotations > 0){
|
||||||
|
while(rotations > 0){
|
||||||
|
for(int r = 0; r < 1; r++){
|
||||||
|
point = markers[i].points.at(markers[i].points.size() - 1);
|
||||||
|
markers[i].points.pop_back();
|
||||||
|
markers[i].points.insert(markers[i].points.begin(), point);
|
||||||
|
}
|
||||||
|
|
||||||
|
rotations--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Rotate 180 degrees.
|
||||||
|
for(int r = 0; r < 2; r++){
|
||||||
|
point = markers[i].points.at(markers[i].points.size() - 1);
|
||||||
|
markers[i].points.pop_back();
|
||||||
|
markers[i].points.insert(markers[i].points.begin(), point);
|
||||||
|
}
|
||||||
|
|
||||||
|
valid_markers.push_back(markers[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < valid_markers.size(); i++){
|
||||||
|
#ifdef DESKTOP
|
||||||
|
// Render the detected valid markers with their codes for debbuging
|
||||||
|
// purposes.
|
||||||
|
oss << valid_markers[i].code;
|
||||||
|
|
||||||
|
cv::putText(mark, oss.str(), cv::Point(5, 250), cv::FONT_HERSHEY_PLAIN, 2, cv::Scalar::all(128), 3, 8);
|
||||||
|
|
||||||
|
oss.str("");
|
||||||
|
oss.clear();
|
||||||
|
|
||||||
|
oss << "Marker[" << i << "]";
|
||||||
|
|
||||||
class Marker{
|
cv::imshow(oss.str(), mark);
|
||||||
public:
|
|
||||||
~Marker();
|
oss.str("");
|
||||||
points_vector points;
|
oss.clear();
|
||||||
int code;
|
#endif
|
||||||
};
|
// Fix the detected corners to better approximate the markers. And
|
||||||
|
// push their codes to the output vector.
|
||||||
float perimeter(points_vector &);
|
cv::cornerSubPix(gray, valid_markers[i].points, cvSize(10, 10), cvSize(-1, -1), TERM_CRITERIA);
|
||||||
int hammDistMarker(cv::Mat);
|
}
|
||||||
cv::Mat rotate(cv::Mat);
|
|
||||||
void binarize(cv::Mat &, cv::Mat &);
|
|
||||||
void findContours(cv::Mat &, contours_vector &, int);
|
|
||||||
void renderContours(contours_vector &, cv::Mat &);
|
|
||||||
void renderMarkers(markers_vector &, cv::Mat &);
|
|
||||||
void warpMarker(Marker &, cv::Mat &, cv::Mat &);
|
|
||||||
int decodeMarker(cv::Mat &);
|
|
||||||
void fixCorners(cv::Mat &, Marker &);
|
|
||||||
void isolateMarkers(const contours_vector &, markers_vector &);
|
|
||||||
|
|
||||||
void getAllMarkers(std::vector<int> & codes, cv::Mat & img){
|
|
||||||
cv::Mat gray, thresh, cont, mark;
|
|
||||||
contours_vector contours;
|
|
||||||
markers_vector markers;
|
|
||||||
markers_vector valid_markers;
|
|
||||||
|
|
||||||
codes.clear();
|
|
||||||
|
|
||||||
cv::cvtColor(img, gray, CV_BGR2GRAY);
|
|
||||||
binarize(gray, thresh);
|
|
||||||
findContours(thresh, contours, 40);
|
|
||||||
isolateMarkers(contours, markers);
|
|
||||||
|
|
||||||
for(int i = 0; i < markers.size(); i++){
|
|
||||||
warpMarker(markers[i], gray, mark);
|
|
||||||
|
|
||||||
int code = decodeMarker(mark);
|
|
||||||
|
|
||||||
if(code != -1){
|
|
||||||
markers[i].code = code;
|
|
||||||
valid_markers.push_back(markers[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i = 0; i < valid_markers.size(); i++)
|
|
||||||
fixCorners(gray, valid_markers[i]);
|
|
||||||
|
|
||||||
cont = cv::Mat::zeros(img.size(), CV_8UC3);
|
|
||||||
renderMarkers(valid_markers, cont);
|
|
||||||
|
|
||||||
img = img + cont;
|
|
||||||
|
|
||||||
for(int i = 0; i < valid_markers.size(); i++){
|
|
||||||
codes.push_back(valid_markers[i].code);
|
|
||||||
}
|
|
||||||
|
|
||||||
markers.clear();
|
|
||||||
contours.clear();
|
|
||||||
valid_markers.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DESKTOP
|
|
||||||
void getAllMarkers_d(std::vector<int> & codes, cv::Mat & img){
|
|
||||||
cv::Mat gray, thresh, cont, mark;
|
|
||||||
contours_vector contours;
|
|
||||||
markers_vector markers;
|
|
||||||
markers_vector valid_markers;
|
|
||||||
std::ostringstream oss;
|
|
||||||
|
|
||||||
codes.clear();
|
|
||||||
|
|
||||||
cv::cvtColor(img, gray, CV_BGR2GRAY);
|
|
||||||
binarize(gray, thresh);
|
|
||||||
findContours(thresh, contours, 40);
|
|
||||||
isolateMarkers(contours, markers);
|
|
||||||
|
|
||||||
for(int i = 0; i < markers.size(); i++){
|
|
||||||
warpMarker(markers[i], gray, mark);
|
|
||||||
|
|
||||||
int code = decodeMarker(mark);
|
|
||||||
|
|
||||||
if(code != -1){
|
|
||||||
markers[i].code = code;
|
|
||||||
valid_markers.push_back(markers[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(int i = 0; i < valid_markers.size(); i++)
|
|
||||||
fixCorners(gray, valid_markers[i]);
|
|
||||||
|
|
||||||
cont = cv::Mat::zeros(img.size(), CV_8UC3);
|
|
||||||
renderMarkers(valid_markers, cont);
|
|
||||||
|
|
||||||
img = img + cont;
|
|
||||||
|
|
||||||
for(int i = 0; i < valid_markers.size(); i++){
|
|
||||||
oss << valid_markers[i].code;
|
|
||||||
|
|
||||||
cv::putText(mark, oss.str(), cv::Point(5, 250), cv::FONT_HERSHEY_PLAIN, 2, cv::Scalar::all(128), 3, 8);
|
|
||||||
|
|
||||||
oss.str("");
|
|
||||||
oss.clear();
|
|
||||||
|
|
||||||
oss << "Marker[" << i << "]";
|
|
||||||
|
|
||||||
cv::imshow(oss.str(), mark);
|
|
||||||
|
|
||||||
oss.str("");
|
|
||||||
oss.clear();
|
|
||||||
|
|
||||||
codes.push_back(valid_markers[i].code);
|
|
||||||
}
|
|
||||||
|
|
||||||
markers.clear();
|
|
||||||
contours.clear();
|
|
||||||
valid_markers.clear();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void binarize(cv::Mat & src, cv::Mat & dst){
|
|
||||||
cv::adaptiveThreshold(src, dst, 255, cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY_INV, 7, 7);
|
|
||||||
}
|
|
||||||
|
|
||||||
void findContours(cv::Mat & img, contours_vector & v, int minP){
|
|
||||||
std::vector<std::vector<cv::Point> > c;
|
|
||||||
cv::findContours(img, c, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
|
|
||||||
|
|
||||||
v.clear();
|
|
||||||
for(size_t i = 0; i < c.size(); i++){
|
|
||||||
if(c[i].size() > minP){
|
|
||||||
v.push_back(c[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void renderContours(contours_vector & v, cv::Mat & dst){
|
|
||||||
cv::drawContours(dst, v, -1, COLOR, 1, CV_AA);
|
|
||||||
}
|
|
||||||
|
|
||||||
void renderMarkers(markers_vector & v, cv::Mat & dst){
|
|
||||||
contours_vector cv;
|
|
||||||
|
|
||||||
for(size_t i = 0; i < v.size(); i++){
|
|
||||||
std::vector<cv::Point> pv;
|
|
||||||
for(size_t j = 0; j < v[i].points.size(); ++j)
|
|
||||||
pv.push_back(cv::Point2f(v[i].points[j].x, v[i].points[j].y));
|
|
||||||
cv.push_back(pv);
|
|
||||||
}
|
|
||||||
|
|
||||||
cv::drawContours(dst, cv, -1, COLOR, 1, CV_AA);
|
|
||||||
}
|
|
||||||
|
|
||||||
void isolateMarkers(const contours_vector & vc, markers_vector & vm){
|
|
||||||
std::vector<cv::Point> appCurve;
|
|
||||||
markers_vector posMarkers;
|
|
||||||
|
|
||||||
for(size_t i = 0; i < vc.size(); ++i){
|
|
||||||
double eps = vc[i].size() * 0.05;
|
|
||||||
cv::approxPolyDP(vc[i], appCurve, eps, true);
|
|
||||||
|
|
||||||
if(appCurve.size() != 4 || !cv::isContourConvex(appCurve)) continue;
|
|
||||||
|
|
||||||
float minD = std::numeric_limits<float>::max();
|
|
||||||
|
|
||||||
for(int i = 0; i < 4; i++){
|
|
||||||
cv::Point side = appCurve[i] - appCurve[(i + 1) % 4];
|
|
||||||
float sqSideLen = side.dot(side);
|
|
||||||
minD = std::min(minD, sqSideLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(minD < MIN_CONTOUR_LENGTH) continue;
|
|
||||||
|
|
||||||
Marker m;
|
|
||||||
|
|
||||||
for(int i = 0; i < 4; i++)
|
|
||||||
m.points.push_back(cv::Point2f(appCurve[i].x, appCurve[i].y));
|
|
||||||
|
|
||||||
cv::Point v1 = m.points[1] - m.points[0];
|
|
||||||
cv::Point v2 = m.points[2] - m.points[0];
|
|
||||||
|
|
||||||
double o = (v1.x * v2.y) - (v1.y * v2.x);
|
|
||||||
if(o < 0.0) std::swap(m.points[1], m.points[3]);
|
|
||||||
|
|
||||||
posMarkers.push_back(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::pair<int, int> > tooNear;
|
|
||||||
for(size_t i = 0; i < posMarkers.size(); ++i){
|
|
||||||
const Marker & m1 = posMarkers[i];
|
|
||||||
|
|
||||||
for(size_t j = i + 1; j < posMarkers.size(); j++){
|
|
||||||
const Marker & m2 = posMarkers[j];
|
|
||||||
|
|
||||||
float dSq = 0.0f;
|
|
||||||
|
|
||||||
for(int c = 0; c < 4; c++){
|
|
||||||
cv::Point v = m1.points[c] - m2.points[c];
|
|
||||||
dSq += v.dot(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
dSq /= 4.0f;
|
|
||||||
|
|
||||||
if(dSq < 100) tooNear.push_back(std::pair<int, int>(i, j));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<bool> remMask(posMarkers.size(), false);
|
|
||||||
|
|
||||||
for(size_t i = 0; i < tooNear.size(); ++i){
|
|
||||||
float p1 = perimeter(posMarkers[tooNear[i].first].points);
|
|
||||||
float p2 = perimeter(posMarkers[tooNear[i].second].points);
|
|
||||||
|
|
||||||
size_t remInd;
|
|
||||||
if(p1 > p2) remInd = tooNear[i].second;
|
|
||||||
else remInd = tooNear[i].first;
|
|
||||||
|
|
||||||
remMask[remInd] = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
vm.clear();
|
|
||||||
for(size_t i = 0; i < posMarkers.size(); ++i){
|
|
||||||
if(remMask[i]) vm.push_back(posMarkers[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void warpMarker(Marker & m, cv::Mat & in, cv::Mat & out){
|
|
||||||
cv::Mat bin;
|
|
||||||
cv::Size markerSize(350, 350);
|
|
||||||
points_vector v;
|
|
||||||
v.push_back(cv::Point2f(0,0));
|
|
||||||
v.push_back(cv::Point2f(markerSize.width-1,0));
|
|
||||||
v.push_back(cv::Point2f(markerSize.width-1,markerSize.height-1));
|
|
||||||
v.push_back(cv::Point2f(0,markerSize.height-1));
|
|
||||||
|
|
||||||
cv::Mat M = cv::getPerspectiveTransform(m.points, v);
|
|
||||||
cv::warpPerspective(in, bin, M, markerSize);
|
|
||||||
|
|
||||||
cv::threshold(bin, out, 128, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
|
|
||||||
}
|
|
||||||
|
|
||||||
int hammDistMarker(cv::Mat bits){
|
|
||||||
int ids[4][5] = {
|
|
||||||
{1,0,0,0,0},
|
|
||||||
{1,0,1,1,1},
|
|
||||||
{0,1,0,0,1},
|
|
||||||
{0,1,1,1,0}
|
|
||||||
};
|
|
||||||
|
|
||||||
int dist = 0;
|
|
||||||
|
|
||||||
for (int y = 0; y < 5; y++){
|
|
||||||
int minSum = 1e5;
|
|
||||||
|
|
||||||
for (int p = 0; p < 4; p++){
|
|
||||||
int sum = 0;
|
|
||||||
|
|
||||||
for (int x = 0; x < 5; x++){
|
|
||||||
sum += bits.at<uchar>(y, x) == ids[p][x] ? 0 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(minSum > sum)
|
|
||||||
minSum = sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
dist += minSum;
|
|
||||||
}
|
|
||||||
|
|
||||||
return dist;
|
|
||||||
}
|
|
||||||
cv::Mat rotate(cv::Mat in){
|
|
||||||
cv::Mat out;
|
|
||||||
in.copyTo(out);
|
|
||||||
for (int i=0;i<in.rows;i++){
|
|
||||||
for (int j=0;j<in.cols;j++){
|
|
||||||
out.at<uchar>(i,j)=in.at<uchar>(in.cols-j-1,i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
int decodeMarker(cv::Mat & marker){
|
|
||||||
bool found = false;
|
|
||||||
int code = 0;
|
|
||||||
cv::Mat bits;
|
|
||||||
|
|
||||||
for(int y = 0; y < 7; y++){
|
|
||||||
int inc = (y == 0 || y == 6) ? 1 : 6;
|
|
||||||
|
|
||||||
for(int x = 0; x < 7; x += inc){
|
|
||||||
int cX = x * 50;
|
|
||||||
int cY = y * 50;
|
|
||||||
|
|
||||||
cv::Mat cell = marker(cv::Rect(cX, cY, 50, 50));
|
|
||||||
|
|
||||||
int nZ = cv::countNonZero(cell);
|
|
||||||
|
|
||||||
// Not a valid marker.
|
|
||||||
if(nZ > (50 * 50) / 2) return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bits = cv::Mat::zeros(5, 5, CV_8UC1);
|
|
||||||
|
|
||||||
|
|
||||||
for(int y = 0; y < 5; y++){
|
|
||||||
for(int x = 0; x < 5; x++){
|
|
||||||
int cX = (x + 1) * 50;
|
|
||||||
int cY = (y + 1) * 50;
|
|
||||||
|
|
||||||
cv::Mat cell = marker(cv::Rect(cX, cY, 50, 50));
|
|
||||||
|
|
||||||
int nZ = cv::countNonZero(cell);
|
|
||||||
|
|
||||||
if(nZ > (50 * 50) / 2) bits.at<uchar>(y, x) = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(hammDistMarker(bits) != 0){
|
|
||||||
for(int r = 1; r < 4; r++){
|
|
||||||
bits = rotate(bits);
|
|
||||||
if(hammDistMarker(bits) != 0) continue;
|
|
||||||
else{ found = true; break;}
|
|
||||||
}
|
|
||||||
}else found = true;
|
|
||||||
|
|
||||||
|
|
||||||
if(found){
|
|
||||||
for(int y = 0; y < 5; y++){
|
|
||||||
code <<= 1;
|
|
||||||
if(bits.at<uchar>(y, 1))
|
|
||||||
code |= 1;
|
|
||||||
|
|
||||||
code <<= 1;
|
|
||||||
if(bits.at<uchar>(y, 3))
|
|
||||||
code |= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return code;
|
|
||||||
}else
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void fixCorners(cv::Mat & img, Marker & m){
|
|
||||||
cv::cornerSubPix(img, m.points, cvSize(10, 10), cvSize(-1, -1), cvTermCriteria(CV_TERMCRIT_ITER, 30, 0.1));
|
|
||||||
}
|
|
||||||
|
|
||||||
float perimeter(points_vector & p){
|
|
||||||
float per = 0.0f, dx, dy;
|
|
||||||
|
|
||||||
for(size_t i; i < p.size(); ++i){
|
|
||||||
dx = p[i].x - p[(i + 1) % p.size()].x;
|
|
||||||
dy = p[i].y - p[(i + 1) % p.size()].y;
|
|
||||||
per += sqrt((dx * dx) + (dy * dy));
|
|
||||||
}
|
|
||||||
|
|
||||||
return per;
|
|
||||||
}
|
|
||||||
|
|
||||||
Marker::~Marker(){
|
|
||||||
points.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Render the detected markers on top of the input image.
|
||||||
|
cont = cv::Mat::zeros(img.size(), CV_8UC3);
|
||||||
|
renderMarkers(valid_markers, cont);
|
||||||
|
img = img + cont;
|
||||||
|
|
||||||
|
// Clear the local vectors.
|
||||||
|
markers.clear();
|
||||||
|
contours.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool findCalibrationPattern(points_vector & corners, cv::Mat & img){
|
||||||
|
bool patternfound;
|
||||||
|
cv::Mat gray;
|
||||||
|
|
||||||
|
// Convert the input image to grayscale and attempt to find the
|
||||||
|
// calibration pattern.
|
||||||
|
cv::cvtColor(img, gray, CV_BGR2GRAY);
|
||||||
|
patternfound = cv::findChessboardCorners(gray, CHESSBOARD_PATTERN_SIZE, corners, PATTERN_DETECTION_FLAGS);
|
||||||
|
|
||||||
|
// If the pattern was found then fix the detected points a bit.
|
||||||
|
if(patternfound)
|
||||||
|
cv::cornerSubPix(gray, corners, cv::Size(11, 11), cv::Size(-1, -1), TERM_CRITERIA);
|
||||||
|
|
||||||
|
// Render the detected pattern.
|
||||||
|
cv::drawChessboardCorners(img, CHESSBOARD_PATTERN_SIZE, cv::Mat(corners), patternfound);
|
||||||
|
|
||||||
|
return patternfound;
|
||||||
|
}
|
||||||
|
|
||||||
|
double getCameraParameters(cv::Mat & camera_matrix, cv::Mat & dist_coeffs, std::vector<points_vector> & image_points, cv::Size image_size){
|
||||||
|
std::vector<cv::Mat> rvecs, tvecs;
|
||||||
|
std::vector<points_vector_3D> object_points;
|
||||||
|
points_vector_3D corner_points;
|
||||||
|
|
||||||
|
// Build the reference object points vector.
|
||||||
|
for(int i = 0; i < CHESSBOARD_PATTERN_SIZE.height; i++){
|
||||||
|
for(int j = 0; j < CHESSBOARD_PATTERN_SIZE.width; j++){
|
||||||
|
corner_points.push_back(cv::Point3f(float( j * SQUARE_SIZE ), float( i * SQUARE_SIZE ), 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
object_points.push_back(corner_points);
|
||||||
|
object_points.resize(image_points.size(), object_points[0]);
|
||||||
|
|
||||||
|
// Build a camera matrix.
|
||||||
|
camera_matrix = cv::Mat::eye(3, 3, CV_64F);
|
||||||
|
|
||||||
|
// Build the distortion coefficients matrix.
|
||||||
|
dist_coeffs = cv::Mat::zeros(8, 1, CV_64F);
|
||||||
|
|
||||||
|
// Calibrate and return the reprojection error.
|
||||||
|
return cv::calibrateCamera(object_points, image_points, image_size, camera_matrix, dist_coeffs, rvecs, tvecs, 0, TERM_CRITERIA);
|
||||||
|
}
|
||||||
|
|
||||||
|
void estimateMarkerPosition(markers_vector & markers, cv::Mat & camMatrix, cv::Mat & distCoeff){
|
||||||
|
cv::Mat rVec, rAux, tAux;
|
||||||
|
cv::Mat_<float> tVec, rotation(3,3);
|
||||||
|
points_vector_3D objectPoints;
|
||||||
|
|
||||||
|
// Assemble a unitary CCW oriented reference polygon.
|
||||||
|
objectPoints.push_back(cv::Point3f(-0.5f, -0.5f, 0.0f));
|
||||||
|
objectPoints.push_back(cv::Point3f(-0.5f, 0.5f, 0.0f));
|
||||||
|
objectPoints.push_back(cv::Point3f( 0.5f, 0.5f, 0.0f));
|
||||||
|
objectPoints.push_back(cv::Point3f( 0.5f, -0.5f, 0.0f));
|
||||||
|
|
||||||
|
for(size_t i = 0; i < markers.size(); i++){
|
||||||
|
// Obtain the translation and rotation vectors.
|
||||||
|
cv::solvePnP(objectPoints, markers[i].points, camMatrix, distCoeff, rAux, tAux);
|
||||||
|
|
||||||
|
// Convert the obtained vectors to float.
|
||||||
|
rAux.convertTo(rVec, CV_32F);
|
||||||
|
tAux.convertTo(tVec, CV_32F);
|
||||||
|
|
||||||
|
// Convert the rotation vector to a rotation matrix.
|
||||||
|
cv::Rodrigues(rVec, rotation);
|
||||||
|
|
||||||
|
// Make the rotation and translation relative to the "camera" and save
|
||||||
|
// the results to the output marker.
|
||||||
|
markers[i].rotation = cv::Mat(rotation.t());
|
||||||
|
markers[i].translation = cv::Mat(-tVec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* PRIVATE HELPER FUNCTIONS *
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find all contours in the input image and save them to the output
|
||||||
|
* vector.
|
||||||
|
*/
|
||||||
|
void findContours(cv::Mat & img, contours_vector & v, int minP){
|
||||||
|
contours_vector c;
|
||||||
|
|
||||||
|
// A contour is discarded if it possess less than the specified
|
||||||
|
// minimum number of points.
|
||||||
|
cv::findContours(img, c, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
|
||||||
|
|
||||||
|
v.clear();
|
||||||
|
for(size_t i = 0; i < c.size(); i++){
|
||||||
|
if(c[i].size() > minP){
|
||||||
|
v.push_back(c[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the input marker vector onto the output image.
|
||||||
|
*/
|
||||||
|
void renderMarkers(markers_vector & v, cv::Mat & dst){
|
||||||
|
contours_vector cv;
|
||||||
|
|
||||||
|
// Extract the points that form every marker into a contours vector.
|
||||||
|
for(size_t i = 0; i < v.size(); i++){
|
||||||
|
std::vector<cv::Point> pv;
|
||||||
|
for(size_t j = 0; j < v[i].points.size(); ++j)
|
||||||
|
pv.push_back(cv::Point2f(v[i].points[j].x, v[i].points[j].y));
|
||||||
|
cv.push_back(pv);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render.
|
||||||
|
cv::drawContours(dst, cv, -1, COLOR, 1, CV_AA);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identify and return all marker candidates.
|
||||||
|
*/
|
||||||
|
void isolateMarkers(const contours_vector & vc, markers_vector & vm){
|
||||||
|
std::vector<cv::Point> appCurve;
|
||||||
|
markers_vector posMarkers;
|
||||||
|
|
||||||
|
// For every detected contour.
|
||||||
|
for(size_t i = 0; i < vc.size(); ++i){
|
||||||
|
double eps = vc[i].size() * 0.05;
|
||||||
|
|
||||||
|
// Approximate the contour with a polygon.
|
||||||
|
cv::approxPolyDP(vc[i], appCurve, eps, true);
|
||||||
|
|
||||||
|
// If the polygon is not a cuadrilateral then this is not a marker
|
||||||
|
// candidate.
|
||||||
|
if(appCurve.size() != 4 || !cv::isContourConvex(appCurve)) continue;
|
||||||
|
|
||||||
|
// Calculate the lenght of the perimeter of this candidate. If it
|
||||||
|
// is too short then discard it.
|
||||||
|
float minD = std::numeric_limits<float>::max();
|
||||||
|
|
||||||
|
for(int i = 0; i < 4; i++){
|
||||||
|
cv::Point side = appCurve[i] - appCurve[(i + 1) % 4];
|
||||||
|
float sqSideLen = side.dot(side);
|
||||||
|
minD = std::min(minD, sqSideLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(minD < MIN_CONTOUR_LENGTH) continue;
|
||||||
|
|
||||||
|
// Save the marker and order it's points counter-clockwise.
|
||||||
|
Marker m;
|
||||||
|
|
||||||
|
for(int i = 0; i < 4; i++)
|
||||||
|
m.points.push_back(cv::Point2f(appCurve[i].x, appCurve[i].y));
|
||||||
|
|
||||||
|
cv::Point v1 = m.points[1] - m.points[0];
|
||||||
|
cv::Point v2 = m.points[2] - m.points[0];
|
||||||
|
|
||||||
|
double o = (v1.x * v2.y) - (v1.y * v2.x);
|
||||||
|
if(o < 0.0) std::swap(m.points[1], m.points[3]);
|
||||||
|
|
||||||
|
posMarkers.push_back(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Identify contours that are to close to each other to eliminate
|
||||||
|
// possible duplicates.
|
||||||
|
std::vector<std::pair<int, int> > tooNear;
|
||||||
|
for(size_t i = 0; i < posMarkers.size(); ++i){
|
||||||
|
const Marker & m1 = posMarkers[i];
|
||||||
|
|
||||||
|
for(size_t j = i + 1; j < posMarkers.size(); j++){
|
||||||
|
const Marker & m2 = posMarkers[j];
|
||||||
|
|
||||||
|
float dSq = 0.0f;
|
||||||
|
|
||||||
|
for(int c = 0; c < 4; c++){
|
||||||
|
cv::Point v = m1.points[c] - m2.points[c];
|
||||||
|
dSq += v.dot(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
dSq /= 4.0f;
|
||||||
|
|
||||||
|
if(dSq < 100) tooNear.push_back(std::pair<int, int>(i, j));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark one of every pair of duplicates to be discarded.
|
||||||
|
std::vector<bool> remMask(posMarkers.size(), false);
|
||||||
|
for(size_t i = 0; i < tooNear.size(); ++i){
|
||||||
|
float p1 = perimeter(posMarkers[tooNear[i].first].points);
|
||||||
|
float p2 = perimeter(posMarkers[tooNear[i].second].points);
|
||||||
|
|
||||||
|
size_t remInd;
|
||||||
|
if(p1 > p2) remInd = tooNear[i].second;
|
||||||
|
else remInd = tooNear[i].first;
|
||||||
|
|
||||||
|
remMask[remInd] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the candidates that survided the duplicates test.
|
||||||
|
vm.clear();
|
||||||
|
for(size_t i = 0; i < posMarkers.size(); ++i){
|
||||||
|
if(!remMask[i]) vm.push_back(posMarkers[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Warp a marker image to remove it's perspective distortion.
|
||||||
|
*/
|
||||||
|
void warpMarker(Marker & m, cv::Mat & in, cv::Mat & out){
|
||||||
|
cv::Mat bin;
|
||||||
|
cv::Size markerSize(350, 350);
|
||||||
|
points_vector v;
|
||||||
|
|
||||||
|
// Assemble a unitary reference polygon.
|
||||||
|
v.push_back(cv::Point2f(0,0));
|
||||||
|
v.push_back(cv::Point2f(markerSize.width-1,0));
|
||||||
|
v.push_back(cv::Point2f(markerSize.width-1,markerSize.height-1));
|
||||||
|
v.push_back(cv::Point2f(0,markerSize.height-1));
|
||||||
|
|
||||||
|
// Warp the input image's perspective to transform it into the reference
|
||||||
|
// polygon's perspective.
|
||||||
|
cv::Mat M = cv::getPerspectiveTransform(m.points, v);
|
||||||
|
cv::warpPerspective(in, bin, M, markerSize);
|
||||||
|
|
||||||
|
// Binarize the warped image into the output image.
|
||||||
|
cv::threshold(bin, out, 128, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the hamming distance of a 5x5 bit matrix.
|
||||||
|
* Function by Daniel Lelis Baggio for "Mastering OpenCV with Practical Computer Vision Projects".
|
||||||
|
*/
|
||||||
|
int hammDistMarker(cv::Mat bits){
|
||||||
|
int ids[4][5] = {
|
||||||
|
{1,0,0,0,0},
|
||||||
|
{1,0,1,1,1},
|
||||||
|
{0,1,0,0,1},
|
||||||
|
{0,1,1,1,0}
|
||||||
|
};
|
||||||
|
|
||||||
|
int dist = 0;
|
||||||
|
|
||||||
|
for (int y = 0; y < 5; y++){
|
||||||
|
int minSum = 1e5;
|
||||||
|
|
||||||
|
for (int p = 0; p < 4; p++){
|
||||||
|
int sum = 0;
|
||||||
|
|
||||||
|
for (int x = 0; x < 5; x++){
|
||||||
|
sum += bits.at<uchar>(y, x) == ids[p][x] ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(minSum > sum)
|
||||||
|
minSum = sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
dist += minSum;
|
||||||
|
}
|
||||||
|
|
||||||
|
return dist;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rotate a matrix by 90 degrees clockwise.
|
||||||
|
*/
|
||||||
|
cv::Mat rotate(cv::Mat in){
|
||||||
|
cv::Mat out;
|
||||||
|
|
||||||
|
in.copyTo(out);
|
||||||
|
for (int i = 0; i < in.rows; i++){
|
||||||
|
for (int j = 0; j < in.cols; j++){
|
||||||
|
out.at<uchar>(i, j) = in.at<uchar>(in.cols-j - 1, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decode a marker image and return it's code. Returns -1 if the image is
|
||||||
|
* not a valid marker.
|
||||||
|
*/
|
||||||
|
int decodeMarker(cv::Mat & marker, int & rotations){
|
||||||
|
bool found = false;
|
||||||
|
int code = 0;
|
||||||
|
cv::Mat bits;
|
||||||
|
|
||||||
|
rotations = 0;
|
||||||
|
|
||||||
|
// Verify that the outer rim of marker cells are all black.
|
||||||
|
for(int y = 0; y < 7; y++){
|
||||||
|
int inc = (y == 0 || y == 6) ? 1 : 6;
|
||||||
|
|
||||||
|
for(int x = 0; x < 7; x += inc){
|
||||||
|
int cX = x * 50;
|
||||||
|
int cY = y * 50;
|
||||||
|
cv::Mat cell = marker(cv::Rect(cX, cY, 50, 50));
|
||||||
|
|
||||||
|
int nZ = cv::countNonZero(cell);
|
||||||
|
|
||||||
|
// If one of the rim cells is 50% white or more then this
|
||||||
|
// is not a valid marker.
|
||||||
|
if(nZ > (50 * 50) / 2) return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a 5x5 matrix to hold a simplified representation of this
|
||||||
|
// marker.
|
||||||
|
bits = cv::Mat::zeros(5, 5, CV_8UC1);
|
||||||
|
|
||||||
|
// For every cell in the marker flip it's corresponding 'bit' in the
|
||||||
|
// bit matrix if it is at least 50 % white.
|
||||||
|
for(int y = 0; y < 5; y++){
|
||||||
|
for(int x = 0; x < 5; x++){
|
||||||
|
int cX = (x + 1) * 50;
|
||||||
|
int cY = (y + 1) * 50;
|
||||||
|
cv::Mat cell = marker(cv::Rect(cX, cY, 50, 50));
|
||||||
|
int nZ = cv::countNonZero(cell);
|
||||||
|
|
||||||
|
if(nZ > (50 * 50) / 2) bits.at<uchar>(y, x) = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calcultate the hamming distance of the bit matrix and each of it's
|
||||||
|
// 90 degree rotations to determine if this marker has a valid code.
|
||||||
|
if(hammDistMarker(bits) != 0){
|
||||||
|
for(int r = 1; r < 4; r++){
|
||||||
|
bits = rotate(bits);
|
||||||
|
rotations++;
|
||||||
|
if(hammDistMarker(bits) != 0) continue;
|
||||||
|
else{ found = true; break;}
|
||||||
|
}
|
||||||
|
}else found = true;
|
||||||
|
|
||||||
|
// If the code is valid then decode it to an int and return it.
|
||||||
|
if(found){
|
||||||
|
for(int y = 0; y < 5; y++){
|
||||||
|
code <<= 1;
|
||||||
|
if(bits.at<uchar>(y, 1))
|
||||||
|
code |= 1;
|
||||||
|
|
||||||
|
code <<= 1;
|
||||||
|
if(bits.at<uchar>(y, 3))
|
||||||
|
code |= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the perimeter of a polygon defined as a vector of points.
|
||||||
|
*/
|
||||||
|
float perimeter(points_vector & p){
|
||||||
|
float per = 0.0f, dx, dy;
|
||||||
|
|
||||||
|
for(size_t i; i < p.size(); ++i){
|
||||||
|
dx = p[i].x - p[(i + 1) % p.size()].x;
|
||||||
|
dy = p[i].y - p[(i + 1) % p.size()].y;
|
||||||
|
per += sqrt((dx * dx) + (dy * dy));
|
||||||
|
}
|
||||||
|
|
||||||
|
return per;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* CLASS METHODS *
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the points vector associated with this marker.
|
||||||
|
*/
|
||||||
|
Marker::~Marker(){
|
||||||
|
points.clear();
|
||||||
|
}
|
||||||
|
} // namespace nxtar
|
||||||
|
@@ -17,13 +17,58 @@
|
|||||||
#define MARKER_HPP
|
#define MARKER_HPP
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <opencv2/opencv.hpp>
|
#include <opencv2/opencv.hpp>
|
||||||
|
|
||||||
namespace nxtar{
|
namespace nxtar{
|
||||||
void getAllMarkers(std::vector<int> &, cv::Mat &);
|
|
||||||
#ifdef DESKTOP
|
|
||||||
void getAllMarkers_d(std::vector<int> &, cv::Mat &);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
class Marker;
|
||||||
|
|
||||||
|
typedef std::vector<cv::Point2f> points_vector;
|
||||||
|
typedef std::vector<Marker> markers_vector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class representing a marker with the geometric transformations needed to
|
||||||
|
* render something on top of it.
|
||||||
|
*/
|
||||||
|
class Marker{
|
||||||
|
public:
|
||||||
|
~Marker();
|
||||||
|
|
||||||
|
int code;
|
||||||
|
points_vector points;
|
||||||
|
cv::Mat translation;
|
||||||
|
cv::Mat rotation;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detect all 5x5 markers in the input image and return their codes in the
|
||||||
|
* output vector.
|
||||||
|
*/
|
||||||
|
void getAllMarkers(markers_vector &, cv::Mat &);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a chessboard calibration pattern in the input image. Returns true
|
||||||
|
* if the pattern was found, false otherwise. The calibration points
|
||||||
|
* detected on the image are saved in the output vector.
|
||||||
|
*/
|
||||||
|
bool findCalibrationPattern(points_vector &, cv::Mat &);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the camera matrix and the distortion coefficients for the camera
|
||||||
|
* that captured the input image points into the output matrices. Returns
|
||||||
|
* the reprojection error as returned by cv::calibrateCamera.
|
||||||
|
*/
|
||||||
|
double getCameraParameters(cv::Mat &, cv::Mat &, std::vector<points_vector> &, cv::Size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Obtains the necesary geometric transformations necessary to move a reference
|
||||||
|
* unitary polygon to the position and rotation of the markers passed as input.
|
||||||
|
* The obtained transformations are given relative to a camera centered in the
|
||||||
|
* origin and are saved inside the input markers.
|
||||||
|
*/
|
||||||
|
void estimateMarkerPosition(markers_vector &, cv::Mat &, cv::Mat &);
|
||||||
|
|
||||||
|
} // namespace nxtar
|
||||||
|
|
||||||
|
#endif // MARKER_HPP
|
||||||
|
BIN
res/drawable-hdpi/ic_nxtar_core_launcher.png
Normal file
After Width: | Height: | Size: 2.8 KiB |
BIN
res/drawable-mdpi/ic_nxtar_core_launcher.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
res/drawable-xhdpi/ic_nxtar_core_launcher.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
res/drawable-xhdpi/ouya_icon.png
Normal file
After Width: | Height: | Size: 101 KiB |
BIN
res/drawable-xxhdpi/ic_nxtar_core_launcher.png
Normal file
After Width: | Height: | Size: 5.0 KiB |
@@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
-->
|
-->
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">NxtAR</string>
|
<string name="app_name">NxtAR-core</string>
|
||||||
<string name="ocv_failed">No se pudo inicializar OpenCV</string>
|
<string name="ocv_failed">Error al inicializar OpenCV</string>
|
||||||
<string name="ocv_success">OpenCV inicializado con exito</string>
|
<string name="ocv_success">OpenCV inicializado con éxito</string>
|
||||||
</resources>
|
</resources>
|
@@ -15,7 +15,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
-->
|
-->
|
||||||
<resources>
|
<resources>
|
||||||
<string name="app_name">NxtAR</string>
|
<string name="app_name">NxtAR-core</string>
|
||||||
<string name="ocv_failed">Failed to initialize OpenCV</string>
|
<string name="ocv_failed">Failed to initialize OpenCV</string>
|
||||||
<string name="ocv_success">OpenCV initialized successfully</string>
|
<string name="ocv_success">OpenCV initialized successfully</string>
|
||||||
</resources>
|
</resources>
|
@@ -24,9 +24,9 @@ import org.opencv.android.Utils;
|
|||||||
import org.opencv.core.Mat;
|
import org.opencv.core.Mat;
|
||||||
import org.opencv.imgproc.Imgproc;
|
import org.opencv.imgproc.Imgproc;
|
||||||
|
|
||||||
import ve.ucv.ciens.ccg.nxtar.interfaces.CVProcessor;
|
import ve.ucv.ciens.ccg.nxtar.interfaces.ActionResolver;
|
||||||
import ve.ucv.ciens.ccg.nxtar.interfaces.MulticastEnabler;
|
import ve.ucv.ciens.ccg.nxtar.interfaces.ImageProcessor;
|
||||||
import ve.ucv.ciens.ccg.nxtar.interfaces.Toaster;
|
import ve.ucv.ciens.ccg.nxtar.utils.ProjectConstants;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.pm.ActivityInfo;
|
import android.content.pm.ActivityInfo;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
@@ -42,73 +42,212 @@ import com.badlogic.gdx.Gdx;
|
|||||||
import com.badlogic.gdx.backends.android.AndroidApplication;
|
import com.badlogic.gdx.backends.android.AndroidApplication;
|
||||||
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
|
import com.badlogic.gdx.backends.android.AndroidApplicationConfiguration;
|
||||||
import com.badlogic.gdx.controllers.mappings.Ouya;
|
import com.badlogic.gdx.controllers.mappings.Ouya;
|
||||||
|
import com.badlogic.gdx.math.Matrix3;
|
||||||
|
import com.badlogic.gdx.math.Vector3;
|
||||||
|
|
||||||
public class MainActivity extends AndroidApplication implements Toaster, MulticastEnabler, CVProcessor{
|
/**
|
||||||
|
* <p>The main activity of the application.</p>
|
||||||
|
*
|
||||||
|
* <p>Provides operating system services to the LibGDX platform
|
||||||
|
* independant code, and handles OpenCV initialization and api calls.</p>
|
||||||
|
*/
|
||||||
|
public class MainActivity extends AndroidApplication implements ActionResolver, ImageProcessor{
|
||||||
|
/**
|
||||||
|
* Tag used for logging.
|
||||||
|
*/
|
||||||
private static final String TAG = "NXTAR_ANDROID_MAIN";
|
private static final String TAG = "NXTAR_ANDROID_MAIN";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class name used for logging.
|
||||||
|
*/
|
||||||
private static final String CLASS_NAME = MainActivity.class.getSimpleName();
|
private static final String CLASS_NAME = MainActivity.class.getSimpleName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Output stream used to codify images as JPEG using Android's Bitmap class.
|
||||||
|
*/
|
||||||
|
private static final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates if OpenCV was initialized sucessfully.
|
||||||
|
*/
|
||||||
|
private static boolean ocvOn = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Intrinsic camera matrix.
|
||||||
|
*/
|
||||||
|
private static Mat cameraMatrix;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Distortion coeffitients matrix.
|
||||||
|
*/
|
||||||
|
private static Mat distortionCoeffs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to set and release multicast locks.
|
||||||
|
*/
|
||||||
private WifiManager wifiManager;
|
private WifiManager wifiManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used to maintain the multicast lock during the service discovery procedure.
|
||||||
|
*/
|
||||||
private MulticastLock multicastLock;
|
private MulticastLock multicastLock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handler used for requesting toast messages from the core LibGDX code.
|
||||||
|
*/
|
||||||
private Handler uiHandler;
|
private Handler uiHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User interface context used to show the toast messages.
|
||||||
|
*/
|
||||||
private Context uiContext;
|
private Context uiContext;
|
||||||
private boolean ocvOn;
|
|
||||||
|
/**
|
||||||
|
* OpenCV asynchronous initializer callback for mobile devices.
|
||||||
|
*/
|
||||||
private BaseLoaderCallback loaderCallback;
|
private BaseLoaderCallback loaderCallback;
|
||||||
private final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
|
||||||
|
|
||||||
/*static{
|
/**
|
||||||
if (!OpenCVLoader.initDebug()){
|
* Indicates if the current video streaming camera has been calibrated.
|
||||||
Gdx.app.exit();
|
*/
|
||||||
}
|
private boolean cameraCalibrated;
|
||||||
System.loadLibrary("cvproc");
|
|
||||||
}*/
|
|
||||||
|
|
||||||
public native void getMarkerCodesAndLocations(long inMat, long outMat, int[] codes);
|
/**
|
||||||
|
* <p>Wrapper for the getAllMarkers native function.</p>
|
||||||
|
*
|
||||||
|
* @param inMat INPUT. The image to analize.
|
||||||
|
* @param outMat OUTPUT. The image with the markers highlighted.
|
||||||
|
* @param codes OUTPUT. The codes for each marker detected. Must be {@link ProjectConstants.MAXIMUM_NUMBER_OF_MARKERS} elements long.
|
||||||
|
* @param camMat INPUT. The intrinsic camera matrix.
|
||||||
|
* @param distMat INPUT. The distortion coefficients of the camera.
|
||||||
|
* @param translations OUTPUT. The markers pose translations. Must be {@link ProjectConstants.MAXIMUM_NUMBER_OF_MARKERS} * 3 elements long.
|
||||||
|
* @param rotations OUTPUT. The markers pose rotations. Must be {@link ProjectConstants.MAXIMUM_NUMBER_OF_MARKERS} * 9 elements long.
|
||||||
|
*/
|
||||||
|
private native void getMarkerCodesAndLocations(long inMat, long outMat, int[] codes, long camMat, long distMat, float[] translations, float[] rotations);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Wrapper for the findCalibrationPattern native function.</p>
|
||||||
|
*
|
||||||
|
* @param inMat INPUT. The image to analize.
|
||||||
|
* @param outMat OUTPUT. The image with the calibration pattern highlighted.
|
||||||
|
* @param points OUTPUT. The spatial location of the calibration points if found.
|
||||||
|
* @return True if the calibration pattern was found. False otherwise.
|
||||||
|
*/
|
||||||
|
private native boolean findCalibrationPattern(long inMat, long outMat, float[] points);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Wrapper around the getCameraParameters native function.</p>
|
||||||
|
*
|
||||||
|
* @param camMat OUTPUT. The intrinsic camera matrix.
|
||||||
|
* @param distMat OUTPUT. The distortion coeffitients matrix.
|
||||||
|
* @param frame INPUT. A sample input image from the camera to calibrate.
|
||||||
|
* @param calibrationPoints INPUT. The calibration points of all samples.
|
||||||
|
* @return The calibration error as returned by OpenCV.
|
||||||
|
*/
|
||||||
|
private native double calibrateCameraParameters(long camMat, long distMat, long frame, float[] calibrationPoints);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Static block. Tries to load OpenCV and the native method implementations
|
||||||
|
* statically if running on an OUYA device.</p>
|
||||||
|
*/
|
||||||
|
static{
|
||||||
|
if(Ouya.runningOnOuya){
|
||||||
|
if(!OpenCVLoader.initDebug())
|
||||||
|
ocvOn = false;
|
||||||
|
|
||||||
|
try{
|
||||||
|
System.loadLibrary("cvproc");
|
||||||
|
ocvOn = true;
|
||||||
|
}catch(UnsatisfiedLinkError u){
|
||||||
|
ocvOn = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Initializes this activity</p>
|
||||||
|
*
|
||||||
|
* <p>This method handles the initialization of LibGDX and OpenCV. OpenCV is
|
||||||
|
* loaded the asynchronous method if the devices is not an OUYA console.</p>
|
||||||
|
*
|
||||||
|
* @param savedInstanceState The application state if it was saved in a previous run.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState){
|
public void onCreate(Bundle savedInstanceState){
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
ocvOn = false;
|
cameraCalibrated = false;
|
||||||
|
|
||||||
|
// Set screen orientation. Portrait on mobile devices, landscape on OUYA.
|
||||||
if(!Ouya.runningOnOuya){
|
if(!Ouya.runningOnOuya){
|
||||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
|
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
|
||||||
}else{
|
}else{
|
||||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
|
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set up the Android related variables.
|
||||||
uiHandler = new Handler();
|
uiHandler = new Handler();
|
||||||
uiContext = this;
|
uiContext = this;
|
||||||
wifiManager = (WifiManager)getSystemService(Context.WIFI_SERVICE);
|
wifiManager = (WifiManager)getSystemService(Context.WIFI_SERVICE);
|
||||||
|
|
||||||
|
// Attempt to initialize OpenCV.
|
||||||
|
if(!Ouya.runningOnOuya){
|
||||||
|
// If running on a moble device, use the asynchronous method aided
|
||||||
|
// by the OpenCV Manager app.
|
||||||
|
loaderCallback = new BaseLoaderCallback(this){
|
||||||
|
@Override
|
||||||
|
public void onManagerConnected(int status){
|
||||||
|
switch(status){
|
||||||
|
case LoaderCallbackInterface.SUCCESS:
|
||||||
|
// If successfully initialized then load the native method implementations and
|
||||||
|
// initialize the static matrices.
|
||||||
|
System.loadLibrary("cvproc");
|
||||||
|
ocvOn = true;
|
||||||
|
cameraMatrix = new Mat();
|
||||||
|
distortionCoeffs = new Mat();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Toast.makeText(uiContext, R.string.ocv_failed, Toast.LENGTH_LONG).show();
|
||||||
|
ocvOn = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Launch the asynchronous initializer.
|
||||||
|
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_7, this, loaderCallback);
|
||||||
|
|
||||||
|
}else{
|
||||||
|
// If running on an OUYA device.
|
||||||
|
if(ocvOn){
|
||||||
|
// If OpenCV loaded successfully then initialize the native matrices.
|
||||||
|
cameraMatrix = new Mat();
|
||||||
|
distortionCoeffs = new Mat();
|
||||||
|
}else{
|
||||||
|
Toast.makeText(uiContext, R.string.ocv_failed, Toast.LENGTH_LONG).show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configure LibGDX.
|
||||||
AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration();
|
AndroidApplicationConfiguration cfg = new AndroidApplicationConfiguration();
|
||||||
cfg.useGL20 = true;
|
cfg.useAccelerometer = true;
|
||||||
cfg.useAccelerometer = false;
|
cfg.useCompass = true;
|
||||||
cfg.useCompass = false;
|
|
||||||
cfg.useWakelock = true;
|
cfg.useWakelock = true;
|
||||||
|
|
||||||
loaderCallback = new BaseLoaderCallback(this){
|
// Launch the LibGDX core game class.
|
||||||
@Override
|
|
||||||
public void onManagerConnected(int status){
|
|
||||||
switch(status){
|
|
||||||
case LoaderCallbackInterface.SUCCESS:
|
|
||||||
System.loadLibrary("cvproc");
|
|
||||||
ocvOn = true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
Toast.makeText(uiContext, R.string.ocv_failed, Toast.LENGTH_LONG).show();
|
|
||||||
Gdx.app.exit();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_7, this, loaderCallback);
|
|
||||||
initialize(new NxtARCore(this), cfg);
|
initialize(new NxtARCore(this), cfg);
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////
|
////////////////////////////////////////////////
|
||||||
// Toaster interface methods. //
|
// OSFunctionalityProvider interface methods. //
|
||||||
////////////////////////////////
|
////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Shows a short message on screen using Android's toast mechanism.</p>
|
||||||
|
*
|
||||||
|
* @param msg The message to show.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void showShortToast(final String msg){
|
public void showShortToast(final String msg){
|
||||||
uiHandler.post(new Runnable(){
|
uiHandler.post(new Runnable(){
|
||||||
@@ -119,6 +258,11 @@ public class MainActivity extends AndroidApplication implements Toaster, Multica
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Shows a long message on screen using Android's toast mechanism.</p>
|
||||||
|
*
|
||||||
|
* @param msg The message to show.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void showLongToast(final String msg){
|
public void showLongToast(final String msg){
|
||||||
uiHandler.post(new Runnable(){
|
uiHandler.post(new Runnable(){
|
||||||
@@ -129,9 +273,9 @@ public class MainActivity extends AndroidApplication implements Toaster, Multica
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/////////////////////////////////////////
|
/**
|
||||||
// MulticastEnabler interface methods. //
|
* <p>Enable the transmision and reception of multicast network messages.</p>
|
||||||
/////////////////////////////////////////
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void enableMulticast(){
|
public void enableMulticast(){
|
||||||
Gdx.app.log(TAG, CLASS_NAME + ".enableMulticast() :: Requesting multicast lock.");
|
Gdx.app.log(TAG, CLASS_NAME + ".enableMulticast() :: Requesting multicast lock.");
|
||||||
@@ -140,6 +284,9 @@ public class MainActivity extends AndroidApplication implements Toaster, Multica
|
|||||||
multicastLock.acquire();
|
multicastLock.acquire();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Disables the transmision and reception of multicast network messages.</p>
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void disableMulticast(){
|
public void disableMulticast(){
|
||||||
Gdx.app.log(TAG, CLASS_NAME + ".disableMulticast() :: Releasing multicast lock.");
|
Gdx.app.log(TAG, CLASS_NAME + ".disableMulticast() :: Releasing multicast lock.");
|
||||||
@@ -149,40 +296,205 @@ public class MainActivity extends AndroidApplication implements Toaster, Multica
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////
|
||||||
|
// CVProcessor interface methods. //
|
||||||
|
////////////////////////////////////
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CVData processFrame(byte[] frame, int w, int h) {
|
public MarkerData findMarkersInFrame(byte[] frame){
|
||||||
if(ocvOn){
|
if(ocvOn){
|
||||||
int codes[] = new int[15];
|
if(cameraCalibrated){
|
||||||
|
int[] codes = new int[ProjectConstants.MAXIMUM_NUMBER_OF_MARKERS];
|
||||||
|
float[] translations = new float[ProjectConstants.MAXIMUM_NUMBER_OF_MARKERS * 3];
|
||||||
|
float[] rotations = new float[ProjectConstants.MAXIMUM_NUMBER_OF_MARKERS * 9];
|
||||||
|
MarkerData data;
|
||||||
|
Bitmap tFrame, mFrame;
|
||||||
|
Mat inImg = new Mat();
|
||||||
|
Mat outImg = new Mat();
|
||||||
|
|
||||||
|
// Fill the codes array with -1 to indicate markers that were not found;
|
||||||
|
for(int i : codes)
|
||||||
|
codes[i] = -1;
|
||||||
|
|
||||||
|
// Decode the input image and convert it to an OpenCV matrix.
|
||||||
|
tFrame = BitmapFactory.decodeByteArray(frame, 0, frame.length);
|
||||||
|
Utils.bitmapToMat(tFrame, inImg);
|
||||||
|
|
||||||
|
// Find the markers in the input image.
|
||||||
|
getMarkerCodesAndLocations(inImg.getNativeObjAddr(), outImg.getNativeObjAddr(), codes, cameraMatrix.getNativeObjAddr(), distortionCoeffs.getNativeObjAddr(), translations, rotations);
|
||||||
|
|
||||||
|
// Encode the output image as a JPEG image.
|
||||||
|
mFrame = Bitmap.createBitmap(outImg.cols(), outImg.rows(), Bitmap.Config.RGB_565);
|
||||||
|
Utils.matToBitmap(outImg, mFrame);
|
||||||
|
mFrame.compress(CompressFormat.JPEG, 100, outputStream);
|
||||||
|
|
||||||
|
// Create and fill the output data structure.
|
||||||
|
data = new MarkerData();
|
||||||
|
data.outFrame = outputStream.toByteArray();
|
||||||
|
data.markerCodes = codes;
|
||||||
|
data.rotationMatrices = new Matrix3[ProjectConstants.MAXIMUM_NUMBER_OF_MARKERS];
|
||||||
|
data.translationVectors = new Vector3[ProjectConstants.MAXIMUM_NUMBER_OF_MARKERS];
|
||||||
|
|
||||||
|
for(int i = 0, p = 0; i < ProjectConstants.MAXIMUM_NUMBER_OF_MARKERS; i++, p += 3){
|
||||||
|
data.translationVectors[i] = new Vector3(translations[p], translations[p + 1], translations[p + 2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int k = 0; k < ProjectConstants.MAXIMUM_NUMBER_OF_MARKERS; k++){
|
||||||
|
data.rotationMatrices[k] = new Matrix3();
|
||||||
|
for(int row = 0; row < 3; row++){
|
||||||
|
for(int col = 0; col < 3; col++){
|
||||||
|
data.rotationMatrices[k].val[col + (row * 3)] = rotations[col + (row * 3) + (9 * k)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up memory.
|
||||||
|
tFrame.recycle();
|
||||||
|
mFrame.recycle();
|
||||||
|
outputStream.reset();
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}else{
|
||||||
|
Gdx.app.debug(TAG, CLASS_NAME + ".findMarkersInFrame(): The camera has not been calibrated.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
Gdx.app.debug(TAG, CLASS_NAME + ".findMarkersInFrame(): OpenCV is not ready or failed to load.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CalibrationData findCalibrationPattern(byte[] frame){
|
||||||
|
if(ocvOn){
|
||||||
|
boolean found;
|
||||||
|
float points[] = new float[ProjectConstants.CALIBRATION_PATTERN_POINTS * 2];
|
||||||
Bitmap tFrame, mFrame;
|
Bitmap tFrame, mFrame;
|
||||||
|
Mat inImg = new Mat(), outImg = new Mat();
|
||||||
|
CalibrationData data = new CalibrationData();
|
||||||
|
|
||||||
|
// Decode the input frame and convert it to an OpenCV Matrix.
|
||||||
tFrame = BitmapFactory.decodeByteArray(frame, 0, frame.length);
|
tFrame = BitmapFactory.decodeByteArray(frame, 0, frame.length);
|
||||||
|
|
||||||
Mat inImg = new Mat();
|
|
||||||
Mat outImg = new Mat();
|
|
||||||
Utils.bitmapToMat(tFrame, inImg);
|
Utils.bitmapToMat(tFrame, inImg);
|
||||||
|
|
||||||
getMarkerCodesAndLocations(inImg.getNativeObjAddr(), outImg.getNativeObjAddr(), codes);
|
// Attempt to find the calibration pattern in the input frame.
|
||||||
|
found = findCalibrationPattern(inImg.getNativeObjAddr(), outImg.getNativeObjAddr(), points);
|
||||||
|
|
||||||
Mat temp = new Mat();
|
// Encode the output image as a JPEG image.
|
||||||
Imgproc.cvtColor(outImg, temp, Imgproc.COLOR_BGR2RGB);
|
mFrame = Bitmap.createBitmap(outImg.cols(), outImg.rows(), Bitmap.Config.RGB_565);
|
||||||
|
Utils.matToBitmap(outImg, mFrame);
|
||||||
mFrame = Bitmap.createBitmap(temp.cols(), temp.rows(), Bitmap.Config.RGB_565);
|
|
||||||
Utils.matToBitmap(temp, mFrame);
|
|
||||||
mFrame.compress(CompressFormat.JPEG, 100, outputStream);
|
mFrame.compress(CompressFormat.JPEG, 100, outputStream);
|
||||||
|
|
||||||
CVData data = new CVData();
|
// Prepare the output data structure.
|
||||||
data.outFrame = outputStream.toByteArray();
|
data.outFrame = outputStream.toByteArray();
|
||||||
data.markerCodes = codes;
|
data.calibrationPoints = found ? points : null;
|
||||||
|
|
||||||
|
// Clean up memory.
|
||||||
tFrame.recycle();
|
tFrame.recycle();
|
||||||
mFrame.recycle();
|
mFrame.recycle();
|
||||||
outputStream.reset();
|
outputStream.reset();
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}else{
|
|
||||||
Gdx.app.debug(TAG, CLASS_NAME + ".processFrame(): OpenCV is not ready or failed to load.");
|
|
||||||
|
|
||||||
|
}else{
|
||||||
|
Gdx.app.debug(TAG, CLASS_NAME + ".findCalibrationPattern(): OpenCV is not ready or failed to load.");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
|
public void calibrateCamera(float[][] calibrationSamples, byte[] frame) {
|
||||||
|
if(ocvOn){
|
||||||
|
float[] calibrationPoints = new float[ProjectConstants.CALIBRATION_PATTERN_POINTS * 2 * ProjectConstants.CALIBRATION_SAMPLES];
|
||||||
|
int w = ProjectConstants.CALIBRATION_PATTERN_POINTS * 2;
|
||||||
|
Bitmap tFrame;
|
||||||
|
Mat inImg = new Mat();
|
||||||
|
|
||||||
|
// Save the calibration points on a one dimensional array for easier parameter passing
|
||||||
|
// to the native code.
|
||||||
|
for(int i = 0; i < ProjectConstants.CALIBRATION_SAMPLES; i++){
|
||||||
|
for(int j = 0, p = 0; j < ProjectConstants.CALIBRATION_PATTERN_POINTS; j++, p += 2){
|
||||||
|
calibrationPoints[p + (w * i)] = calibrationSamples[i][p];
|
||||||
|
calibrationPoints[(p + 1) + (w * i)] = calibrationSamples[i][p + 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode the input image and convert it to an OpenCV matrix.
|
||||||
|
tFrame = BitmapFactory.decodeByteArray(frame, 0, frame.length);
|
||||||
|
Utils.bitmapToMat(tFrame, inImg);
|
||||||
|
|
||||||
|
// Attempt to obtain the camera parameters.
|
||||||
|
double error = calibrateCameraParameters(cameraMatrix.getNativeObjAddr(), distortionCoeffs.getNativeObjAddr(), inImg.getNativeObjAddr(), calibrationPoints);
|
||||||
|
Gdx.app.log(TAG, CLASS_NAME + "calibrateCamera(): calibrateCameraParameters retured " + Double.toString(error));
|
||||||
|
cameraCalibrated = true;
|
||||||
|
|
||||||
|
}else{
|
||||||
|
Gdx.app.debug(TAG, CLASS_NAME + ".calibrateCamera(): OpenCV is not ready or failed to load.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] undistortFrame(byte[] frame){
|
||||||
|
if(ocvOn){
|
||||||
|
if(cameraCalibrated){
|
||||||
|
byte undistortedFrame[];
|
||||||
|
Bitmap tFrame, mFrame;
|
||||||
|
Mat inImg = new Mat(), outImg = new Mat();
|
||||||
|
|
||||||
|
// Decode the input frame and convert it to an OpenCV Matrix.
|
||||||
|
tFrame = BitmapFactory.decodeByteArray(frame, 0, frame.length);
|
||||||
|
Utils.bitmapToMat(tFrame, inImg);
|
||||||
|
|
||||||
|
// Apply the undistort correction to the input frame.
|
||||||
|
Imgproc.undistort(inImg, outImg, cameraMatrix, distortionCoeffs);
|
||||||
|
|
||||||
|
// Encode the output image as a JPEG image.
|
||||||
|
mFrame = Bitmap.createBitmap(outImg.cols(), outImg.rows(), Bitmap.Config.RGB_565);
|
||||||
|
Utils.matToBitmap(outImg, mFrame);
|
||||||
|
mFrame.compress(CompressFormat.JPEG, 100, outputStream);
|
||||||
|
|
||||||
|
// Prepare the return frame.
|
||||||
|
undistortedFrame = outputStream.toByteArray();
|
||||||
|
|
||||||
|
// Clean up memory.
|
||||||
|
tFrame.recycle();
|
||||||
|
mFrame.recycle();
|
||||||
|
outputStream.reset();
|
||||||
|
|
||||||
|
return undistortedFrame;
|
||||||
|
|
||||||
|
}else{
|
||||||
|
Gdx.app.debug(TAG, CLASS_NAME + ".undistortFrame(): Camera has not been calibrated.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
Gdx.app.debug(TAG, CLASS_NAME + ".undistortFrame(): OpenCV is not ready or failed to load.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCameraCalibrated() {
|
||||||
|
return ocvOn && cameraCalibrated;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getFocalPointX() {
|
||||||
|
return ocvOn && cameraCalibrated ? (float)cameraMatrix.get(0, 0)[0] : 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getFocalPointY() {
|
||||||
|
return ocvOn && cameraCalibrated ? (float)cameraMatrix.get(1, 1)[0] : 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getCameraCenterX() {
|
||||||
|
return ocvOn && cameraCalibrated ? (float)cameraMatrix.get(0, 2)[0] : 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getCameraCenterY() {
|
||||||
|
return ocvOn && cameraCalibrated ? (float)cameraMatrix.get(1, 2)[0] : 0.0f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|