diff --git a/README.md b/README.md
index 9ce079d..c6b9e17 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,11 @@
# WebARKitLib
The C/C++ source code of WebARKit, from Artoolkit5 and extended.
-Updated to [Eigen](https://eigen.tuxfamily.org) 3.4.0 and Emscripten emsdk 3.1.26.
+
+Updated to [Eigen](https://eigen.tuxfamily.org) 3.4.0 and Emscripten emsdk 3.1.26.
+
+## Features
+
+The library containes the following features:
+**Artoolkit5** C/C++ code used by [jsartoolkitNFT](https://github.com/webarkit/jsartoolkitNFT) and [ARnft](https://github.com/webarkit/ARnft) (see lib and include folders). Note that is not the full Artoolkit5 library, but only the code needed by jsartoolkitNFT and ARnft. The code is updated to Eigen 3.4.0 and can be compiled with Emscripten emsdk 3.1.26.
+**WebARKit** C++ code, which is our experimental code for WebAR. It is completetly independent from Artoolkit5 and can be used as a standalone library. It can be compiled with Emscripten emsdk 3.1.26.
\ No newline at end of file
diff --git a/WebARKit/WebARKitLog.cpp b/WebARKit/WebARKitLog.cpp
new file mode 100644
index 0000000..9280853
--- /dev/null
+++ b/WebARKit/WebARKitLog.cpp
@@ -0,0 +1,212 @@
+/*
+ * WebARKitLog.cpp
+ * WebARKit
+ *
+ * This file is part of WebARKit.
+ *
+ * WebARKit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * WebARKit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with WebARKit. If not, see .
+ *
+ * As a special exception, the copyright holders of this library give you
+ * permission to link this library with independent modules to produce an
+ * executable, regardless of the license terms of these independent modules, and to
+ * copy and distribute the resulting executable under terms of your choice,
+ * provided that you also meet, for each linked independent module, the terms and
+ * conditions of the license of that module. An independent module is a module
+ * which is neither derived from nor based on this library. If you modify this
+ * library, you may extend this exception to your version of the library, but you
+ * are not obligated to do so. If you do not wish to do so, delete this exception
+ * statement from your version.
+ *
+ * Copyright 2015-2016 Daqri, LLC.
+ * Copyright 2003-2015 ARToolworks, Inc.
+ * Copyright 2023 WebARKit.
+ *
+ * Author(s): Hirokazu Kato, Philip Lamb, Walter Perdan
+ *
+ * This code was taken from Artoolkit5 https://github.com/artoolkitx/artoolkit5
+ * with small modifications to adapt to existing WebARKIt code
+ *
+ */
+
+#include
+
+#ifndef _WIN32
+# include // pthread_self(), pthread_equal()
+# ifdef __APPLE__
+# include
+# endif
+#else
+# include
+# define snprintf _snprintf
+#endif
+
+//
+// Global required for logging functions.
+//
+int webarkitLogLevel = WEBARKIT_LOG_LEVEL_DEFAULT;
+static WEBARKIT_LOG_LOGGER_CALLBACK webarkitLogLoggerCallback = NULL;
+static int webarkitLogLoggerCallBackOnlyIfOnSameThread = 0;
+#ifndef _WIN32
+static pthread_t webarkitLogLoggerThread;
+#else
+static DWORD webarkitLogLoggerThreadID;
+#endif
+#define WEBARKIT_LOG_WRONG_THREAD_BUFFER_SIZE 4096
+static char *webarkitLogWrongThreadBuffer = NULL;
+static size_t webarkitLogWrongThreadBufferSize = 0;
+static size_t webarkitLogWrongThreadBufferCount = 0;
+
+
+void webarkitLogSetLogger(WEBARKIT_LOG_LOGGER_CALLBACK callback, int callBackOnlyIfOnSameThread)
+{
+ webarkitLogLoggerCallback = callback;
+ webarkitLogLoggerCallBackOnlyIfOnSameThread = callBackOnlyIfOnSameThread;
+ if (callback && callBackOnlyIfOnSameThread) {
+#ifndef _WIN32
+ webarkitLogLoggerThread = pthread_self();
+#else
+ webarkitLogLoggerThreadID = GetCurrentThreadId();
+#endif
+ if (!webarkitLogWrongThreadBuffer) {
+ if ((webarkitLogWrongThreadBuffer = static_cast(malloc(sizeof(char) * WEBARKIT_LOG_WRONG_THREAD_BUFFER_SIZE)))) {
+ webarkitLogWrongThreadBufferSize = WEBARKIT_LOG_WRONG_THREAD_BUFFER_SIZE;
+ }
+ }
+ } else {
+ if (webarkitLogWrongThreadBuffer) {
+ free(webarkitLogWrongThreadBuffer);
+ webarkitLogWrongThreadBuffer = NULL;
+ webarkitLogWrongThreadBufferSize = 0;
+ }
+ }
+}
+
+void webarkitLog(const char *tag, const int logLevel, const char *format, ...)
+{
+ if (logLevel < webarkitLogLevel) return;
+ if (!format || !format[0]) return;
+
+ va_list ap;
+ va_start(ap, format);
+ webarkitLogv(tag, logLevel, format, ap);
+ va_end(ap);
+}
+
+void webarkitLogv(const char *tag, const int logLevel, const char *format, va_list ap)
+{
+ va_list ap2;
+ char *buf = NULL;
+ size_t len;
+ const char *logLevelStrings[] = {
+ "debug",
+ "info",
+ "warning",
+ "error"
+ };
+ const size_t logLevelStringsCount = (sizeof(logLevelStrings)/sizeof(logLevelStrings[0]));
+ size_t logLevelStringLen;
+
+ if (logLevel < webarkitLogLevel) return;
+ if (!format || !format[0]) return;
+
+ // Count length required to unpack varargs.
+ va_copy(ap2, ap);
+#ifdef _WIN32
+ len = _vscprintf(format, ap);
+#else
+ len = vsnprintf(NULL, 0, format, ap2);
+#endif
+ va_end(ap2);
+ if (len < 1) return;
+
+ // Add characters required for logLevelString.
+ if (logLevel >= 0 && logLevel < (int)logLevelStringsCount) {
+ logLevelStringLen = 3 + strlen(logLevelStrings[logLevel]); // +3 for brackets and a space, e.g. "[debug] ".
+ } else {
+ logLevelStringLen = 0;
+ }
+
+ buf = (char *)malloc((logLevelStringLen + len + 1) * sizeof(char)); // +1 for nul-term.
+
+ if (logLevelStringLen > 0) {
+ snprintf(buf, logLevelStringLen + 1, "[%s] ", logLevelStrings[logLevel]);
+ }
+
+ vsnprintf(buf + logLevelStringLen, len + 1, format, ap);
+ len += logLevelStringLen;
+
+ if (webarkitLogLoggerCallback) {
+
+ if (!webarkitLogLoggerCallBackOnlyIfOnSameThread) {
+ (*webarkitLogLoggerCallback)(buf);
+ } else {
+#ifndef _WIN32
+ if (!pthread_equal(pthread_self(), webarkitLogLoggerThread))
+#else
+ if (GetCurrentThreadId() != webarkitLogLoggerThreadID)
+#endif
+ {
+ // On non-log thread, put it into buffer if we can.
+ if (webarkitLogWrongThreadBuffer && (webarkitLogWrongThreadBufferCount < webarkitLogWrongThreadBufferSize)) {
+ if (len <= (webarkitLogWrongThreadBufferSize - (webarkitLogWrongThreadBufferCount + 4))) { // +4 to reserve space for "...\0".
+ strncpy(&webarkitLogWrongThreadBuffer[webarkitLogWrongThreadBufferCount], buf, len + 1);
+ webarkitLogWrongThreadBufferCount += len;
+ } else {
+ strncpy(&webarkitLogWrongThreadBuffer[webarkitLogWrongThreadBufferCount], "...", 4);
+ webarkitLogWrongThreadBufferCount = webarkitLogWrongThreadBufferSize; // Mark buffer as full.
+ }
+ }
+ } else {
+ // On log thread, print buffer if anything was in it, then the current message.
+ if (webarkitLogWrongThreadBufferCount > 0) {
+ (*webarkitLogLoggerCallback)(webarkitLogWrongThreadBuffer);
+ webarkitLogWrongThreadBufferCount = 0;
+ }
+ (*webarkitLogLoggerCallback)(buf);
+ }
+ }
+
+ } else {
+#if defined(__ANDROID__)
+ int logLevelA;
+ switch (logLevel) {
+ case WEBARKIT_LOG_LEVEL_REL_INFO: logLevelA = ANDROID_LOG_ERROR; break;
+ case WEBARKIT_LOG_LEVEL_ERROR: logLevelA = ANDROID_LOG_ERROR; break;
+ case WEBARKIT_LOG_LEVEL_WARN: logLevelA = ANDROID_LOG_WARN; break;
+ case WEBARKIT_LOG_LEVEL_INFO: logLevelA = ANDROID_LOG_INFO; break;
+ case WEBARKIT_LOG_LEVEL_DEBUG: default: logLevelA = ANDROID_LOG_DEBUG; break;
+ }
+ __android_log_write(logLevelA, (tag ? tag : "libAR"), buf);
+ //#elif defined(_WINRT)
+ // OutputDebugStringA(buf);
+#elif defined(__APPLE__)
+ if (os_log_create == NULL) { // os_log only available macOS 10.12 / iOS 10.0 and later.
+ fprintf(stderr, "%s", buf);
+ } else {
+ os_log_type_t type;
+ switch (logLevel) {
+ case WEBARKIT_LOG_LEVEL_REL_INFO: type = OS_LOG_TYPE_DEFAULT; break;
+ case WEBARKIT_LOG_LEVEL_ERROR: type = OS_LOG_TYPE_ERROR; break;
+ case WEBARKIT_LOG_LEVEL_WARN: type = OS_LOG_TYPE_DEFAULT; break;
+ case WEBARKIT_LOG_LEVEL_INFO: type = OS_LOG_TYPE_INFO; break;
+ case WEBARKIT_LOG_LEVEL_DEBUG: default: type = OS_LOG_TYPE_DEBUG; break;
+ }
+ os_log_with_type(OS_LOG_DEFAULT, type, "%{public}s", buf);
+ }
+#else
+ fprintf(stderr, "%s", buf);
+#endif
+ }
+ free(buf);
+}
diff --git a/WebARKit/WebARKitTrackers/WebARKitOpticalTracking/WebARKitConfig.cpp b/WebARKit/WebARKitTrackers/WebARKitOpticalTracking/WebARKitConfig.cpp
new file mode 100644
index 0000000..2bef19c
--- /dev/null
+++ b/WebARKit/WebARKitTrackers/WebARKitOpticalTracking/WebARKitConfig.cpp
@@ -0,0 +1,6 @@
+#include
+
+extern const double GOOD_MATCH_RATIO = 0.7f;
+extern const int MAX_FEATURES = 8000;
+extern const int N = 10;
+extern const int MIN_NUM_MATCHES = 20;
\ No newline at end of file
diff --git a/WebARKit/WebARKitTrackers/WebARKitOpticalTracking/WebARKitTracker.cpp b/WebARKit/WebARKitTrackers/WebARKitOpticalTracking/WebARKitTracker.cpp
new file mode 100644
index 0000000..b94e4ba
--- /dev/null
+++ b/WebARKit/WebARKitTrackers/WebARKitOpticalTracking/WebARKitTracker.cpp
@@ -0,0 +1,259 @@
+#include
+#include
+
+namespace webarkit {
+
+class WebARKitTracker::WebARKitTrackerImpl {
+ public:
+ WebARKitTrackerImpl() : corners(4), initialized(false), output(17, 0.0), _valid(false), numMatches(0){};
+ ~WebARKitTrackerImpl() = default;
+
+ void initialize(webarkit::TRACKER_TYPE trackerType) { setDetectorType(trackerType); }
+
+ void initTracker(uchar* refData, size_t refCols, size_t refRows) {
+ WEBARKIT_LOGi("Init Tracker!\n");
+ cv::Mat refGray(refRows, refCols, CV_8UC1, refData);
+
+ this->_featureDetector->detectAndCompute(refGray, cv::noArray(), refKeyPts, refDescr);
+
+ corners[0] = cvPoint(0, 0);
+ corners[1] = cvPoint(refCols, 0);
+ corners[2] = cvPoint(refCols, refRows);
+ corners[3] = cvPoint(0, refRows);
+
+ initialized = true;
+
+ WEBARKIT_LOGi("Tracker ready!\n");
+ };
+
+ void processFrameData(uchar* frameData, size_t frameCols, size_t frameRows, ColorSpace colorSpace) {
+ cv::Mat grayFrame;
+ if (colorSpace == ColorSpace::RGBA) {
+ cv::Mat colorFrame(frameRows, frameCols, CV_8UC4, frameData);
+ grayFrame.create(frameRows, frameCols, CV_8UC1);
+ cv::cvtColor(colorFrame, grayFrame, cv::COLOR_RGBA2GRAY);
+ } else if (colorSpace == ColorSpace::GRAY) {
+ grayFrame = cv::Mat(frameRows, frameCols, CV_8UC1, frameData);
+ }
+ processFrame(grayFrame);
+ grayFrame.release();
+ };
+
+ std::vector getOutputData() { return output; };
+
+ bool isValid() { return _valid; };
+
+ protected:
+ bool resetTracking(cv::Mat& currIm) {
+ if (!initialized) {
+ WEBARKIT_LOGe("Reference image not found. AR is unintialized!\n");
+ return NULL;
+ }
+
+ WEBARKIT_LOGi("Reset Tracking!\n");
+
+ clear_output();
+
+ cv::Mat frameDescr;
+ std::vector frameKeyPts;
+
+ this->_featureDetector->detectAndCompute(currIm, cv::noArray(), frameKeyPts, frameDescr);
+
+ std::vector> knnMatches;
+ _matcher->knnMatch(frameDescr, refDescr, knnMatches, 2);
+
+ framePts.clear();
+ std::vector refPts;
+
+ // find the best matches
+ for (size_t i = 0; i < knnMatches.size(); ++i) {
+ if (knnMatches[i][0].distance < GOOD_MATCH_RATIO * knnMatches[i][1].distance) {
+ framePts.push_back(frameKeyPts[knnMatches[i][0].queryIdx].pt);
+ refPts.push_back(refKeyPts[knnMatches[i][0].trainIdx].pt);
+ }
+ }
+
+ bool valid;
+
+ if (framePts.size() >= MIN_NUM_MATCHES) {
+ m_H = cv::findHomography(refPts, framePts, cv::RANSAC);
+ if ((valid = homographyValid(m_H))) {
+ numMatches = framePts.size();
+
+ if (currIm.empty()) {
+ WEBARKIT_LOGe("prevIm is empty!\n");
+ return NULL;
+ }
+ currIm.copyTo(prevIm);
+ }
+ }
+
+ return valid;
+ };
+
+ bool track(cv::Mat& currIm) {
+ if (!initialized) {
+ WEBARKIT_LOGe("Reference image not found. AR is unintialized!\n");
+ return NULL;
+ }
+
+ if (prevIm.empty()) {
+ WEBARKIT_LOGe("Tracking is uninitialized!\n");
+ return NULL;
+ }
+
+ WEBARKIT_LOGi("Start tracking!\n");
+ clear_output();
+
+ // use optical flow to track keypoints
+ std::vector err;
+ std::vector status;
+ std::vector currPts, goodPtsCurr, goodPtsPrev;
+ bool valid;
+ calcOpticalFlowPyrLK(prevIm, currIm, framePts, currPts, status, err);
+
+ // calculate average variance
+ double mean, avg_variance = 0.0;
+ double sum = 0.0;
+ double diff;
+ std::vector diffs;
+ for (size_t i = 0; i < framePts.size(); ++i) {
+ if (status[i]) {
+ goodPtsCurr.push_back(currPts[i]);
+ goodPtsPrev.push_back(framePts[i]);
+
+ diff = sqrt(pow(currPts[i].x - framePts[i].x, 2.0) + pow(currPts[i].y - framePts[i].y, 2.0));
+ sum += diff;
+ diffs.push_back(diff);
+ }
+ }
+
+ mean = sum / diffs.size();
+ for (int i = 0; i < goodPtsCurr.size(); ++i) {
+ avg_variance += pow(diffs[i] - mean, 2);
+ }
+ avg_variance /= diffs.size();
+
+ if ((goodPtsCurr.size() > numMatches / 2) && (1.75 > avg_variance)) {
+ cv::Mat transform = estimateAffine2D(goodPtsPrev, goodPtsCurr);
+
+ // add row of {0,0,1} to transform to make it 3x3
+ cv::Mat row = cv::Mat::zeros(1, 3, CV_64F);
+ row.at(0, 2) = 1.0;
+ transform.push_back(row);
+
+ // update homography matrix
+ m_H = transform * m_H;
+
+ // set old points to new points
+ framePts = goodPtsCurr;
+ if ((valid = homographyValid(m_H))) {
+ fill_output(m_H);
+ }
+ }
+
+ currIm.copyTo(prevIm);
+
+ return valid;
+ };
+
+ void processFrame(cv::Mat& frame) {
+ if (!this->_valid) {
+ this->_valid = resetTracking(frame);
+ } else {
+ this->_valid = track(frame);
+ }
+ };
+
+ bool homographyValid(cv::Mat& H) {
+ if (H.empty()) {
+ return false;
+ }
+ const double det = H.at(0, 0) * H.at(1, 1) - H.at(1, 0) * H.at(0, 1);
+ return 1 / N < fabs(det) && fabs(det) < N;
+ };
+
+ void fill_output(cv::Mat& H) {
+ std::vector warped(4);
+ cv::perspectiveTransform(corners, warped, H);
+
+ output[0] = H.at(0, 0);
+ output[1] = H.at(0, 1);
+ output[2] = H.at(0, 2);
+ output[3] = H.at(1, 0);
+ output[4] = H.at(1, 1);
+ output[5] = H.at(1, 2);
+ output[6] = H.at(2, 0);
+ output[7] = H.at(2, 1);
+ output[8] = H.at(2, 2);
+
+ output[9] = warped[0].x;
+ output[10] = warped[0].y;
+ output[11] = warped[1].x;
+ output[12] = warped[1].y;
+ output[13] = warped[2].x;
+ output[14] = warped[2].y;
+ output[15] = warped[3].x;
+ output[16] = warped[3].y;
+ };
+
+ void clear_output() { output = std::vector(17, 0.0); };
+
+ bool _valid;
+
+ std::vector corners;
+
+ cv::Mat m_H;
+
+ cv::Mat prevIm;
+
+ int numMatches;
+
+ std::vector framePts;
+
+ bool initialized;
+
+ private:
+ std::vector output; // 9 from homography matrix, 8 from warped corners*/
+
+ cv::Ptr _featureDetector;
+
+ cv::Ptr _matcher;
+
+ cv::Mat refGray, refDescr;
+
+ std::vector refKeyPts;
+
+ void setDetectorType(webarkit::TRACKER_TYPE trackerType) {
+ if (trackerType == webarkit::TRACKER_TYPE::AKAZE_TRACKER) {
+ this->_featureDetector = cv::AKAZE::create();
+ } else if (trackerType == webarkit::TRACKER_TYPE::ORB_TRACKER) {
+ this->_featureDetector = cv::ORB::create(MAX_FEATURES);
+ }
+ _matcher = cv::BFMatcher::create();
+ };
+};
+
+WebARKitTracker::WebARKitTracker() : _trackerImpl(new WebARKitTrackerImpl()) {}
+
+WebARKitTracker::~WebARKitTracker() = default; //destructor
+
+WebARKitTracker::WebARKitTracker(WebARKitTracker&&) = default; //copy constructor
+
+WebARKitTracker& WebARKitTracker::operator=(WebARKitTracker&&) = default; //move assignment operator
+
+void WebARKitTracker::initialize(webarkit::TRACKER_TYPE trackerType) { _trackerImpl->initialize(trackerType); }
+
+void WebARKitTracker::initTracker(uchar* refData, size_t refCols, size_t refRows) {
+ _trackerImpl->initTracker(refData, refCols, refRows);
+}
+
+void WebARKitTracker::processFrameData(uchar* frameData, size_t frameCols, size_t frameRows, ColorSpace colorSpace) {
+ _trackerImpl->processFrameData(frameData, frameCols, frameRows, colorSpace);
+}
+
+std::vector WebARKitTracker::getOutputData() { return _trackerImpl->getOutputData(); }
+
+bool WebARKitTracker::isValid() { return _trackerImpl->isValid(); }
+
+} // namespace webarkit
\ No newline at end of file
diff --git a/WebARKit/WebARKitTrackers/WebARKitOpticalTracking/include/WebARKitTrackers/WebARKitOpticalTracking/WebARKitConfig.h b/WebARKit/WebARKitTrackers/WebARKitOpticalTracking/include/WebARKitTrackers/WebARKitOpticalTracking/WebARKitConfig.h
new file mode 100644
index 0000000..a65156e
--- /dev/null
+++ b/WebARKit/WebARKitTrackers/WebARKitOpticalTracking/include/WebARKitTrackers/WebARKitOpticalTracking/WebARKitConfig.h
@@ -0,0 +1,7 @@
+#ifndef WEBARKIT_CONFIG_H
+#define WEBARKIT_CONFIG_H
+extern const double GOOD_MATCH_RATIO;
+extern const int MAX_FEATURES;
+extern const int N;
+extern const int MIN_NUM_MATCHES;
+#endif
diff --git a/WebARKit/WebARKitTrackers/WebARKitOpticalTracking/include/WebARKitTrackers/WebARKitOpticalTracking/WebARKitEnums.h b/WebARKit/WebARKitTrackers/WebARKitOpticalTracking/include/WebARKitTrackers/WebARKitOpticalTracking/WebARKitEnums.h
new file mode 100644
index 0000000..db1a8fa
--- /dev/null
+++ b/WebARKit/WebARKitTrackers/WebARKitOpticalTracking/include/WebARKitTrackers/WebARKitOpticalTracking/WebARKitEnums.h
@@ -0,0 +1,19 @@
+#ifndef WEBARKIT_ENUMS_H
+#define WEBARKIT_ENUMS_H
+
+namespace webarkit {
+
+enum TRACKER_TYPE {
+ AKAZE_TRACKER = 0,
+ ORB_TRACKER = 1
+};
+
+enum ColorSpace {
+ RGB = 0,
+ RGBA = 1,
+ GRAY = 2
+};
+
+} // namespace webarkit
+
+#endif
\ No newline at end of file
diff --git a/WebARKit/WebARKitTrackers/WebARKitOpticalTracking/include/WebARKitTrackers/WebARKitOpticalTracking/WebARKitTracker.h b/WebARKit/WebARKitTrackers/WebARKitOpticalTracking/include/WebARKitTrackers/WebARKitOpticalTracking/WebARKitTracker.h
new file mode 100644
index 0000000..98c758b
--- /dev/null
+++ b/WebARKit/WebARKitTrackers/WebARKitOpticalTracking/include/WebARKitTrackers/WebARKitOpticalTracking/WebARKitTracker.h
@@ -0,0 +1,43 @@
+#ifndef WEBARKIT_TRACKER_H
+#define WEBARKIT_TRACKER_H
+
+#include "WebARKitEnums.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+namespace webarkit {
+
+class WebARKitTracker {
+ public:
+ WebARKitTracker();
+
+ ~WebARKitTracker();
+
+ WebARKitTracker(WebARKitTracker&&);
+
+ WebARKitTracker& operator=(WebARKitTracker&&);
+
+ void initialize(webarkit::TRACKER_TYPE trackerType);
+
+ void initTracker(uchar* refData, size_t refCols, size_t refRows);
+
+ void processFrameData(uchar* frameData, size_t frameCols, size_t frameRows, ColorSpace colorSpace);
+
+ std::vector getOutputData();
+
+ bool isValid();
+
+ private:
+ class WebARKitTrackerImpl;
+
+ std::shared_ptr _trackerImpl;
+};
+
+} // namespace webarkit
+
+#endif
\ No newline at end of file
diff --git a/WebARKit/WebARKitTrackers/WebARKitOpticalTracking/include/WebARKitTrackers/WebARKitOpticalTracking/WebARKitUtils.h b/WebARKit/WebARKitTrackers/WebARKitOpticalTracking/include/WebARKitTrackers/WebARKitOpticalTracking/WebARKitUtils.h
new file mode 100644
index 0000000..7537b0e
--- /dev/null
+++ b/WebARKit/WebARKitTrackers/WebARKitOpticalTracking/include/WebARKitTrackers/WebARKitOpticalTracking/WebARKitUtils.h
@@ -0,0 +1,58 @@
+#include
+
+namespace webarkit {
+
+static cv::Mat im_gray(uchar data[], size_t cols, size_t rows) {
+ uint32_t idx;
+ uchar gray[rows][cols];
+ for (int i = 0; i < rows; ++i) {
+ for (int j = 0; j < cols; ++j) {
+ idx = (i * cols * 4) + j * 4;
+
+ // rgba to rgb
+ uchar r = data[idx];
+ uchar g = data[idx + 1];
+ uchar b = data[idx + 2];
+ // uchar a = data[idx + 3];
+
+ // turn frame image to gray scale
+ gray[i][j] = (0.30 * r) + (0.59 * g) + (0.11 * b);
+ }
+ }
+
+ return cv::Mat(rows, cols, CV_8UC1, gray);
+}
+
+static cv::Mat grayscale(uchar data[], size_t cols, size_t rows, ColorSpace colorType) {
+ int cn;
+ switch (colorType) {
+ case ColorSpace::RGBA:
+ cn = 4;
+ break;
+ case ColorSpace::RGB:
+ cn = 3;
+ break;
+ case ColorSpace::GRAY:
+
+ std::cout << "Grayscale input is not allowed with grayscale !" << std::endl;
+
+ break;
+ default:
+ cn = 4;
+ }
+ auto size = cols * rows;
+ auto q = 0;
+ std::vector gray;
+ uchar r;
+ uchar g;
+ uchar b;
+ for (auto p = 0; p < size; p++) {
+ r = data[q + 0], g = data[q + 1], b = data[q + 2];
+ // https://stackoverflow.com/a/596241/5843642
+ gray.push_back((r + r + r + b + g + g + g + g) >> 3);
+ q += cn;
+ }
+ return cv::Mat(cols, rows, CV_8UC1, gray.data());
+}
+
+} // namespace webarkit
\ No newline at end of file
diff --git a/WebARKit/include/WebARKitLog.h b/WebARKit/include/WebARKitLog.h
new file mode 100644
index 0000000..fb25dd7
--- /dev/null
+++ b/WebARKit/include/WebARKitLog.h
@@ -0,0 +1,161 @@
+/*
+ * WebARKitLog.h
+ * WebARKit
+ *
+ * This file is part of WebARKit.
+ *
+ * WebARKit is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * WebARKit is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with WebARKit. If not, see .
+ *
+ * As a special exception, the copyright holders of this library give you
+ * permission to link this library with independent modules to produce an
+ * executable, regardless of the license terms of these independent modules, and to
+ * copy and distribute the resulting executable under terms of your choice,
+ * provided that you also meet, for each linked independent module, the terms and
+ * conditions of the license of that module. An independent module is a module
+ * which is neither derived from nor based on this library. If you modify this
+ * library, you may extend this exception to your version of the library, but you
+ * are not obligated to do so. If you do not wish to do so, delete this exception
+ * statement from your version.
+ *
+ * Copyright 2015-2016 Daqri, LLC.
+ * Copyright 2003-2015 ARToolworks, Inc.
+ * Copyright 2023 WebARKit.
+ *
+ * Author(s): Hirokazu Kato, Philip Lamb, Walter Perdan
+ *
+ * This code was taken from Artoolkit5 https://github.com/artoolkitx/artoolkit5
+ * with small modifications to adapt to existing WebARKIt code
+ *
+ */
+
+/*!
+ @file log.h
+ @brief Logging utilities.
+ @details
+ Various routines to format and redirect log output.
+ @Copyright 2015-2017 Daqri, LLC.
+ */
+
+#ifndef WEBARKIT_LOG_H
+#define WEBARKIT_LOG_H
+
+#include
+#include
+#include
+#include
+#ifndef _WIN32 // errno is defined in stdlib.h on Windows.
+# ifdef EMSCRIPTEN // errno is not in sys/
+# include
+# else
+# include
+# endif
+#endif
+#ifdef __ANDROID__
+# include
+#endif
+#ifdef _WIN32
+# define ARUTIL_CALLBACK __stdcall
+#else
+# define ARUTIL_CALLBACK
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum {
+ WEBARKIT_LOG_LEVEL_DEBUG = 0,
+ WEBARKIT_LOG_LEVEL_INFO,
+ WEBARKIT_LOG_LEVEL_WARN,
+ WEBARKIT_LOG_LEVEL_ERROR,
+ WEBARKIT_LOG_LEVEL_REL_INFO
+};
+#define WEBARKIT_LOG_LEVEL_DEFAULT WEBARKIT_LOG_LEVEL_INFO
+
+/*!
+ @var int webarkitLogLevel
+ @brief Sets the severity level. Log messages below the set severity level are not logged.
+ @details
+ All calls to WebARKIt's logging facility include a "log level" parameter, which specifies
+ the severity of the log message. (The severities are defined in <WebARKitLog.h>.)
+ Setting this global allows for filtering of log messages. All log messages lower than
+ the set level will not be logged by webarkitLog().
+ Note that debug log messages created using the WEBARKIT_LOGd() macro will be logged only in
+ debug builds, irrespective of the log level.
+ @see webarkitLog
+*/
+extern int webarkitLogLevel;
+
+/*!
+ @brief Write a string to the current logging facility.
+ @details
+ The default logging facility varies by platform, but on Unix-like platforms is typically
+ the standard error file descriptor. However, logging may be redirected to some other
+ facility by webarkitLogSetLogger.
+
+ Newlines are not automatically appended to log output.
+ @param tag A tag to supply to an OS-specific logging function to specify the source
+ of the error message. May be NULL, in which case "libwebarkit" will be used.
+ @param logLevel The severity of the log message. Defined in %lt;WebARKitLog.h>.
+ Log output is written to the logging facility provided the logLevel meets or
+ exceeds the minimum level specified in global webarkitLogLevel.
+ @param format Log format string, in the form of printf().
+ @see webarkitLogLevel
+ @see webarkitLogSetLogger
+*/
+
+void webarkitLog(const char *tag, const int logLevel, const char *format, ...);
+void webarkitLogv(const char *tag, const int logLevel, const char *format, va_list ap);
+
+typedef void (ARUTIL_CALLBACK *WEBARKIT_LOG_LOGGER_CALLBACK)(const char *logMessage);
+
+/*!
+ @brief Divert logging to a callback, or revert to default logging.
+ @details
+ The default logging facility varies by platform, but on Unix-like platforms is typically
+ the standard error file descriptor. However, logging may be redirected to some other
+ facility by this function.
+ @param callback The function which will be called with the log output, or NULL to
+ cancel redirection.
+ @param callBackOnlyIfOnSameThread If non-zero, then the callback will only be called
+ if the call to webarkitLog is made on the same thread as the thread which called this function,
+ and if the webarkitLog call is made on a different thread, log output will be buffered until
+ the next call to webarkitLog on the original thread.
+
+ The purpose of this is to prevent logging from secondary threads in cases where the
+ callback model of the target platform precludes this.
+ @see webarkitLog
+*/
+void webarkitLogSetLogger(WEBARKIT_LOG_LOGGER_CALLBACK callback, int callBackOnlyIfOnSameThread);
+
+#ifdef WEBARKIT_DEBUG
+# define WEBARKIT_LOGd(...) webarkitLog(NULL, WEBARKIT_LOG_LEVEL_DEBUG, __VA_ARGS__)
+#else
+# define WEBARKIT_LOGd(...)
+#endif
+#define WEBARKIT_LOGi(...) webarkitLog(NULL, WEBARKIT_LOG_LEVEL_INFO, __VA_ARGS__)
+#define WEBARKIT_LOGw(...) webarkitLog(NULL, WEBARKIT_LOG_LEVEL_WARN, __VA_ARGS__)
+#define WEBARKIT_LOGe(...) webarkitLog(NULL, WEBARKIT_LOG_LEVEL_ERROR, __VA_ARGS__)
+#define WEBARKIT_LOGperror(s) webarkitLog(NULL, WEBARKIT_LOG_LEVEL_ERROR, ((s != NULL) ? "%s: %s\n" : "%s%s\n"), ((s != NULL) ? s : ""), strerror(errno))
+
+#ifdef __ANDROID__
+# define WEBARKIT_LOG(...) __android_log_print(ANDROID_LOG_INFO, "WebARKit", __VA_ARGS__)
+#else
+# define WEBARKIT_LOG(...) printf(__VA_ARGS__)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif //#ifndef WEBARKIT_LOG_H