Skip to content

Commit a28b766

Browse files
authored
Merge pull request #5 from fuzailpalnak/feature/split-n-stich-georeference
stitch and split
2 parents 72ea982 + 0b7e00f commit a28b766

File tree

3 files changed

+182
-5
lines changed

3 files changed

+182
-5
lines changed

README.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,29 @@ GTKit's modular structure allows you to import specific functionalities as neede
8787
</tr>
8888
</table>
8989

90+
### Stitch And Split Geo Reference Image
91+
```python
92+
import numpy as np
93+
94+
from gtkit.imgops import georead, geowrite
95+
from gtkit.imgops import StitchNSplitGeo
96+
97+
sns = StitchNSplitGeo(split_size=(256, 256, 3), img_size=(1500, 1500, 3))
98+
image = georead(r"22978945_15.tiff")
99+
100+
stitched_image = np.zeros((1500, 1500, 3))
101+
for win_number, window in sns:
102+
split_image, meta = sns.split(image, window)
103+
# ....Processing on image
104+
stitched_image = sns.stitch(split_image, stitched_image, window)
105+
106+
geowrite(
107+
save_path=r"new.tiff",
108+
image=stitched_image,
109+
transform=image.transform,
110+
crs=image.crs,
111+
)
112+
```
90113
## Documentation
91114

92115
For detailed information on available methods, classes, and their usage, refer to the [GTKit Documentation](https://gtkit.readthedocs.io).

gtkit/imgops.py

Lines changed: 156 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,167 @@
55
import cv2
66
import numpy as np
77
import rasterio
8+
from image_fragment.fragment import Fragment, ImageFragment
89
from osgeo import gdal, osr
910
from rasterio.features import shapes
1011
from rasterio.io import BufferedDatasetWriter, DatasetWriter
1112
from shapely.geometry import shape
1213

14+
from gtkit.imutils import get_pixel_resolution, get_affine_transform
1315
from gtkit.mesh import create_mesh_using_img_param
1416

1517

18+
class StitchNSplit:
19+
"""
20+
Class for splitting images into smaller fragments.
21+
22+
Attributes:
23+
split_size (tuple): Size of the fragments to split the image into.
24+
img_size (tuple): Size of the original image.
25+
image_fragment (ImageFragment): Image fragment object for managing fragments.
26+
"""
27+
28+
def __init__(self, split_size: tuple, img_size: tuple):
29+
"""
30+
Initialize the Split class.
31+
32+
Parameters:
33+
split_size (tuple): Size of the fragments to split the image into.
34+
img_size (tuple): Size of the original image.
35+
36+
Raises:
37+
ValueError: If the split size is greater than the image size.
38+
"""
39+
40+
if split_size[0] > img_size[0] or split_size[1] > img_size[1]:
41+
raise ValueError(
42+
"Size to Split Can't Be Greater than Image, Given {},"
43+
" Expected <= {}".format(split_size, (img_size[0], img_size[1]))
44+
)
45+
self.split_size = split_size
46+
self.img_size = img_size
47+
48+
self.image_fragment = ImageFragment.image_fragment_3d(
49+
fragment_size=self.split_size, org_size=self.img_size
50+
)
51+
52+
def __len__(self):
53+
"""
54+
Get the number of fragments.
55+
56+
Returns:
57+
int: Number of fragments.
58+
"""
59+
60+
return len(self.image_fragment.collection)
61+
62+
def __getitem__(self, index):
63+
"""
64+
Get a fragment by index.
65+
66+
Parameters:
67+
index (int): Index of the fragment.
68+
69+
Returns:
70+
tuple: Index and the corresponding fragment.
71+
"""
72+
return index, self.image_fragment.collection[index]
73+
74+
def split(
75+
self, image: Union[BufferedDatasetWriter, DatasetWriter], fragment: Fragment
76+
):
77+
"""
78+
Split the image using a windowing approach.
79+
80+
Parameters:
81+
image (rasterio.io.DatasetReader): Input image dataset reader object.
82+
fragment (Fragment): Fragment object specifying the region of interest.
83+
84+
Returns:
85+
tuple: A tuple containing the extracted image data and additional keyword arguments.
86+
"""
87+
raise NotImplementedError
88+
89+
def stitch(self, image: np.ndarray, stitched_image: np.ndarray, fragment: Fragment):
90+
"""
91+
Stitch an image fragment onto a larger stitched image.
92+
93+
This method transfers the data from the provided image fragment onto the specified location
94+
in the larger stitched image.
95+
96+
Parameters:
97+
image (np.ndarray): The image fragment data to be stitched onto the larger image.
98+
stitched_image (np.ndarray): The larger stitched image onto which the fragment will be stitched.
99+
fragment (Fragment): The fragment specifying the region in the larger image where the fragment will be placed.
100+
101+
Returns:
102+
np.ndarray: The stitched image with the fragment transferred onto it.
103+
"""
104+
raise NotImplementedError
105+
106+
107+
class StitchNSplitGeo(StitchNSplit):
108+
"""
109+
Subclass of Split specialized for geospatial image splitting.
110+
"""
111+
112+
def __init__(self, split_size: tuple, img_size: tuple):
113+
"""
114+
Initialize the SplitGeo class.
115+
116+
Parameters:
117+
split_size (tuple): Size of the fragments to split the image into.
118+
img_size (tuple): Size of the original image.
119+
"""
120+
super().__init__(split_size, img_size)
121+
122+
def split(
123+
self, image: Union[BufferedDatasetWriter, DatasetWriter], fragment: Fragment
124+
) -> (np.ndarray, dict):
125+
"""
126+
Internal method to extract data from a fragment of a geospatial image.
127+
128+
Parameters:
129+
image (rasterio.io.DatasetReader): Input image dataset reader object.
130+
fragment (Fragment): Fragment object specifying the region of interest.
131+
132+
Returns:
133+
tuple: A tuple containing the extracted image data and additional keyword arguments.
134+
"""
135+
136+
split_image = image.read(window=fragment.position)
137+
138+
kwargs_split_image = image.meta.copy()
139+
kwargs_split_image.update(
140+
{
141+
"height": self.split_size[0],
142+
"width": self.split_size[1],
143+
"transform": image.window_transform(fragment.position),
144+
}
145+
)
146+
147+
return split_image.swapaxes(0, 1).swapaxes(1, 2), kwargs_split_image
148+
149+
def stitch(self, image: np.ndarray, stitched_image: np.ndarray, fragment: Fragment):
150+
"""
151+
Stitch an image fragment onto a larger stitched image.
152+
153+
This method transfers the data from the provided image fragment onto the specified location
154+
in the larger stitched image.
155+
156+
Parameters:
157+
image (np.ndarray): The image fragment data to be stitched onto the larger image.
158+
stitched_image (np.ndarray): The larger stitched image onto which the fragment will be stitched.
159+
fragment (Fragment): The fragment specifying the region in the larger image where the fragment will be placed.
160+
161+
Returns:
162+
np.ndarray: The stitched image with the fragment transferred onto it.
163+
"""
164+
return fragment.transfer_fragment(
165+
transfer_from=image, transfer_to=stitched_image
166+
)
167+
168+
16169
@dataclass
17170
class Bitmap:
18171
"""
@@ -121,8 +274,9 @@ def geowrite(
121274
transform (affine.Affine): The affine transformation matrix.
122275
crs (str)
123276
"""
277+
assert image.ndim == 3, f"Input Image must of shape HxWxC"
278+
bands = image.shape[-1]
124279

125-
bands = 1 if image.ndim == 2 else image.shape[-1]
126280
with rasterio.open(
127281
save_path,
128282
"w",
@@ -134,7 +288,7 @@ def geowrite(
134288
transform=transform,
135289
crs=crs,
136290
) as dst:
137-
dst.write(image, indexes=1)
291+
dst.write(np.rollaxis(image, axis=2))
138292

139293

140294
def georead(

setup.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,13 @@
1414

1515
setup(
1616
name="gtkit",
17-
version="0.1.0",
17+
version="0.1.1",
1818
author="Fuzail Palnak",
1919
author_email="fuzailpalnak@gmail.com",
2020
url="https://github.com/fuzailpalnak/gtkit",
2121
description="A library designed to streamline GIS (Geographic Information System) related tasks."
22-
" Whether it is geometry, GeoDataFrames, images, or mathematical operations, "
23-
"GTKit provides a set of commonly used methods and operations to simplify your workflow.",
22+
" Whether it is geometry, GeoDataFrames, images, or mathematical operations, "
23+
"GTKit provides a set of commonly used methods and operations to simplify your workflow.",
2424
long_description=long_description,
2525
long_description_content_type="text/markdown",
2626
packages=find_packages(),

0 commit comments

Comments
 (0)