ai-station-code/wudingpv/post_processing/potential.py

203 lines
7.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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()