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