summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEino-Ville Talvala <etalvala@google.com>2018-06-03 17:32:53 -0700
committerEino-Ville Talvala <etalvala@google.com>2018-06-05 00:24:01 -0700
commit7cffc831bcf26e6ef973e615e3002b78c344fcfb (patch)
treeb7004e46d7b71d700beb97a3986947a247ec1395
parent7b8a1fd27d12d1b3ea711b0edca6ff5b07f5beb1 (diff)
downloadav-7cffc831bcf26e6ef973e615e3002b78c344fcfb.tar.gz
CameraService: Add unit tests for DistortionMapper
- Make cameraserver_test test module reachable by build system - Fix minor compilation error in CameraProviderManagerTest - Add tests to verify: - Initialization of DistortionMapper - Transforms with an identity distortion function - Round-trip transform ~1e6 points with a large distortion function - Raw to corrected transform compared against OpenCV undistortPoints, using python to generate the comparison coordinate lists as a C++ header Test: atest cameraservice_test Bug: 79885994 Change-Id: Iae3d6f9de2e6c79dd5cea5ca35ee5100b38441f4
-rw-r--r--services/camera/libcameraservice/Android.mk5
-rw-r--r--services/camera/libcameraservice/device3/DistortionMapper.cpp1
-rw-r--r--services/camera/libcameraservice/tests/Android.mk1
-rw-r--r--services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp1
-rw-r--r--services/camera/libcameraservice/tests/DistortionMapperComp.py47
-rw-r--r--services/camera/libcameraservice/tests/DistortionMapperTest.cpp278
-rw-r--r--services/camera/libcameraservice/tests/DistortionMapperTest_OpenCvData.h2009
7 files changed, 2342 insertions, 0 deletions
diff --git a/services/camera/libcameraservice/Android.mk b/services/camera/libcameraservice/Android.mk
index 5697a8739a..96261ab0ef 100644
--- a/services/camera/libcameraservice/Android.mk
+++ b/services/camera/libcameraservice/Android.mk
@@ -97,3 +97,8 @@ LOCAL_CFLAGS += -Wall -Wextra -Werror
LOCAL_MODULE:= libcameraservice
include $(BUILD_SHARED_LIBRARY)
+
+# Build tests too
+
+include $(LOCAL_PATH)/tests/Android.mk
+
diff --git a/services/camera/libcameraservice/device3/DistortionMapper.cpp b/services/camera/libcameraservice/device3/DistortionMapper.cpp
index 82923bd307..9229079717 100644
--- a/services/camera/libcameraservice/device3/DistortionMapper.cpp
+++ b/services/camera/libcameraservice/device3/DistortionMapper.cpp
@@ -195,6 +195,7 @@ status_t DistortionMapper::updateCalibration(const CameraMetadata &result) {
}
mValidMapping = true;
+ // Need to recalculate grid
mValidGrids = false;
return OK;
diff --git a/services/camera/libcameraservice/tests/Android.mk b/services/camera/libcameraservice/tests/Android.mk
index 37a05c2746..f77069c32f 100644
--- a/services/camera/libcameraservice/tests/Android.mk
+++ b/services/camera/libcameraservice/tests/Android.mk
@@ -18,6 +18,7 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES:= $(call all-cpp-files-under, .)
LOCAL_SHARED_LIBRARIES := \
+ libbase \
libcutils \
libcameraservice \
libhidlbase \
diff --git a/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp b/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
index c1d6e850c9..ef93d9a9ca 100644
--- a/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
+++ b/services/camera/libcameraservice/tests/CameraProviderManagerTest.cpp
@@ -190,6 +190,7 @@ struct TestStatusListener : public CameraProviderManager::StatusListener {
hardware::camera::common::V1_0::CameraDeviceStatus) override {}
void onTorchStatusChanged(const String8 &,
hardware::camera::common::V1_0::TorchModeStatus) override {}
+ void onNewProviderRegistered() override {}
};
TEST(CameraProviderManagerTest, InitializeTest) {
diff --git a/services/camera/libcameraservice/tests/DistortionMapperComp.py b/services/camera/libcameraservice/tests/DistortionMapperComp.py
new file mode 100644
index 0000000000..dea36a7b3e
--- /dev/null
+++ b/services/camera/libcameraservice/tests/DistortionMapperComp.py
@@ -0,0 +1,47 @@
+# Calculates comparison output values for DistortionMapperTest.cpp:CompareToOpenCV
+#
+# Assumes a python that has numpy and cv2 (OpenCV) available
+
+import numpy as np
+import cv2
+
+Fx = 1000
+Fy = 1000
+Cx = 500
+Cy = 500
+# s = 0 - not supported by OpenCV
+
+K = np.array([[Fx, 0, Cx],[0, Fy, Cy],[0, 0, 1]])
+
+# Order is k1, k2, t1, t2, k3
+dist = np.array([0.1, -0.003, 0.02, 0.01, 0.004])
+
+np.random.seed(1234)
+
+activeArray = np.array([[1000, 750]])
+
+rawCoords = np.floor(np.random.rand(1000,2) * activeArray)
+
+# OpenCV needs either row count or col count = 1 for some reason
+rawCoords2 = rawCoords.reshape(-1, 1, 2)
+
+# P is the output camera matrix, K is the input; use the same for both
+expCoords = cv2.undistortPoints(rawCoords2, K, dist, P = K)
+
+with open('DistortionMapperTest_OpenCvData.h','w') as f:
+ f.write('// Generated by DistortionMapperComp.py\n');
+ f.write('// for use by DistortionMapperTest.cpp\n\n');
+
+ f.write('namespace openCvData {\n')
+ f.write('std::array<int32_t, %d> rawCoords = {\n' % (rawCoords.shape[0] * rawCoords.shape[1]))
+ for i in range(rawCoords.shape[0]):
+ f.write(' %d, %d,\n' % (rawCoords[i][0], rawCoords[i][1]))
+ f.write('};\n')
+
+ f.write('std::array<int32_t, %d> expCoords = {\n' % (expCoords.shape[0] * expCoords.shape[2]))
+ for i in range(expCoords.shape[0]):
+ f.write(' %d, %d,\n' % (expCoords[i][0][0], expCoords[i][0][1]))
+ f.write('};\n')
+ f.write('} // namespace openCvData\n')
+
+print "DistortionMapperTest_OpenCvData.h generated"
diff --git a/services/camera/libcameraservice/tests/DistortionMapperTest.cpp b/services/camera/libcameraservice/tests/DistortionMapperTest.cpp
new file mode 100644
index 0000000000..b489931b9f
--- /dev/null
+++ b/services/camera/libcameraservice/tests/DistortionMapperTest.cpp
@@ -0,0 +1,278 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_NDEBUG 0
+#define LOG_TAG "DistortionMapperTest"
+
+#include <random>
+
+#include <gtest/gtest.h>
+#include <android-base/stringprintf.h>
+#include <android-base/chrono_utils.h>
+
+#include "../device3/DistortionMapper.h"
+
+using namespace android;
+using namespace android::camera3;
+
+
+int32_t testActiveArray[] = {100, 100, 1000, 750};
+
+float testICal[] = { 1000.f, 1000.f, 500.f, 500.f, 0.f };
+
+float identityDistortion[] = { 0.f, 0.f, 0.f, 0.f, 0.f};
+
+std::array<int32_t, 12> basicCoords = {
+ 0, 0,
+ testActiveArray[2] - 1, 0,
+ testActiveArray[2] - 1, testActiveArray[3] - 1,
+ 0, testActiveArray[3] - 1,
+ testActiveArray[2] / 2, testActiveArray[3] / 2,
+ 251, 403 // A particularly bad coordinate for current grid count/array size
+};
+
+
+void setupTestMapper(DistortionMapper *m, float distortion[5]) {
+ CameraMetadata deviceInfo;
+
+ deviceInfo.update(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE,
+ testActiveArray, 4);
+
+ deviceInfo.update(ANDROID_LENS_INTRINSIC_CALIBRATION,
+ testICal, 5);
+
+ deviceInfo.update(ANDROID_LENS_DISTORTION,
+ distortion, 5);
+
+ m->setupStaticInfo(deviceInfo);
+}
+
+TEST(DistortionMapperTest, Initialization) {
+ CameraMetadata deviceInfo;
+
+ ASSERT_FALSE(DistortionMapper::isDistortionSupported(deviceInfo));
+
+ uint8_t distortionModes[] =
+ {ANDROID_DISTORTION_CORRECTION_MODE_OFF,
+ ANDROID_DISTORTION_CORRECTION_MODE_FAST,
+ ANDROID_DISTORTION_CORRECTION_MODE_HIGH_QUALITY};
+
+ deviceInfo.update(ANDROID_DISTORTION_CORRECTION_AVAILABLE_MODES,
+ distortionModes, 1);
+
+ ASSERT_FALSE(DistortionMapper::isDistortionSupported(deviceInfo));
+
+ deviceInfo.update(ANDROID_DISTORTION_CORRECTION_AVAILABLE_MODES,
+ distortionModes, 3);
+
+ ASSERT_TRUE(DistortionMapper::isDistortionSupported(deviceInfo));
+
+ DistortionMapper m;
+
+ ASSERT_FALSE(m.calibrationValid());
+
+ ASSERT_NE(m.setupStaticInfo(deviceInfo), OK);
+
+ ASSERT_FALSE(m.calibrationValid());
+
+ deviceInfo.update(ANDROID_SENSOR_INFO_PRE_CORRECTION_ACTIVE_ARRAY_SIZE,
+ testActiveArray, 4);
+
+ deviceInfo.update(ANDROID_LENS_INTRINSIC_CALIBRATION,
+ testICal, 5);
+
+ deviceInfo.update(ANDROID_LENS_DISTORTION,
+ identityDistortion, 5);
+
+ ASSERT_EQ(m.setupStaticInfo(deviceInfo), OK);
+
+ ASSERT_TRUE(m.calibrationValid());
+
+ CameraMetadata captureResult;
+
+ ASSERT_NE(m.updateCalibration(captureResult), OK);
+
+ captureResult.update(ANDROID_LENS_INTRINSIC_CALIBRATION,
+ testICal, 5);
+ captureResult.update(ANDROID_LENS_DISTORTION,
+ identityDistortion, 5);
+
+ ASSERT_EQ(m.updateCalibration(captureResult), OK);
+
+}
+
+TEST(DistortionMapperTest, IdentityTransform) {
+ status_t res;
+
+ DistortionMapper m;
+ setupTestMapper(&m, identityDistortion);
+
+ auto coords = basicCoords;
+ res = m.mapCorrectedToRaw(coords.data(), 5);
+ ASSERT_EQ(res, OK);
+
+ for (size_t i = 0; i < coords.size(); i++) {
+ EXPECT_EQ(coords[i], basicCoords[i]);
+ }
+
+ res = m.mapRawToCorrected(coords.data(), 5);
+ ASSERT_EQ(res, OK);
+
+ for (size_t i = 0; i < coords.size(); i++) {
+ EXPECT_EQ(coords[i], basicCoords[i]);
+ }
+
+ std::array<int32_t, 8> rects = {
+ 0, 0, 100, 100,
+ testActiveArray[2] - 100, testActiveArray[3]-100, 100, 100
+ };
+
+ auto rectsOrig = rects;
+ res = m.mapCorrectedRectToRaw(rects.data(), 2);
+ ASSERT_EQ(res, OK);
+
+ for (size_t i = 0; i < rects.size(); i++) {
+ EXPECT_EQ(rects[i], rectsOrig[i]);
+ }
+
+ res = m.mapRawRectToCorrected(rects.data(), 2);
+ ASSERT_EQ(res, OK);
+
+ for (size_t i = 0; i < rects.size(); i++) {
+ EXPECT_EQ(rects[i], rectsOrig[i]);
+ }
+}
+
+TEST(DistortionMapperTest, LargeTransform) {
+ status_t res;
+ constexpr int maxAllowedPixelError = 2; // Maximum per-pixel error allowed
+ constexpr int bucketsPerPixel = 3; // Histogram granularity
+
+ unsigned int seed = 1234; // Ensure repeatability for debugging
+ const size_t coordCount = 1e6; // Number of random test points
+
+ float bigDistortion[] = {0.1, -0.003, 0.004, 0.02, 0.01};
+
+ DistortionMapper m;
+ setupTestMapper(&m, bigDistortion);
+
+ std::default_random_engine gen(seed);
+
+ std::uniform_int_distribution<int> x_dist(0, testActiveArray[2] - 1);
+ std::uniform_int_distribution<int> y_dist(0, testActiveArray[3] - 1);
+
+ std::vector<int32_t> randCoords(coordCount * 2);
+
+ for (size_t i = 0; i < randCoords.size(); i += 2) {
+ randCoords[i] = x_dist(gen);
+ randCoords[i + 1] = y_dist(gen);
+ }
+
+ randCoords.insert(randCoords.end(), basicCoords.begin(), basicCoords.end());
+
+ auto origCoords = randCoords;
+
+ base::Timer correctedToRawTimer;
+ res = m.mapCorrectedToRaw(randCoords.data(), randCoords.size() / 2);
+ auto correctedToRawDurationMs = correctedToRawTimer.duration();
+ EXPECT_EQ(res, OK);
+
+ base::Timer rawToCorrectedTimer;
+ res = m.mapRawToCorrected(randCoords.data(), randCoords.size() / 2);
+ auto rawToCorrectedDurationMs = rawToCorrectedTimer.duration();
+ EXPECT_EQ(res, OK);
+
+ float correctedToRawDurationPerCoordUs =
+ (std::chrono::duration_cast<std::chrono::duration<double, std::micro>>(
+ correctedToRawDurationMs) / (randCoords.size() / 2) ).count();
+ float rawToCorrectedDurationPerCoordUs =
+ (std::chrono::duration_cast<std::chrono::duration<double, std::micro>>(
+ rawToCorrectedDurationMs) / (randCoords.size() / 2) ).count();
+
+ RecordProperty("CorrectedToRawDurationPerCoordUs",
+ base::StringPrintf("%f", correctedToRawDurationPerCoordUs));
+ RecordProperty("RawToCorrectedDurationPerCoordUs",
+ base::StringPrintf("%f", rawToCorrectedDurationPerCoordUs));
+
+ // Calculate mapping errors after round trip
+ float totalErrorSq = 0;
+ // Basic histogram; buckets go from [N to N+1)
+ std::array<int, maxAllowedPixelError * bucketsPerPixel> histogram = {0};
+ int outOfHistogram = 0;
+
+ for (size_t i = 0; i < randCoords.size(); i += 2) {
+ int xOrig = origCoords[i];
+ int yOrig = origCoords[i + 1];
+ int xMapped = randCoords[i];
+ int yMapped = randCoords[i + 1];
+
+ float errorSq = (xMapped - xOrig) * (xMapped - xOrig) +
+ (yMapped - yOrig) * (yMapped - yOrig);
+
+ EXPECT_LE(errorSq, maxAllowedPixelError * maxAllowedPixelError) << "( " <<
+ xOrig << "," << yOrig << ") -> (" << xMapped << "," << yMapped << ")";
+
+ // Note: Integer coordinates, so histogram will be clumpy; error distances can only be of
+ // form sqrt(X^2+Y^2) where X, Y are integers, so:
+ // 0, 1, sqrt(2), 2, sqrt(5), sqrt(8), 3, sqrt(10), sqrt(13), 4 ...
+ totalErrorSq += errorSq;
+ float errorDist = std::sqrt(errorSq);
+ if (errorDist < maxAllowedPixelError) {
+ int histBucket = static_cast<int>(errorDist * bucketsPerPixel); // rounds down
+ histogram[histBucket]++;
+ } else {
+ outOfHistogram++;
+ }
+ }
+
+ float rmsError = std::sqrt(totalErrorSq / randCoords.size());
+ RecordProperty("RmsError", base::StringPrintf("%f", rmsError));
+ for (size_t i = 0; i < histogram.size(); i++) {
+ std::string label = base::StringPrintf("HistogramBin[%f,%f)",
+ (float)i/bucketsPerPixel, (float)(i + 1)/bucketsPerPixel);
+ RecordProperty(label, histogram[i]);
+ }
+ RecordProperty("HistogramOutOfRange", outOfHistogram);
+}
+
+// Compare against values calculated by OpenCV
+// undistortPoints() method, which is the same as mapRawToCorrected
+// See script DistortionMapperComp.py
+#include "DistortionMapperTest_OpenCvData.h"
+
+TEST(DistortionMapperTest, CompareToOpenCV) {
+ status_t res;
+
+ float bigDistortion[] = {0.1, -0.003, 0.004, 0.02, 0.01};
+
+ // Expect to match within sqrt(2) radius pixels
+ const int32_t maxSqError = 2;
+
+ DistortionMapper m;
+ setupTestMapper(&m, bigDistortion);
+
+ using namespace openCvData;
+
+ res = m.mapRawToCorrected(rawCoords.data(), rawCoords.size() / 2);
+
+ for (size_t i = 0; i < rawCoords.size(); i+=2) {
+ int32_t dist = (rawCoords[i] - expCoords[i]) * (rawCoords[i] - expCoords[i]) +
+ (rawCoords[i + 1] - expCoords[i + 1]) * (rawCoords[i + 1] - expCoords[i + 1]);
+ EXPECT_LE(dist, maxSqError)
+ << "(" << rawCoords[i] << ", " << rawCoords[i + 1] << ") != ("
+ << expCoords[i] << ", " << expCoords[i + 1] << ")";
+ }
+}
diff --git a/services/camera/libcameraservice/tests/DistortionMapperTest_OpenCvData.h b/services/camera/libcameraservice/tests/DistortionMapperTest_OpenCvData.h
new file mode 100644
index 0000000000..f996bd5c3e
--- /dev/null
+++ b/services/camera/libcameraservice/tests/DistortionMapperTest_OpenCvData.h
@@ -0,0 +1,2009 @@
+// Generated by DistortionMapperComp.py
+// for use by DistortionMapperTest.cpp
+
+namespace openCvData {
+std::array<int32_t, 2000> rawCoords = {
+ 191, 466,
+ 437, 589,
+ 779, 204,
+ 276, 601,
+ 958, 656,
+ 357, 375,
+ 683, 534,
+ 370, 420,
+ 503, 10,
+ 772, 661,
+ 364, 461,
+ 75, 276,
+ 933, 488,
+ 397, 591,
+ 316, 426,
+ 869, 327,
+ 802, 107,
+ 704, 528,
+ 218, 693,
+ 442, 681,
+ 59, 138,
+ 47, 506,
+ 594, 399,
+ 43, 421,
+ 329, 377,
+ 111, 455,
+ 565, 5,
+ 617, 684,
+ 790, 744,
+ 958, 593,
+ 285, 468,
+ 478, 146,
+ 382, 40,
+ 451, 736,
+ 123, 89,
+ 738, 440,
+ 471, 80,
+ 229, 674,
+ 416, 401,
+ 6, 225,
+ 436, 459,
+ 918, 469,
+ 705, 112,
+ 746, 623,
+ 633, 328,
+ 152, 426,
+ 528, 713,
+ 480, 376,
+ 536, 614,
+ 57, 502,
+ 767, 531,
+ 796, 418,
+ 965, 110,
+ 29, 445,
+ 114, 713,
+ 325, 145,
+ 457, 690,
+ 879, 189,
+ 348, 136,
+ 901, 529,
+ 726, 675,
+ 779, 449,
+ 291, 113,
+ 335, 493,
+ 73, 41,
+ 323, 442,
+ 853, 215,
+ 173, 100,
+ 994, 134,
+ 317, 426,
+ 9, 675,
+ 977, 417,
+ 84, 249,
+ 728, 106,
+ 552, 204,
+ 974, 500,
+ 255, 81,
+ 776, 586,
+ 761, 685,
+ 658, 426,
+ 201, 523,
+ 952, 667,
+ 993, 614,
+ 545, 338,
+ 890, 729,
+ 593, 274,
+ 323, 653,
+ 215, 551,
+ 365, 601,
+ 782, 526,
+ 622, 370,
+ 840, 534,
+ 443, 23,
+ 363, 548,
+ 475, 258,
+ 640, 94,
+ 171, 552,
+ 127, 277,
+ 604, 77,
+ 802, 709,
+ 979, 660,
+ 627, 697,
+ 724, 537,
+ 41, 329,
+ 282, 251,
+ 83, 570,
+ 509, 495,
+ 630, 278,
+ 446, 311,
+ 480, 737,
+ 373, 9,
+ 921, 654,
+ 351, 472,
+ 357, 159,
+ 223, 314,
+ 72, 488,
+ 755, 699,
+ 376, 222,
+ 371, 620,
+ 901, 320,
+ 2, 31,
+ 141, 448,
+ 106, 222,
+ 58, 465,
+ 22, 641,
+ 306, 569,
+ 563, 28,
+ 565, 494,
+ 183, 598,
+ 612, 416,
+ 629, 514,
+ 240, 590,
+ 856, 545,
+ 692, 354,
+ 856, 498,
+ 333, 388,
+ 394, 23,
+ 576, 637,
+ 951, 512,
+ 76, 307,
+ 41, 130,
+ 565, 129,
+ 566, 385,
+ 868, 540,
+ 903, 208,
+ 256, 524,
+ 901, 737,
+ 640, 247,
+ 606, 616,
+ 627, 88,
+ 285, 740,
+ 431, 430,
+ 527, 148,
+ 165, 375,
+ 990, 295,
+ 714, 131,
+ 70, 118,
+ 161, 212,
+ 536, 579,
+ 880, 478,
+ 852, 448,
+ 693, 402,
+ 889, 39,
+ 783, 108,
+ 58, 44,
+ 51, 386,
+ 404, 749,
+ 108, 245,
+ 997, 300,
+ 883, 426,
+ 953, 664,
+ 779, 23,
+ 962, 389,
+ 207, 656,
+ 224, 103,
+ 725, 730,
+ 535, 333,
+ 22, 454,
+ 964, 725,
+ 930, 138,
+ 622, 309,
+ 363, 27,
+ 868, 504,
+ 87, 665,
+ 782, 237,
+ 818, 380,
+ 21, 325,
+ 446, 179,
+ 830, 558,
+ 586, 369,
+ 487, 200,
+ 605, 565,
+ 270, 391,
+ 98, 535,
+ 884, 425,
+ 994, 134,
+ 12, 342,
+ 931, 634,
+ 473, 676,
+ 225, 228,
+ 714, 543,
+ 18, 214,
+ 580, 698,
+ 338, 90,
+ 516, 524,
+ 298, 646,
+ 905, 576,
+ 261, 703,
+ 938, 558,
+ 910, 177,
+ 494, 607,
+ 954, 478,
+ 910, 519,
+ 42, 625,
+ 369, 702,
+ 483, 93,
+ 964, 12,
+ 676, 105,
+ 155, 487,
+ 981, 521,
+ 761, 318,
+ 138, 162,
+ 764, 40,
+ 490, 135,
+ 630, 413,
+ 567, 613,
+ 938, 144,
+ 712, 523,
+ 258, 686,
+ 532, 418,
+ 322, 253,
+ 332, 734,
+ 203, 500,
+ 574, 38,
+ 542, 155,
+ 91, 652,
+ 27, 726,
+ 327, 307,
+ 135, 95,
+ 413, 463,
+ 132, 730,
+ 180, 570,
+ 482, 576,
+ 302, 11,
+ 463, 527,
+ 66, 501,
+ 345, 443,
+ 229, 200,
+ 932, 619,
+ 145, 485,
+ 883, 556,
+ 515, 101,
+ 39, 625,
+ 117, 392,
+ 873, 29,
+ 692, 357,
+ 169, 47,
+ 32, 181,
+ 112, 303,
+ 42, 694,
+ 935, 607,
+ 188, 440,
+ 903, 725,
+ 67, 238,
+ 696, 480,
+ 632, 621,
+ 713, 251,
+ 167, 573,
+ 359, 66,
+ 729, 660,
+ 41, 131,
+ 420, 255,
+ 44, 84,
+ 438, 53,
+ 816, 649,
+ 131, 144,
+ 437, 728,
+ 773, 98,
+ 927, 620,
+ 392, 105,
+ 52, 69,
+ 886, 126,
+ 362, 490,
+ 604, 296,
+ 374, 47,
+ 428, 539,
+ 768, 145,
+ 862, 21,
+ 902, 177,
+ 128, 238,
+ 848, 624,
+ 345, 179,
+ 535, 203,
+ 34, 470,
+ 520, 31,
+ 757, 741,
+ 801, 257,
+ 335, 263,
+ 442, 434,
+ 617, 132,
+ 864, 532,
+ 170, 641,
+ 19, 481,
+ 162, 193,
+ 342, 4,
+ 438, 597,
+ 675, 408,
+ 564, 10,
+ 608, 741,
+ 224, 440,
+ 835, 594,
+ 329, 267,
+ 960, 167,
+ 211, 115,
+ 495, 195,
+ 555, 54,
+ 378, 345,
+ 778, 540,
+ 231, 18,
+ 257, 307,
+ 8, 353,
+ 852, 692,
+ 231, 743,
+ 5, 251,
+ 789, 73,
+ 442, 285,
+ 832, 533,
+ 355, 18,
+ 693, 315,
+ 858, 431,
+ 940, 660,
+ 458, 12,
+ 68, 240,
+ 592, 457,
+ 512, 108,
+ 876, 553,
+ 373, 621,
+ 90, 48,
+ 505, 700,
+ 148, 427,
+ 59, 126,
+ 69, 679,
+ 447, 79,
+ 665, 376,
+ 409, 545,
+ 172, 288,
+ 267, 231,
+ 177, 361,
+ 629, 44,
+ 196, 209,
+ 707, 245,
+ 425, 528,
+ 159, 329,
+ 629, 693,
+ 356, 614,
+ 640, 536,
+ 738, 728,
+ 246, 31,
+ 247, 33,
+ 705, 626,
+ 934, 353,
+ 512, 197,
+ 98, 599,
+ 142, 604,
+ 879, 374,
+ 914, 309,
+ 200, 482,
+ 399, 460,
+ 437, 444,
+ 951, 414,
+ 903, 103,
+ 1, 459,
+ 541, 585,
+ 821, 715,
+ 609, 217,
+ 826, 282,
+ 609, 465,
+ 441, 149,
+ 443, 693,
+ 671, 61,
+ 572, 90,
+ 999, 748,
+ 694, 280,
+ 401, 693,
+ 244, 498,
+ 481, 26,
+ 110, 671,
+ 892, 686,
+ 307, 223,
+ 659, 446,
+ 984, 461,
+ 154, 623,
+ 815, 69,
+ 887, 12,
+ 863, 674,
+ 850, 489,
+ 328, 409,
+ 237, 653,
+ 176, 277,
+ 759, 229,
+ 616, 164,
+ 872, 485,
+ 473, 175,
+ 833, 73,
+ 205, 176,
+ 596, 471,
+ 982, 132,
+ 799, 116,
+ 360, 716,
+ 130, 204,
+ 809, 724,
+ 92, 437,
+ 405, 674,
+ 84, 135,
+ 50, 225,
+ 190, 6,
+ 127, 84,
+ 730, 179,
+ 901, 246,
+ 874, 177,
+ 378, 406,
+ 515, 310,
+ 388, 255,
+ 402, 342,
+ 382, 493,
+ 881, 429,
+ 428, 193,
+ 865, 129,
+ 579, 545,
+ 730, 302,
+ 117, 572,
+ 533, 541,
+ 597, 317,
+ 933, 745,
+ 547, 547,
+ 27, 647,
+ 998, 243,
+ 850, 458,
+ 441, 395,
+ 779, 188,
+ 462, 635,
+ 678, 275,
+ 137, 302,
+ 931, 504,
+ 419, 426,
+ 41, 746,
+ 619, 584,
+ 931, 256,
+ 811, 654,
+ 665, 441,
+ 893, 336,
+ 244, 610,
+ 697, 307,
+ 5, 715,
+ 605, 4,
+ 498, 448,
+ 300, 346,
+ 495, 439,
+ 869, 624,
+ 778, 411,
+ 613, 550,
+ 566, 581,
+ 986, 591,
+ 614, 118,
+ 476, 212,
+ 153, 582,
+ 58, 59,
+ 664, 392,
+ 446, 230,
+ 17, 220,
+ 267, 27,
+ 804, 250,
+ 891, 607,
+ 964, 718,
+ 591, 233,
+ 918, 37,
+ 225, 272,
+ 412, 708,
+ 579, 140,
+ 596, 700,
+ 134, 736,
+ 153, 615,
+ 677, 303,
+ 217, 580,
+ 847, 397,
+ 409, 13,
+ 148, 603,
+ 419, 254,
+ 297, 538,
+ 997, 413,
+ 889, 126,
+ 883, 527,
+ 422, 647,
+ 235, 422,
+ 26, 285,
+ 361, 68,
+ 45, 256,
+ 355, 746,
+ 944, 98,
+ 518, 357,
+ 401, 697,
+ 515, 607,
+ 881, 572,
+ 464, 55,
+ 470, 150,
+ 208, 133,
+ 354, 683,
+ 433, 133,
+ 752, 37,
+ 82, 28,
+ 465, 452,
+ 181, 389,
+ 710, 693,
+ 529, 728,
+ 547, 4,
+ 472, 391,
+ 152, 490,
+ 130, 340,
+ 982, 99,
+ 60, 50,
+ 96, 614,
+ 629, 587,
+ 77, 728,
+ 882, 472,
+ 929, 298,
+ 488, 514,
+ 281, 507,
+ 495, 593,
+ 218, 559,
+ 454, 306,
+ 922, 113,
+ 130, 286,
+ 541, 708,
+ 323, 73,
+ 947, 642,
+ 26, 88,
+ 829, 103,
+ 569, 358,
+ 306, 42,
+ 936, 678,
+ 722, 490,
+ 392, 730,
+ 711, 369,
+ 326, 86,
+ 972, 205,
+ 187, 161,
+ 760, 708,
+ 501, 496,
+ 347, 96,
+ 681, 293,
+ 26, 375,
+ 528, 167,
+ 1, 334,
+ 505, 60,
+ 822, 180,
+ 9, 168,
+ 84, 619,
+ 714, 183,
+ 63, 320,
+ 706, 538,
+ 193, 555,
+ 956, 386,
+ 430, 17,
+ 507, 514,
+ 138, 504,
+ 39, 323,
+ 854, 316,
+ 88, 42,
+ 103, 363,
+ 674, 68,
+ 832, 582,
+ 61, 241,
+ 377, 376,
+ 449, 350,
+ 104, 280,
+ 21, 336,
+ 893, 581,
+ 249, 548,
+ 315, 372,
+ 50, 436,
+ 282, 220,
+ 126, 669,
+ 451, 488,
+ 809, 212,
+ 273, 289,
+ 421, 699,
+ 867, 333,
+ 29, 80,
+ 196, 178,
+ 824, 672,
+ 27, 429,
+ 805, 315,
+ 525, 214,
+ 658, 67,
+ 822, 605,
+ 191, 478,
+ 832, 352,
+ 580, 81,
+ 462, 664,
+ 464, 349,
+ 196, 29,
+ 615, 423,
+ 108, 556,
+ 183, 261,
+ 480, 482,
+ 621, 570,
+ 286, 369,
+ 681, 382,
+ 768, 224,
+ 546, 183,
+ 443, 607,
+ 103, 172,
+ 791, 424,
+ 827, 731,
+ 965, 712,
+ 551, 69,
+ 740, 423,
+ 745, 341,
+ 155, 746,
+ 889, 602,
+ 411, 159,
+ 294, 467,
+ 248, 599,
+ 18, 360,
+ 734, 512,
+ 421, 519,
+ 367, 174,
+ 785, 545,
+ 706, 23,
+ 239, 278,
+ 581, 65,
+ 232, 609,
+ 752, 603,
+ 294, 585,
+ 224, 217,
+ 848, 558,
+ 332, 425,
+ 699, 68,
+ 53, 647,
+ 629, 652,
+ 87, 649,
+ 41, 718,
+ 227, 563,
+ 400, 302,
+ 253, 380,
+ 184, 42,
+ 366, 539,
+ 474, 691,
+ 170, 538,
+ 869, 96,
+ 974, 565,
+ 916, 28,
+ 285, 617,
+ 274, 38,
+ 147, 12,
+ 782, 261,
+ 749, 41,
+ 78, 592,
+ 370, 83,
+ 405, 488,
+ 436, 151,
+ 443, 556,
+ 96, 383,
+ 843, 745,
+ 630, 214,
+ 126, 10,
+ 338, 363,
+ 546, 27,
+ 61, 17,
+ 507, 199,
+ 445, 730,
+ 797, 213,
+ 555, 148,
+ 790, 65,
+ 837, 180,
+ 434, 320,
+ 102, 681,
+ 149, 680,
+ 10, 130,
+ 839, 232,
+ 848, 683,
+ 899, 650,
+ 837, 190,
+ 843, 463,
+ 984, 457,
+ 651, 490,
+ 552, 139,
+ 980, 71,
+ 748, 393,
+ 290, 171,
+ 503, 698,
+ 574, 742,
+ 429, 312,
+ 627, 680,
+ 69, 412,
+ 154, 538,
+ 135, 3,
+ 537, 12,
+ 535, 34,
+ 153, 632,
+ 797, 227,
+ 398, 336,
+ 20, 463,
+ 804, 175,
+ 400, 369,
+ 501, 250,
+ 105, 480,
+ 151, 146,
+ 57, 686,
+ 830, 119,
+ 867, 380,
+ 128, 84,
+ 222, 667,
+ 450, 522,
+ 390, 466,
+ 716, 375,
+ 760, 624,
+ 559, 407,
+ 587, 18,
+ 989, 53,
+ 817, 102,
+ 153, 269,
+ 253, 164,
+ 563, 360,
+ 93, 385,
+ 197, 360,
+ 277, 7,
+ 887, 280,
+ 416, 658,
+ 760, 411,
+ 902, 690,
+ 465, 424,
+ 28, 105,
+ 399, 620,
+ 455, 520,
+ 637, 491,
+ 769, 0,
+ 300, 521,
+ 90, 392,
+ 894, 722,
+ 705, 573,
+ 344, 188,
+ 667, 111,
+ 470, 16,
+ 759, 154,
+ 840, 581,
+ 176, 663,
+ 93, 151,
+ 372, 130,
+ 345, 425,
+ 156, 581,
+ 33, 8,
+ 320, 395,
+ 629, 661,
+ 641, 17,
+ 695, 663,
+ 751, 197,
+ 507, 93,
+ 608, 519,
+ 77, 303,
+ 513, 605,
+ 98, 354,
+ 567, 401,
+ 184, 440,
+ 785, 748,
+ 52, 32,
+ 528, 452,
+ 82, 532,
+ 116, 147,
+ 779, 341,
+ 308, 275,
+ 763, 135,
+ 137, 375,
+ 14, 260,
+ 337, 378,
+ 492, 262,
+ 202, 119,
+ 561, 334,
+ 855, 683,
+ 876, 724,
+ 202, 544,
+ 571, 437,
+ 456, 436,
+ 67, 4,
+ 468, 592,
+ 922, 540,
+ 125, 539,
+ 615, 290,
+ 785, 76,
+ 402, 556,
+ 12, 696,
+ 460, 52,
+ 909, 92,
+ 894, 153,
+ 931, 373,
+ 360, 120,
+ 726, 626,
+ 318, 733,
+ 472, 424,
+ 146, 74,
+ 86, 564,
+ 742, 236,
+ 845, 400,
+ 832, 139,
+ 275, 437,
+ 929, 42,
+ 818, 123,
+ 439, 274,
+ 65, 590,
+ 512, 132,
+ 520, 443,
+ 444, 107,
+ 961, 313,
+ 130, 488,
+ 587, 191,
+ 287, 603,
+ 56, 208,
+ 936, 628,
+ 908, 445,
+ 773, 258,
+ 383, 283,
+ 425, 530,
+ 244, 133,
+ 216, 543,
+ 631, 595,
+ 785, 108,
+ 87, 192,
+ 640, 427,
+ 889, 688,
+ 152, 89,
+ 10, 209,
+ 122, 343,
+ 188, 5,
+ 896, 748,
+ 806, 22,
+ 535, 457,
+ 851, 307,
+ 261, 566,
+ 791, 590,
+ 947, 300,
+ 658, 394,
+ 418, 305,
+ 371, 632,
+ 470, 438,
+ 165, 410,
+ 538, 380,
+ 643, 408,
+ 318, 591,
+ 564, 311,
+ 327, 690,
+ 930, 8,
+ 93, 100,
+ 627, 196,
+ 582, 416,
+ 200, 492,
+ 943, 267,
+ 31, 355,
+ 67, 374,
+ 692, 57,
+ 229, 373,
+ 542, 371,
+ 801, 230,
+ 114, 420,
+ 769, 326,
+ 83, 448,
+ 846, 137,
+ 912, 77,
+ 126, 3,
+ 784, 420,
+ 660, 391,
+ 795, 188,
+ 530, 42,
+ 137, 106,
+ 663, 80,
+ 757, 340,
+ 694, 267,
+ 768, 612,
+ 926, 155,
+ 600, 25,
+ 292, 31,
+ 97, 225,
+ 60, 437,
+ 724, 563,
+ 698, 85,
+ 286, 196,
+ 66, 1,
+ 269, 25,
+ 467, 405,
+ 204, 171,
+ 653, 14,
+ 299, 360,
+ 521, 719,
+ 760, 602,
+ 329, 282,
+ 687, 530,
+ 110, 200,
+ 30, 300,
+ 6, 501,
+ 868, 281,
+ 281, 76,
+ 805, 363,
+ 876, 114,
+ 219, 549,
+ 65, 611,
+ 859, 23,
+ 66, 354,
+ 205, 169,
+ 434, 174,
+ 828, 668,
+ 814, 720,
+ 663, 34,
+ 875, 707,
+ 969, 561,
+ 932, 66,
+ 834, 548,
+ 961, 86,
+ 263, 148,
+ 145, 202,
+ 83, 146,
+ 947, 727,
+ 3, 138,
+ 927, 514,
+ 814, 742,
+ 80, 430,
+ 866, 184,
+ 593, 731,
+ 193, 219,
+ 496, 490,
+ 606, 530,
+ 314, 334,
+ 301, 327,
+ 50, 715,
+ 178, 57,
+ 936, 626,
+ 972, 617,
+ 33, 427,
+ 147, 435,
+ 83, 341,
+ 859, 244,
+ 337, 688,
+ 637, 124,
+ 874, 71,
+ 590, 474,
+ 332, 120,
+ 640, 290,
+ 816, 171,
+ 665, 431,
+ 79, 31,
+ 857, 110,
+ 103, 79,
+ 293, 397,
+ 866, 651,
+ 356, 73,
+ 438, 710,
+ 41, 233,
+ 782, 596,
+ 852, 407,
+ 590, 104,
+ 34, 116,
+ 756, 276,
+ 282, 181,
+ 871, 275,
+ 888, 712,
+ 872, 279,
+ 645, 324,
+ 730, 524,
+ 430, 302,
+ 601, 486,
+ 114, 529,
+ 359, 317,
+ 313, 426,
+ 33, 732,
+ 970, 211,
+ 657, 582,
+ 945, 501,
+ 450, 630,
+ 822, 697,
+ 702, 600,
+ 958, 289,
+ 732, 96,
+ 205, 662,
+ 695, 533,
+ 369, 433,
+ 83, 445,
+ 176, 315,
+ 239, 95,
+ 895, 682,
+ 628, 118,
+ 730, 741,
+ 779, 734,
+ 804, 314,
+ 465, 567,
+ 810, 106,
+ 81, 268,
+ 968, 518,
+ 22, 159,
+ 726, 504,
+ 38, 269,
+ 751, 649,
+ 954, 659,
+};
+std::array<int32_t, 2000> expCoords = {
+ 190, 464,
+ 437, 588,
+ 774, 203,
+ 276, 599,
+ 939, 646,
+ 356, 373,
+ 681, 533,
+ 369, 419,
+ 500, 7,
+ 765, 655,
+ 363, 460,
+ 75, 272,
+ 920, 484,
+ 397, 590,
+ 315, 424,
+ 861, 326,
+ 795, 107,
+ 701, 526,
+ 220, 688,
+ 442, 678,
+ 59, 134,
+ 50, 501,
+ 593, 398,
+ 44, 417,
+ 327, 375,
+ 111, 452,
+ 562, 3,
+ 614, 680,
+ 780, 734,
+ 941, 586,
+ 284, 467,
+ 476, 142,
+ 379, 36,
+ 451, 731,
+ 122, 85,
+ 735, 439,
+ 469, 76,
+ 231, 670,
+ 415, 400,
+ 8, 221,
+ 435, 458,
+ 906, 466,
+ 701, 111,
+ 741, 619,
+ 632, 327,
+ 151, 423,
+ 527, 709,
+ 479, 375,
+ 535, 612,
+ 59, 498,
+ 762, 529,
+ 791, 417,
+ 948, 113,
+ 31, 441,
+ 119, 705,
+ 323, 141,
+ 457, 687,
+ 869, 189,
+ 346, 132,
+ 890, 525,
+ 721, 670,
+ 775, 448,
+ 288, 108,
+ 334, 492,
+ 74, 38,
+ 322, 441,
+ 845, 215,
+ 171, 96,
+ 975, 137,
+ 316, 425,
+ 17, 665,
+ 961, 414,
+ 83, 245,
+ 723, 105,
+ 551, 201,
+ 958, 495,
+ 253, 77,
+ 770, 583,
+ 754, 679,
+ 657, 425,
+ 201, 521,
+ 934, 657,
+ 973, 605,
+ 544, 336,
+ 875, 717,
+ 592, 272,
+ 323, 650,
+ 215, 549,
+ 365, 600,
+ 777, 524,
+ 621, 369,
+ 832, 531,
+ 440, 19,
+ 362, 547,
+ 474, 255,
+ 637, 92,
+ 171, 549,
+ 126, 273,
+ 601, 74,
+ 792, 701,
+ 959, 649,
+ 624, 692,
+ 721, 535,
+ 42, 325,
+ 280, 247,
+ 86, 565,
+ 508, 494,
+ 629, 276,
+ 445, 309,
+ 479, 732,
+ 370, 5,
+ 905, 645,
+ 350, 471,
+ 355, 155,
+ 221, 311,
+ 73, 484,
+ 748, 692,
+ 374, 218,
+ 371, 618,
+ 891, 319,
+ 6, 29,
+ 141, 445,
+ 105, 218,
+ 60, 461,
+ 28, 633,
+ 306, 567,
+ 560, 25,
+ 564, 493,
+ 184, 595,
+ 611, 415,
+ 628, 513,
+ 240, 587,
+ 847, 541,
+ 690, 353,
+ 848, 495,
+ 331, 386,
+ 391, 19,
+ 575, 635,
+ 936, 507,
+ 76, 303,
+ 42, 126,
+ 563, 126,
+ 565, 384,
+ 858, 536,
+ 892, 209,
+ 255, 522,
+ 884, 724,
+ 639, 245,
+ 604, 614,
+ 624, 86,
+ 287, 734,
+ 430, 429,
+ 525, 145,
+ 164, 372,
+ 974, 295,
+ 710, 130,
+ 70, 114,
+ 159, 208,
+ 535, 578,
+ 871, 475,
+ 844, 446,
+ 691, 401,
+ 876, 43,
+ 777, 108,
+ 59, 41,
+ 52, 382,
+ 404, 744,
+ 107, 241,
+ 980, 300,
+ 874, 424,
+ 935, 654,
+ 771, 24,
+ 948, 387,
+ 209, 652,
+ 222, 99,
+ 718, 722,
+ 534, 331,
+ 25, 449,
+ 943, 711,
+ 916, 140,
+ 621, 307,
+ 360, 23,
+ 859, 501,
+ 92, 658,
+ 777, 236,
+ 812, 379,
+ 22, 321,
+ 444, 175,
+ 822, 554,
+ 585, 368,
+ 486, 197,
+ 604, 564,
+ 268, 389,
+ 100, 531,
+ 875, 423,
+ 975, 137,
+ 14, 338,
+ 915, 626,
+ 472, 673,
+ 223, 224,
+ 711, 541,
+ 19, 210,
+ 578, 694,
+ 336, 85,
+ 515, 523,
+ 298, 643,
+ 892, 570,
+ 263, 698,
+ 923, 552,
+ 898, 178,
+ 493, 606,
+ 940, 474,
+ 898, 515,
+ 47, 618,
+ 369, 698,
+ 481, 89,
+ 945, 18,
+ 673, 103,
+ 155, 484,
+ 964, 516,
+ 757, 317,
+ 136, 158,
+ 757, 41,
+ 488, 131,
+ 629, 412,
+ 566, 611,
+ 924, 146,
+ 709, 521,
+ 259, 682,
+ 531, 417,
+ 320, 250,
+ 333, 729,
+ 202, 498,
+ 571, 35,
+ 540, 152,
+ 95, 645,
+ 36, 715,
+ 325, 304,
+ 134, 91,
+ 412, 462,
+ 137, 722,
+ 181, 567,
+ 481, 575,
+ 300, 7,
+ 462, 526,
+ 68, 497,
+ 344, 442,
+ 227, 196,
+ 917, 611,
+ 145, 482,
+ 872, 551,
+ 513, 97,
+ 44, 618,
+ 116, 389,
+ 861, 32,
+ 690, 356,
+ 168, 43,
+ 33, 177,
+ 111, 299,
+ 49, 685,
+ 920, 600,
+ 187, 438,
+ 887, 713,
+ 67, 234,
+ 694, 479,
+ 630, 619,
+ 710, 250,
+ 168, 570,
+ 356, 62,
+ 724, 655,
+ 42, 127,
+ 418, 252,
+ 45, 81,
+ 436, 49,
+ 807, 643,
+ 130, 140,
+ 437, 723,
+ 767, 98,
+ 912, 612,
+ 390, 101,
+ 53, 66,
+ 875, 128,
+ 361, 489,
+ 603, 294,
+ 371, 43,
+ 427, 538,
+ 763, 144,
+ 850, 24,
+ 891, 178,
+ 126, 234,
+ 838, 618,
+ 343, 175,
+ 534, 200,
+ 36, 466,
+ 517, 28,
+ 749, 732,
+ 796, 256,
+ 333, 260,
+ 441, 433,
+ 615, 129,
+ 855, 528,
+ 172, 636,
+ 22, 476,
+ 160, 189,
+ 339, 0,
+ 438, 596,
+ 673, 407,
+ 561, 8,
+ 605, 735,
+ 223, 438,
+ 826, 589,
+ 327, 264,
+ 945, 169,
+ 209, 111,
+ 494, 192,
+ 552, 51,
+ 377, 343,
+ 773, 537,
+ 229, 14,
+ 255, 304,
+ 10, 349,
+ 840, 683,
+ 234, 736,
+ 7, 247,
+ 782, 73,
+ 441, 282,
+ 824, 530,
+ 352, 14,
+ 691, 314,
+ 850, 429,
+ 923, 650,
+ 455, 8,
+ 68, 236,
+ 591, 456,
+ 510, 104,
+ 866, 549,
+ 373, 619,
+ 90, 45,
+ 504, 696,
+ 147, 424,
+ 59, 122,
+ 75, 671,
+ 445, 75,
+ 664, 375,
+ 408, 544,
+ 170, 284,
+ 265, 227,
+ 175, 358,
+ 625, 42,
+ 194, 205,
+ 704, 244,
+ 424, 527,
+ 157, 326,
+ 626, 689,
+ 356, 612,
+ 638, 535,
+ 731, 720,
+ 244, 27,
+ 245, 29,
+ 701, 623,
+ 922, 352,
+ 511, 194,
+ 101, 594,
+ 144, 600,
+ 870, 373,
+ 903, 308,
+ 199, 480,
+ 398, 459,
+ 436, 443,
+ 938, 412,
+ 891, 105,
+ 4, 454,
+ 540, 584,
+ 810, 706,
+ 608, 215,
+ 820, 281,
+ 608, 464,
+ 439, 145,
+ 443, 690,
+ 667, 60,
+ 570, 87,
+ 974, 731,
+ 692, 279,
+ 401, 690,
+ 243, 496,
+ 478, 22,
+ 114, 664,
+ 878, 676,
+ 305, 219,
+ 658, 445,
+ 967, 457,
+ 156, 619,
+ 807, 70,
+ 873, 16,
+ 851, 666,
+ 842, 486,
+ 327, 407,
+ 238, 649,
+ 174, 273,
+ 755, 228,
+ 614, 161,
+ 863, 482,
+ 471, 171,
+ 824, 74,
+ 203, 172,
+ 595, 470,
+ 964, 135,
+ 792, 116,
+ 361, 712,
+ 128, 200,
+ 799, 715,
+ 92, 434,
+ 405, 671,
+ 84, 131,
+ 50, 221,
+ 189, 3,
+ 126, 80,
+ 726, 178,
+ 891, 246,
+ 865, 178,
+ 377, 405,
+ 514, 308,
+ 386, 252,
+ 401, 340,
+ 381, 492,
+ 872, 427,
+ 426, 189,
+ 855, 130,
+ 578, 544,
+ 727, 301,
+ 119, 568,
+ 532, 540,
+ 596, 315,
+ 914, 731,
+ 546, 546,
+ 33, 639,
+ 981, 244,
+ 842, 456,
+ 440, 394,
+ 774, 187,
+ 462, 633,
+ 676, 273,
+ 135, 298,
+ 918, 500,
+ 418, 425,
+ 50, 734,
+ 617, 582,
+ 919, 256,
+ 802, 648,
+ 664, 440,
+ 884, 335,
+ 244, 607,
+ 695, 306,
+ 14, 704,
+ 601, 2,
+ 497, 447,
+ 298, 344,
+ 494, 438,
+ 858, 618,
+ 774, 410,
+ 612, 549,
+ 565, 580,
+ 967, 583,
+ 612, 115,
+ 475, 209,
+ 154, 578,
+ 59, 56,
+ 663, 391,
+ 444, 227,
+ 18, 216,
+ 265, 23,
+ 799, 249,
+ 879, 601,
+ 943, 704,
+ 590, 231,
+ 903, 41,
+ 223, 268,
+ 412, 704,
+ 577, 137,
+ 594, 696,
+ 139, 727,
+ 155, 611,
+ 675, 302,
+ 217, 577,
+ 840, 396,
+ 406, 9,
+ 150, 599,
+ 417, 251,
+ 296, 537,
+ 980, 410,
+ 878, 128,
+ 873, 523,
+ 422, 645,
+ 234, 420,
+ 27, 281,
+ 358, 64,
+ 45, 252,
+ 356, 740,
+ 929, 101,
+ 517, 356,
+ 401, 694,
+ 514, 606,
+ 870, 567,
+ 462, 51,
+ 468, 146,
+ 206, 129,
+ 354, 680,
+ 431, 129,
+ 745, 37,
+ 83, 25,
+ 464, 451,
+ 180, 386,
+ 705, 687,
+ 528, 723,
+ 544, 1,
+ 471, 390,
+ 152, 487,
+ 129, 337,
+ 964, 103,
+ 61, 47,
+ 99, 609,
+ 627, 585,
+ 84, 718,
+ 873, 469,
+ 917, 298,
+ 488, 513,
+ 280, 506,
+ 494, 592,
+ 218, 557,
+ 453, 304,
+ 908, 115,
+ 129, 282,
+ 540, 704,
+ 320, 69,
+ 930, 633,
+ 28, 85,
+ 821, 104,
+ 568, 357,
+ 304, 38,
+ 919, 667,
+ 719, 489,
+ 392, 725,
+ 709, 368,
+ 323, 81,
+ 956, 206,
+ 185, 157,
+ 753, 701,
+ 500, 495,
+ 345, 92,
+ 679, 292,
+ 27, 371,
+ 526, 164,
+ 3, 330,
+ 503, 56,
+ 815, 180,
+ 11, 164,
+ 88, 613,
+ 711, 182,
+ 63, 316,
+ 703, 536,
+ 193, 552,
+ 942, 384,
+ 427, 13,
+ 506, 513,
+ 138, 501,
+ 40, 319,
+ 847, 315,
+ 88, 39,
+ 102, 360,
+ 670, 66,
+ 824, 578,
+ 61, 237,
+ 376, 374,
+ 448, 348,
+ 103, 276,
+ 22, 332,
+ 881, 576,
+ 249, 546,
+ 313, 370,
+ 51, 432,
+ 280, 216,
+ 130, 663,
+ 450, 487,
+ 803, 211,
+ 271, 286,
+ 421, 696,
+ 859, 332,
+ 31, 77,
+ 194, 174,
+ 814, 665,
+ 29, 425,
+ 800, 314,
+ 524, 211,
+ 654, 65,
+ 814, 600,
+ 190, 476,
+ 826, 351,
+ 577, 78,
+ 462, 662,
+ 463, 347,
+ 194, 25,
+ 614, 422,
+ 110, 552,
+ 181, 257,
+ 479, 481,
+ 619, 569,
+ 284, 367,
+ 679, 381,
+ 764, 223,
+ 545, 180,
+ 443, 606,
+ 102, 168,
+ 786, 423,
+ 816, 721,
+ 944, 699,
+ 548, 66,
+ 737, 422,
+ 742, 340,
+ 160, 737,
+ 877, 596,
+ 409, 155,
+ 293, 466,
+ 248, 596,
+ 20, 356,
+ 731, 510,
+ 420, 518,
+ 365, 170,
+ 779, 542,
+ 700, 23,
+ 237, 275,
+ 578, 62,
+ 233, 606,
+ 747, 599,
+ 294, 583,
+ 222, 213,
+ 839, 554,
+ 331, 424,
+ 694, 67,
+ 58, 640,
+ 627, 649,
+ 91, 642,
+ 49, 708,
+ 227, 561,
+ 398, 299,
+ 251, 378,
+ 182, 38,
+ 365, 538,
+ 473, 688,
+ 170, 535,
+ 858, 98,
+ 956, 558,
+ 901, 33,
+ 285, 615,
+ 272, 34,
+ 146, 9,
+ 778, 260,
+ 743, 41,
+ 81, 587,
+ 368, 79,
+ 404, 487,
+ 434, 147,
+ 443, 555,
+ 96, 380,
+ 830, 734,
+ 628, 212,
+ 126, 7,
+ 336, 361,
+ 543, 24,
+ 62, 15,
+ 506, 196,
+ 445, 725,
+ 792, 212,
+ 553, 145,
+ 783, 66,
+ 829, 180,
+ 433, 318,
+ 107, 674,
+ 152, 674,
+ 12, 127,
+ 832, 232,
+ 837, 675,
+ 885, 642,
+ 830, 190,
+ 836, 461,
+ 967, 453,
+ 650, 489,
+ 550, 136,
+ 961, 76,
+ 745, 392,
+ 288, 167,
+ 502, 694,
+ 572, 736,
+ 428, 310,
+ 624, 676,
+ 70, 408,
+ 155, 535,
+ 135, 0,
+ 534, 9,
+ 532, 31,
+ 155, 627,
+ 792, 226,
+ 397, 334,
+ 23, 458,
+ 798, 175,
+ 399, 367,
+ 500, 247,
+ 106, 477,
+ 149, 142,
+ 63, 677,
+ 822, 120,
+ 859, 379,
+ 127, 80,
+ 224, 663,
+ 449, 521,
+ 389, 465,
+ 714, 374,
+ 754, 620,
+ 558, 406,
+ 584, 16,
+ 969, 59,
+ 809, 103,
+ 151, 265,
+ 251, 160,
+ 562, 359,
+ 93, 382,
+ 195, 357,
+ 275, 3,
+ 878, 280,
+ 416, 656,
+ 756, 410,
+ 887, 680,
+ 464, 423,
+ 30, 102,
+ 399, 618,
+ 454, 519,
+ 636, 490,
+ 761, 2,
+ 299, 520,
+ 90, 388,
+ 878, 710,
+ 702, 571,
+ 342, 184,
+ 664, 109,
+ 467, 12,
+ 754, 153,
+ 831, 577,
+ 178, 658,
+ 92, 147,
+ 370, 126,
+ 344, 424,
+ 157, 577,
+ 36, 7,
+ 318, 393,
+ 626, 658,
+ 637, 16,
+ 691, 659,
+ 747, 196,
+ 505, 89,
+ 607, 518,
+ 77, 299,
+ 512, 604,
+ 97, 350,
+ 566, 400,
+ 183, 438,
+ 775, 738,
+ 54, 30,
+ 527, 451,
+ 84, 528,
+ 115, 143,
+ 775, 340,
+ 306, 272,
+ 758, 134,
+ 136, 372,
+ 15, 256,
+ 335, 376,
+ 491, 259,
+ 200, 115,
+ 560, 332,
+ 843, 675,
+ 862, 713,
+ 202, 541,
+ 570, 436,
+ 455, 435,
+ 68, 2,
+ 468, 591,
+ 909, 535,
+ 126, 535,
+ 614, 288,
+ 778, 76,
+ 402, 555,
+ 20, 686,
+ 458, 48,
+ 896, 95,
+ 883, 154,
+ 919, 372,
+ 358, 116,
+ 721, 622,
+ 319, 728,
+ 471, 423,
+ 145, 70,
+ 88, 559,
+ 739, 235,
+ 838, 399,
+ 824, 139,
+ 274, 435,
+ 913, 46,
+ 810, 123,
+ 438, 271,
+ 69, 584,
+ 510, 128,
+ 519, 442,
+ 442, 103,
+ 947, 312,
+ 130, 485,
+ 585, 188,
+ 287, 601,
+ 56, 204,
+ 920, 620,
+ 897, 443,
+ 769, 257,
+ 381, 280,
+ 424, 529,
+ 242, 129,
+ 216, 541,
+ 629, 593,
+ 779, 108,
+ 86, 188,
+ 639, 426,
+ 875, 678,
+ 151, 85,
+ 12, 205,
+ 121, 340,
+ 187, 2,
+ 879, 735,
+ 797, 24,
+ 534, 456,
+ 844, 306,
+ 261, 564,
+ 784, 586,
+ 934, 300,
+ 657, 393,
+ 417, 303,
+ 371, 630,
+ 469, 437,
+ 164, 407,
+ 537, 379,
+ 642, 407,
+ 318, 589,
+ 563, 309,
+ 328, 686,
+ 913, 14,
+ 93, 96,
+ 625, 194,
+ 581, 415,
+ 199, 490,
+ 930, 267,
+ 32, 351,
+ 67, 370,
+ 687, 56,
+ 227, 370,
+ 541, 370,
+ 796, 229,
+ 114, 417,
+ 765, 325,
+ 84, 444,
+ 837, 138,
+ 898, 80,
+ 126, 0,
+ 780, 419,
+ 659, 390,
+ 789, 187,
+ 527, 39,
+ 136, 102,
+ 659, 78,
+ 754, 339,
+ 692, 266,
+ 762, 608,
+ 913, 157,
+ 597, 23,
+ 290, 27,
+ 96, 221,
+ 61, 433,
+ 720, 561,
+ 694, 84,
+ 284, 192,
+ 68, 0,
+ 267, 21,
+ 466, 404,
+ 202, 167,
+ 649, 13,
+ 297, 358,
+ 520, 715,
+ 755, 598,
+ 327, 279,
+ 685, 529,
+ 109, 196,
+ 31, 296,
+ 10, 496,
+ 860, 280,
+ 279, 72,
+ 800, 362,
+ 865, 116,
+ 219, 547,
+ 69, 605,
+ 847, 26,
+ 66, 350,
+ 203, 165,
+ 432, 170,
+ 818, 661,
+ 804, 711,
+ 659, 33,
+ 861, 697,
+ 952, 555,
+ 917, 70,
+ 826, 544,
+ 944, 90,
+ 260, 144,
+ 143, 198,
+ 83, 142,
+ 927, 713,
+ 5, 135,
+ 914, 510,
+ 803, 732,
+ 81, 426,
+ 857, 184,
+ 590, 726,
+ 191, 215,
+ 495, 489,
+ 605, 529,
+ 312, 332,
+ 299, 324,
+ 57, 705,
+ 176, 53,
+ 920, 618,
+ 953, 608,
+ 35, 423,
+ 146, 432,
+ 83, 337,
+ 851, 244,
+ 338, 684,
+ 634, 122,
+ 863, 73,
+ 589, 473,
+ 330, 116,
+ 639, 288,
+ 809, 171,
+ 664, 430,
+ 80, 28,
+ 847, 111,
+ 103, 75,
+ 291, 395,
+ 854, 644,
+ 353, 69,
+ 438, 706,
+ 41, 229,
+ 776, 592,
+ 845, 405,
+ 588, 101,
+ 35, 113,
+ 752, 275,
+ 280, 177,
+ 863, 275,
+ 873, 701,
+ 864, 279,
+ 644, 323,
+ 727, 522,
+ 429, 300,
+ 600, 485,
+ 115, 525,
+ 357, 315,
+ 312, 424,
+ 42, 721,
+ 955, 212,
+ 655, 580,
+ 931, 497,
+ 450, 628,
+ 812, 689,
+ 698, 597,
+ 944, 289,
+ 727, 95,
+ 207, 657,
+ 692, 531,
+ 368, 432,
+ 84, 441,
+ 174, 312,
+ 237, 91,
+ 881, 672,
+ 625, 116,
+ 723, 733,
+ 770, 725,
+ 799, 313,
+ 465, 566,
+ 803, 106,
+ 80, 264,
+ 952, 513,
+ 23, 155,
+ 723, 502,
+ 39, 265,
+ 745, 644,
+ 936, 649,
+};
+} // namespace openCvData