需求背景接上一篇文章python瓦片图下载/合并/绘图/标记_风一样的男子&的博客-CSDN博客
django restframework 程序入口
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任务队列来执行拼接瓦片图操作
@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就可以做了