image_service_edit.py 10.4 KB
# coding=utf-8
#author:        4N
#createtime:    2021/7/19
#email:         nheweijun@sina.com


from app.util.component.ApiTemplate import ApiTemplate
from ..models import Service,ImageService,Image,db,ServiceFunction,TileScheme
import datetime
import json
import configure
import uuid
import os
import cv2
import numpy
import random
from kazoo.client import KazooClient
from .util.ImageData import ImageData
from .util.MyThread import MyThread
from app.util.component.ModelVisitor import ModelVisitor
class Api(ApiTemplate):

    api_name = "修改影像服务"

    def process(self):

        # 返回结果
        res = {}

        try:

            guid = self.para.get("guid")
            service = Service.query.filter_by(guid=guid)
            this_time = datetime.datetime.now()
            image_guids = self.para.get("image_guids")
            functions = self.para.get("functions")

            service_update = {}
            image_update = {}

            for key in self.para.keys():
                if key in ["name","title","state","description","catalog_guid"]:
                    service_update[key] = self.para.get(key)
                if key in ["name","scheme_guid"]:
                    image_update[key] = self.para.get(key)

            #修改切片方案的处理
            if self.para.get("scheme_guid"):
                tilesche = TileScheme.query.filter_by(guid=self.para.get("scheme_guid")).one_or_none()
                image_update["scheme"] = json.dumps(ModelVisitor.object_to_json(tilesche))

            image_service = ImageService.query.filter_by(service_guid=guid)

            # 修改功能
            if functions:
                new_types = functions.split(",")
                old_functions = ServiceFunction.query.filter_by(service_guid=guid).all()
                for function in old_functions:
                    if function.type not in new_types:
                        db.session.delete(function)
                for new_type in new_types:
                    if new_type not in [fun.type for fun in old_functions]:
                        service_function = ServiceFunction(guid=uuid.uuid1().__str__(),type=new_type,
                                                           service_guid=guid)
                        db.session.add(service_function)

            #修改影像
            image_service_exetent = []
            if image_guids:
                imgservice:ImageService = image_service.one_or_none()
                imgservice.images = []

                for g in image_guids.split(","):
                    image = Image.query.filter_by(guid=g).one_or_none()
                    if image:
                        image_extent = json.loads(image.extent)
                        if not image_service_exetent:
                            image_service_exetent = image_extent
                        else:
                            image_service_exetent[0] = min(image_extent[0], image_service_exetent[0])
                            image_service_exetent[1] = min(image_extent[1], image_service_exetent[1])
                            image_service_exetent[2] = max(image_extent[2], image_service_exetent[2])
                            image_service_exetent[3] = max(image_extent[3], image_service_exetent[3])
                        imgservice.images.append(image)
                    image_update["extent"] = json.dumps(image_service_exetent)

            if image_update:
                image_service.update(image_update)

            if service_update or image_update or functions:
                service_update["update_time"] = this_time

                if image_guids:
                    overview_file = self.get_overview(image_guids,image_service_exetent)
                    service_update["overview"] = "http://{}/API/Service/Overview/{}".format(configure.deploy_ip_host, overview_file)

                service.update(service_update)

            db.session.commit()
            res["result"] = True

        except Exception as e:
            db.session.rollback()
            raise e

        return res

    def get_overview(self,guids,image_service_exetent):
        from app import GLOBAL_DIC

        intersect_image =  Image.query.filter(Image.guid.in_(guids.split(","))).all()
        query_extent = image_service_exetent

        if query_extent[2] - query_extent[0] > query_extent[3] - query_extent[1]:
            offset = ((query_extent[2] - query_extent[0]) - (query_extent[3] - query_extent[1])) / 2.0
            query_extent = [query_extent[0], query_extent[1] - offset, query_extent[2],
                            query_extent[3] + offset]
        else:
            offset = ((query_extent[3] - query_extent[1]) - (query_extent[2] - query_extent[0])) / 2.0
            query_extent = [query_extent[0] - offset, query_extent[1], query_extent[2] + offset,
                            query_extent[3]]

        height = 512
        width = 512


        # 缓存zookeeper
        zoo = GLOBAL_DIC.get("zookeeper")
        if zoo is None:
            zoo: KazooClient = KazooClient(hosts=configure.zookeeper, timeout=100)
            zoo.start()
            GLOBAL_DIC["zookeeper"] = zoo
        else:
            if not zoo.connected:
                zoo.start()

        servers = GLOBAL_DIC.get("servers")
        if servers is None:
            servers = zoo.get_children("/rpc")
            servers.append("本地服务器")
            GLOBAL_DIC["servers"] = servers
        else:
            servers = GLOBAL_DIC.get("servers")


        if len(intersect_image) > 1:

            # 结果矩阵
            empty_list = [numpy.zeros((height, width), dtype=int) + 65536,
                          numpy.zeros((height, width), dtype=int) + 65536,
                          numpy.zeros((height, width), dtype=int) + 65536]

            pixel_array = numpy.zeros((height, width, 3), dtype=int)
            thread_list = []

            for image in intersect_image:
                # 该影像的服务器,随机选取一个
                image_servers = image.server.split(",")
                image_servers = [ser for ser in image_servers if ser in servers]
                if len(image_servers) > 0:
                    indx = int(random.random() * len(image_servers))
                    image_server = image_servers[indx]
                else:
                    image_server = "None"
                bands = json.loads(image.band_view)

                image_data = ImageData(image_server, ModelVisitor.object_to_json(image))

                thread: MyThread = MyThread(image_data.get_data, args=(query_extent, bands, height, width))
                thread.start()
                thread_list.append(thread)

            for thread in thread_list:
                thread.join()
                data = thread.get_result()

                # 掩膜在中央接口生成,合图
                mask = numpy.zeros((height, width), dtype=int)
                mask2 = numpy.zeros((height, width), dtype=int)
                jizhun = data[:, :, 0]
                mask[jizhun == 65536] = 1
                mask[jizhun != 65536] = 0
                mask2[jizhun == 65536] = 0
                mask2[jizhun != 65536] = 1
                # 掩膜计算
                for i, d in enumerate(empty_list):
                    empty_list[i] = empty_list[i] * mask + data[:, :, i] * mask2

            for ii in [0, 1, 2]:
                # opencv 颜色排序为GBR
                pixel_array[:, :, 2 - ii] = empty_list[ii]


        elif len(intersect_image) == 1:
            # 该影像的服务器,随机选取一个
            image = intersect_image[0]
            image_servers = image.server.split(",")
            image_servers = [ser for ser in image_servers if ser in servers]
            if len(image_servers) > 0:
                indx = int(random.random() * len(image_servers))
                image_server = image_servers[indx]
            else:
                image_server = "None"

            bands = json.loads(image.band_view)

            image_data = ImageData(image_server,ModelVisitor.object_to_json(image))

            pixel_array_t = image_data.get_data(query_extent, bands, height, width)

            pixel_array = numpy.zeros((height, width, 3), dtype=int)
            for ii in [0, 1, 2]:
                # opencv 颜色排序为GBR
                pixel_array[:, :, 2 - ii] = pixel_array_t[:, :, ii]
        else:
            # 结果矩阵
            pixel_array = numpy.zeros((height, width, 3), dtype=int) + 65536

        dir_path = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), "overview")
        gid = uuid.uuid1().__str__()
        store_file = os.path.join(dir_path, "{}.jpg".format(gid))
        cv2.imwrite(store_file, pixel_array, [cv2.IMWRITE_JPEG_QUALITY, 30])

        return "{}.jpg".format(gid)

    api_doc = {
        "tags": ["影像接口"],
        "parameters": [

            {"name": "guid",
             "in": "formData",
             "type": "string",
             "description": "[地图服务,切片服务,影像服务]guid"},

            {"name": "name",
             "in": "formData",
             "type": "string",
             "description": "[地图服务,切片服务,影像服务]"},


            {"name": "title",
             "in": "formData",
             "type": "string",
             "description": "[地图服务,切片服务,影像服务]"},
            {"name": "description",
             "in": "formData",
             "type": "string",
             "description": "[地图服务,切片服务,影像服务]"},

            {"name": "catalog_guid",
             "in": "formData",
             "type": "string",
             "description": "[地图服务,切片服务,影像服务]"},

            {"name": "functions",
             "in": "formData",
             "type": "string",
             "description": "[地图服务,切片服务,影像服务]以逗号相隔,可选WMTS,WMS"},


            {"name": "image_guids",
             "in": "formData",
             "type": "string","description":"修改该服务的影像,用逗号相隔"},
        ],
        "responses": {
            200: {
                "schema": {
                    "properties": {
                    }
                }
            }
        }
    }