Python タイル マップの結合/画像の後処理 (2)

要件 背景 前回の記事からの続きPython タイルマップのダウンロード/マージ/描画/マーク

djangorestframeworkプログラムエントリ

path('api/v1/make_panorama_solar/', views.MakePanorama.as_view())

class MakePanorama(views.APIView):
    """
    @description  :光伏全景图制作
    ---------
    @param  :
    -------
    @Returns  :
    -------
    """
    permission_classes = (MyPermission,)		# 重点

    coreapi_fields_post = (
            DocParam(name="task_id", location='body', description='任务id'),
            DocParam(name="zone_id", location='body', description='区域id'),
        )
    
    def post(self, request):
        """
        @description  :光伏全景图制作
        ---------
        @params  :
        -------
        @Returns  :
        -------
        """
        context = {'code': codes.normal_code, 'msg': message.normal_code}
        task_id = str(request.data.get("task_id", ""))  # 任务id
        zone_id = str(request.data.get("zone_id", ""))  # zone_id
        zoom = int(request.data.get("zoom", 17))  # zone_id
        if zone_id:
            print(task_id, zone_id)
            result = tasks_make_panorama.make_panorama.delay(task_id, zone_id, zoom)
            # time.sleep(1)
            # print(result.get(propagate=False))
            status = result.ready()
            context["status"] = status
        else:
            context["code"] = codes.empty_param_code
            context["msg"] = message.empty_param_code
        return JsonResponse(context)

セロリタスクキューを使用してタイルイメージのスプライシング操作を実行する

@celery_app.task(time_limit=3600, name='make_panorama')  # 制作全景图
def make_panorama(task_id, zone_id, zoom):
    """
    @description  :制作全景图
    ---------
    @param  :
    -------
    @Returns  :
    -------
    """
    try:
        # 判断是否需要重新下载并合并瓦片图、判断minio里是否存在文件,一个区域共享一个全景图,每个任务有自己的全景图
        panorama_list = minio.bucket_list_files(settings.MINIO_PANORAMA_BUCKET, "/".join([settings.REPORT_SOLAR_PANORAMA_DIR, zone_id + f"_{zoom}.jpg"]))
        if len(panorama_list) > 0:
            print("exits panorama-get")
            image_obj = minio.download_file(settings.MINIO_PANORAMA_BUCKET, "/".join([settings.REPORT_SOLAR_PANORAMA_DIR, zone_id + f"_{zoom}.jpg"]))
        else:
            print("begin_make_panorama")
            start_time = time.time()
            left_top_x, left_top_y, right_buttom_x, right_buttom_y = get_zone_gps_max(zone_id)
            # print(float(left_top[0]), float(left_top[1]), float(right_buttom[0]), float(right_buttom[1]))
            # for zoom in range(zoom, zoom+1):
            image_obj = download_main(float(left_top_x), float(left_top_y),
                            float(right_buttom_x), float(right_buttom_y),
                            zoom, r'.\\Temp\\test-one.tif', server="xx",
                            style="xx_AREA:xx_super_hd", zone_id=zone_id)
            end_time = time.time()
            print('lasted a total of {:.2f} seconds'.format(end_time - start_time))
        print("end_make_tile,begin mark panel on the panorama")
        gen_panel_tiles_relations(zone_id, zoom)
        if task_id:
            mark_solar_report_panorama(image_obj, zone_id, task_id, zoom)
        else:
            print("no task info")
        return True
    except Exception as e:
        traceback.print_exc()

 タイル マップをダウンロードしてコードをマージする

def merge_tiles(results, zone_id, zoom):
    """
    @description  :合并瓦片图
    ---------
    @param  :
    -------
    @Returns  :
    -------
    """
    x_y = list(results.keys())
    x_l = sorted(list(set([str(i).split("_")[0] for i in x_y])))
    y_l = sorted(list(set([str(i).split("_")[1] for i in x_y])))
    # print("x_l:", x_l)
    # print("y_l:", y_l)
    new_image = Image.new('RGB', (len(x_l)*256, len(y_l)*256))
    for index, item in results.items():
        x_index, y_index = index.split("_")
        # print("x_l.index(x_index):", x_l.index(x_index))
        # print("y_l.index(y_index):", y_l.index(y_index))
        x_offset = x_l.index(x_index) * 256
        y_offset = y_l.index(y_index) * 256
        picio = io.BytesIO(item)
        item = Image.open(picio)
        new_image.paste(item, (x_offset, y_offset))
    # upload to minio server
    # file_size = len(new_image)
    imgByteArr = io.BytesIO()
    new_image.save(imgByteArr, format="JPEG")
    imgByteArr.seek(0)
    if minio.upload_file(settings.MINIO_PANORAMA_BUCKET, "/".join([settings.REPORT_SOLAR_PANORAMA_DIR, zone_id + f"_{zoom}.jpg"]), imgByteArr, len(imgByteArr.getvalue()), "application/octet-stream"):
        return imgByteArr.getvalue()
    else:
        print("upload_file_error")
        return False

def get_urls(x1, y1, x2, y2, z, source, style):
    """
    @description  :左上角x1,y1右下角x2,y2
    ---------
    @param  :
    -------
    @Returns  :
    -------
    """
    pos1x, pos1y = wgs_to_tile(x1, y1, z)  # 左上角的瓦片图坐标
    pos2x, pos2y = wgs_to_tile(x2, y2, z)
    print("pos1x, pos1y:", pos1x, pos1y)
    print("pos2x, pos2y:", pos2x, pos2y)
    lenx = abs(pos2x - pos1x) + 1
    leny = abs(pos2y - pos1y) + 1
    print("Total tiles number:{x} X {y}".format(x=lenx, y=leny))
    print("pos1y, pos1y + leny:", pos1y, pos1y + leny)
    print("pos1x, pos1x + lenx:", pos1x, pos1x + lenx)
    urls = [get_url(source, i, j, z, style) for j in range(pos1y, pos1y + leny) for i in range(pos1x, pos1x + lenx)]
    return urls

def download_tiles(urls, multi=1):
    """
    @description  :下载瓦片
    ---------
    @param  :
    -------
    @Returns  :
    -------
    """
    # url_len = len(urls)
    # datas = [None] * url_len
    datas = dict()
    if multi < 1 or multi > 20 or not isinstance(multi, int):
        raise Exception("multi of Downloader shuold be int and between 1 to 20.")
    tasks = [Downloader(i, multi, urls, datas) for i in range(multi)]
    for i in tasks:
        i.start()
    for i in tasks:
        i.join()
    return datas

def download_main(left, top, right, bottom, zoom, filePath, style='s', server="Google China", zone_id=""):
    """
    Download images based on spatial extent.

    East longitude is positive and west longitude is negative.
    North latitude is positive, south latitude is negative.

    Parameters
    ----------
    left, top : left-top coordinate, for example (100.361,38.866)
    right, bottom : right-bottom coordinate
    z : zoom
    filePath : File path for storing results, TIFF format
    style :
        m for map;
        s for satellite;
        y for satellite with label;
        t for terrain;
        p for terrain with label;
        h for label;
    source : Google China (default) or Google
    """
    # Get the urls of all tiles in the extent
    urls = get_urls(left, top, right, bottom, zoom, server, style)
    print("瓦片图总数:", len(urls))

    # Group URLs based on the number of CPU cores to achieve roughly equal amounts of tasks
    urls_group = [urls[i:i + math.ceil(len(urls) / 2)] for i in
                  range(0, len(urls), math.ceil(len(urls) / 2))]
    # urls_group = [urls[i:i + math.ceil(len(urls) / multiprocessing.cpu_count())] for i in
    #               range(0, len(urls), math.ceil(len(urls) / multiprocessing.cpu_count()))]
    print(urls_group)
    # return False
    # Each set of URLs corresponds to a process for downloading tile maps
    print('Tiles downloading......瓦片图下载中')
    # results = []
    pool = multiprocessing.Pool(2)
    # pool = multiprocessing.Pool(multiprocessing.cpu_count())
    print("cpu_count:", multiprocessing.cpu_count())
    print("pool", pool)
    results = pool.map(download_tiles, urls_group)
    pool.close()
    pool.join()
    print("results:", type(results[0]))
    # print("results:", list(results)[0])
    # 单排从上至下排列
    results = dict(sorted([i for j in results for i in j.items()], key=lambda x: x[0]))
    print('Tiles download complete 瓦片图 下载成功')
    image_obj = merge_tiles(results, zone_id, zoom)
    return image_obj

 タイル画像をダウンロードして結合するコードが完成しました。あとは画像上に枠をマークするなど、opencvで行えます。

おすすめ

転載: blog.csdn.net/xiaofeixia666888/article/details/130887733