Imgaug

wrappers for common imgaug functions, that accept image and ocr data frame of bounding boxes

from torch_snippets.loader import read, pd, show

IM = read("/Users/yeshwanth.y/code/torch_snippets/assets/Preamble.png")
DF = pd.read_csv("/Users/yeshwanth.y/code/torch_snippets/assets/Preamble.csv")
DF = to_relative(DF, *IM.shape[:2])
DF.head()
x y X Y text block_id
0 0.249538 0.253501 0.569316 0.305322 ConstITUtIO 0
1 0.288355 0.369748 0.401109 0.397759 NLTHE 1
2 0.402957 0.369748 0.510166 0.397759 PEOPLE 1
3 0.493530 0.371148 0.545287 0.394958 OF 1
4 0.548983 0.369748 0.630314 0.397759 INDIA, 1

Rescale

im = IM.copy()
im = rescale(im, sz=(400, 600))
show(im, sz=5)

df = DF.copy()
im = IM.copy()
im, df = rescale(im, df, (400, 600))
show(im, df=df, sz=5)
df.head()
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
/Users/yeshwanth.y/code/torch_snippets/nbs/imgaug_loader.ipynb Cell 8 in <cell line: 3>()
      <a href='vscode-notebook-cell:/Users/yeshwanth.y/code/torch_snippets/nbs/imgaug_loader.ipynb#W6sZmlsZQ%3D%3D?line=0'>1</a> df = DF.copy()
      <a href='vscode-notebook-cell:/Users/yeshwanth.y/code/torch_snippets/nbs/imgaug_loader.ipynb#W6sZmlsZQ%3D%3D?line=1'>2</a> im = IM.copy()
----> <a href='vscode-notebook-cell:/Users/yeshwanth.y/code/torch_snippets/nbs/imgaug_loader.ipynb#W6sZmlsZQ%3D%3D?line=2'>3</a> im, df = rescale(im, df, (400, 600))
      <a href='vscode-notebook-cell:/Users/yeshwanth.y/code/torch_snippets/nbs/imgaug_loader.ipynb#W6sZmlsZQ%3D%3D?line=3'>4</a> show(im, df=df, sz=5)
      <a href='vscode-notebook-cell:/Users/yeshwanth.y/code/torch_snippets/nbs/imgaug_loader.ipynb#W6sZmlsZQ%3D%3D?line=4'>5</a> df.head()

/Users/yeshwanth.y/code/torch_snippets/nbs/imgaug_loader.ipynb Cell 8 in rescale(im, bbs, sz)
    <a href='vscode-notebook-cell:/Users/yeshwanth.y/code/torch_snippets/nbs/imgaug_loader.ipynb#W6sZmlsZQ%3D%3D?line=110'>111</a> H, W = get_size(sz, h, w)
    <a href='vscode-notebook-cell:/Users/yeshwanth.y/code/torch_snippets/nbs/imgaug_loader.ipynb#W6sZmlsZQ%3D%3D?line=111'>112</a> aug = iaa.Resize({"height": H, "width": W})
--> <a href='vscode-notebook-cell:/Users/yeshwanth.y/code/torch_snippets/nbs/imgaug_loader.ipynb#W6sZmlsZQ%3D%3D?line=112'>113</a> im, bbs = do(im, bbs, aug)
    <a href='vscode-notebook-cell:/Users/yeshwanth.y/code/torch_snippets/nbs/imgaug_loader.ipynb#W6sZmlsZQ%3D%3D?line=113'>114</a> if to_pil:
    <a href='vscode-notebook-cell:/Users/yeshwanth.y/code/torch_snippets/nbs/imgaug_loader.ipynb#W6sZmlsZQ%3D%3D?line=114'>115</a>     im = PIL.Image.fromarray(im)

/Users/yeshwanth.y/code/torch_snippets/nbs/imgaug_loader.ipynb Cell 8 in do(img, bbs, aug, cval)
     <a href='vscode-notebook-cell:/Users/yeshwanth.y/code/torch_snippets/nbs/imgaug_loader.ipynb#W6sZmlsZQ%3D%3D?line=41'>42</a>         __df = combine_xyXY_to_bb(__df)
     <a href='vscode-notebook-cell:/Users/yeshwanth.y/code/torch_snippets/nbs/imgaug_loader.ipynb#W6sZmlsZQ%3D%3D?line=42'>43</a>     bbs = __df
---> <a href='vscode-notebook-cell:/Users/yeshwanth.y/code/torch_snippets/nbs/imgaug_loader.ipynb#W6sZmlsZQ%3D%3D?line=43'>44</a> if bbs == []:
     <a href='vscode-notebook-cell:/Users/yeshwanth.y/code/torch_snippets/nbs/imgaug_loader.ipynb#W6sZmlsZQ%3D%3D?line=44'>45</a>     return img, []
     <a href='vscode-notebook-cell:/Users/yeshwanth.y/code/torch_snippets/nbs/imgaug_loader.ipynb#W6sZmlsZQ%3D%3D?line=45'>46</a> return img, bbs

File ~/miniconda3/lib/python3.9/site-packages/pandas/core/ops/__init__.py:705, in _comp_method_FRAME.<locals>.f(self, other)
    701 @Appender(f"Wrapper for comparison method {op_name}")
    702 def f(self, other):
    703     axis = 1  # only relevant for Series other case
--> 705     self, other = _align_method_FRAME(self, other, axis, level=None, flex=False)
    707     # See GH#4537 for discussion of scalar op behavior
    708     new_data = dispatch_to_series(self, other, op, axis=axis)

File ~/miniconda3/lib/python3.9/site-packages/pandas/core/ops/__init__.py:503, in _align_method_FRAME(left, right, axis, flex, level)
    496         raise ValueError(
    497             "Unable to coerce to Series/DataFrame, "
    498             f"dimension must be <= 2: {right.shape}"
    499         )
    501 elif is_list_like(right) and not isinstance(right, (ABCSeries, ABCDataFrame)):
    502     # GH17901
--> 503     right = to_series(right)
    505 if flex is not None and isinstance(right, ABCDataFrame):
    506     if not left._indexed_same(right):

File ~/miniconda3/lib/python3.9/site-packages/pandas/core/ops/__init__.py:465, in _align_method_FRAME.<locals>.to_series(right)
    463 else:
    464     if len(left.columns) != len(right):
--> 465         raise ValueError(
    466             msg.format(req_len=len(left.columns), given_len=len(right))
    467         )
    468     right = left._constructor_sliced(right, index=left.columns)
    469 return right

ValueError: Unable to coerce to Series, length must be 6: given 0

Rotate

for i in range(11):
    angle = (i - 5) * 5
    print(angle)
    im = rotate(IM, angle=angle)
    show(im, sz=1)
-25

-20

-15

-10

-5

0

5

10

15

20

25

df = DF.copy()
im = IM.copy()
im, df = rotate(im, df, 90)
show(im, df=df, sz=20)
print(type(im))
df.head()

<class 'numpy.ndarray'>
text block_id x y X Y
0 ConstITUtIO 0 0.693277 0.249538 0.745098 0.569316
1 NLTHE 1 0.600840 0.288355 0.628852 0.401109
2 PEOPLE 1 0.600840 0.402957 0.628852 0.510166
3 OF 1 0.603641 0.493530 0.627451 0.545287
4 INDIA, 1 0.600840 0.548983 0.628852 0.630314

Pad

df = DF.copy()
im = IM.copy()
im, df = pad(im, df, deltas=(90, 90), cval=0)
show(im, df=df, sz=20)
print(type(im))
df.head()

<class 'numpy.ndarray'>
text block_id x y X Y
0 ConstITUtIO 0 0.310536 0.302521 0.550832 0.343137
1 NLTHE 1 0.340111 0.394958 0.425139 0.417367
2 PEOPLE 1 0.426987 0.394958 0.506470 0.417367
3 OF 1 0.493530 0.396359 0.532348 0.415966
4 INDIA, 1 0.536044 0.394958 0.597043 0.417367

Augmentations as Monads

All functions will work with data frames that contain either of absolute/relative coordinates, and will preserve the image type (np.ndarray or PIL.Image.Image) too

df = DF.copy()
im = IM.copy()
height, width = im.shape
show(df.head())
im = PIL.Image.fromarray(im)
im, df = rotate(im, df, 45, cval=127)
im, df = pad(im, df, deltas=(200, 200), cval=0)
im, df = rescale(im, df, sz=(300, 300))
show(im, df=df, sz=20)
print(type(im))
df.head()
x y X Y text block_id
0 0.249538 0.253501 0.569316 0.305322 ConstITUtIO 0
1 0.288355 0.369748 0.401109 0.397759 NLTHE 1
2 0.402957 0.369748 0.510166 0.397759 PEOPLE 1
3 0.493530 0.371148 0.545287 0.394958 OF 1
4 0.548983 0.369748 0.630314 0.397759 INDIA, 1

<class 'PIL.Image.Image'>
text block_id x y X Y
0 ConstITUtIO 0 0.500000 0.326667 0.613333 0.440000
1 NLTHE 1 0.473333 0.383333 0.516667 0.426667
2 PEOPLE 1 0.506667 0.416667 0.550000 0.460000
3 OF 1 0.536667 0.446667 0.560000 0.470000
4 INDIA, 1 0.550000 0.460000 0.586667 0.493333