203 lines
7.1 KiB
Python
203 lines
7.1 KiB
Python
#!/usr/bin/env python
|
||
# -*- coding: utf-8 -*-
|
||
"""
|
||
@project:
|
||
@File : 从合成里边提取剩余屋顶并计算潜力
|
||
@Author : qiqq
|
||
@create_time : 2023/11/6 15:29
|
||
"""
|
||
import os
|
||
from tqdm import tqdm
|
||
from collections import namedtuple
|
||
from PIL import Image
|
||
import numpy as np
|
||
import cv2
|
||
import random
|
||
|
||
|
||
|
||
def generate_random_colors(n):
|
||
Cls = namedtuple('cls', ['name', 'id', 'color'])
|
||
colors = [
|
||
Cls('backgroud', 0, (0, 0, 0))
|
||
]
|
||
while len(colors) < n:
|
||
# 随机生成一个元组,元组中每个值在 0-255 之间
|
||
color = Cls("roof"+str(len(colors)),len(colors),tuple(random.randint(0, 255) for _ in range(3)))
|
||
colors.append(color)
|
||
return list(colors)
|
||
|
||
|
||
def get_putpalette(Clss, color_other=[0, 0, 0]):
|
||
'''
|
||
灰度图转8bit彩色图
|
||
:param Clss:颜色映射表
|
||
:param color_other:其余颜色设置
|
||
:return:
|
||
'''
|
||
putpalette = []
|
||
for cls in Clss:
|
||
putpalette += list(cls.color)
|
||
putpalette += color_other * (255 - len(Clss))
|
||
return putpalette
|
||
|
||
|
||
|
||
##chatgpt的代码二值图像连通区域分析与标记算法
|
||
def connected_component_analysis(binary_image):
|
||
# 使用findContours函数查找连通区域
|
||
contours, _ = cv2.findContours(binary_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) #最合适的一个
|
||
|
||
|
||
# 对每个连通区域进行标记
|
||
labeled_image = np.zeros_like(binary_image, dtype=np.uint16)
|
||
for i, contour in enumerate(contours):
|
||
cv2.drawContours(labeled_image, [contour], -1, i + 1, -1)
|
||
|
||
# 统计连通区域数量
|
||
num_labels = len(contours)
|
||
|
||
return labeled_image, num_labels
|
||
###############################################
|
||
|
||
#1.从合成的多目标图中里边单独提取剩余屋顶形成二值图并保存
|
||
def extract_remainroof():
|
||
savename="remainroof"
|
||
savepath_root=""
|
||
path1=r""#多目标结果图的路径
|
||
savepath=os.path.join(savepath_root,savename)
|
||
|
||
if not os.path.exists(savepath):
|
||
os.makedirs(savepath)
|
||
|
||
imgss=[i for i in os.listdir(path1) if i.endswith("png")]
|
||
for i in tqdm(imgss):
|
||
im=os.path.join(path1,i)
|
||
imm=np.array(Image.open(im))
|
||
imm=(imm==1) * 1 #剩余屋顶在多目标结果图中的索引是1
|
||
result = np.uint8(imm)
|
||
|
||
#可视化保存
|
||
palette = [0, 0, 0, 255, 0, 0, 0, 255, 0, 0, 0, 255]
|
||
result = Image.fromarray(result).convert('P') #
|
||
result.putpalette(palette)
|
||
result.save(os.path.join(savepath, i))
|
||
|
||
|
||
#对1提取的剩余屋顶进行实例化
|
||
def remainroof_instanced():
|
||
pathh = r"" #剩余屋顶保存的文件夹
|
||
savepath_root=""
|
||
savename = "r"
|
||
savepath = os.path.join(savepath_root, savename)
|
||
if not os.path.exists(savepath):
|
||
os.makedirs(savepath)
|
||
for i in tqdm(os.listdir(pathh)):
|
||
imgp = os.path.join(pathh, i)
|
||
binary_image = np.array(Image.open(imgp))
|
||
labeled_image, num_labels = connected_component_analysis(binary_image)
|
||
#实例化后只对那些图中小于256个实例的图像进行可视化保存,大于256的可视化不了
|
||
if num_labels<256:
|
||
palette = generate_random_colors(num_labels)
|
||
result = np.uint8(labeled_image)
|
||
result = Image.fromarray(result).convert('P')
|
||
# 原来的
|
||
l = get_putpalette(palette)
|
||
result.putpalette(l)
|
||
result.save(os.path.join(savepath,i))
|
||
|
||
else:
|
||
result = np.uint8(labeled_image)
|
||
result = Image.fromarray(result).convert('P')
|
||
result.save(os.path.join(savepath, i))
|
||
|
||
|
||
|
||
'''
|
||
3.
|
||
取交集
|
||
2步骤的实例化步骤存在缺陷比如 一个圆环,实例化之后会将这个圆环填补成完整的原 导致实例化后的屋顶偏大
|
||
用没实例化之前的 * 实例化后的
|
||
'''
|
||
|
||
def yu():
|
||
path1=r""#没实例化之前的 #也就是过程1的结果
|
||
path2=r""#实例化之后的 #也就是过程2的结果
|
||
savepath_root=""
|
||
savename = ""
|
||
savepath = os.path.join(savepath_root, savename)
|
||
|
||
if not os.path.exists(savepath):
|
||
os.makedirs(savepath)
|
||
|
||
for i in tqdm(os.listdir(path1)):
|
||
img1 = os.path.join(path1, i)
|
||
img2 = os.path.join(path2, i)
|
||
binary_image = np.array(Image.open(img1))
|
||
instanceimage = np.array(Image.open(img2))
|
||
result=binary_image*instanceimage
|
||
num_labels=np.unique(result)
|
||
t=len(num_labels)
|
||
if t< 256:
|
||
palette = generate_random_colors(t)
|
||
result = np.uint8(result)
|
||
result = Image.fromarray(result).convert('P')
|
||
# 原来的
|
||
l = get_putpalette(palette)
|
||
result.putpalette(l)
|
||
result.save(os.path.join(savepath, i))
|
||
# print("1ok")
|
||
else:
|
||
result = np.uint8(result)
|
||
result = Image.fromarray(result).convert('P')
|
||
result.save(os.path.join(savepath, i))
|
||
# print("2ok")
|
||
|
||
|
||
|
||
#4.计算潜力
|
||
def potentialmain():
|
||
pathh = r""#过程3的结果
|
||
gsd=0.26*0.26 #每个像素实际所占的面积
|
||
singlepvare = 1.28 #每块光伏板的面积
|
||
th=296 #阈值,小于这个阈值的屋顶就不计算他的潜力了 296是像素。
|
||
total_pv=0
|
||
total_roof=0
|
||
avalibale=1
|
||
for index,i in enumerate(os.listdir(pathh)):
|
||
imgp = os.path.join(pathh, i)
|
||
_image = np.array(Image.open(imgp))
|
||
liss=np.unique(_image)
|
||
labeled_image=_image
|
||
image_deployedpv=0
|
||
image_roof=0
|
||
|
||
for n in liss:
|
||
nnumbelr = np.sum(labeled_image == n)
|
||
if nnumbelr <th:
|
||
labeled_image[labeled_image==n]=0 ##!!
|
||
newnum_labels = np.unique(labeled_image)
|
||
for k in newnum_labels[1:]: # 注意0是背景
|
||
current_instance_roofpiex = np.sum(labeled_image == k) # 统计当前实例的像素个数
|
||
current_instance_roofare = current_instance_roofpiex * gsd * avalibale ##计算当前实例的面积
|
||
current_instance_deployedpv = current_instance_roofare // singlepvare # 当前实例的可部署的光伏组件的数量
|
||
print(f"当前图{index+1}的处理后的实例{k}的像素为{current_instance_roofpiex},面积为{current_instance_roofare},可安装的光伏组件块数为{current_instance_deployedpv}")
|
||
# pertotal_pv = pertotal_pv + deployedpv
|
||
# pertotal_roof = pertotal_roof + roofare
|
||
image_deployedpv += current_instance_deployedpv
|
||
image_roof += current_instance_roofare
|
||
total_pv += image_deployedpv # 总计可以部署的光伏组件数量
|
||
total_roof += image_roof
|
||
print(f"当前图{i}的,可安装的光伏组件块数为{image_deployedpv}")
|
||
print("++++++++++++++++++++++++++")
|
||
print("总计的图像可安装的光伏面板的块数为:", total_pv)
|
||
print("总计可用的屋顶的面积为:", total_roof)
|
||
|
||
print("200ww总计光伏组件容量:", total_pv * 200)
|
||
return total_pv
|
||
|
||
|
||
potentialmain()
|
||
|
||
|