[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 ...
随机推荐
- unity无限循环报错的定位
晚上遇到了,碰到了程序一运行就卡住的尴尬问题,然后百度下,看了看,Get到了一个新的skill. 1. 打开对应的VS程序,选择“调试/Attach Unity Debuger”菜单来调试代码. 2. ...
- Codeforces Round #409 (rated, Div. 2, based on VK Cup 2017 Round 2) 题解【ABCDE】
A. Vicious Keyboard 题意:给你一个字符串,里面只会包含VK,这两种字符,然后你可以改变一个字符,你要求VK这个字串出现的次数最多. 题解:数据范围很小,暴力枚举改变哪个字符,然后c ...
- UVA 11613 Acme Corporation(不固定流量的最小费用流)
题意好长....变量好多.... 增加源点跟汇点.然后将每个月份看成一个点,然后拆成两个点u 跟 u+n. 从s向每个u连一条<n[u], m[i]>的弧,表示最多生产量及价值. 从每个u ...
- iOS开发-适配器和外观模式
适配器模式,属于结构型模式,其主要作用是将一个类的接口转换成客户希望的另外一个接口.适配器模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作.适配器模式有对象适配器和类适配器两种,类适配器模 ...
- SharedPreferences 原理 源码 进程间通信 MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- Android GUI之View测量
在上篇文章(http://www.cnblogs.com/jerehedu/p/4607599.html#gui)中,根据源码探索了View的绘制过程,过程有三个主要步骤,分别为测量.布局.绘制.系统 ...
- WPF腾讯视频通话开发
一.IntPtr.HandleC#中的IntPtr类型称为“平台特定的整数类型”,它们用于本机资源,如窗口句柄. 1.WPF窗口句柄IntPtr wnip = new System.Windows.I ...
- [Python设计模式] 第7章 找人帮忙追美眉——代理模式
github地址:https://github.com/cheesezh/python_design_patterns 题目1 Boy追求Girl,给Girl送鲜花,送巧克力,送洋娃娃. class ...
- volitile关键字
1.volatile关键字的两层语义 一旦一个共享变量(类的成员变量.类的静态成员变量)被volatile修饰之后,那么就具备了两层语义: 1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修 ...
- 如何获取ubuntu源码包里面的源码?
ubuntu 源仓库说明 1.在获取源码包之前,确保在软件源配置文件/etc/apt/sources.list中添加了deb-src项 vim /etc/apt/sources.list # # de ...