{"notes":[{"id":"classic-cnns/stn","category":"classic-cnns","legacyPath":"","legacySlug":"","legacyPaths":[],"title":"STN","subtitle":"Moving Heaven and Earth","author":"Z. Yuan","paperDate":"2015-06-05","publishedOn":"2025-11-27","world":"external/stn","paperTitle":"Spatial Transformer Networks","paperUrl":"https://arxiv.org/abs/1506.02025","bibliography":{"title":"Spatial Transformer Networks","authors":["Max Jaderberg","Karen Simonyan","Andrew Zisserman","Koray Kavukcuoglu"],"url":"https://arxiv.org/abs/1506.02025","pdfUrl":"https://arxiv.org/pdf/1506.02025v3","codeUrl":null,"preprint":{"id":"1506.02025","submittedOn":"2015-06-05","url":"https://arxiv.org/abs/1506.02025"},"publication":null,"citation":"@misc{classiccnnsstn2015,\n  title = {{Spatial Transformer Networks}},\n  author = {Max Jaderberg and Karen Simonyan and Andrew Zisserman and Koray Kavukcuoglu},\n  year = {2015},\n  eprint = {1506.02025},\n  archivePrefix = {arXiv},\n  url = {https://arxiv.org/abs/1506.02025}\n}\n","citationPath":"/content/papers/citations/classic-cnns/stn.e823b15c17eb.bib"},"thumbnail":{"src":"/content/papers/assets/7b29191fd34e282fbd2d0fa901014f5770192cf1641d814b39b43a903817fb7f.png","width":480,"height":364},"locale":"en","path":"/content/papers/en/classic-cnns/stn.324b148dd6d3.md","headings":[{"id":"defining-the-problem","text":"Defining the Problem","depth":2},{"id":"solving-the-problem","text":"Solving the Problem","depth":2},{"id":"three-components","text":"Three Components","depth":3},{"id":"grid-generator-working-backward-from-the-output","text":"Grid Generator: Working Backward from the Output","depth":3},{"id":"sampler-taking-values-between-grid-points","text":"Sampler: Taking Values Between Grid Points","depth":3},{"id":"putting-it-into-a-network","text":"Putting It into a Network","depth":3},{"id":"discussion","text":"Discussion","depth":2},{"id":"distorted-mnist","text":"Distorted MNIST","depth":3},{"id":"street-view-house-numbers","text":"Street View House Numbers","depth":3},{"id":"fine-grained-bird-classification","text":"Fine-Grained Bird Classification","depth":3},{"id":"conclusion","text":"Conclusion","depth":2}],"anchorAliases":{},"guide":null,"relatedReading":[{"id":"text-recognition/rare","relation":"referenced","topic":""}]},{"id":"text-recognition/rare","category":"text-recognition","legacyPath":"text-recognition/1603-rare","legacySlug":"1603-rare","legacyPaths":[],"title":"RARE","subtitle":"Automatic Rectification","author":"Z. Yuan","paperDate":"2016","publishedOn":"2024-10-08","paperTitle":"Robust Scene Text Recognition With Automatic Rectification","paperUrl":"https://openaccess.thecvf.com/content_cvpr_2016/html/Shi_Robust_Scene_Text_CVPR_2016_paper.html","bibliography":{"title":"Robust Scene Text Recognition With Automatic Rectification","authors":["Baoguang Shi","Xinggang Wang","Pengyuan Lyu","Cong Yao","Xiang Bai"],"url":"https://openaccess.thecvf.com/content_cvpr_2016/html/Shi_Robust_Scene_Text_CVPR_2016_paper.html","pdfUrl":"https://openaccess.thecvf.com/content_cvpr_2016/papers/Shi_Robust_Scene_Text_CVPR_2016_paper.pdf","codeUrl":null,"preprint":null,"publication":{"venue":"CVPR","year":2016,"kind":"conference","url":"https://openaccess.thecvf.com/content_cvpr_2016/html/Shi_Robust_Scene_Text_CVPR_2016_paper.html"},"citation":"@inproceedings{textrecognitionrare2016,\n  title = {{Robust Scene Text Recognition With Automatic Rectification}},\n  author = {Baoguang Shi and Xinggang Wang and Pengyuan Lyu and Cong Yao and Xiang Bai},\n  year = {2016},\n  booktitle = {CVPR},\n  url = {https://openaccess.thecvf.com/content_cvpr_2016/html/Shi_Robust_Scene_Text_CVPR_2016_paper.html}\n}\n","citationPath":"/content/papers/citations/text-recognition/rare.e993d8c6fce6.bib"},"thumbnail":{"src":"/content/papers/assets/ede56fcdf7e421a6d8418d322e7a516326d84123169b83be8f9badb72fbb994e.jpg","width":1224,"height":496},"locale":"en","path":"/content/papers/en/text-recognition/rare.8f2b9e1a4f82.md","headings":[{"id":"defining-the-problem","text":"Defining the Problem","depth":2},{"id":"solving-the-problem","text":"Solving the Problem","depth":2},{"id":"spatial-transformer-network","text":"Spatial Transformer Network","depth":3},{"id":"localization-network","text":"Localization Network","depth":3},{"id":"grid-generator","text":"Grid Generator","depth":3},{"id":"sampler","text":"Sampler","depth":3},{"id":"encoder-decoder","text":"Encoder-Decoder","depth":3},{"id":"dictionary-assisted-recognition","text":"Dictionary-Assisted Recognition","depth":3},{"id":"model-training","text":"Model Training","depth":3},{"id":"evaluation-metrics","text":"Evaluation Metrics","depth":3},{"id":"discussion","text":"Discussion","depth":2},{"id":"comparison-with-other-methods","text":"Comparison with Other Methods","depth":3},{"id":"conclusion","text":"Conclusion","depth":2}],"anchorAliases":{},"guide":null,"relatedReading":[{"id":"text-recognition/sar","relation":"comparison","topic":"Recognizing curved or irregular text"},{"id":"text-recognition/dan","relation":"comparison","topic":"Recognizing curved or irregular text"}]}],"text":"Show a convolutional network a crooked handwritten digit, and it can usually still recognize it.\n\nWhere does that tolerance come from? Partly from max pooling: it takes the maximum within a small $2\\times2$ region, so if a feature shifts by a pixel or two, the output stays the same. Stack many layers, and the network gains a certain tolerance for changes in position.\n\nBut this tolerance builds up bit by bit, and its range is fixed. Max Jaderberg, Karen Simonyan, Andrew Zisserman, and Koray Kavukcuoglu of Google DeepMind released this paper in June 2015, and it was later published at NIPS 2015. They wanted the network to decide for itself how to shift, scale, and rotate a given image so it's easiest to recognize.\n\n## Defining the Problem\n\nThe authors start by pointing out the limitations of max pooling. Its region is usually small, say $2\\times2$ pixels, so invariance to position has to build up slowly over many layers of convolution and pooling; feature maps in the intermediate layers actually have no invariance to large transformations of the input.\n\nThe root of the problem is that the pooling mechanism is hard-coded in advance: where it pools and over how large a region have nothing to do with what the input looks like.\n\nThe authors wanted a different kind of module:\n\n- **Decides how to transform based on the input**: each image gets its own transformation, instead of every image sharing the same treatment.\n- **Acts on the whole feature map**: it can crop, scale, rotate, or even apply non-rigid warps, without being confined to a local region.\n- **Needs no extra annotation**: nobody tells it the correct rotation angle or box; it learns only from the final task loss.\n- **Trains directly with backpropagation**: the optimization procedure stays the same, so it can be inserted into existing convolutional networks.\n\nFirst, let's see what the result looks like:\n\n[![Three rows of MNIST examples, four columns each. (a) Handwritten digits that have been translated, scaled, rotated, or had noise added; (b) the sampling box predicted by the module, drawn as a colored quadrilateral on the original image; (c) the digit after transformation by the sampling box, straightened and enlarged; (d) the prediction of the classification network that follows: 7, 5, and 6](/content/papers/assets/7b29191fd34e282fbd2d0fa901014f5770192cf1641d814b39b43a903817fb7f.png)](/content/papers/assets/7b29191fd34e282fbd2d0fa901014f5770192cf1641d814b39b43a903817fb7f.png)\n\n*Figure 1 from the paper, excerpted from [**page 2 of the v3 PDF**](https://arxiv.org/pdf/1506.02025v3#page=2). (a) Distorted MNIST inputs; (b) the transformation predicted by the module; (c) the transformed result; (d) the prediction of the classification network that follows. The whole network is trained with class labels only.*\n\nThe third row is especially clear: the 6 is small, with clutter around it; the module finds the 6 on its own, crops it, enlarges it, and hands it to the classification network. At no point does anyone tell it where the 6 is.\n\n## Solving the Problem\n\n### Three Components\n\n[![Architecture of the spatial transformer module. The input feature map U splits into two paths: one goes into the localisation network, which outputs the transformation parameters θ, from which the grid generator computes the sampling grid T_θ(G); the other goes straight to the sampler, which samples from U according to the grid and outputs the feature map V](/content/papers/assets/96a7134077ab04428f529111ff95e65d6863c038ad037e4d679cb1d2de57c0bb.png)](/content/papers/assets/96a7134077ab04428f529111ff95e65d6863c038ad037e4d679cb1d2de57c0bb.png)\n\n*Figure 2 from the paper, excerpted from [**page 3 of the v3 PDF**](https://arxiv.org/pdf/1506.02025v3#page=3). Together, the localisation network, the grid generator, and the sampler make up a spatial transformer.*\n\nThe module consists of three components in sequence:\n\n1. **Localisation network**: reads the feature map $U$ and outputs the transformation parameters $\\theta$. It can be a fully connected network or a convolutional network; all it needs is a final regression layer that outputs $\\theta$.\n2. **Grid generator**: uses $\\theta$ to compute a set of sampling points $\\mathcal{T}_\\theta(G)$, that is, “where in the input each output pixel should take its value from.”\n3. **Sampler**: takes values from $U$ at the sampling points, producing the output $V$.\n\nFor multi-channel input, every channel uses the same transformation, so the spatial correspondence between channels doesn't get scrambled.\n\nThere's nothing special about the localisation network; the key parts are the next two steps. Let's walk through them with a small example.\n\n### Grid Generator: Working Backward from the Output\n\nAssume for now that the transformation is a 2D affine transformation, which needs only 6 parameters:\n\n$$\n\\begin{pmatrix} x_i^s \\\\ y_i^s \\end{pmatrix}\n= \\mathcal{T}_\\theta(G_i)\n= \\begin{bmatrix} \\theta_{11} & \\theta_{12} & \\theta_{13} \\\\ \\theta_{21} & \\theta_{22} & \\theta_{23} \\end{bmatrix}\n\\begin{pmatrix} x_i^t \\\\ y_i^t \\\\ 1 \\end{pmatrix}\n$$\n\n$(x_i^t, y_i^t)$ are the coordinates of the $i$-th pixel on the output grid, with superscript $t$ for target; $(x_i^s, y_i^s)$ is the position in the input it takes its value from, with superscript $s$ for source.\n\nNote the direction: the formula computes **input** coordinates from **output** coordinates. That way every output pixel is guaranteed a source and there are no holes, the same approach used for texture mapping in computer graphics.\n\nAll coordinates are normalized to $[-1, 1]$: the top-left corner of both output and input is $(-1, -1)$ and the bottom-right is $(1, 1)$, so the same $\\theta$ works whatever the size of the feature map.\n\nSuppose the output is $3\\times3$ and we want to zoom in 2× on the input's top-left corner. We can set $\\theta_{11}=\\theta_{22}=0.5$ and $\\theta_{13}=\\theta_{23}=-0.5$:\n\n```python\nimport torch\nimport torch.nn.functional as F\n\n# The output is a regular 3×3 grid; coordinates are normalized to [-1, 1]\ntheta = torch.tensor([[[0.5, 0.0, -0.5],\n                       [0.0, 0.5, -0.5]]])          # zoom in 2× on the top-left corner\ngrid = F.affine_grid(theta, size=(1, 1, 3, 3), align_corners=True)\nprint(\"x_s:\\n\", grid[0, ..., 0])\nprint(\"y_s:\\n\", grid[0, ..., 1])\n```\n\n```text\nx_s:\n tensor([[-1.0000, -0.5000,  0.0000],\n        [-1.0000, -0.5000,  0.0000],\n        [-1.0000, -0.5000,  0.0000]])\ny_s:\n tensor([[-1.0000, -1.0000, -1.0000],\n        [-0.5000, -0.5000, -0.5000],\n        [ 0.0000,  0.0000,  0.0000]])\n```\n\nThe output grid's $x^t$ values are $-1, 0, 1$; multiply by 0.5 and subtract 0.5, and you get $x^s = -1, -0.5, 0$: the 3 output pixels take values only from the left half of the input. The same goes for the $y$ direction. The $3\\times3$ output corresponds to the top-left quarter of the input.\n\n[![Two diagrams. (a) The green sampling points on the input U form a neat regular grid that maps one-to-one onto the output V, so the output is the same as the input; (b) the sampling points are affinely transformed into a tilted, shrunken parallelogram that covers only part of the digit, and the output V is the digit straightened and enlarged](/content/papers/assets/89651828c63ac51ce8bd1efa4deffe57d50cca84735217ef8b2c9087b5b760c8.png)](/content/papers/assets/89651828c63ac51ce8bd1efa4deffe57d50cca84735217ef8b2c9087b5b760c8.png)\n\n*Figure 3 from the paper, excerpted from [**page 4 of the v3 PDF**](https://arxiv.org/pdf/1506.02025v3#page=4). (a) The identity transformation: the sampling grid is the regular grid; (b) the sampling grid after an affine transformation.*\n\nThis figure draws the same idea. In (a), the sampling points form a regular grid, and the output is the same as the input; in (b), the sampling points are affinely transformed into a tilted parallelogram that covers only part of the input, so the output is the cropped, rotated, and enlarged result.\n\nThe 6 affine parameters can express cropping, translation, rotation, scaling, and skew. When the absolute value of the determinant of the left $2\\times2$ submatrix is less than 1, the sampling grid shrinks into a parallelogram of smaller area, which amounts to cropping out a region.\n\n$\\mathcal{T}_\\theta$ can take other forms too. The authors give a few examples: an attention form that allows only cropping, translation, and isotropic scaling (3 parameters, $s, t_x, t_y$); an 8-parameter plane projective transformation; and the thin plate spline (TPS), which can apply non-rigid warps. The only requirement is that $\\mathcal{T}_\\theta$ be differentiable with respect to its parameters, so that gradients can flow from the sampling points back to $\\theta$.\n\n### Sampler: Taking Values Between Grid Points\n\nSampling points rarely land exactly on integer grid points, so the sampler needs an interpolation kernel. The authors write it in a general form and then focus on bilinear interpolation:\n\n$$\nV_i^c = \\sum_{n}^{H}\\sum_{m}^{W} U_{nm}^c\\,\\max\\!\\big(0,\\ 1-|x_i^s-m|\\big)\\,\\max\\!\\big(0,\\ 1-|y_i^s-n|\\big)\n$$\n\nEach output value is a weighted average of the four pixels nearest the sampling point, with weights determined by distance.\n\nThe key is that this expression has (sub-)gradients with respect to both $U$ and the sampling coordinates $x_i^s$ and $y_i^s$. Once the gradient reaches the sampling coordinates, it can flow back to $\\theta$, and finally to the localisation network.\n\nLet's switch to a $\\theta$ whose sampling points don't land exactly on grid points, and try it on a $5\\times5$ input whose pixel values run from 0 at the top left to 24 at the bottom right:\n\n```python\nimport torch\nimport torch.nn.functional as F\n\nU = torch.arange(25, dtype=torch.float32).reshape(1, 1, 5, 5)   # a 5×5 input with values 0 to 24\ntheta = torch.tensor([[[0.4, 0.0, -0.3],\n                       [0.0, 0.4, -0.3]]], requires_grad=True)\ngrid = F.affine_grid(theta, size=(1, 1, 3, 3), align_corners=True)\nprint(\"Sampled x coordinates (in pixels):\", [round(v, 2) for v in ((grid[0, 0, :, 0] + 1) * 2).tolist()])\n\nV = F.grid_sample(U, grid, mode=\"bilinear\", align_corners=True)\nprint(V[0, 0])\n\nV.sum().backward()               # pick an arbitrary loss and see whether the gradient reaches θ\nprint(theta.grad)\n```\n\n```text\nSampled x coordinates (in pixels): [0.6, 1.4, 2.2]\ntensor([[ 3.6000,  4.4000,  5.2000],\n        [ 7.6000,  8.4000,  9.2000],\n        [11.6000, 12.4000, 13.2000]], grad_fn=<SelectBackward0>)\ntensor([[[ 0.,  0., 18.],\n         [ 0.,  0., 90.]]])\n```\n\nThis input's values are “row × 5 + column.” The first sampling point lands at row 0.6, column 0.6, and bilinear interpolation gives $0.6\\times5+0.6=3.6$. It isn't on any integer grid point; its value is a distance-weighted blend of the four surrounding pixels.\n\nThe gradient made it back to $\\theta$ too. The gradient of the translation parameter $\\theta_{13}$ is 18: shifting the sampling grid right by one normalized unit means shifting it by two pixels, which raises each sampled value by 2, and over 9 sampling points that adds up to 18. $\\theta_{23}$ shifts the grid downward, raising each value by 10, for a total of 90. The gradients of the other four parameters are all 0: this input increases evenly from left to right and from top to bottom, so when the grid is scaled or skewed about its center, the sampled values on one side drop while those on the other side rise, and the two cancel exactly.\n\nThat's why the whole module can be trained end to end: the gradient of the loss with respect to the output $V$ passes through the sampler to the sampling coordinates, through the grid generator to $\\theta$, and finally into the weights of the localisation network. Nobody has to supply the correct transformation.\n\n\n> [!NOTE]\n> \n> Bilinear interpolation isn't differentiable exactly at grid points, so sub-gradients have to be used there. The authors also note that in practice there's no need to actually sum over every input position; only the four pixels around each sampling point matter, so it computes quickly on a GPU.\n\n\n### Putting It into a Network\n\nThe module can be inserted anywhere in a convolutional network, and as many times as you like:\n\n- **In series, at different depths**: modules deeper in the network see more abstract features, and their localisation networks have more information for deciding how to transform.\n- **In parallel**: when a feature map contains several objects or parts that need separate handling, several modules can sit side by side, each focusing on one. The authors also note a limitation: in a purely feedforward network, the number of parallel modules caps the number of objects the network can handle separately.\n\nThe output size $H'$, $W'$ can also differ from the input's, so the module can downsample along the way. However, an interpolation kernel with small support, such as bilinear, can cause aliasing when downsampling.\n\n## Discussion\n\n### Distorted MNIST\n\nThe authors make several distorted versions of MNIST: rotation (R); rotation, translation, and scaling (RTS); projective transformation (P); and elastic warping (E). They compare an ordinary fully connected network (FCN) and a convolutional network (CNN) against versions with a spatial transformer module added at the input (ST-FCN, ST-CNN), using affine (Aff), projective (Proj), and 16-control-point TPS transformations. All models have about the same number of parameters, the classification part always has three weight layers, and the CNN has two max pooling layers.\n\n| Model | R | RTS | P | E |\n| --- | ---: | ---: | ---: | ---: |\n| FCN | 2.1 | 5.2 | 3.1 | 3.2 |\n| CNN | 1.2 | 0.8 | 1.5 | 1.4 |\n| ST-FCN, Aff | 1.2 | 0.8 | 1.5 | 2.7 |\n| ST-FCN, TPS | 1.1 | 0.8 | 1.4 | 2.4 |\n| ST-CNN, Aff | 0.7 | 0.5 | 0.8 | 1.2 |\n| ST-CNN, Proj | 0.8 | 0.6 | 0.8 | 1.3 |\n| ST-CNN, TPS | 0.7 | 0.5 | 0.8 | 1.1 |\n\n*Table: Error rates (%) excerpted from Table 1 of the paper, omitting the projective version of ST-FCN.*\n\nUnder every distortion, the network with the module beats its corresponding baseline. The most interesting column is RTS: ST-FCN, with no convolution or pooling at all, gets 0.8% error, the same as the CNN with two pooling layers. The authors take this to show that a spatial transformer is another way to achieve spatial invariance. ST-CNN does better still than ST-FCN, because pooling provides even more invariance and convolutions are better at modeling local structure.\n\nOn a $60\\times60$ version with translated digits and background clutter, the gaps are larger: FCN 13.2%, CNN 3.5%, ST-FCN 2.0%, ST-CNN 1.7%.\n\nOf the three transformations, TPS is the most powerful: it can mold elastically warped digits back into something close to the standard shape, and it doesn't overfit on the simpler rotation data. The authors also observe that all the models turn digits into an upright “standard” pose, which is the mean pose in the training data.\n\n### Street View House Numbers\n\nSVHN consists of about 200,000 real photos of house numbers, each with 1 to 5 digits that vary widely in size and arrangement; the task is to recognize the whole digit sequence. The authors' baseline model has 11 hidden layers, ending in 5 independent softmax classifiers, each predicting the digit at one position.\n\nThey extend this baseline in two ways:\n\n- **ST-CNN Single**: one module right after the input, with a four-layer convolutional network as its localisation network.\n- **ST-CNN Multi**: a module before each of the first four convolutional layers, each with a two-layer fully connected localisation network of 32 units per layer; all modules except the first transform feature maps.\n\nAll modules use affine transformations and bilinear sampling, and the regression layers of the localisation networks are all initialized to output the identity transformation.\n\n| Model | 64px | 128px |\n| --- | ---: | ---: |\n| Maxout CNN | 4.0 | — |\n| CNN (the authors' baseline) | 4.0 | 5.6 |\n| DRAM* | 3.9 | 4.5 |\n| ST-CNN Single | 3.7 | 3.9 |\n| ST-CNN Multi | 3.6 | 3.9 |\n\n*Table: Sequence error rates (%) excerpted from Table 2 of the paper. 64px means $64\\times64$ crops centered on the digit sequence; 128px means looser $128\\times128$ crops with more background. DRAM uses model averaging and Monte Carlo averaging; all the others are single models with a single forward pass.*\n\nAt 64px, ST-CNN Multi set the best result at the time, 3.6%. At 128px, with more background, the baseline CNN slips to 5.6% while ST-CNN holds at 3.9%: the modules crop out and enlarge the region where the digits are, so the network's resolution and capacity are spent on the digits. The cost is small: a forward plus backward pass of ST-CNN Multi is only 6% slower than the baseline CNN.\n\n### Fine-Grained Bird Classification\n\nCUB-200-2011 covers 200 bird species, with about 6,000 training images and 5,800 test images. The birds vary in size and orientation, and the images aren't tightly cropped around them; telling species apart means looking at fine textures and shapes.\n\nThe authors' baseline is already strong: an Inception network with batch normalization, pretrained on ImageNet and fine-tuned on CUB, reaches 82.3%, beating the previous best of 81.0%. They then add 2 or 4 modules in parallel, applying attention-form transformations to the input image; the patch cropped by each module is described by its own Inception subnetwork, and the results are concatenated for classification. The whole network is trained with class labels only.\n\n| Model | Accuracy |\n| --- | ---: |\n| CNN (baseline), 224px | 82.3% |\n| 2×ST-CNN, 224px | 83.1% |\n| 2×ST-CNN, 448px | 83.9% |\n| 4×ST-CNN, 448px | 84.1% |\n\n*Table: Excerpted from Table 3 of the paper.*\n\nThe 4-module version reaches 84.1%, 1.8 percentage points above the baseline. The authors also found 22 images overlapping between the ImageNet training set and the CUB test set (out of 5,794); with those removed, the result is 84.0%.\n\nMore interesting is the division of labor the modules learn: in the 2-module version, one becomes a bird-head detector while the other keeps its eye on the body. Earlier methods used keypoint annotations to train a separate detector for each part; here there are no part annotations at all, and the modules find the parts in the data on their own.\n\nThe input can be 448px without adding computation, because each module's transformed output is downsampled to 224px before being passed to the rest of the network.\n\n## Conclusion\n\nThe spatial transformer hands “how to look at this image” over to the network to learn as well: the localisation network predicts a transformation, the grid generator computes the sampling positions, and differentiable bilinear sampling lets gradients flow all the way back. The module needs no extra annotation and no change to the loss function.\n\nThe experiments cover distorted MNIST, real house-number photos, and fine-grained bird classification, and in every case the results beat baselines under the same conditions. Without any hints, the modules also learned to straighten digits, crop out house numbers, and look at a bird's head and body separately. The authors also point out its limits: the number of parallel modules caps how many objects can be handled separately, and downsampling may cause aliasing.\n\nA spatial transformer can be dropped straight into an existing network, with no change to the loss function and no extra annotation. PyTorch already has `affine_grid` and `grid_sample` built in; the examples above were written with these two functions, so wiring one up yourself isn't hard.\n\nIf your data has a lot of skew or perspective distortion, like signboard text in street scenes, try putting one in front of your network; that's how [RARE](/blog/papers/text-recognition/rare) does text recognition.\n","imageSizes":{"/content/papers/assets/7b29191fd34e282fbd2d0fa901014f5770192cf1641d814b39b43a903817fb7f.png":{"width":480,"height":364},"/content/papers/assets/96a7134077ab04428f529111ff95e65d6863c038ad037e4d679cb1d2de57c0bb.png":{"width":832,"height":330},"/content/papers/assets/89651828c63ac51ce8bd1efa4deffe57d50cca84735217ef8b2c9087b5b760c8.png":{"width":820,"height":364}}}
