[Artoolkit] Marker of nftSimple
重点看:markers.dat 的解析原理
1.
int main(int argc, char** argv)
{
char glutGamemode[];
const char *cparam_name = "Data2/camera_para.dat";
char vconf[] = "";
const char markerConfigDataFilename[] = "Data2/markers.dat";
2.
// Load marker(s).
newMarkers(markerConfigDataFilename, &markersNFT, &markersNFTCount);
if (!markersNFTCount) {
ARLOGe("Error loading markers from config. file '%s'.\n", markerConfigDataFilename);
cleanup();
exit(-);
}
ARLOGi("Marker count = %d\n", markersNFTCount); //等于1
3.
// Marker data has been loaded, so now load NFT data.
if (!loadNFTData()) {
ARLOGe("Error loading NFT data.\n");
cleanup();
exit(-);
}
newMarkers 到底是如何工作的呢?
# Number of markers # Entries for each marker. Format is:
#
# Name of pattern file (relative to this file)
# Marker type (SINGLE)
# Marker width in millimetres (floating point number)
# Optional tokens:
# FILTER [x] Enable pose estimate filtering for the preceding marker
# x (optional) specifies the cutoff frequency. Default
# value is AR_FILTER_TRANS_MAT_CUTOFF_FREQ_DEFAULT, which
# at time of writing, equals 5.0.
# A blank line ../DataNFT/pinball
NFT
FILTER 15.0
void newMarkers(const char *markersConfigDataFilePathC, ARMarkerNFT **markersNFT_out, int *markersNFTCount_out)
{
FILE *fp;
char buf[MAXPATHLEN], buf1[MAXPATHLEN];
int tempI;
ARMarkerNFT *markersNFT;
int markersNFTCount;
ARdouble tempF;
int i;
char markersConfigDataDirC[MAXPATHLEN];
size_t markersConfigDataDirCLen; if (!markersConfigDataFilePathC || markersConfigDataFilePathC[] == '\0' || !markersNFT_out || !markersNFTCount_out) return; // Load the marker data file.
ARLOGd("Opening marker config. data file from path '%s'.\n", markersConfigDataFilePathC);
arUtilGetDirectoryNameFromPath(markersConfigDataDirC, markersConfigDataFilePathC, MAXPATHLEN, ); // 1 = add '/' at end.
markersConfigDataDirCLen = strlen(markersConfigDataDirC);
if ((fp = fopen(markersConfigDataFilePathC, "r")) == NULL) {
ARLOGe("Error: unable to locate marker config data file '%s'.\n", markersConfigDataFilePathC);
return;
} // First line is number of markers to read.
get_buff(buf, MAXPATHLEN, fp, );
if (sscanf(buf, "%d", &tempI) != ) {
ARLOGe("Error in marker configuration data file; expected marker count.\n");
fclose(fp);
return;
} arMallocClear(markersNFT, ARMarkerNFT, tempI);
markersNFTCount = tempI; ARLOGd("Reading %d marker configuration(s).\n", markersNFTCount); 37 for (i = ; i < markersNFTCount; i++) { // Read marker file name.
if (!get_buff(buf, MAXPATHLEN, fp, )) {
ARLOGe("Error in marker configuration data file; expected marker name.\n");
break;
} // Read marker type.
if (!get_buff(buf1, MAXPATHLEN, fp, )) {
ARLOGe("Error in marker configuration data file; expected marker type.\n");
break;
} // Interpret marker type, and read more data.
if (strcmp(buf1, "SINGLE") == ) {
ARLOGe("Error in marker configuration data file; SINGLE markers not supported in this build.\n");
} else if (strcmp(buf1, "MULTI") == ) {
ARLOGe("Error in marker configuration data file; MULTI markers not supported in this build.\n");
} else if (strcmp(buf1, "NFT") == ) {
markersNFT[i].valid = markersNFT[i].validPrev = FALSE;
arMalloc(markersNFT[i].datasetPathname, char, markersConfigDataDirCLen + strlen(buf) + );
strcpy(markersNFT[i].datasetPathname, markersConfigDataDirC);
strcpy(markersNFT[i].datasetPathname + markersConfigDataDirCLen, buf);
markersNFT[i].pageNo = -;
} else {
ARLOGe("Error in marker configuration data file; unsupported marker type %s.\n", buf1);
} // Look for optional tokens. A blank line marks end of options.
while (get_buff(buf, MAXPATHLEN, fp, ) && (buf[] != '\0')) {
if (strncmp(buf, "FILTER", ) == ) {
markersNFT[i].filterCutoffFrequency = AR_FILTER_TRANS_MAT_CUTOFF_FREQ_DEFAULT;
markersNFT[i].filterSampleRate = AR_FILTER_TRANS_MAT_SAMPLE_RATE_DEFAULT;
if (strlen(buf) != ) {
if (sscanf(&buf[],
#ifdef ARDOUBLE_IS_FLOAT
"%f"
#else
"%lf"
#endif
, &tempF) == ) markersNFT[i].filterCutoffFrequency = tempF;
}
markersNFT[i].ftmi = arFilterTransMatInit(markersNFT[i].filterSampleRate, markersNFT[i].filterCutoffFrequency);
}
// Unknown tokens are ignored.
}
84 }
fclose(fp); // If not all markers were read, an error occurred.
if (i < markersNFTCount) { // Clean up.
for (; i >= ; i--) {
if (markersNFT[i].datasetPathname) free(markersNFT[i].datasetPathname);
if (markersNFT[i].ftmi) arFilterTransMatFinal(markersNFT[i].ftmi);
}
free(markersNFT); *markersNFTCount_out = ;
*markersNFT_out = NULL;
return;
} *markersNFTCount_out = markersNFTCount;
*markersNFT_out = markersNFT;
}
typedef struct _ARMarkerNFT {
// ARMarker protected
bool valid;
bool validPrev;
ARdouble trans[][];
ARPose pose;
ARdouble marker_width;
ARdouble marker_height;
// ARMarker private
ARFilterTransMatInfo *ftmi; // 变换矩阵,为何使用链表的形式?
ARdouble filterCutoffFrequency;
ARdouble filterSampleRate;
// ARMarkerNFT
int pageNo;
char *datasetPathname;
} ARMarkerNFT;
loadNFTData 开始分析。
// References globals: markersNFTCount
// Modifies globals: threadHandle, surfaceSet[], surfaceSetCount, markersNFT[]
static int loadNFTData(void)
{
int i;
KpmRefDataSet *refDataSet; // If data was already loaded, stop KPM tracking thread and unload previously loaded data.
if (threadHandle) {
ARLOGi("Reloading NFT data.\n");
unloadNFTData();
} else {
ARLOGi("Loading NFT data.\n");
} refDataSet = NULL; 18 for (i = ; i < markersNFTCount; i++) { // 重点在这里!
// (1) Load KPM data.
KpmRefDataSet *refDataSet2;
ARLOGi("Reading %s.fset3\n", markersNFT[i].datasetPathname);
if (kpmLoadRefDataSet(markersNFT[i].datasetPathname, "fset3", &refDataSet2) < ) {
ARLOGe("Error reading KPM data from %s.fset3\n", markersNFT[i].datasetPathname);
markersNFT[i].pageNo = -;
continue;
}
markersNFT[i].pageNo = surfaceSetCount;
ARLOGi(" Assigned page no. %d.\n", surfaceSetCount);
if (kpmChangePageNoOfRefDataSet(refDataSet2, KpmChangePageNoAllPages, surfaceSetCount) < ) {
ARLOGe("Error: kpmChangePageNoOfRefDataSet\n");
exit(-);
}
if (kpmMergeRefDataSet(&refDataSet, &refDataSet2) < ) {
ARLOGe("Error: kpmMergeRefDataSet\n");
exit(-);
}
ARLOGi(" Done.\n"); // (2) Load AR2 data.
ARLOGi("Reading %s.fset\n", markersNFT[i].datasetPathname); if ((surfaceSet[surfaceSetCount] = ar2ReadSurfaceSet(markersNFT[i].datasetPathname, "fset", NULL)) == NULL ) {
ARLOGe("Error reading data from %s.fset\n", markersNFT[i].datasetPathname);
}
ARLOGi(" Done.\n"); surfaceSetCount++;
if (surfaceSetCount == PAGES_MAX) break;
49 }
if (kpmSetRefDataSet(kpmHandle, refDataSet) < ) {
ARLOGe("Error: kpmSetRefDataSet\n");
exit(-);
}
kpmDeleteRefDataSet(&refDataSet); // Start the KPM tracking thread.
threadHandle = trackingInitInit(kpmHandle);
if (!threadHandle) exit(-); ARLOGi("Loading of NFT data complete.\n");
return (TRUE);
}
需要找个multi marker的例子再继续分析。
[Artoolkit] Marker of nftSimple的更多相关文章
- [Artoolkit] Marker Training
Link: Documentation About the Traditional Template Square Marker Limitations (重要) Traditional Templa ...
- 本人AI知识体系导航 - AI menu
Relevant Readable Links Name Interesting topic Comment Edwin Chen 非参贝叶斯 徐亦达老板 Dirichlet Process 学习 ...
- [Artoolkit] Framework Analysis of nftSimple
What is nftSimple? Loads NFT dataset names from a configuration file. The example uses the “Pinball. ...
- [Artoolkit] Android Sample of nftSimple
结合:[Artoolkit] ARToolKit's SDK Structure on Android 重难点:aRBaseLib/, nftSimple/, libcpufeatures.a aRB ...
- 【AR实验室】ARToolKit之制作自己的Marker/NFT
0x00 - 前言 看过example后,就会想自己动动手,这里改改那里修修.我们先试着添加自己喜欢的marker/nft进行识别. 比如我做了一个法拉利的marker: 还有网上找了一个法拉利log ...
- [Artoolkit] kpmMatching & Tracking of nftSimple
1. kpmMatching thread main() --> loadNFTData() --> trackingInitInit() --> In static void *t ...
- [Artoolkit] ARToolKit's SDK Structure on Android
Most applications on Android are developed in Java, and Android provides a rich framework of classes ...
- 【AR实验室】ARToolKit之Example篇
0x00 - 前言 PS : 我突然意识到ARToolKit本质可能就是一个可以实时求解相机内外参的解决方案. 拿到一个新的SDK,90%的人应该都会先跑一下Example.拿到ARToolKit的S ...
- 【AR实验室】ARToolKit之概述篇
0x00 - 前言 我从去年就开始对AR(Augmented Reality)技术比较关注,但是去年AR行业一直处于偶尔发声的状态,丝毫没有其"异姓同名"的兄弟VR(Virtual ...
随机推荐
- 将java项目传输到centos7服务端
http://www.xdowns.com/so.asp?keyword=flashfxp 下载flashfxp之后进行一系列配置即可 https://cloud.baidu.com/?from=co ...
- File构建实例的路径:绝对路径和相对路径
public static void main(String[] args) throws Exception { File file = new File("bin/dyan.txt&qu ...
- Fragment的可见再载入的方法(真正的Fragment的OnResume和OnPause)
一 起因 我们在做应用的过程中,一个应用的界面可能是多个Fragment切换而成的.可是如果在每次应用启动的时候就去载入大量的网络数据(如果你的每一个Fragment都须要载入网络数据.你也能够理解为 ...
- python3简单使用requests 用户代理,cookie池
官方文档:http://docs.python-requests.org/en/master/ 参考文档:http://www.cnblogs.com/zhaof/p/6915127.html#und ...
- 利用python制作在Linux服务器后台定时运行的任务-邮件提醒
1. 自动任务的功能为: 定时扫描数据库中的记录,然后发邮件 代码如下 scheduleMail.py import pymysql import smtplib from email.mime.te ...
- Selenium 致命杀手(有关自动化的通病)
Do your scripts suffer from the following automation test flaky symptoms? Test randomly fail Works o ...
- settings.xml配置详解
简单值 一半顶层settings元素是简单值,它们表示的一系列值可以配置Maven的核心行为:settings.xml中的简单顶层元素 < settings xmlns="http:/ ...
- IIS 之 应用程序池
IIS(Internet Information Services),由于我使用的是Windows10系统,所以本文以其内置 10.0.14393.0 版本说明. 应用程序池 → 右键(待设置应用程序 ...
- MongoDB 聚合操作(转)
在MongoDB中,有两种方式计算聚合:Pipeline 和 MapReduce.Pipeline查询速度快于MapReduce,但是MapReduce的强大之处在于能够在多台Server上并行执行复 ...
- [Android实例] Activity实例StartActivity出现NullPointer异常
[Android实例] Activity实例StartActivity出现NullPointer异常 [android实例教程] 在Android低版本(如2.3.3)中出现如下“界面跳转”的错误: ...