JeVoisBase  1.7
JeVois Smart Embedded Machine Vision Toolkit Base Modules
Share this page:
ARMarkerSquare.c
Go to the documentation of this file.
1 /*
2  * ARMarkerSquare.c
3  * ARToolKit5
4  *
5  * Demonstration of ARToolKit NFT with models rendered in OSG,
6  * and marker pose estimates filtered to reduce jitter.
7  *
8  * Press '?' while running for help on available key commands.
9  *
10  * Disclaimer: IMPORTANT: This Daqri software is supplied to you by Daqri
11  * LLC ("Daqri") in consideration of your agreement to the following
12  * terms, and your use, installation, modification or redistribution of
13  * this Daqri software constitutes acceptance of these terms. If you do
14  * not agree with these terms, please do not use, install, modify or
15  * redistribute this Daqri software.
16  *
17  * In consideration of your agreement to abide by the following terms, and
18  * subject to these terms, Daqri grants you a personal, non-exclusive
19  * license, under Daqri's copyrights in this original Daqri software (the
20  * "Daqri Software"), to use, reproduce, modify and redistribute the Daqri
21  * Software, with or without modifications, in source and/or binary forms;
22  * provided that if you redistribute the Daqri Software in its entirety and
23  * without modifications, you must retain this notice and the following
24  * text and disclaimers in all such redistributions of the Daqri Software.
25  * Neither the name, trademarks, service marks or logos of Daqri LLC may
26  * be used to endorse or promote products derived from the Daqri Software
27  * without specific prior written permission from Daqri. Except as
28  * expressly stated in this notice, no other rights or licenses, express or
29  * implied, are granted by Daqri herein, including but not limited to any
30  * patent rights that may be infringed by your derivative works or by other
31  * works in which the Daqri Software may be incorporated.
32  *
33  * The Daqri Software is provided by Daqri on an "AS IS" basis. DAQRI
34  * MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
35  * THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
36  * FOR A PARTICULAR PURPOSE, REGARDING THE DAQRI SOFTWARE OR ITS USE AND
37  * OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
38  *
39  * IN NO EVENT SHALL DAQRI BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
40  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
41  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
42  * INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
43  * MODIFICATION AND/OR DISTRIBUTION OF THE DAQRI SOFTWARE, HOWEVER CAUSED
44  * AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
45  * STRICT LIABILITY OR OTHERWISE, EVEN IF DAQRI HAS BEEN ADVISED OF THE
46  * POSSIBILITY OF SUCH DAMAGE.
47  *
48  * Copyright 2015 Daqri LLC. All Rights Reserved.
49  * Copyright 2011-2015 ARToolworks, Inc. All Rights Reserved.
50  *
51  * Author(s): Philip Lamb.
52  *
53  */
54 
56 
57 #ifdef _WIN32
58 # include <windows.h>
59 # define MAXPATHLEN MAX_PATH
60 #else
61 # include <sys/param.h> // MAXPATHLEN
62 #endif
63 #include <stdlib.h> // calloc()
64 #include <string.h>
65 
66 const ARPose ARPoseUnity = {{1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f}};
67 
68 static char *get_buff(char *buf, int n, FILE *fp, int skipblanks)
69 {
70  char *ret;
71  size_t l;
72 
73  do {
74  ret = fgets(buf, n, fp);
75  if (ret == NULL) return (NULL); // EOF or error.
76 
77  // Remove NLs and CRs from end of string.
78  l = strlen(buf);
79  while (l > 0) {
80  if (buf[l - 1] != '\n' && buf[l - 1] != '\r') break;
81  l--;
82  buf[l] = '\0';
83  }
84  } while (buf[0] == '#' || (skipblanks && buf[0] == '\0')); // Reject comments and blank lines.
85 
86  return (ret);
87 }
88 
89 void newMarkers(const char *markersConfigDataFilePathC, ARPattHandle *arPattHandle, ARMarkerSquare **markersSquare_out, int *markersSquareCount_out, int *patternDetectionMode_out)
90 {
91  FILE *fp;
92  char buf[MAXPATHLEN], buf1[MAXPATHLEN];
93  int tempI;
94  ARMarkerSquare *markersSquare;
95  int markersSquareCount;
96  ARdouble tempF;
97  int i;
98  char markersConfigDataDirC[MAXPATHLEN];
99  size_t markersConfigDataDirCLen;
100  int patt_type = 0;
101 
102  if (!markersConfigDataFilePathC || markersConfigDataFilePathC[0] == '\0' || !markersSquareCount_out || !markersSquare_out) return;
103 
104  // Load the marker data file.
105  ARLOGd("Opening marker config. data file from path '%s'.\n", markersConfigDataFilePathC);
106  arUtilGetDirectoryNameFromPath(markersConfigDataDirC, markersConfigDataFilePathC, MAXPATHLEN, 1); // 1 = add '/' at end.
107  markersConfigDataDirCLen = strlen(markersConfigDataDirC);
108  if ((fp = fopen(markersConfigDataFilePathC, "r")) == NULL) {
109  ARLOGe("Error: unable to locate marker config data file '%s'.\n", markersConfigDataFilePathC);
110  return;
111  }
112 
113  // First line is number of markers to read.
114  get_buff(buf, MAXPATHLEN, fp, 1);
115  if (sscanf(buf, "%d", &tempI) != 1 ) {
116  ARLOGe("Error in marker configuration data file; expected marker count.\n");
117  fclose(fp);
118  return;
119  }
120 
121  arMallocClear(markersSquare, ARMarkerSquare, tempI);
122  markersSquareCount = tempI;
123 
124  ARLOGd("Reading %d marker configuration(s).\n", markersSquareCount);
125 
126  for (i = 0; i < markersSquareCount; i++) {
127 
128  // Read marker name.
129  if (!get_buff(buf, MAXPATHLEN, fp, 1)) {
130  ARLOGe("Error in marker configuration data file; expected marker name.\n");
131  break;
132  }
133 
134  // Read marker type.
135  if (!get_buff(buf1, MAXPATHLEN, fp, 1)) {
136  ARLOGe("Error in marker configuration data file; expected marker type.\n");
137  break;
138  }
139 
140  // Interpret marker type, and read more data.
141  if (strcmp(buf1, "SINGLE") == 0) {
142  markersSquare[i].valid = markersSquare[i].validPrev = FALSE;
143 
144  // Read marker width.
145  if (!get_buff(buf1, MAXPATHLEN, fp, 1) || sscanf(buf1,
146 #ifdef ARDOUBLE_IS_FLOAT
147  "%f"
148 #else
149  "%lf"
150 #endif
151  , &tempF) != 1) {
152  ARLOGe("Error in marker configuration data file; expected marker width.\n");
153  break;
154  }
155 
156  // Interpret marker name (still in buf), test if it's a pattern number, load as pattern file if not.
157  if (sscanf(buf, "%d", &tempI) != 1) {
158  if (!arPattHandle) {
159  ARLOGe("Error: Marker pattern file '%s' specified but only barcodes allowed.\n", markersSquare[i].patternPathname);
160  break;
161  }
162  arMalloc(markersSquare[i].patternPathname, char, markersConfigDataDirCLen + strlen(buf) + 1);
163  strcpy(markersSquare[i].patternPathname, markersConfigDataDirC);
164  strcpy(markersSquare[i].patternPathname + markersConfigDataDirCLen, buf);
165 
166  // Now load pattern file.
167  if ((markersSquare[i].patt_id = arPattLoad(arPattHandle, markersSquare[i].patternPathname)) < 0 ) {
168  ARLOGe("Error: Unable to load marker pattern from file'%s'.\n", markersSquare[i].patternPathname);
169  break;
170  }
171  markersSquare[i].marker_width = markersSquare[i].marker_height = tempF;
172  markersSquare[i].patt_type = AR_PATTERN_TYPE_TEMPLATE;
173  patt_type |= 0x01;
174  } else {
175  markersSquare[i].patternPathname = NULL;
176  markersSquare[i].patt_id = tempI;
177  //ARLOGi("markersSquare[%d].patt_id = %d\n",i,markersSquare[i].patt_id);
178  //ARLOGi("tempI = %d\n",tempI);
179  markersSquare[i].marker_width = markersSquare[i].marker_height = tempF;
180  markersSquare[i].patt_type = AR_PATTERN_TYPE_MATRIX;
181  patt_type |= 0x02;
182  }
183 
184  } else if (strcmp(buf1, "MULTI") == 0) {
185  ARLOGe("Error in marker configuration data file; MULTI markers not supported in this build.\n");
186  } else if (strcmp(buf1, "NFT") == 0) {
187  ARLOGe("Error in marker configuration data file; NFT markers not supported in this build.\n");
188  } else {
189  ARLOGe("Error in marker configuration data file; unsupported marker type %s.\n", buf1);
190  }
191 
192  // Look for optional tokens. A blank line marks end of options.
193  while (get_buff(buf, MAXPATHLEN, fp, 0) && (buf[0] != '\0')) {
194  if (strncmp(buf, "FILTER", 6) == 0) {
195  markersSquare[i].filterCutoffFrequency = AR_FILTER_TRANS_MAT_CUTOFF_FREQ_DEFAULT;
196  markersSquare[i].filterSampleRate = AR_FILTER_TRANS_MAT_SAMPLE_RATE_DEFAULT;
197  if (strlen(buf) != 6) {
198  if (sscanf(&buf[6],
199 #ifdef ARDOUBLE_IS_FLOAT
200  "%f"
201 #else
202  "%lf"
203 #endif
204  , &tempF) == 1) markersSquare[i].filterCutoffFrequency = tempF;
205  }
206  markersSquare[i].ftmi = arFilterTransMatInit(markersSquare[i].filterSampleRate, markersSquare[i].filterCutoffFrequency);
207  }
208  // Unknown tokens are ignored.
209  }
210  }
211  fclose(fp);
212 
213  // If not all markers were read, an error occurred.
214  if (i < markersSquareCount) {
215 
216  // Clean up.
217  for (; i >= 0; i--) {
218  if (markersSquare[i].patt_type == AR_PATTERN_TYPE_TEMPLATE && markersSquare[i].patt_id && arPattHandle) arPattFree(arPattHandle, markersSquare[i].patt_id);
219  if (markersSquare[i].patternPathname) free(markersSquare[i].patternPathname);
220  if (markersSquare[i].ftmi) arFilterTransMatFinal(markersSquare[i].ftmi);
221  }
222  free(markersSquare);
223 
224  *markersSquareCount_out = 0;
225  *markersSquare_out = NULL;
226  if (patternDetectionMode_out) *patternDetectionMode_out = -1;
227  return;
228  }
229 
230  *markersSquareCount_out = markersSquareCount;
231  *markersSquare_out = markersSquare;
232  //ARLOGi("patternDetectionMode_out = %d\n", patternDetectionMode_out);
233  if (patternDetectionMode_out) {
234  // Work out square marker detection mode.
235  //ARLOGi("patternDetectionMode_out = %d\n", patternDetectionMode_out);
236  if ((patt_type & 0x03) == 0x03) {*patternDetectionMode_out = AR_TEMPLATE_MATCHING_COLOR_AND_MATRIX; }
237  else if (patt_type & 0x02) {*patternDetectionMode_out = AR_MATRIX_CODE_DETECTION;}
238  else {*patternDetectionMode_out = AR_TEMPLATE_MATCHING_COLOR;}
239  }
240 }
241 
242 void deleteMarkers(ARMarkerSquare **markersSquare_p, int *markersSquareCount_p, ARPattHandle *arPattHandle)
243 {
244  int i;
245 
246  if (!markersSquare_p || !*markersSquare_p || !*markersSquareCount_p || *markersSquareCount_p < 1) return;
247 
248  for (i = 0; i < *markersSquareCount_p; i++) {
249  if ((*markersSquare_p)[i].patt_type == AR_PATTERN_TYPE_TEMPLATE && (*markersSquare_p)[i].patt_id && arPattHandle) arPattFree(arPattHandle, (*markersSquare_p)[i].patt_id);
250  if ((*markersSquare_p)[i].patternPathname) {
251  free((*markersSquare_p)[i].patternPathname);
252  (*markersSquare_p)[i].patternPathname = NULL;
253  }
254  if ((*markersSquare_p)[i].ftmi) {
255  arFilterTransMatFinal((*markersSquare_p)[i].ftmi);
256  (*markersSquare_p)[i].ftmi = NULL;
257  }
258  }
259  free(*markersSquare_p);
260  *markersSquare_p = NULL;
261  *markersSquareCount_p = 0;
262 }
char * patternPathname
ARdouble marker_width
ARdouble marker_height
ARdouble filterSampleRate
void newMarkers(const char *markersConfigDataFilePathC, ARPattHandle *arPattHandle, ARMarkerSquare **markersSquare_out, int *markersSquareCount_out, int *patternDetectionMode_out)
ARdouble filterCutoffFrequency
ARFilterTransMatInfo * ftmi
void deleteMarkers(ARMarkerSquare **markersSquare_p, int *markersSquareCount_p, ARPattHandle *arPattHandle)
#define AR_PATTERN_TYPE_TEMPLATE
#define AR_PATTERN_TYPE_MATRIX
const ARPose ARPoseUnity