tesseract v5.3.3.20231005
networkio_test.cc
Go to the documentation of this file.
1// (C) Copyright 2017, Google Inc.
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5// http://www.apache.org/licenses/LICENSE-2.0
6// Unless required by applicable law or agreed to in writing, software
7// distributed under the License is distributed on an "AS IS" BASIS,
8// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9// See the License for the specific language governing permissions and
10// limitations under the License.
11
12#include "networkio.h"
13#include "include_gunit.h"
14#include "stridemap.h"
15#ifdef INCLUDE_TENSORFLOW
16# include <tensorflow/compiler/xla/array2d.h> // for xla::Array2D
17#endif
18
19namespace tesseract {
20
22protected:
23 void SetUp() override {
24 std::locale::global(std::locale(""));
25 }
26
27#ifdef INCLUDE_TENSORFLOW
28 // Sets up an Array2d object of the given size, initialized to increasing
29 // values starting with start.
30 std::unique_ptr<xla::Array2D<int>> SetupArray(int ysize, int xsize, int start) {
31 std::unique_ptr<xla::Array2D<int>> a(new xla::Array2D<int>(ysize, xsize));
32 int value = start;
33 for (int y = 0; y < ysize; ++y) {
34 for (int x = 0; x < xsize; ++x) {
35 (*a)(y, x) = value++;
36 }
37 }
38 return a;
39 }
40 // Sets up a NetworkIO with a batch of 2 "images" of known values.
41 void SetupNetworkIO(NetworkIO *nio) {
42 std::vector<std::unique_ptr<xla::Array2D<int>>> arrays;
43 arrays.push_back(SetupArray(3, 4, 0));
44 arrays.push_back(SetupArray(4, 5, 12));
45 std::vector<std::pair<int, int>> h_w_sizes;
46 for (size_t i = 0; i < arrays.size(); ++i) {
47 h_w_sizes.emplace_back(arrays[i].get()->height(), arrays[i].get()->width());
48 }
49 StrideMap stride_map;
50 stride_map.SetStride(h_w_sizes);
51 nio->ResizeToMap(true, stride_map, 2);
52 // Iterate over the map, setting nio's contents from the arrays.
53 StrideMap::Index index(stride_map);
54 do {
55 int value = (*arrays[index.index(FD_BATCH)])(index.index(FD_HEIGHT), index.index(FD_WIDTH));
56 nio->SetPixel(index.t(), 0, 128 + value, 0.0f, 128.0f);
57 nio->SetPixel(index.t(), 1, 128 - value, 0.0f, 128.0f);
58 } while (index.Increment());
59 }
60#endif
61};
62
63// Tests that the initialization via SetPixel works and the resize correctly
64// fills with zero where image sizes don't match.
65TEST_F(NetworkioTest, InitWithZeroFill) {
66#ifdef INCLUDE_TENSORFLOW
67 NetworkIO nio;
68 nio.Resize2d(true, 32, 2);
69 int width = nio.Width();
70 for (int t = 0; t < width; ++t) {
71 nio.SetPixel(t, 0, 0, 0.0f, 128.0f);
72 nio.SetPixel(t, 1, 0, 0.0f, 128.0f);
73 }
74 // The initialization will wipe out all previously set values.
75 SetupNetworkIO(&nio);
77 StrideMap::Index index(nio.stride_map());
78 int next_t = 0;
79 int pos = 0;
80 do {
81 int t = index.t();
82 // The indexed values just increase monotonically.
83 int value = nio.i(t)[0];
84 EXPECT_EQ(value, pos);
85 value = nio.i(t)[1];
86 EXPECT_EQ(value, -pos);
87 // When we skip t values, the data is always 0.
88 while (next_t < t) {
89 EXPECT_EQ(nio.i(next_t)[0], 0);
90 EXPECT_EQ(nio.i(next_t)[1], 0);
91 ++next_t;
92 }
93 ++pos;
94 ++next_t;
95 } while (index.Increment());
96 EXPECT_EQ(pos, 32);
97 EXPECT_EQ(next_t, 40);
98#else
99 LOG(INFO) << "Skip test because of missing xla::Array2D";
100 GTEST_SKIP();
101#endif
102}
103
104// Tests that CopyWithYReversal works.
105TEST_F(NetworkioTest, CopyWithYReversal) {
106#ifdef INCLUDE_TENSORFLOW
107 NetworkIO nio;
108 SetupNetworkIO(&nio);
109 NetworkIO copy;
110 copy.CopyWithYReversal(nio);
111 StrideMap::Index index(copy.stride_map());
112 int next_t = 0;
113 int pos = 0;
114 std::vector<int> expected_values = {8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2,
115 3, 27, 28, 29, 30, 31, 22, 23, 24, 25, 26,
116 17, 18, 19, 20, 21, 12, 13, 14, 15, 16};
117 do {
118 int t = index.t();
119 // The indexed values match the expected values.
120 int value = copy.i(t)[0];
121 EXPECT_EQ(value, expected_values[pos]);
122 value = copy.i(t)[1];
123 EXPECT_EQ(value, -expected_values[pos]);
124 // When we skip t values, the data is always 0.
125 while (next_t < t) {
126 EXPECT_EQ(copy.i(next_t)[0], 0) << "Failure t = " << next_t;
127 EXPECT_EQ(copy.i(next_t)[1], 0) << "Failure t = " << next_t;
128 ++next_t;
129 }
130 ++pos;
131 ++next_t;
132 } while (index.Increment());
133 EXPECT_EQ(pos, 32);
134 EXPECT_EQ(next_t, 40);
135#else
136 LOG(INFO) << "Skip test because of missing xla::Array2D";
137 GTEST_SKIP();
138#endif
139}
140
141// Tests that CopyWithXReversal works.
142TEST_F(NetworkioTest, CopyWithXReversal) {
143#ifdef INCLUDE_TENSORFLOW
144 NetworkIO nio;
145 SetupNetworkIO(&nio);
146 NetworkIO copy;
147 copy.CopyWithXReversal(nio);
148 StrideMap::Index index(copy.stride_map());
149 int next_t = 0;
150 int pos = 0;
151 std::vector<int> expected_values = {3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9,
152 8, 16, 15, 14, 13, 12, 21, 20, 19, 18, 17,
153 26, 25, 24, 23, 22, 31, 30, 29, 28, 27};
154 do {
155 int t = index.t();
156 // The indexed values match the expected values.
157 int value = copy.i(t)[0];
158 EXPECT_EQ(value, expected_values[pos]);
159 value = copy.i(t)[1];
160 EXPECT_EQ(value, -expected_values[pos]);
161 // When we skip t values, the data is always 0.
162 while (next_t < t) {
163 EXPECT_EQ(copy.i(next_t)[0], 0) << "Failure t = " << next_t;
164 EXPECT_EQ(copy.i(next_t)[1], 0) << "Failure t = " << next_t;
165 ++next_t;
166 }
167 ++pos;
168 ++next_t;
169 } while (index.Increment());
170 EXPECT_EQ(pos, 32);
171 EXPECT_EQ(next_t, 40);
172#else
173 LOG(INFO) << "Skip test because of missing xla::Array2D";
174 GTEST_SKIP();
175#endif
176}
177
178// Tests that CopyWithXYTranspose works.
179TEST_F(NetworkioTest, CopyWithXYTranspose) {
180#ifdef INCLUDE_TENSORFLOW
181 NetworkIO nio;
182 SetupNetworkIO(&nio);
183 NetworkIO copy;
184 copy.CopyWithXYTranspose(nio);
185 StrideMap::Index index(copy.stride_map());
186 int next_t = 0;
187 int pos = 0;
188 std::vector<int> expected_values = {0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7,
189 11, 12, 17, 22, 27, 13, 18, 23, 28, 14, 19,
190 24, 29, 15, 20, 25, 30, 16, 21, 26, 31};
191 do {
192 int t = index.t();
193 // The indexed values match the expected values.
194 int value = copy.i(t)[0];
195 EXPECT_EQ(value, expected_values[pos]);
196 value = copy.i(t)[1];
197 EXPECT_EQ(value, -expected_values[pos]);
198 // When we skip t values, the data is always 0.
199 while (next_t < t) {
200 EXPECT_EQ(copy.i(next_t)[0], 0);
201 EXPECT_EQ(copy.i(next_t)[1], 0);
202 ++next_t;
203 }
204 ++pos;
205 ++next_t;
206 } while (index.Increment());
207 EXPECT_EQ(pos, 32);
208 EXPECT_EQ(next_t, 40);
209#else
210 LOG(INFO) << "Skip test because of missing xla::Array2D";
211 GTEST_SKIP();
212#endif
213}
214
215} // namespace tesseract
@ LOG
@ INFO
Definition: log.h:28
int value
const double y
#define GTEST_SKIP()
Definition: gtest.h:1889
#define EXPECT_EQ(val1, val2)
Definition: gtest.h:2043
@ FD_WIDTH
Definition: stridemap.h:35
@ FD_BATCH
Definition: stridemap.h:33
@ FD_HEIGHT
Definition: stridemap.h:34
TEST_F(EuroText, FastLatinOCR)
void ZeroInvalidElements()
Definition: networkio.cpp:86
void CopyWithXReversal(const NetworkIO &src)
Definition: networkio.cpp:888
void CopyWithXYTranspose(const NetworkIO &src)
Definition: networkio.cpp:906
int Width() const
Definition: networkio.h:102
void Resize2d(bool int_mode, int width, int num_features)
Definition: networkio.cpp:35
void CopyWithYReversal(const NetworkIO &src)
Definition: networkio.cpp:868
const StrideMap & stride_map() const
Definition: networkio.h:128
const int8_t * i(int t) const
Definition: networkio.h:118
void SetPixel(int t, int f, int pixel, float black, float contrast)
Definition: networkio.cpp:290