Ejemplo n.º 1
0
class FittingBbox:
    def __init__(self, zoom_level=19):
        self._mercator = GlobalMercator()
        self._zoom_level = zoom_level

    def get(self, bbox):
        t_minx, t_miny, t_maxx, t_maxy = self.bbox_to_tiles(bbox)
        bbox = self._bbox_from(t_minx, t_miny, t_maxx, t_maxy)
        return bbox

    def bbox_to_tiles(self, bbox):
        m_minx, m_miny = self._mercator.LatLonToMeters(bbox.bottom, bbox.left)
        m_maxx, m_maxy = self._mercator.LatLonToMeters(bbox.top, bbox.right)
        t_maxx, t_maxy = self._mercator.MetersToTile(m_maxx, m_maxy,
                                                     self._zoom_level)
        t_minx, t_miny = self._mercator.MetersToTile(m_minx, m_miny,
                                                     self._zoom_level)
        return t_minx, t_miny, t_maxx, t_maxy

    def generate_bbox(self, tx, ty):
        bottom, left, top, right = self._mercator.TileLatLonBounds(
            tx, ty, self._zoom_level)
        bbox = Bbox.from_lbrt(left, bottom, right, top)
        return bbox

    def _bbox_from(self, t_minx, t_miny, t_maxx, t_maxy):
        bottom, left, _, _ = self._mercator.TileLatLonBounds(
            t_minx, t_miny, self._zoom_level)
        _, _, top, right = self._mercator.TileLatLonBounds(
            t_maxx, t_maxy, self._zoom_level)
        return Bbox.from_lbrt(left, bottom, right, top)
Ejemplo n.º 2
0
class Manager:
    def __init__(self, bbox=None, configuration=None, standalone=False):
        self.standalone = standalone
        self.big_bbox = bbox
        self.job_queue_name = 'jobs'
        self.mercator = GlobalMercator()
        self.small_bboxes = []
        self.configuration = configuration

    def run(self):
        self._generate_small_bboxes()
        if not self.standalone:
            self._enqueue_jobs(self.configuration)
        else:
            worker_functions.standalone(bboxes=self.small_bboxes, configuration=self.configuration)

    def _generate_small_bboxes(self):
        m_minx, m_miny = self.mercator.LatLonToMeters(self.big_bbox.bottom, self.big_bbox.left)
        rows = self._calc_rows()
        columns = self._calc_columns()
        side = int(self.configuration.JOB.bboxsize)

        for x in range(0, columns):
            for y in range(0, rows):
                bottom, left = self.mercator.MetersToLatLon(m_minx + (side * x), m_miny + (side * y))
                top, right = self.mercator.MetersToLatLon(m_minx + (side * (x + 1)), m_miny + (side * (y + 1)))
                small_bbox = Bbox(left=left, bottom=bottom, right=right, top=top)
                self.small_bboxes.append(small_bbox)

    def _enqueue_jobs(self, configuration):
        redis_connection = Redis(host=configuration.REDIS.server, port=configuration.REDIS.port, password=configuration.REDIS.password)
        queue = Queue(self.job_queue_name, connection=redis_connection)
        for small_bbox in self.small_bboxes:
            queue.enqueue_call(func=worker_functions.detect, args=(small_bbox, self.configuration),
                               timeout=self.configuration.JOB.timeout)
        print('Number of enqueued jobs in queue \'{0}\': {1}'.format(self.job_queue_name, len(queue)))

    def _calc_rows(self):
        _, m_miny = self.mercator.LatLonToMeters(self.big_bbox.bottom, self.big_bbox.left)
        _, m_maxy = self.mercator.LatLonToMeters(self.big_bbox.top, self.big_bbox.right)
        meter_in_y = m_maxy - m_miny
        return int(math.ceil(meter_in_y / int(self.configuration.JOB.bboxsize)))

    def _calc_columns(self):
        m_min_x, _ = self.mercator.LatLonToMeters(self.big_bbox.bottom, self.big_bbox.left)
        m_max_x, _ = self.mercator.LatLonToMeters(self.big_bbox.top, self.big_bbox.right)
        meter_in_x = m_max_x - m_min_x
        return int(math.ceil(meter_in_x / int(self.configuration.JOB.bboxsize)))
Ejemplo n.º 3
0
class WmsApi:
    def __init__(self, zoom_level=19):
        self.config = self._read_wms_config()
        self.auth = self.set_auth()
        self.zoom_level = zoom_level
        self._auth_monkey_patch(self.auth)
        self.mercator = GlobalMercator()

        from owslib.wms import WebMapService
        self.wms = WebMapService(url=self.config.get(section='WMS',
                                                     option='Url'),
                                 version=self.config.get(section='WMS',
                                                         option='Version'))

    def set_auth(self):
        user = self.config.get(section='CREDENTIALS',
                               option='NtlmUser',
                               fallback=None)
        password = self.config.get(section='CREDENTIALS',
                                   option='NtlmPassword',
                                   fallback=None)
        return HttpNtlmAuth(
            user,
            password) if user is not None and password is not None else None

    def _read_wms_config(self):
        current_directory = os.path.dirname(os.path.abspath(__file__))
        config_file = os.path.join(current_directory, 'wms.ini')
        config = configparser.ConfigParser()
        if not os.path.isfile(config_file):
            raise Exception("The WMS config file does not exist! " +
                            config_file)
        config.read(config_file)
        self.check_wms_config_fields(config)
        return config

    @staticmethod
    def _auth_monkey_patch(auth):
        AuthMonkeyPatch(auth)

    def get_image(self, bbox):
        bbox_ = self._box(bbox)
        bbox_ = self.mercator.LatLonToMeters(
            bbox_[3], bbox_[0]) + self.mercator.LatLonToMeters(
                bbox_[1], bbox_[2])
        size = self._calculate_image_size(bbox, self.zoom_level)
        image = self._get(
            layers=[self.config.get(section='WMS', option='Layer')],
            srs=self.config.get(section='WMS', option='Srs'),
            bbox=bbox_,
            size=size,
            format='image/jpeg',
        )
        return image

    def get_image_size(self, bbox):
        return self._calculate_image_size(bbox, self.zoom_level)

    @staticmethod
    def _calculate_image_size(bbox, zoom_level):
        meters_per_pixel = geo_helper.meters_per_pixel(zoom_level, bbox.bottom)
        width_meter = bbox.node_left_down().get_distance_in_meter(
            bbox.node_right_down())
        height_meter = bbox.node_left_down().get_distance_in_meter(
            bbox.node_left_up())
        height = int(height_meter / meters_per_pixel)
        width = int(width_meter / meters_per_pixel)
        return width, height

    def _get(self, **kwargs):
        img = self.wms.getmap(**kwargs)
        return Image.open(BytesIO(img.read()))

    @staticmethod
    def _box(bbox):
        node_left_down = bbox.node_left_down()
        node_right_up = bbox.node_right_up()
        return node_left_down.longitude, node_left_down.latitude, node_right_up.longitude, node_right_up.latitude

    @staticmethod
    def check_wms_config_fields(config):
        if not config.has_section('WMS'):
            raise Exception("Section 'WMS' is not in WMS config file!")
        if not config.has_option('WMS', 'Url'):
            raise Exception("'Url' is not in 'WMS' section!")
        if not config.has_option('WMS', 'Srs'):
            raise Exception("'Srs' is not in 'WMS' section!")
        if not config.has_option('WMS', 'Version'):
            raise Exception("'Version' is not in 'WMS' section!")
        if not config.has_option('WMS', 'Layer'):
            raise Exception("'Layer' is not in 'WMS' section!")
Ejemplo n.º 4
0
class OtherApi:
    def __init__(self, zoom_level=19):
        self._mercator = GlobalMercator()
        self._zoom_level = zoom_level
        self.tile = None

    def get_image(self, bbox):
        t_minx, t_miny, t_maxx, t_maxy = self._bbox_to_tile_indexes(bbox)
        images = self._download_images(t_minx, t_miny, t_maxx, t_maxy)
        image_matrix = self._to_image_matrix(images, t_minx, t_miny, t_maxx, t_maxy)
        image = self._to_image(image_matrix)
        big_bbox = self._generate_bbox(t_minx, t_miny, t_maxx, t_maxy)
        self.tile = Tile(image, big_bbox)
        return self._crop(self.tile, bbox)

    @staticmethod
    def _to_image_matrix(images, t_minx, t_miny, t_maxx, t_maxy):
        image_matrix = []
        row = 0
        url_number = 0
        for ty in range(t_miny, t_maxy + 1):
            image_matrix.append([])
            for tx in range(t_minx, t_maxx + 1):
                image = images[url_number]
                image_matrix[row].append(image)
                url_number += 1
            row += 1
        return image_matrix

    def _download_images(self, t_minx, t_miny, t_maxx, t_maxy):
        url_builder = UrlBuilder(self._zoom_level)
        urls = url_builder.get_urls_by_tiles(t_minx, t_miny, t_maxx, t_maxy)
        loader = MultiLoader(urls)
        loader.download()
        return loader.results

    @staticmethod
    def _to_image(image_matrix):
        num_rows = len(image_matrix)
        num_cols = len(image_matrix[0])
        width, height = image_matrix[0][0].size

        result = Image.new("RGB", (num_cols * width, num_rows * height))

        for y in range(0, num_rows):
            for x in range(0, num_cols):
                result.paste(image_matrix[y][x], (x * width, (num_rows - 1 - y) * height))
        return result

    def _bbox_to_tile_indexes(self, bbox):
        m_minx, m_miny = self._mercator.LatLonToMeters(bbox.bottom, bbox.left)
        m_maxx, m_maxy = self._mercator.LatLonToMeters(bbox.top, bbox.right)
        t_maxx, t_maxy = self._mercator.MetersToTile(m_maxx, m_maxy, self._zoom_level)
        t_minx, t_miny = self._mercator.MetersToTile(m_minx, m_miny, self._zoom_level)
        return t_minx, t_miny, t_maxx, t_maxy

    def _generate_bbox(self, t_minx, t_miny, t_maxx, t_maxy):
        bottom, left, _, _ = self._mercator.TileLatLonBounds(t_minx, t_miny, self._zoom_level)
        _, _, top, right = self._mercator.TileLatLonBounds(t_maxx, t_maxy, self._zoom_level)
        return Bbox(left=left, bottom=bottom, right=right, top=top)

    @staticmethod
    def _crop(tile, bbox):
        left, bottom = tile.get_pixel(bbox.node_left_down())
        right, top = tile.get_pixel(bbox.node_right_up())
        box = (left, top, right, bottom)
        cropped_image = tile.image.crop(box)
        image = Image.frombytes(mode='RGB', data=cropped_image.tobytes(), size=cropped_image.size)
        return image
Ejemplo n.º 5
0
class Manager(object):
    small_bbox_side_length = 2000.0
    timeout = 5400

    def __init__(self, bbox, job_queue_name, search=None):
        self.big_bbox = bbox
        self.job_queue_name = job_queue_name
        self.mercator = GlobalMercator()
        self.small_bboxes = []
        self.search = self._search(search)

    @classmethod
    def from_big_bbox(cls, big_bbox, redis, job_queue_name, search=None):
        manager = cls(big_bbox, job_queue_name, cls._search(search))
        manager._generate_small_bboxes()
        manager._enqueue_jobs(redis)
        return manager

    def _generate_small_bboxes(self):
        m_minx, m_miny = self.mercator.LatLonToMeters(self.big_bbox.bottom,
                                                      self.big_bbox.left)
        rows = self._calc_rows()
        columns = self._calc_columns()
        side = Manager.small_bbox_side_length

        for x in range(0, columns):
            for y in range(0, rows):
                bottom, left = self.mercator.MetersToLatLon(
                    m_minx + (side * x), m_miny + (side * y))
                top, right = self.mercator.MetersToLatLon(
                    m_minx + (side * (x + 1)), m_miny + (side * (y + 1)))
                small_bbox = Bbox.from_lbrt(left, bottom, right, top)
                self.small_bboxes.append(small_bbox)

    def _enqueue_jobs(self, redis):
        redis_connection = Redis(redis[0], redis[1], password=redis[2])
        queue = Queue(self.job_queue_name, connection=redis_connection)
        for small_bbox in self.small_bboxes:
            queue.enqueue_call(func=detect,
                               args=(small_bbox, redis, self.search),
                               timeout=Manager.timeout)
        print('Number of enqueued jobs in queue \'{0}\': {1}'.format(
            self.job_queue_name, len(queue)))

    def _calc_rows(self):
        _, m_miny = self.mercator.LatLonToMeters(self.big_bbox.bottom,
                                                 self.big_bbox.left)
        _, m_maxy = self.mercator.LatLonToMeters(self.big_bbox.top,
                                                 self.big_bbox.right)
        meter_in_y = m_maxy - m_miny
        return int(math.ceil(meter_in_y / Manager.small_bbox_side_length))

    def _calc_columns(self):
        m_min_x, _ = self.mercator.LatLonToMeters(self.big_bbox.bottom,
                                                  self.big_bbox.left)
        m_max_x, _ = self.mercator.LatLonToMeters(self.big_bbox.top,
                                                  self.big_bbox.right)
        meter_in_x = m_max_x - m_min_x
        return int(math.ceil(meter_in_x / Manager.small_bbox_side_length))

    @staticmethod
    def _search(search):
        return Search() if search is None else search