diff --git a/examples/inception_v3/tests/CMakeLists.txt b/examples/inception_v3/tests/CMakeLists.txt index 8c48124..7423a0f 100644 --- a/examples/inception_v3/tests/CMakeLists.txt +++ b/examples/inception_v3/tests/CMakeLists.txt @@ -14,11 +14,13 @@ target_include_directories(test_inception_v3 PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/.. ${CUDANet_INCLUDE_DIRS} ${CUDAToolkit_INCLUDE_DIRS} + ${OpenCV_INCLUDE_DIRS} ) target_link_libraries(test_inception_v3 ${GTEST_BOTH_LIBRARIES} ${CUDANet_LIBRARY} + ${OpenCV_LIBS} CUDA::cudart inception_v3_lib ) diff --git a/examples/inception_v3/tests/basic_conv2d.py b/examples/inception_v3/tests/basic_conv2d.py deleted file mode 100644 index 54da82d..0000000 --- a/examples/inception_v3/tests/basic_conv2d.py +++ /dev/null @@ -1,90 +0,0 @@ -import sys -import torch -from torchvision.models.inception import BasicConv2d - -sys.path.append("../../../tools") -from utils import print_cpp_vector - -basic_conv2d = BasicConv2d( - in_channels=3, - out_channels=6, - kernel_size=3, - stride=1, - padding=1, -) - -conv_weights = torch.tensor([ - 0.18365, 0.08568, 0.08126, 0.68022, 0.41391, 0.71204, 0.66917, - 0.63586, 0.28914, 0.43624, 0.03018, 0.47986, 0.71336, 0.82706, - 0.587, 0.58516, 0.29813, 0.19312, 0.42975, 0.62522, 0.34256, - 0.28057, 0.37367, 0.54325, 0.63421, 0.46445, 0.56908, 0.95247, - 0.73934, 0.51263, 0.14464, 0.0956, 0.68846, 0.14675, 0.75427, - 0.50547, 0.37078, 0.03316, 0.42855, 0.94293, 0.73855, 0.86475, - 0.20687, 0.37793, 0.77947, 0.24402, 0.07547, 0.22212, 0.57188, - 0.5098, 0.71999, 0.63828, 0.53237, 0.42874, 0.43621, 0.87348, - 0.0073, 0.07752, 0.45232, 0.78307, 0.74813, 0.73456, 0.0378, - 0.78518, 0.6989, 0.50484, 0.74265, 0.39178, 0.91015, 0.11684, - 0.11499, 0.10394, 0.30637, 0.86116, 0.63743, 0.64142, 0.97882, - 0.30948, 0.32144, 0.76108, 0.81794, 0.50111, 0.82209, 0.49028, - 0.79417, 0.3257, 0.32221, 0.4007, 0.86371, 0.2271, 0.9414, - 0.66233, 0.60802, 0.65701, 0.41021, 0.1135, 0.21892, 0.93389, - 0.65786, 0.26068, 0.59535, 0.15048, 0.48185, 0.91072, 0.18252, - 0.64154, 0.89179, 0.54726, 0.60756, 0.31149, 0.30717, 0.79877, - 0.71727, 0.12418, 0.48471, 0.46097, 0.66898, 0.35467, 0.38027, - 0.16989, 0.88578, 0.84377, 0.26529, 0.26057, 0.30256, 0.84876, - 0.8849, 0.08982, 0.88191, 0.1944, 0.42052, 0.62898, 0.692, - 0.51155, 0.99903, 0.56947, 0.73144, 0.88091, 0.28472, 0.98895, - 0.41364, 0.1927, 0.07227, 0.421, 0.85347, 0.19329, 0.07098, - 0.19418, 0.06585, 0.49083, 0.85071, 0.96747, 0.45057, 0.54361, - 0.49552, 0.23454, 0.97412, 0.26663, 0.09274, 0.1662, 0.04784, - 0.76303 -]).reshape(6, 3, 3, 3) - -bn_weights = torch.tensor([ - 0.69298, 0.27049, 0.85854, 0.52973, 0.29644, 0.68932 -]) - -bn_biases = torch.tensor([ - 0.74976, 0.42745, 0.22132, 0.21262, 0.03726, 0.9719 -]) - -basic_conv2d.conv.weight = torch.nn.Parameter(conv_weights) - -basic_conv2d.bn.weight = torch.nn.Parameter(bn_weights) -basic_conv2d.bn.bias = torch.nn.Parameter(bn_biases) - -input = torch.tensor([ - 0.75539, 0.17641, 0.8331, 0.80627, 0.51712, 0.87756, 0.97027, - 0.21354, 0.28498, 0.05118, 0.37124, 0.40528, 0.13661, 0.08692, - 0.73809, 0.57278, 0.73534, 0.31338, 0.15362, 0.80245, 0.49524, - 0.81208, 0.24074, 0.42534, 0.62236, 0.75915, 0.06382, 0.66723, - 0.13448, 0.96896, 0.87197, 0.67366, 0.67885, 0.49345, 0.08446, - 0.94116, 0.8659, 0.22848, 0.53262, 0.51307, 0.89661, 0.72223, - 0.90541, 0.47353, 0.85476, 0.04177, 0.04039, 0.7917, 0.56188, - 0.53777, 0.91714, 0.84847, 0.16995, 0.59803, 0.05454, 0.00365, - 0.01429, 0.42586, 0.31519, 0.222, 0.9149, 0.51885, 0.82969, - 0.42778, 0.82913, 0.01303, 0.92699, 0.09225, 0.00284, 0.75769, - 0.74072, 0.59012, 0.40777, 0.0469, 0.08751, 0.23163, 0.51327, - 0.67095, 0.31971, 0.97841, 0.82292, 0.58917, 0.31565, 0.4728, - 0.41885, 0.36524, 0.28194, 0.70945, 0.36008, 0.23199, 0.71093, - 0.33364, 0.34199, 0.42114, 0.40026, 0.77819, 0.79858, 0.93793, - 0.45238, 0.97922, 0.73814, 0.11831, 0.08414, 0.56552, 0.99841, - 0.53862, 0.71138, 0.42274, 0.48724, 0.48201, 0.5361, 0.97138, - 0.27607, 0.33018, 0.07456, 0.77788, 0.58824, 0.77027, 0.3938, - 0.28081, 0.14074, 0.06907, 0.75419, 0.11888, 0.35715, 0.34481, - 0.05669, 0.21063, 0.8664, 0.00087, 0.88281, 0.55202, 0.68655, - 0.96262, 0.53907, 0.9227, 0.74055, 0.84487, 0.22792, 0.83233, - 0.42938, 0.39054, 0.59604, 0.4141, 0.25982, 0.9311, 0.35475, - 0.71432, 0.29186, 0.16604, 0.90708, 0.00171, 0.11541, 0.35719, - 0.9221, 0.18793, 0.90198, 0.29281, 0.72144, 0.54645, 0.71165, - 0.59584, 0.24041, 0.60954, 0.64945, 0.8122, 0.34145, 0.92178, - 0.99894, 0.25076, 0.45067, 0.71997, 0.09573, 0.57334, 0.63273, - 0.49469, 0.72747, 0.33449, 0.13755, 0.49458, 0.50319, 0.91328, - 0.57269, 0.21927, 0.36831, 0.88708, 0.62277, 0.08318, 0.01425, - 0.17998, 0.34614, 0.82303 -]).reshape(1, 3, 8, 8) - -with torch.no_grad(): - output = basic_conv2d(input) - output = torch.flatten(output) - print_cpp_vector(output) \ No newline at end of file diff --git a/examples/inception_v3/tests/preprocessing.py b/examples/inception_v3/tests/preprocessing.py new file mode 100644 index 0000000..568a25d --- /dev/null +++ b/examples/inception_v3/tests/preprocessing.py @@ -0,0 +1,60 @@ +import sys + +import torch +import torchvision.transforms as transforms +from PIL import Image +import numpy as np + +sys.path.append("../../../tools") +from utils import print_cpp_vector + +torch.manual_seed(0) + +def generate_random_image(size=(24, 24)): + # Generate a random RGB image + random_image = np.random.randint(0, 256, size=(*size, 3), dtype=np.uint8) + return Image.fromarray(random_image) + +def preprocess_image(image, resize=16, crop=16): + preprocess = transforms.Compose([ + transforms.Resize(resize), + transforms.CenterCrop(crop), + transforms.ToTensor(), + transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]), + ]) + return preprocess(image) + +def normalize_tensor(tensor): + normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) + return normalize(tensor) + + +def gen_preprocess_test_result(): + # Generate a random image + random_image = generate_random_image() + random_image.save("resources/test_image.jpg") + + # Preprocess the image + preprocessed = preprocess_image(random_image) + + # Print the preprocessed data + print("Preprocessed image data:") + print_cpp_vector(preprocessed.flatten(), "output") + + +def gen_normalize_test_result(): + input_tensor = torch.rand(3, 8, 8) + + print("Input tensor: ") + print_cpp_vector(input_tensor.flatten(), "input") + + normalized = normalize_tensor(input_tensor) + print_cpp_vector(normalized.flatten(), "expected_output") + + +if __name__ == "__main__": + # print("Preprocess Test\n") + # gen_preprocess_test_result() + + print("\nNormalize Test\n") + gen_normalize_test_result() \ No newline at end of file diff --git a/examples/inception_v3/tests/test_preprocessing.cpp b/examples/inception_v3/tests/test_preprocessing.cpp new file mode 100644 index 0000000..009c833 --- /dev/null +++ b/examples/inception_v3/tests/test_preprocessing.cpp @@ -0,0 +1,266 @@ +#include + +#include +#include +#include +#include + +TEST(ImageProcessingTest, TestNormalization) { + std::vector input = { + 0.49626f, 0.76822f, 0.08848f, 0.13203f, 0.30742f, 0.63408f, 0.49009f, + 0.89644f, 0.45563f, 0.63231f, 0.34889f, 0.40172f, 0.02233f, 0.16886f, + 0.29389f, 0.51852f, 0.69767f, 0.80001f, 0.16103f, 0.28227f, 0.68161f, + 0.91519f, 0.3971f, 0.87416f, 0.41941f, 0.55291f, 0.95274f, 0.03616f, + 0.18523f, 0.37342f, 0.3051f, 0.932f, 0.17591f, 0.26983f, 0.15068f, + 0.03172f, 0.20813f, 0.9298f, 0.72311f, 0.74234f, 0.5263f, 0.24366f, + 0.58459f, 0.03315f, 0.13872f, 0.24224f, 0.81547f, 0.79316f, 0.27825f, + 0.48196f, 0.81978f, 0.99707f, 0.69844f, 0.56755f, 0.83524f, 0.2056f, + 0.59317f, 0.11235f, 0.15346f, 0.24171f, 0.72624f, 0.70108f, 0.20382f, + 0.65105f, 0.77449f, 0.43689f, 0.51909f, 0.61585f, 0.81019f, 0.9801f, + 0.11469f, 0.31677f, 0.6965f, 0.91427f, 0.9351f, 0.94118f, 0.59951f, + 0.06521f, 0.546f, 0.1872f, 0.03402f, 0.94425f, 0.88018f, 0.00124f, + 0.59359f, 0.41577f, 0.41772f, 0.27112f, 0.69228f, 0.20385f, 0.6833f, + 0.75285f, 0.85794f, 0.68696f, 0.00513f, 0.17565f, 0.74966f, 0.60465f, + 0.10996f, 0.21209f, 0.97037f, 0.83691f, 0.28199f, 0.37416f, 0.0237f, + 0.49101f, 0.12347f, 0.11432f, 0.47245f, 0.57507f, 0.29523f, 0.79669f, + 0.19573f, 0.95369f, 0.84265f, 0.07836f, 0.37556f, 0.52256f, 0.57295f, + 0.61859f, 0.69621f, 0.52995f, 0.25604f, 0.73659f, 0.02038f, 0.20365f, + 0.37484f, 0.25644f, 0.32508f, 0.09019f, 0.39364f, 0.60688f, 0.17427f, + 0.47434f, 0.85793f, 0.4486f, 0.5139f, 0.45687f, 0.60119f, 0.81792f, + 0.97362f, 0.81753f, 0.97471f, 0.46384f, 0.05084f, 0.26296f, 0.84045f, + 0.49676f, 0.25148f, 0.11684f, 0.03207f, 0.078f, 0.39858f, 0.7742f, + 0.77032f, 0.01778f, 0.81189f, 0.10875f, 0.39429f, 0.29726f, 0.40369f, + 0.40183f, 0.05133f, 0.06828f, 0.42176f, 0.50647f, 0.27286f, 0.68835f, + 0.04997f, 0.46626f, 0.93971f, 0.29605f, 0.9515f, 0.68108f, 0.04877f, + 0.81635f, 0.4423f, 0.2768f, 0.89983f, 0.09595f, 0.55365f, 0.39532f, + 0.85706f, 0.63957f, 0.74025f, 0.67658f, 0.37976f, 0.39485f, 0.08796f, + 0.77092f, 0.89699f, 0.84211f + }; + std::vector expected_output = { + 0.04916f, 1.23678f, -1.73154f, -1.54135f, -0.77545f, 0.651f, + 0.02224f, 1.7967f, -0.12826f, 0.64326f, -0.59435f, -0.36368f, + -2.02041f, -1.38053f, -0.83455f, 0.14638f, 0.92868f, 1.3756f, + -1.41472f, -0.88529f, 0.85855f, 1.87858f, -0.38384f, 1.69937f, + -0.28643f, 0.29654f, 2.04252f, -1.95998f, -1.30903f, -0.48726f, + -0.78559f, 1.95197f, -1.34974f, -0.93959f, -1.45991f, -1.97939f, + -1.20904f, 1.94235f, 1.03978f, 1.12374f, 0.18033f, -1.05389f, + 0.4349f, -1.97313f, -1.51215f, -1.06011f, 1.4431f, 1.34568f, + -0.90283f, -0.01328f, 1.46192f, 2.2361f, 0.93206f, 0.36046f, + 1.52945f, -1.22009f, 0.47237f, -1.6273f, -1.44779f, -1.06241f, + 1.05343f, 0.94358f, -1.22784f, 0.72512f, 1.42181f, -0.08531f, + 0.28166f, 0.71363f, 1.5812f, 2.33972f, -1.52371f, -0.62158f, + 1.07368f, 2.04587f, 2.13886f, 2.16597f, 0.64066f, -1.7446f, + 0.40177f, -1.20001f, -1.88383f, 2.17967f, 1.89366f, -2.0302f, + 0.61422f, -0.1796f, -0.1709f, -0.82535f, 1.05481f, -1.12568f, + 1.01471f, 1.32524f, 1.79436f, 1.03105f, -2.0128f, -1.25156f, + 1.31097f, 0.66362f, -1.54483f, -1.08888f, 2.29632f, 1.70049f, + -0.77684f, -0.36537f, -1.92991f, 0.15631f, -1.48451f, -1.52535f, + 0.07344f, 0.53157f, -0.7177f, 1.52093f, -1.16192f, 2.22181f, + 1.72612f, -1.6859f, -0.35912f, 0.29715f, 0.5221f, 0.72584f, + 1.07238f, 0.33013f, -0.8927f, 1.25265f, -1.94475f, -1.12658f, + -0.36234f, -0.89088f, -0.35963f, -1.4036f, -0.05492f, 0.89279f, + -1.02992f, 0.30373f, 2.00856f, 0.18933f, 0.47954f, 0.22607f, + 0.86751f, 1.83075f, 2.52277f, 1.82901f, 2.52759f, 0.25706f, + -1.57849f, -0.63573f, 1.9309f, 0.40337f, -0.68677f, -1.28514f, + -1.66189f, -1.4578f, -0.03297f, 1.63646f, 1.6192f, -1.7254f, + 1.80396f, -1.32113f, -0.05202f, -0.48327f, -0.01026f, -0.01854f, + -1.57633f, -1.50097f, 0.07005f, 0.44652f, -0.59172f, 1.25489f, + -1.58235f, 0.26781f, 2.37204f, -0.48865f, 2.42445f, 1.22256f, + -1.58769f, 1.82377f, 0.16135f, -0.57424f, 2.19479f, -1.37799f, + 0.65623f, -0.04749f, 2.00469f, 1.0381f, 1.48557f, 1.20258f, + -0.11661f, -0.04957f, -1.41351f, 1.62188f, 2.18217f, 1.93828f + }; + + const int height = 8; + const int width = 8; + const int channels = 3; + + ASSERT_EQ(input.size(), channels * height * width); + ASSERT_EQ(expected_output.size(), channels * height * width); + + cv::Mat image(height, width, CV_32FC3); + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) { + for (int c = 0; c < channels; ++c) { + image.at(y, x)[c] = input[c * height * width + y * width + x]; + } + } + } + + cv::Mat mean(image.size(), CV_32FC3, cv::Scalar(0.485, 0.456, 0.406)); + cv::Mat std(image.size(), CV_32FC3, cv::Scalar(0.229, 0.224, 0.225)); + cv::subtract(image, mean, image); + cv::divide(image, std, image); + + std::vector output(channels * height * width); + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) { + for (int c = 0; c < channels; ++c) { + output[c * height * width + y * width + x] = image.at(y, x)[c]; + } + } + } + + ASSERT_EQ(output.size(), expected_output.size()); + for (size_t i = 0; i < output.size(); ++i) { + EXPECT_NEAR(output[i], expected_output[i], 1e-3f) + << "Mismatch at index " << i + << " (channel=" << (i / (height * width)) + << ", y=" << ((i % (height * width)) / width) + << ", x=" << ((i % (height * width)) % width) << ")"; + } + +} + +TEST(ImageProcessingTest, TestPreprocessing) { + int input_size = 24; + int resize_size = 16; + int crop_size = 16; + + std::string input_path = "../tests/resources/test_image.jpg"; + std::vector expected_output = { + -0.23418f, -0.57668f, -1.07329f, 0.77618f, 0.26244f, 0.02269f, + 1.52967f, 0.34806f, 0.43368f, 0.22819f, -0.91917f, -0.83355f, + 0.46793f, 0.36519f, -0.09718f, -0.11431f, -0.47393f, -1.19317f, + -0.06293f, 0.9988f, 0.74193f, 0.51931f, 0.84468f, 0.09119f, + 0.27956f, 0.09119f, 0.14256f, -0.01156f, -0.23418f, 0.09119f, + -0.08006f, 0.81043f, -0.23418f, 0.89605f, 0.96455f, 0.50218f, + 0.57068f, -0.04581f, 0.82755f, 0.51931f, 0.72481f, 0.84468f, + -0.35405f, -0.57668f, -0.42255f, -0.47393f, -0.69655f, 0.58781f, + 0.9303f, 0.84468f, -0.83355f, -0.50818f, -0.35405f, 0.72481f, + 0.9303f, -0.3883f, 0.19394f, -0.04581f, 0.31381f, -0.71367f, + -1.24454f, -0.47393f, 0.26244f, -0.78217f, -0.43968f, 0.36519f, + 0.91318f, -0.28556f, -0.01156f, 1.08443f, 0.75905f, -0.67942f, + 0.33094f, 0.02269f, 0.41656f, 0.58781f, 0.02269f, -0.71367f, + -0.3198f, -0.30268f, -0.16568f, -0.18281f, 1.15292f, 0.00557f, + -0.35405f, -0.16568f, 0.70768f, 0.48506f, 0.38231f, 1.03305f, + 0.9988f, -0.02868f, -0.7308f, -0.91917f, -0.01156f, 0.65631f, + -0.71367f, 0.03981f, 0.87893f, 0.00557f, 0.03981f, -0.42255f, + 0.46793f, 0.33094f, -0.11431f, -0.35405f, -0.61093f, -0.16568f, + -1.09042f, 0.05694f, -0.14856f, 0.74193f, -0.42255f, 0.24531f, + 0.91318f, 0.70768f, 1.03305f, 1.03305f, 1.08443f, 0.67343f, + -0.71367f, -1.14179f, -0.54243f, 0.19394f, -0.42255f, -0.43968f, + -0.85067f, 0.34806f, -0.30268f, 0.17681f, 0.75905f, 0.81043f, + 0.91318f, 1.15292f, 0.41656f, 0.58781f, -0.5253f, -0.43968f, + -0.28556f, -0.47393f, 0.27956f, -0.37118f, 0.57068f, 0.58781f, + 0.12544f, -0.25131f, -0.25131f, -0.04581f, 0.9988f, 1.1358f, + 1.10155f, 0.10831f, -0.09718f, 0.24531f, -0.43968f, -0.78217f, + -0.18281f, 0.82755f, 0.45081f, 0.26244f, 0.22819f, -0.81642f, + -0.11431f, -0.23418f, 0.07406f, 0.22819f, -0.23418f, -0.7993f, + -0.25131f, -0.16568f, -0.35405f, -0.9363f, -0.30268f, 0.98168f, + 0.72481f, -0.21706f, -0.09718f, -0.42255f, -0.54243f, -0.02868f, + 0.07406f, -1.07329f, 0.24531f, -0.01156f, 0.57068f, 0.15969f, + 0.65631f, -0.28556f, -0.57668f, 0.91318f, 0.9303f, -0.19993f, + -0.74792f, -0.40543f, -0.37118f, -0.76505f, -0.11431f, 0.07406f, + 0.33094f, 1.10155f, 0.34806f, 0.36519f, 0.84468f, 0.7933f, + 0.45081f, 0.19394f, -0.23418f, -0.9363f, -0.04581f, -0.02868f, + 0.14256f, -1.07329f, -0.8678f, -0.16568f, -0.25131f, 0.84468f, + 1.32417f, -0.5253f, -0.37118f, 0.57068f, 0.15969f, -0.71367f, + -0.7993f, 0.50218f, -0.55955f, -0.40543f, -0.09718f, -0.25131f, + -0.91917f, -0.69655f, -0.49105f, 0.9303f, 0.15969f, 0.63918f, + 0.63918f, 0.8618f, 1.10155f, -0.21706f, 0.48506f, 0.45081f, + -0.5253f, -0.33693f, 0.36519f, -0.04581f, 0.43368f, -0.37118f, + 0.17681f, -0.08006f, 0.03981f, 1.0673f, 0.48506f, 0.36519f, + 0.45081f, 0.07406f, 0.07406f, 0.12544f, 0.59034f, -0.23249f, + -0.51261f, 0.73039f, -0.09244f, -0.39006f, -0.7577f, -0.0049f, + -0.60014f, -0.89776f, -0.14496f, 0.41527f, -0.32003f, 0.7479f, + -0.44258f, -0.19748f, 0.60784f, -0.61765f, 0.17017f, 0.38025f, + 0.34524f, 0.10014f, -0.42507f, -0.33753f, -0.39006f, 0.15266f, + 0.60784f, -0.10994f, 0.53782f, 0.73039f, -0.30252f, -0.56513f, + 0.993f, -0.0049f, -0.16246f, -0.14496f, 0.22269f, -0.37255f, + 0.38025f, -0.05742f, -0.53011f, -0.7577f, -0.25f, -0.33753f, + -0.05742f, 0.18768f, -0.53011f, -0.26751f, 0.27521f, -1.0028f, + -0.23249f, -0.25f, 0.66036f, 0.03011f, 0.71289f, 0.83543f, + -0.23249f, 0.64286f, -0.70518f, -0.44258f, 0.13515f, 0.13515f, + 0.69538f, 0.53782f, -0.67017f, -1.33543f, 0.31022f, -0.21499f, + 0.48529f, -0.65266f, -0.09244f, 0.46779f, 0.71289f, 0.38025f, + -0.86274f, -0.21499f, 0.32773f, -0.70518f, 0.2402f, -0.88025f, + -0.53011f, -1.12535f, -0.12745f, -0.09244f, 0.46779f, 0.71289f, + 0.94048f, 0.36275f, -0.05742f, 0.15266f, 0.31022f, 1.02801f, + 1.16807f, -0.40756f, 0.5028f, -0.16246f, 0.5028f, 0.18768f, + -0.09244f, -0.91527f, 0.95798f, 0.39776f, 0.78291f, 0.78291f, + 0.13515f, 0.06513f, 0.27521f, 0.81793f, -0.25f, -0.09244f, + 0.15266f, 0.43277f, 0.80042f, -0.16246f, -0.35504f, -0.40756f, + 0.31022f, -0.32003f, 0.29272f, 0.08263f, -0.35504f, -0.98529f, + -0.81022f, -0.42507f, -0.03992f, -0.02241f, -0.23249f, -0.12745f, + 0.92297f, 0.43277f, -0.40756f, -0.17997f, -0.7577f, -0.25f, + 0.81793f, 0.87045f, 0.94048f, 0.32773f, 0.17017f, -0.03992f, + 0.83543f, -0.12745f, -0.12745f, 0.13515f, -0.09244f, -0.33753f, + 0.22269f, 0.64286f, -0.51261f, 0.18768f, 0.08263f, 1.29062f, + 1.11555f, 0.55532f, 0.73039f, -0.30252f, -0.86274f, -0.56513f, + -0.14496f, -0.37255f, -0.19748f, 0.06513f, -0.93277f, 0.06513f, + -0.60014f, -0.88025f, -0.67017f, -0.05742f, 0.31022f, 0.32773f, + -0.56513f, 0.2577f, -0.17997f, -0.0049f, -0.53011f, -0.98529f, + 0.46779f, -0.39006f, 0.01261f, -0.10994f, 0.80042f, 0.15266f, + -0.44258f, 0.43277f, 0.88796f, -0.12745f, -0.86274f, -0.0049f, + 0.69538f, 1.2381f, -0.23249f, 0.17017f, 0.36275f, -0.10994f, + 1.43067f, 1.30812f, 1.16807f, 1.34314f, 0.88796f, 1.04552f, + 0.60784f, 0.22269f, -0.12745f, 0.5028f, 0.13515f, 0.48529f, + -0.09244f, -0.17997f, -0.14496f, 1.44818f, 0.71289f, 0.08263f, + 0.10014f, 0.03011f, 0.53782f, 1.02801f, 1.0105f, 0.90546f, + -0.23249f, 0.66036f, 1.11555f, 0.29272f, 0.52031f, 0.76541f, + -0.32003f, 0.69538f, -0.30252f, -0.93277f, 0.43277f, 0.22269f, + 0.08263f, 1.20308f, 0.17017f, 0.5028f, 0.97549f, 0.71289f, + 0.39776f, 0.36275f, 0.83543f, -0.23249f, -0.30252f, 0.59034f, + -0.16246f, 0.34524f, 0.43277f, 0.08263f, 0.2577f, 0.64286f, + 0.71289f, 0.20518f, -0.16246f, 0.76541f, 1.51821f, -0.10994f, + -0.72269f, -1.5105f, -0.51468f, -0.37525f, 0.2522f, 1.21081f, + 1.76854f, 0.51364f, 0.6705f, 1.22824f, 0.58336f, 0.53107f, + 0.65307f, 0.75765f, 0.33935f, 0.65307f, -0.20096f, 0.74022f, + -0.51468f, -0.77612f, -0.00924f, 1.40253f, 0.23477f, -0.61926f, + 0.07791f, -0.00924f, -0.39268f, 0.58336f, 0.04305f, 0.47878f, + 0.72279f, 0.18248f, 0.26963f, 0.68793f, 0.49621f, 0.18248f, + -0.27068f, -0.06152f, 0.89708f, -0.35782f, -0.21839f, -0.09638f, + 0.07791f, 1.10623f, 0.51364f, 0.02562f, 0.60078f, -0.02667f, + -0.09638f, -0.49725f, 0.47878f, 0.07791f, -0.60183f, -0.20096f, + 1.10623f, 0.51364f, 0.58336f, -0.37525f, -0.06152f, 0.07791f, + 0.86222f, 0.56593f, -0.21839f, -0.07895f, 0.46135f, 0.06048f, + 0.16505f, 0.68793f, 0.46135f, 0.47878f, 0.42649f, 0.39163f, + 0.79251f, -0.18353f, 0.2522f, 1.0888f, 0.77508f, 0.19991f, + 0.33935f, 0.07791f, 0.72279f, 0.79251f, 1.31538f, 0.49621f, + 0.61821f, 0.28706f, 0.56593f, 1.45482f, 1.24566f, 0.70536f, + 1.87312f, 1.64654f, 1.15852f, 1.59425f, 0.42649f, -0.11381f, + 0.00819f, 0.04305f, 0.40906f, 1.00166f, 0.18248f, 0.40906f, + 0.84479f, 0.09534f, 0.5485f, 0.16505f, 0.35678f, 0.18248f, + 0.94937f, 1.33281f, -0.11381f, -0.09638f, 0.32192f, 0.47878f, + -0.37525f, 0.80993f, 0.75765f, 0.80993f, 0.93194f, 0.60078f, + -0.06152f, -0.02667f, 0.72279f, 0.6705f, -0.47983f, 0.19991f, + -0.25325f, -0.34039f, 0.40906f, -0.06152f, 0.1302f, 1.3851f, + 0.9668f, 0.58336f, 1.05394f, 1.12366f, 0.19991f, -0.11381f, + 0.58336f, 0.18248f, 1.01909f, -0.63669f, 0.3742f, -0.32296f, + -0.44497f, -1.12471f, 0.40906f, 1.05394f, -0.14867f, 0.00819f, + 0.93194f, 0.39163f, 1.07137f, -0.35782f, 0.40906f, 1.17595f, + 0.93194f, -0.67155f, 0.11277f, 0.39163f, 1.21081f, -0.0441f, + 1.14109f, 0.5485f, 0.06048f, -0.0441f, -0.14867f, 0.63564f, + 0.02562f, 0.84479f, 0.58336f, 0.56593f, -0.07895f, -0.00924f, + 0.32192f, 0.2522f, 0.61821f, -0.5844f, 0.9668f, 0.6705f, + 1.22824f, 0.53107f, -0.32296f, -0.95041f, -0.67155f, -0.13124f, + 0.21734f, 0.65307f, 1.12366f, 0.56593f, -0.77612f, 0.07791f, + 0.39163f, 0.91451f, 0.33935f, 0.84479f, 0.6705f, -0.18353f, + -0.65412f, -0.98527f, -0.68898f, -0.11381f, 0.68793f, 1.21081f, + 1.15852f, 0.80993f, -0.35782f, 0.91451f, 0.61821f, 1.00166f, + 0.32192f, 0.68793f, 0.26963f, 0.42649f, -0.51468f, -0.77612f, + 0.6705f, 0.77508f, 0.84479f, 0.5485f, 0.58336f, 0.87965f, + 0.63564f, 0.33935f, 0.32192f, 0.18248f, 0.18248f, 1.14109f, + 0.75765f, 0.11277f, -0.27068f, 0.51364f, 0.86222f, -0.35782f, + 1.0888f, -0.02667f, -0.21839f, 0.18248f, 0.02562f, 0.28706f, + 0.11277f, 0.19991f, 0.35678f, -0.02667f, 0.18248f, 0.18248f, + 0.44392f, 1.54196f, 1.14109f, -0.68898f, -0.86327f, -0.2881f, + 1.05394f, 0.70536f, -0.42754f, -1.0027f, 1.40253f, 1.43739f + }; + + ASSERT_EQ(expected_output.size(), crop_size * crop_size * 3); + + // Process the image using your function + std::vector output = + readAndNormalizeImage(input_path, resize_size, crop_size); + + // Compare the output with the expected output + ASSERT_EQ(output.size(), crop_size * crop_size * 3); + for (size_t i = 0; i < output.size(); ++i) { + EXPECT_NEAR(output[i], expected_output[i], 1e-5) + << "Mismatch at index " << i << " (y=" << (i / (crop_size * 3)) + << ", x=" << ((i / 3) % crop_size) << ", channel=" << (i % 3) + << ")"; + } +} \ No newline at end of file