遥感数据集制作(Potsdam数据集为例):TIF图像转JPG,TIF标签转PNG,图像重叠裁剪
文章目录
- TIF图像转JPG
- TIF标签转PNG
- 图像重叠裁剪
- 图像重命名
- 数据集转COCO格式
- 数据集转VOC格式
遥感图像不同于一般的自然图像,由于波段数量、图像位深度等原因,TIF图像数据不能使用简单的格式转换方法。本文以Potsdam数据集为例,制作能够直接用于深度学习的数据集。
Potsdam数据集的内容如下:
本文使用2_Ortho_RGB(图像数据RGB通道顺序)和5_Labels_all(标签数据)作为示例进行数据集制作。
TIF图像转JPG
TIF转JPG借鉴了文章怎么读取tif格式的卫星遥感数据,并将数据输入到神经网络模型中进行训练
# -*- coding: UTF-8 -*-
import numpy as np
import os
from PIL import Image
from osgeo import gdaldef readTif(imgPath, bandsOrder=[1, 2, 3]):"""读取GEO tif影像的前三个波段值,并按照R.G.B顺序存储到形状为【原长*原宽*3】的数组中:param imgPath: 图像存储全路径:param bandsOrder: RGB对应的波段顺序,如高分二号多光谱包含蓝B,绿g,红R,近红Nir外四个波段,RGB对应的波段为3,2,1:return: R.G.B三维数组"""dataset = gdal.Open(imgPath, gdal.GA_ReadOnly)cols = dataset.RasterXSizerows = dataset.RasterYSizedata = np.empty([rows, cols, 3], dtype=float)for i in range(3):band = dataset.GetRasterBand(bandsOrder[i])oneband_data = band.ReadAsArray()data[:, :, i] = oneband_datareturn datadef stretchImg(imgPath, resultPath, lower_percent=0.5, higher_percent=99.5):"""#将光谱DN值映射至0-255,并保存:param imgPath: 需要转换的tif影像路径(***.tif):param resultPath: 转换后的文件存储路径(***.jpg):param lower_percent: 低值拉伸比率:param higher_percent: 高值拉伸比率:return: 无返回参数,直接输出图片"""RGB_Array = readTif(imgPath)band_Num = RGB_Array.shape[2]JPG_Array = np.zeros_like(RGB_Array, dtype=np.uint8)for i in range(band_Num):minValue = 0maxValue = 255# 获取数组RGB_Array某个百分比分位上的值low_value = np.percentile(RGB_Array[:, :, i], lower_percent)high_value = np.percentile(RGB_Array[:, :, i], higher_percent)temp_value = minValue + (RGB_Array[:, :, i] - low_value) * (maxValue - minValue) / (high_value - low_value)temp_value[temp_value < minValue] = minValuetemp_value[temp_value > maxValue] = maxValueJPG_Array[:, :, i] = temp_valueoutputImg = Image.fromarray(np.uint8(JPG_Array))outputImg.save(resultPath)def Batch_Convert_tif_to_jpg(imgdir, savedir):# 检查保存目录是否存在,如果不存在则创建if not os.path.exists(savedir):os.makedirs(savedir)# 获取文件夹下所有tif文件名称,并存入列表file_name_list = os.listdir(imgdir)for name in file_name_list:# 获取图片文件全路径img_path = os.path.join(imgdir, name)# 获取文件名,不包含扩展名filename = os.path.splitext(name)[0]savefilename = filename + ".jpg"# 文件存储全路径savepath = os.path.join(savedir, savefilename)stretchImg(img_path, savepath)print(f"Converted {filename} to jpg format.")print("Done!")# 主函数,首先调用
if __name__ == '__main__':imgdir = r"F:\Potsdam\2_Ortho_RGB" # tif文件所在的【文件夹】savedir = r"F:\Potsdam\jpg" # 转为jpg后存储的【文件夹】Batch_Convert_tif_to_jpg(imgdir, savedir)

TIF标签转PNG
如果标签图像是单通道的,那么可以简单地进行格式转换以适应深度学习模型的输入要求。然而,当标签图像以RGB格式存在时,则需要使用RGB字典进行映射。
import os
from PIL import Image
import numpy as npdef rgb_to_single_channel(rgb_image_path, output_path, rgb_dict):"""将RGB图像转换为单通道图像,使用指定的RGB字典来映射类别标签。:param rgb_image_path: RGB图像的路径:param output_path: 转换后图像的保存路径:param rgb_dict: RGB字典,键是RGB元组,值是对应的类别标签"""# 读取RGB图像rgb_image = Image.open(rgb_image_path)# 将图像转换为numpy数组rgb_array = np.array(rgb_image)# 创建一个空的单通道图像数组single_channel_array = np.zeros((rgb_array.shape[0], rgb_array.shape[1]), dtype=np.uint8)# 将RGB值转换为单一的标量值for rgb, label in rgb_dict.items():# 将图像中的每个像素的RGB值与rgb_dict中的RGB元组进行比较# 如果匹配,则将对应的类别标签赋给单通道图像的对应像素single_channel_array[np.all(rgb_array == rgb, axis=-1)] = label# 将单通道数组转换为图像并保存single_channel_image = Image.fromarray(single_channel_array, mode='L')single_channel_image.save(output_path)def convert_tif_to_png(image_folder, output_folder, rgb_dict):"""将指定文件夹中的所有TIFF图像转换为PNG格式,并保存到另一个文件夹中。如果图像是单通道图像,则直接转换为PNG。如果图像是RGB图像,则使用rgb_to_single_channel函数进行转换。:param image_folder: 包含TIFF图像的文件夹路径。:param output_folder: 保存转换后的PNG图像的文件夹路径。:param rgb_dict: RGB字典,用于rgb_to_single_channel函数。"""# 检查输出文件夹是否存在,如果不存在则创建它if not os.path.exists(output_folder):os.makedirs(output_folder)# 遍历图像文件夹中的所有文件for filename in os.listdir(image_folder):filepath = os.path.join(image_folder, filename)# 检查文件是否为TIFF格式if filename.endswith('.tif'):try:# 打开TIFF图像image = Image.open(filepath)# 检查图像是否为单通道图像if image.mode == 'L':# 如果是单通道图像,直接转换为PNGoutput_filename = os.path.splitext(filename)[0] + '.png'output_filepath = os.path.join(output_folder, output_filename)image.save(output_filepath, 'PNG')print(f"Converted {filename} to png format.")else:# 如果是RGB图像,使用rgb_to_single_channel函数进行转换output_filename = os.path.splitext(filename)[0] + '_single_channel.png'output_filepath = os.path.join(output_folder, output_filename)rgb_to_single_channel(filepath, output_filepath, rgb_dict)print(f"Converted {filename} to single channel png format.")except Exception as e:print(f"Error converting {filename}: {str(e)}")# 指定图像文件夹和输出文件夹
image_folder = r"F:\Potsdam\5_Labels_all"
output_folder = r"F:\Potsdam\png"# 定义RGB字典
rgb_dict = {(255, 255, 255): 1, # 不透水路面 Impervious surfaces (RGB: 255, 255, 255)(0, 0, 255): 2, # 建筑物 Building (RGB: 0, 0, 255)(0, 255, 255): 3, # 低植被 Low vegetation (RGB: 0, 255, 255)(0, 255, 0): 4, # 树木 Tree (RGB: 0, 255, 0)(255, 255, 0): 5, # 汽车 Car (RGB: 255, 255, 0)(255, 0, 0): 255 # 背景 Clutter/background (RGB: 255, 0, 0)
}# 调用函数进行转换
convert_tif_to_png(image_folder, output_folder, rgb_dict)

图像重叠裁剪
由于遥感图像数据集的珍贵性,我们可以使用重叠裁剪的方式扩充数据集数量,当然也可以设置为0不重叠。
import os
from PIL import Imagedef crop_images(image_path, save_path, subimage_size, overlap_ratio):"""将图像裁剪成指定大小的子图像,并允许设置子图像之间的重叠比例。只有完全覆盖原始图像的子图像才会被保存。:param image_path: 原始图像路径:param save_path: 保存子图像的路径:param subimage_size: 子图像大小(宽度和高度):param overlap_ratio: 子图像之间的重叠比例,范围在0到1之间"""# 确保保存路径存在os.makedirs(save_path, exist_ok=True)# 遍历图像路径中的所有文件for filename in os.listdir(image_path):# 检查文件是否为图像格式if filename.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp', '.tif')):# 打开图像img = Image.open(os.path.join(image_path, filename))width, height = img.size# 计算子图像的步长,包括重叠部分step = int(subimage_size * (1 - overlap_ratio))# 计算需要划分的行列数num_rows = (height // step) + (1 if height % step > 0 else 0)num_cols = (width // step) + (1 if width % step > 0 else 0)# 遍历并保存每个子图片for row in range(num_rows):for col in range(num_cols):# 计算子图像的左上角和右下角坐标left = col * steptop = row * stepright = left + subimage_sizebottom = top + subimage_size# 检查子图像是否完全覆盖原始图像if right <= width and bottom <= height:# 裁剪子图像sub_img = img.crop((left, top, right, bottom))# 构建子图像的文件名base_name, ext = os.path.splitext(filename)sub_filename = f"{base_name}_row{row}_col{col}{ext}"# 保存子图像sub_img.save(os.path.join(save_path, sub_filename))print(f"{filename} cropping complete.")crop_images(r'F:\Potsdam\jpg',r'F:\Potsdam\jpg_512_0.5',512, 0.5)crop_images(r'F:\Potsdam\png',r'F:\Potsdam\png_512_0.5',512, 0.5)

图像重命名
在构建遥感图像数据集的过程中,会遇到图像集和相应的标签集在文件命名上的不一致问题。这种不一致性会导致无法直接将数据集用于深度学习模型的训练,因为模型通常需要图像和标签数据具有完全匹配的文件名,以确保它们可以正确地配对。
import osdef rename(directory, str):# 检查目录是否存在if not os.path.exists(directory):print("path error!")return# 获取目录下所有文件files = os.listdir(directory)# 循环处理每个文件for file in files:if file.endswith(('.png', '.jpg', '.jpeg', '.bmp', '.tif')):# 检查文件名中是否包含if str in file:# 构建新的文件名new_file_name = file.replace(str, '')# 旧文件路径old_file_path = os.path.join(directory, file)# 新文件路径new_file_path = os.path.join(directory, new_file_name)try:# 重命名文件os.rename(old_file_path, new_file_path)print(f" {file} rename {new_file_name}")except Exception as e:print(f" {file} error:{e}")# 指定路径
jpg_directory_path = r"F:\Potsdam\jpg_512_0.5"
png_directory_path = r"F:\Potsdam\png_512_0.5"
jpg_str="_RGB"
png_str="_label_single_channel"# 执行重命名操作
rename(jpg_directory_path, jpg_str)
rename(png_directory_path, png_str)


数据集转COCO格式
某些深度学习模型是根据公共自然图像数据集格式进行数据集格式处理,这里给出COCO数据集的格式转化。
import os
import json
import shutil
import random
from PIL import Image# 原始JPG图片路径
jpg_path = r'F:\Five-Billion-Pixels\jpg_512'
# 原始PNG标签路径
png_path = r'F:\Five-Billion-Pixels\png_24_512'
# COCO数据集路径
coco_path = r'F:\Five-Billion-Pixels\coco-stuff'# 确保COCO数据集路径存在
if not os.path.exists(coco_path):os.makedirs(coco_path)# 创建COCO数据集的目录结构
annotations_path = os.path.join(coco_path, 'annotations')
images_path = os.path.join(coco_path, 'images')
train_images_path = os.path.join(images_path, 'train2017')
val_images_path = os.path.join(images_path, 'val2017')
train_annotations_path = os.path.join(annotations_path, 'train2017')
val_annotations_path = os.path.join(annotations_path, 'val2017')os.makedirs(annotations_path, exist_ok=True)
os.makedirs(images_path, exist_ok=True)
os.makedirs(train_images_path, exist_ok=True)
os.makedirs(val_images_path, exist_ok=True)
os.makedirs(train_annotations_path, exist_ok=True)
os.makedirs(val_annotations_path, exist_ok=True)# 获取JPG图片列表
jpg_images = [f for f in os.listdir(jpg_path) if f.lower().endswith('.jpg')]# 随机划分数据集
random.shuffle(jpg_images)
split_index = int(len(jpg_images) * 0.8) # 80%的数据用于训练,20%的数据用于验证
train_images = jpg_images[:split_index]
val_images = jpg_images[split_index:]# 复制图像和标签到对应的目录
def copy_images_and_labels(image_list, src_image_path, src_label_path, dst_image_path, dst_label_path):for image_name in image_list:# 复制图像shutil.copy(os.path.join(src_image_path, image_name), os.path.join(dst_image_path, image_name))# 复制标签label_name = image_name.replace('.jpg', '.png')shutil.copy(os.path.join(src_label_path, label_name), os.path.join(dst_label_path, label_name))# 复制训练集图像和标签
copy_images_and_labels(train_images, jpg_path, png_path, train_images_path, train_annotations_path)# 复制验证集图像和标签
copy_images_and_labels(val_images, jpg_path, png_path, val_images_path, val_annotations_path)
数据集转VOC格式
某些深度学习模型是根据公共自然图像数据集格式进行数据集格式处理,这里给出VOC数据集的格式转化。
import os
import shutil
import randomdef create_voc_dataset(image_folder, label_folder):# 定义 VOC 数据集的主目录和子目录voc_root = 'VOCdevkit'voc_dataset = 'VOC2012'voc_images = os.path.join(voc_root, voc_dataset, 'JPEGImages')voc_labels = os.path.join(voc_root, voc_dataset, 'SegmentationClassAug')voc_image_sets = os.path.join(voc_root, voc_dataset, 'ImageSets', 'Segmentation')# 创建 VOC 数据集所需的目录结构os.makedirs(voc_images, exist_ok=True)os.makedirs(voc_labels, exist_ok=True)os.makedirs(voc_image_sets, exist_ok=True)# 遍历图像文件夹中的所有图像文件for root, dirs, files in os.walk(image_folder):for filename in files:if filename.endswith('.jpg'):# 构建图像文件的完整路径image_path = os.path.join(root, filename)# 构建 VOC 数据集中的图像路径voc_image_path = os.path.join(voc_images, filename)# 将图像复制到 VOC 数据集目录shutil.copy(image_path, voc_image_path)print('图像已复制')# 遍历标签文件夹中的所有标签文件for root, dirs, files in os.walk(label_folder):for filename in files:if filename.endswith('.png'):# 构建标签文件的完整路径label_path = os.path.join(root, filename)# 构建 VOC 数据集中的标签路径voc_label_path = os.path.join(voc_labels, filename)# 将标签复制到 VOC 数据集目录shutil.copy(label_path, voc_label_path)print('标签已复制')# 获取图像文件夹中的所有文件名(不含扩展名)image_filenames = [os.path.splitext(filename)[0] for root, dirs, files in os.walk(image_folder) for filename in files if filename.endswith('.jpg')]# 随机打乱文件名列表random.shuffle(image_filenames)# 计算训练集和验证集的分割点split_index = int(len(image_filenames) * 0.8)# 分割训练集和验证集train_files = image_filenames[:split_index]val_files = image_filenames[split_index:]# 生成 train.txt 文件train_file_path = os.path.join(voc_image_sets, 'train.txt')with open(train_file_path, 'w') as train_file:for filename in train_files:train_file.write(filename + '\n')# 生成 val.txt 文件val_file_path = os.path.join(voc_image_sets, 'val.txt')with open(val_file_path, 'w') as val_file:for filename in val_files:val_file.write(filename + '\n')# 打印成功提示信息print('train.txt 和 val.txt 已成功创建。')# 提供图像文件夹和标签文件夹的路径
image_folder = r'F:\WHDLD\Images'
label_folder = r'F:\WHDLD\Labels'# 调用函数创建 VOC 数据集
create_voc_dataset(image_folder, label_folder)
相关文章:
遥感数据集制作(Potsdam数据集为例):TIF图像转JPG,TIF标签转PNG,图像重叠裁剪
文章目录 TIF图像转JPGTIF标签转PNG图像重叠裁剪图像重命名数据集转COCO格式数据集转VOC格式 遥感图像不同于一般的自然图像,由于波段数量、图像位深度等原因,TIF图像数据不能使用简单的格式转换方法。本文以Potsdam数据集为例,制作能够直接用…...
根据web访问日志,封禁请求量异常的IP,如IP在半小 时后恢复正常则解除封禁
在网络安全日益受到重视的今天,如何有效防范恶意流量和攻击成为了每个网站管理员必须面对的问题。恶意流量不仅会影响网站的正常运行,还可能导致服务器崩溃,给网站带来不可估量的损失。为了应对这一问题,我们特别推出了一款实用的…...
2.go语言初始(二)
本篇博客涉及到go 的基础数据类型、 go 语言中的运算符、转义字符、格式化输出、字符串操作 go 语言中的运算符 在 go 语言中,基本数据类型主要包括以下几类:整数类型、浮点数类型、复数类型、布尔类型、字符串类型、字节类型(byte…...
MQTT对比HTTP
吞吐量:根据3G网络的测量结果,MQTT的吞吐量比HTTP快93倍。这意味着在相同的网络条件下,MQTT能够更有效地传输数据,从而在处理大量数据或实时数据传输时具有更高的效率。架构与模式:MQTT基于发布/订阅模型,提…...
暴力数据结构之二叉树(堆的相关知识)
1. 堆的基本了解 堆(heap)是计算机科学中一种特殊的数据结构,通常被视为一个完全二叉树,并且可以用数组来存储。堆的主要应用是在一组变化频繁(增删查改的频率较高)的数据集中查找最值。堆分为大根堆和小根…...
死锁调试技巧:工作线程和用户界面线程
有人碰到了一个死锁问题,找到我们想请我们看看,这个是关于应用程序用户界面相关的死锁问题。 我也不清楚他为什么会找上我们,可能是因为我们经常会和窗口管理器打交道吧。 下面,我们来看看死锁的两个线程。 >> 请移步至 …...
蓝桥杯-外卖店优先级(简单写法)
“饱了么”外卖系统中维护着 N 家外卖店,编号 1∼N。 每家外卖店都有一个优先级,初始时 (0 时刻) 优先级都为 0。 每经过 1 个时间单位,如果外卖店没有订单,则优先级会减少 1,最低减到 0;而如果外卖店有订…...
VueRouter使用总结
VueRouter 是 Vue.js 的官方路由管理器,用于构建单页面应用(SPA)。在使用 VueRouter 时,开发者可以定义路由映射规则,并在 Vue 组件中通过编程式导航或声明式导航的方式控制页面的跳转和展示。以下是 VueRouter 使用的…...
Flink checkpoint 源码分析- Checkpoint snapshot 处理流程
背景 在上一篇博客中我们分析了代码中barrier的是如何流动传递的。Flink checkpoint 源码分析- Checkpoint barrier 传递源码分析-CSDN博客 最后跟踪到了代码org.apache.flink.streaming.runtime.io.checkpointing.CheckpointedInputGate#handleEvent 现在我们接着跟踪相应…...
Leaflet.canvaslabel在Ajax异步请求时bindPopup无效的解决办法
目录 前言 一、场景重现 1、遇到问题的代码 2、问题排查 二、通过实验验证猜想 1、排查LayerGroup和FeatureGroup 2、排查Leaflet.canvaslabel.js 三、柳暗花明又一村 1、点聚类的办法 2、歪打正着 总结 前言 在上一篇博客中介绍了基于SpringBoot的全国风景区WebGIS按…...
Go 处理错误
如果你习惯了 try catch 这样的语法后,会觉得处理错误真简单,然后你再来接触 Go 的错误异常,你会发现他好复杂啊,怎么到处都是 error,到处都需要处理 error。 首先咱们需要知道 Go 语言里面有个约定,就是一…...
python读取excel数据写入mysql
概述 业务中有时会需要解析excel中的数据,按照要求处理后,写入到db中; 用python处理这个正好简便快捷 demo 没有依赖就 pip install pymysql一下 import pymysql from pymysql.converters import escape_string from openpyxl import loa…...
flutter日期选择器仅选择年、月
引入包:flutter_datetime_picker: 1.5.0 封装 import package:flutter/cupertino.dart; import package:flutter/material.dart; import package:flutter_datetime_picker/flutter_datetime_picker.dart;class ATuiDateTimePicker {static Future<DateTime> …...
素数筛详解c++
一、埃式筛法 代码 二、线性筛法(欧拉筛法) 主要的思想就是一个质数的倍数(倍数为1除外)肯定是合数,那么我们利用这个质数算出合数,然后划掉这个合数,下次就可以不用判断它是不是质数,节省了大量的时间。 …...
【Python超详细的学习笔记】Python超详细的学习笔记,涉及多个领域,是个很不错的笔记
获取笔记链接 Python超详细的学习笔记 一,逆向加密模块 1,Python中运行JS代码 1.1 解决中文乱码或者报错问题 import subprocess from functools import partial subprocess.Popen partial(subprocess.Popen, encodingutf-8) import execjs1.2 常用…...
TINA 使用教程
常用功能 分析-电气规则检查:短路,断路等分析- 直流分析 交流分析 瞬态分析 视图-分离曲线 由于输出的容性负载导致的振荡 增加5欧电阻后OK 横扫参数 添加横扫曲线的电阻,选择R3:8K-20K PWL和WAV文件的支持 示例一:…...
weblogic 任意文件上传 CVE-2018-2894
一、漏洞简介 在 Weblogic Web Service Test Page 中存在一处任意文件上传漏洞, Web Service Test Page 在"生产模式"下默认不开启,所以该漏洞有一定限制。利用该 漏洞,可以上传任意 jsp 文件,进而获取服务器权限。 二…...
我的第一个网页:武理天协
1. html代码 1.1 首页.html <!DOCTYPE html> <html lang"zh"> <head><meta charset"UTF-8"><title>武理天协</title><link rel"stylesheet" href"./style.css"><link rel"stylesh…...
机器学习笔记 KAN网络架构简述(Kolmogorov-Arnold Networks)
一、简述 在最近的研究中,出现了号称传统多层感知器 (MLP) 的突破性替代方案,重塑了人工神经网络 (ANN) 的格局。这种创新架构被称为柯尔莫哥洛夫-阿诺德网络 (KAN),它提出了一种受柯尔莫哥洛夫-阿诺德表示定理启发的函数逼近的方法。 与 MLP 不同,MLP 依赖于各个节…...
基于网络爬虫技术的网络新闻分析(二)
目录 2 系统需求分析 2.1 系统需求概述 2.2 系统需求分析 2.2.1 系统功能要求 2.2.2 系统IPO图 2.2 系统非功能性需求分析 3 系统概要设计 3.1 设计约束 3.1.1 需求约束 3.1.2 设计策略 3.1.3 技术实现 3.3 模块结构 3.3.1 模块结构图 3.3.2 系统层次图 3.3.3…...
Docker 运行 Kafka 带 SASL 认证教程
Docker 运行 Kafka 带 SASL 认证教程 Docker 运行 Kafka 带 SASL 认证教程一、说明二、环境准备三、编写 Docker Compose 和 jaas文件docker-compose.yml代码说明:server_jaas.conf 四、启动服务五、验证服务六、连接kafka服务七、总结 Docker 运行 Kafka 带 SASL 认…...
高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...
Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...
selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
return this;返回的是谁
一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请,不同级别的经理有不同的审批权限: // 抽象处理者:审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...
Java编程之桥接模式
定义 桥接模式(Bridge Pattern)属于结构型设计模式,它的核心意图是将抽象部分与实现部分分离,使它们可以独立地变化。这种模式通过组合关系来替代继承关系,从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...
[免费]微信小程序问卷调查系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】
大家好,我是java1234_小锋老师,看到一个不错的微信小程序问卷调查系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】,分享下哈。 项目视频演示 【免费】微信小程序问卷调查系统(SpringBoot后端Vue管理端) Java毕业设计_哔哩哔哩_bilibili 项…...
