import numpy as np

import lqmtest_x3_2_load_data
import lqmtest_x3_4_conv_proc

class ModelObj: # 网络对象
    def __init__(self, ObjID, ObjType, ObjLable, ParaString, ObjX, ObjY):
        self.ObjID = ObjID  # 图元号
        self.ObjType = ObjType  # 图元类别
        self.ObjLable = ObjLable  # 对象标签
        self.ParaString = ParaString  # 参数字符串
        self.ObjX = ObjX  # 对象位置x坐标
        self.ObjY = ObjY  # 对象位置y坐标
class Pool_Class(ModelObj):  # 池化对象
    def __init__(self, ObjID, ObjType, ObjLable, ParaString, ObjX, ObjY):
        super().__init__(ObjID, ObjType, ObjLable, ParaString, ObjX, ObjY)
        self.MaxPoolProc = self.pool_proc  # 基本操作函数
        self.SetPollPara = self.setpool_para  # 参数设置函数
    def pool_proc(self, image, PoolPara):
        pool_mode = PoolPara["pool_mode"]
        pool_size = PoolPara["pool_size"]
        stride = PoolPara["stride"]
        c, h, w = image.shape  # 获取输入特征图的高度和宽度
        out_h = int((h - pool_size) / stride) + 1  # 计算输出特征图的高度
        out_w = int((w - pool_size) / stride) + 1  # 计算输出特征图的宽度
        out = np.zeros((c, out_h, out_w))  # 初始化输出特征图为全零数组
        for k in range(c):  # 对于输出的每一个位置上计算：
            for i in range(out_h):
                for j in range(out_w):
                    window = image[k, i * stride:i * stride + pool_size,
                             j * stride:j * stride + pool_size]
                    if pool_mode == "max":  # 最大池化
                        out[k][i][j] = np.max(window)
                    elif pool_mode == "avg":  # 平均池化
                        out[k][i][j] = np.mean(window)
                    elif pool_mode == "min":  # 最小池化
                        out[k][i][j] = np.min(window)
                    else:  # 无效的池化类型
                        raise ValueError("Invalid pooling mode")
        return out  # 返回特征图。
    def setpool_para(self):  # 定义设置池化参数的函数
        pool_mode = input("请输入池化模式（max/avg/min）: ")  # 用户输入池化模式
        pool_size = int(input("请输入池化大小: "))  # 用户输入池化大小
        stride = int(input("请输入步长: "))  # 用户输入步长
        PoolPara = {"pool_mode": pool_mode, "pool_size": pool_size,
                    "stride": stride}  # 返回PoolPara参数，这里用字典来存储
        return PoolPara  # 返回PoolPara参数
if __name__ == '__main__':
    DataSet = lqmtest_x3_2_load_data.Data_Class("DataSet1", 1, "数据集1", [], 120, 330)
    # setload_data()函数，获取加载数据集的参数
    DataPara = DataSet.SetDataPara()
    train_images, test_images = DataSet.LoadData(DataPara)

    Conv = lqmtest_x3_4_conv_proc.Conv_Class("Conv1", 2, "卷积1", [], 250, 330)
    ConvPara = Conv.SetConvPara()
    for i in range(len(train_images) // 32):
        images = train_images[i * 32:(i + 1) * 32]
        conv_images = []  # 存储卷积处理后的图片的列表
        for image in images:  # 获取训练集的图片数据
            dim = len(image.shape)  # 获取矩阵的维度
            if dim == 2:  # 如果是二维矩阵,则转化为三维矩阵
                image_h, image_w = image.shape
                image = np.reshape(image, (1, image_h, image_w))
                # 调用ConvProc()函数，根据ConvPara参数完成卷积计算
                output = Conv.ConvProc(image, ConvPara)
                conv_images.append(output)  # 将卷积结果存储到列表
            elif dim == 3:  # 若为三维矩阵，则保持不变直接卷积处理
                output = Conv.ConvProc(image, ConvPara)
                conv_images.append(output)
        # 将卷积处理后的图片列表转换为数组形式，方便后续处理
        conv_images = np.array(conv_images)
        
    Pool = Pool_Class("Pool1", 3, "最大池化1", [], 380, 330)
    PoolPara = Pool.SetPollPara()
    pool_images = []  # 存储池化处理后的图片的列表
    for image in conv_images:  # 获取卷积后的图片数据
        output = Pool.MaxPoolProc(image, PoolPara)
        pool_images.append(output)  # 将池化结果存储到列表
    # 将池化处理后的图片列表转换为数组形式，方便后续处理
    pool_images = np.array(pool_images)
