Skip to content

Commit

Permalink
add tests
Browse files Browse the repository at this point in the history
  • Loading branch information
christianrauch committed Jan 31, 2024
1 parent 4fb31d5 commit 121eb31
Show file tree
Hide file tree
Showing 5 changed files with 222 additions and 0 deletions.
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -210,3 +210,7 @@ if (BUILD_EXAMPLES)
# install example programs
install(TARGETS apriltag_demo RUNTIME DESTINATION bin)
endif()

if(BUILD_TESTING)
add_subdirectory(test)
endif()
20 changes: 20 additions & 0 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
enable_testing()

add_library(getline OBJECT getline.c)

add_executable(test_detection test_detection.c)
target_link_libraries(test_detection ${PROJECT_NAME} getline)

# test images with true detection
set(TEST_IMAGE_NAMES
"33369213973_9d9bb4cc96_c"
"34085369442_304b6bafd9_c"
"34139872896_defdb2f8d9_c"
)

foreach(IMG IN LISTS TEST_IMAGE_NAMES)
add_test(NAME test_detection_${IMG}
COMMAND $<TARGET_FILE:test_detection> data/${IMG}
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
)
endforeach()
55 changes: 55 additions & 0 deletions test/getline.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#include "getline.h"
#include <errno.h>
#include <stdlib.h>

// https://stackoverflow.com/a/47229318/8144672
/* The original code is public domain -- Will Hartung 4/9/09 */
/* Modifications, public domain as well, by Antti Haapala, 11/10/17 - Switched to getc on 5/23/19 */

ssize_t getline(char **lineptr, size_t *n, FILE *stream) {
size_t pos;
int c;

if (lineptr == NULL || stream == NULL || n == NULL) {
errno = EINVAL;
return -1;
}

c = getc(stream);
if (c == EOF) {
return -1;
}

if (*lineptr == NULL) {
*lineptr = malloc(128);
if (*lineptr == NULL) {
return -1;
}
*n = 128;
}

pos = 0;
while(c != EOF) {
if (pos + 1 >= *n) {
size_t new_size = *n + (*n >> 2);
if (new_size < 128) {
new_size = 128;
}
char *new_ptr = realloc(*lineptr, new_size);
if (new_ptr == NULL) {
return -1;
}
*n = new_size;
*lineptr = new_ptr;
}

((unsigned char *)(*lineptr))[pos ++] = c;
if (c == '\n') {
break;
}
c = getc(stream);
}

(*lineptr)[pos] = '\0';
return pos;
}
9 changes: 9 additions & 0 deletions test/getline.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

#include <stddef.h>
#include <stdio.h>
#include <stdint.h>

typedef intptr_t ssize_t;

ssize_t getline(char **lineptr, size_t *n, FILE *stream);
134 changes: 134 additions & 0 deletions test/test_detection.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
#include <stdarg.h>
#include <apriltag.h>
#include <tag36h11.h>
#include <common/pjpeg.h>

#include "getline.h"


char*
format(const char* fmt, ...)
{
va_list args1;
va_list args2;

va_start(args1, fmt);
va_copy(args2, args1);

const int N = vsnprintf(NULL, 0, fmt, args1);
va_end(args1);

if (N < 0) {
va_end(args2);
return NULL;
}

char* res_fmt = calloc(N+1, sizeof(char));
const int n = vsnprintf(res_fmt, N+1, fmt, args2);
va_end(args2);

if (n != N) {
free(res_fmt);
return NULL;
}

// caller has to free returned string
return res_fmt;
}

int
detection_corner_compare_function(const void *_a, const void *_b)
{
apriltag_detection_t *a = *(apriltag_detection_t**) _a;
apriltag_detection_t *b = *(apriltag_detection_t**) _b;

return memcmp(a->p, b->p, sizeof(a));
}

int
main(int argc, char *argv[])
{
if (argc!=2) {
return EXIT_FAILURE;
}

// load image
char* const path_img = format("%s.jpg", argv[1]);
pjpeg_t *pjpeg = pjpeg_create_from_file(path_img, 0, NULL);
image_u8_t *im = pjpeg_to_u8_baseline(pjpeg);
free(path_img);

// load true detection
char* const path_det_true = format("%s.txt", argv[1]);
FILE *fp = fopen(path_det_true, "r");
if (fp == NULL) {
return EXIT_FAILURE;
}
free(path_det_true);

apriltag_detector_t *td = apriltag_detector_create();
apriltag_family_t *tf = tag36h11_create();
apriltag_detector_add_family(td, tf);

const char fmt[] = "%i, %i, (%.4lf %.4lf), (%.4lf %.4lf), (%.4lf %.4lf), (%.4lf %.4lf)";

bool ok = true;

zarray_t *detections = apriltag_detector_detect(td, im);

// sort detections by detected corners for deterministic sorting order
zarray_sort(detections, detection_corner_compare_function);

int i = 0;
for (; i < zarray_size(detections); i++) {
apriltag_detection_t *det;
zarray_get(detections, i, &det);

char* const det_fmt = format(fmt,
i, det->id,
det->p[0][0], det->p[0][1], det->p[1][0], det->p[1][1],
det->p[2][0], det->p[2][1], det->p[3][0], det->p[3][1]);

char* line = NULL;
size_t len = 0;
const ssize_t nread = getline(&line, &len, fp);
if (nread == -1) {
free(line);
return EXIT_FAILURE;
}

printf("Got: %s\n", det_fmt);
printf("Expected: %s\n", line);

// compare strings without the newline character (\n)
if (strncmp(det_fmt, line, nread-1) != 0) {
fprintf(stderr, "Mismatch.\nGot:\n %s\nExpected:\n %s\n", det_fmt, line);
ok = false;
}

free(det_fmt);
free(line);
}

// check that we compared the expected amount of detections
// if there are no "true" detections left, we should be at the end of the file
// if there are no "detected" detections left, we should be at the end of the array
if ((fgetc(fp) != -1) && (i != zarray_size(detections))) {
return EXIT_FAILURE;
}

fclose(fp);

apriltag_detections_destroy(detections);
image_u8_destroy(im);
pjpeg_destroy(pjpeg);

apriltag_detector_destroy(td);
tag36h11_destroy(tf);

if (!ok) {
return EXIT_FAILURE;
}

return EXIT_SUCCESS;
}

0 comments on commit 121eb31

Please sign in to comment.