-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Browse files
Browse the repository at this point in the history
- Loading branch information
1 parent
6063523
commit 3bc44aa
Showing
56 changed files
with
6,936 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
from typing import List, Tuple | ||
|
||
|
||
class GeoLocalizator: | ||
def geo_localize(self, trees: List, coordenates: Tuple) -> List: | ||
""" | ||
Localize from Tree object List all them coordenates. | ||
:param List trees: The list with all trees to operate with. | ||
:param Tuple coordenates: The coordenates off the target image. | ||
:return: The list off all Trees with all coordenates calculated. | ||
""" | ||
self._coordenates = coordenates | ||
|
||
for tree in trees: | ||
x, y = self._calculate_coordenates(tree) | ||
tree.set_coordenates(x, y) | ||
|
||
return trees | ||
|
||
def _calculate_coordenates(self, tree: "Tree") -> Tuple: | ||
""" | ||
Localize Tree object with its coordenates. | ||
:param Tree tree: The Tree to work with. | ||
:return: The Tuple of GPS coordenates witch represent its center. | ||
""" | ||
x = None | ||
y = None | ||
return x, y |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
from typing import List | ||
|
||
import numpy as np | ||
import numpy.typing as npt | ||
|
||
from keras_retinanet import models | ||
from keras_retinanet.utils.gpu import setup_gpu | ||
from keras_retinanet.utils.image import preprocess_image, resize_image | ||
|
||
from .Tree import Tree | ||
|
||
|
||
class NeuralNetwork: | ||
def __init__(self, path_to_model: str, score: float = 0.5): | ||
""" | ||
Neural Network will use RetinaNet to detect trees. | ||
:param str path_to_model: The path where the model is stored. | ||
:param float score: Score of confidance. 0.5 by default. | ||
""" | ||
|
||
# select GPU | ||
gpu = 0 | ||
setup_gpu(gpu) | ||
|
||
# Load RetinaNet model | ||
self._model = models.load_model(path_to_model, backbone_name="resnet50") | ||
|
||
# Set score confidance | ||
self._score = score | ||
|
||
def detect_trees(self, img: npt.ArrayLike, row: int, col: int) -> List: | ||
""" | ||
Detect trees in sub-image. | ||
:param npt.ArrayLike img: The image where detection will be. Must be (400x400x3). | ||
:param int row: Padding row. | ||
:param int col: Padding col. | ||
:return: List with all detected trees. | ||
""" | ||
|
||
# Preprocess image | ||
image = preprocess_image(img) | ||
image, scale = resize_image(image) | ||
|
||
# Predict Trees | ||
boxes, scores, labels = self._model.predict_on_batch( | ||
np.expand_dims(image, axis=0) | ||
) | ||
|
||
# Scale boxes | ||
boxes /= scale | ||
|
||
# Generate Tree objects | ||
trees = [] | ||
for box, score, _ in zip(boxes[0], scores[0], labels[0]): | ||
# Boxes are sorted from 1->0 | ||
if score < 0.5: | ||
break | ||
|
||
box = box.astype(int) | ||
|
||
x1, y1, x2, y2 = box | ||
width = x2 - x1 | ||
height = y2 - y1 | ||
trees.append(Tree(y1 + row, x1 + col, width, height)) | ||
|
||
return trees |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
class Tree: | ||
def __init__(self, row: int, col: int, width: int, height: int): | ||
self._row = row | ||
self._col = col | ||
self._width = width | ||
self._height = height | ||
self._coordx = None | ||
self._coordy = None | ||
|
||
def set_coordenates(self, x: float, y: float): | ||
""" | ||
Set coordenates in Tree object. | ||
:param float x: x coordenate (West-East). | ||
:param float y: y coordenate (North-Sourth). | ||
""" | ||
self._coordx = x | ||
self._coordy = y |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,43 @@ | ||
from typing import List, Tuple | ||
|
||
import cv2 as cv | ||
import numpy as np | ||
import numpy.typing as npt | ||
|
||
|
||
class TreeDetector: | ||
def __init__(self, img): | ||
self.__img = cv.imread(img) | ||
def __init__(self, nn): | ||
""" | ||
TreeDetector constructor. | ||
:param NeuralNetwork nn: the neural network witch we will used. | ||
""" | ||
self._img = None | ||
self._coordenates = None | ||
self._nn = nn # Neural Network | ||
self._trees = [] | ||
|
||
def recognize(self, img: npt.ArrayLike, coordenates: Tuple) -> List: | ||
""" | ||
Recognize trees in image. | ||
def recognize(self): | ||
return "done" | ||
:param npt.ArrayLike img: The target image. | ||
:param tuple coordenates: The coordenates of the image. | ||
:return: the list with all detected trees. | ||
""" | ||
self._img = img | ||
self._slide() | ||
return self._trees | ||
|
||
def slide(self): | ||
return 400 | ||
def _slide(self): | ||
""" | ||
Iterates around the image and calls NN to detect trees in sub-image. | ||
""" | ||
STEP = 400 | ||
cols, rows = self._img.shape[:-1] | ||
for col in range(0, cols - STEP, STEP): | ||
for row in range(0, rows - STEP, STEP): | ||
trees = self._nn.detect_trees( | ||
self._img[row : row + STEP, col : col + STEP], row, col | ||
) | ||
self._trees.append(trees) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
from typing import List | ||
|
||
import cv2 as cv | ||
import numpy.typing as npt | ||
|
||
|
||
class TreePainter: | ||
def draw(self, canvas: npt.ArrayLike, trees: List): | ||
""" | ||
Draw all trees in image. | ||
:param npt.ArrayLike canvas: The image witch will be used as canvas. | ||
:param List trees: The list off all trees. | ||
""" | ||
|
||
for tree in trees: | ||
continue |
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
from .dynamic import * # noqa: F401,F403 | ||
from .common import * # noqa: F401,F403 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
""" | ||
Copyright 2017-2018 Fizyr (https://fizyr.com) | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
""" | ||
Copyright 2017-2018 Fizyr (https://fizyr.com) | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
""" | ||
|
||
import keras.backend | ||
from .dynamic import meshgrid | ||
|
||
|
||
def bbox_transform_inv(boxes, deltas, mean=None, std=None): | ||
""" Applies deltas (usually regression results) to boxes (usually anchors). | ||
Before applying the deltas to the boxes, the normalization that was previously applied (in the generator) has to be removed. | ||
The mean and std are the mean and std as applied in the generator. They are unnormalized in this function and then applied to the boxes. | ||
Args | ||
boxes : np.array of shape (B, N, 4), where B is the batch size, N the number of boxes and 4 values for (x1, y1, x2, y2). | ||
deltas: np.array of same shape as boxes. These deltas (d_x1, d_y1, d_x2, d_y2) are a factor of the width/height. | ||
mean : The mean value used when computing deltas (defaults to [0, 0, 0, 0]). | ||
std : The standard deviation used when computing deltas (defaults to [0.2, 0.2, 0.2, 0.2]). | ||
Returns | ||
A np.array of the same shape as boxes, but with deltas applied to each box. | ||
The mean and std are used during training to normalize the regression values (networks love normalization). | ||
""" | ||
if mean is None: | ||
mean = [0, 0, 0, 0] | ||
if std is None: | ||
std = [0.2, 0.2, 0.2, 0.2] | ||
|
||
width = boxes[:, :, 2] - boxes[:, :, 0] | ||
height = boxes[:, :, 3] - boxes[:, :, 1] | ||
|
||
x1 = boxes[:, :, 0] + (deltas[:, :, 0] * std[0] + mean[0]) * width | ||
y1 = boxes[:, :, 1] + (deltas[:, :, 1] * std[1] + mean[1]) * height | ||
x2 = boxes[:, :, 2] + (deltas[:, :, 2] * std[2] + mean[2]) * width | ||
y2 = boxes[:, :, 3] + (deltas[:, :, 3] * std[3] + mean[3]) * height | ||
|
||
pred_boxes = keras.backend.stack([x1, y1, x2, y2], axis=2) | ||
|
||
return pred_boxes | ||
|
||
|
||
def shift(shape, stride, anchors): | ||
""" Produce shifted anchors based on shape of the map and stride size. | ||
Args | ||
shape : Shape to shift the anchors over. | ||
stride : Stride to shift the anchors with over the shape. | ||
anchors: The anchors to apply at each location. | ||
""" | ||
shift_x = (keras.backend.arange(0, shape[1], dtype=keras.backend.floatx()) + keras.backend.constant(0.5, dtype=keras.backend.floatx())) * stride | ||
shift_y = (keras.backend.arange(0, shape[0], dtype=keras.backend.floatx()) + keras.backend.constant(0.5, dtype=keras.backend.floatx())) * stride | ||
|
||
shift_x, shift_y = meshgrid(shift_x, shift_y) | ||
shift_x = keras.backend.reshape(shift_x, [-1]) | ||
shift_y = keras.backend.reshape(shift_y, [-1]) | ||
|
||
shifts = keras.backend.stack([ | ||
shift_x, | ||
shift_y, | ||
shift_x, | ||
shift_y | ||
], axis=0) | ||
|
||
shifts = keras.backend.transpose(shifts) | ||
number_of_anchors = keras.backend.shape(anchors)[0] | ||
|
||
k = keras.backend.shape(shifts)[0] # number of base points = feat_h * feat_w | ||
|
||
shifted_anchors = keras.backend.reshape(anchors, [1, number_of_anchors, 4]) + keras.backend.cast(keras.backend.reshape(shifts, [k, 1, 4]), keras.backend.floatx()) | ||
shifted_anchors = keras.backend.reshape(shifted_anchors, [k * number_of_anchors, 4]) | ||
|
||
return shifted_anchors |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import os | ||
|
||
_BACKEND = "tensorflow" | ||
|
||
if "KERAS_BACKEND" in os.environ: | ||
_backend = os.environ["KERAS_BACKEND"] | ||
|
||
backends = { | ||
"cntk", | ||
"tensorflow", | ||
"theano" | ||
} | ||
|
||
assert _backend in backends | ||
|
||
_BACKEND = _backend | ||
|
||
if _BACKEND == "cntk": | ||
from .cntk_backend import * # noqa: F401,F403 | ||
elif _BACKEND == "theano": | ||
from .theano_backend import * # noqa: F401,F403 | ||
elif _BACKEND == "tensorflow": | ||
from .tensorflow_backend import * # noqa: F401,F403 | ||
else: | ||
raise ValueError("Unknown backend: " + str(_BACKEND)) |
Oops, something went wrong.