Skip to content

Commit

Permalink
Se añaden las clases a falta de hacerlas funcionales #8 #9
Browse files Browse the repository at this point in the history
  • Loading branch information
PabloAsensio committed Apr 14, 2021
1 parent 6063523 commit 3bc44aa
Show file tree
Hide file tree
Showing 56 changed files with 6,936 additions and 6 deletions.
30 changes: 30 additions & 0 deletions src/GeoLocalizator.py
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
68 changes: 68 additions & 0 deletions src/NeuralNetwork.py
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
18 changes: 18 additions & 0 deletions src/Tree.py
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
43 changes: 37 additions & 6 deletions src/TreeDetector.py
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)
17 changes: 17 additions & 0 deletions src/TreePainter.py
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 added src/__init__.py
Empty file.
Empty file added src/keras_retinanet/__init__.py
Empty file.
2 changes: 2 additions & 0 deletions src/keras_retinanet/backend/__init__.py
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
15 changes: 15 additions & 0 deletions src/keras_retinanet/backend/cntk_backend.py
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.
"""
85 changes: 85 additions & 0 deletions src/keras_retinanet/backend/common.py
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
25 changes: 25 additions & 0 deletions src/keras_retinanet/backend/dynamic.py
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))
Loading

0 comments on commit 3bc44aa

Please sign in to comment.