Mosaic數據增強介紹

1. 核心概念與目標

Mosaic 是一種在計算機視覺(尤其是目標檢測任務)中非常流行且強大的數據增強技術。它最早由 Ultralytics 的 Alexey Bochkovskiy 在?YOLOv4?中提出并推廣,后來被廣泛應用于 YOLOv5, YOLOv7, YOLOv8 等模型以及其他目標檢測框架中。

  • 核心思想:?將?4 張不同的訓練圖像?按照隨機的位置、比例和排列方式(例如 2x2 網格)拼接組合成?1 張新的合成圖像

  • 主要目標:

    • 豐富上下文信息:?模型在一張圖中同時看到來自 4 個不同場景的對象和背景,學習更魯棒的特征和上下文關系。

    • 提升小目標檢測:?原始圖像中的小目標在被縮小后放入合成圖像中,可能變得極其微小且密集,迫使模型學習檢測更具挑戰性的小目標。

    • 增加目標密度:?合成圖像通常包含比單張原始圖像更多的目標(最多 4 倍),讓模型在單次前向傳播中看到更多樣本,提高訓練效率。

    • 模擬遮擋與裁剪:?拼接過程天然地裁剪了原始圖像的部分區域,模擬了目標被遮擋或只出現部分的情況。

    • 減少對大批量 (Large Batch Size) 的依賴:?單張合成圖像包含的信息量相當于一個小批次 (mini-batch) 的數據,即使物理批大小較小,模型在每次迭代中也能處理更豐富的信息,降低了訓練對超大物理批大小的硬件要求。

    • 增強模型魯棒性:?通過引入大幅度的幾何變換(縮放、平移、裁剪)和內容變化,提升模型對各種尺度、位置、背景變化的泛化能力。

2. 具體實現步驟

以下是 Mosaic 增強的典型實現流程:

(1)隨機選擇 4 張圖像:?從訓練數據集中隨機抽取 4 張原始圖像 (img1,?img2,?img3,?img4) 及其對應的標注(邊界框?bboxes?+ 類別?labels)。

(2)定義合成圖像尺寸:?確定最終合成圖像的目標尺寸 (通常是模型的輸入尺寸,如?640x640)。

(3)確定拼接中心點 (隨機):

  • 在目標尺寸的寬度 (W) 和高度 (H) 范圍內,隨機生成一個中心點坐標?(xc, yc)。這個點將作為 4 張圖像分割線的交點。
  • xc?通常在?[0.25*W, 0.75*W]?之間隨機,yc?通常在?[0.25*H, 0.75*H]?之間隨機。這確保了拼接點不會太靠近邊緣,從而讓每張原始圖像都有足夠部分被包含進來。

(4)劃分 4 個區域:?中心點?(xc, yc)?將目標畫布劃分為 4 個矩形區域(左上、右上、左下、右下)。

(5)放置并縮放 4 張圖像:

  • 左上區域:?放置?img1。根據左上區域的大小 (xc * yc),對?img1?進行縮放(可能放大或縮小),使其填充該區域。將縮放后的?img1?粘貼到畫布的?(0, 0)?到?(xc, yc)?區域。
  • 右上區域:?放置?img2。根據右上區域的大小 ((W - xc) * yc),對?img2?進行縮放,使其填充該區域。粘貼到?(xc, 0)?到?(W, yc)
  • 左下區域:?放置?img3。根據左下區域大小 (xc * (H - yc)),縮放?img3,填充該區域。粘貼到?(0, yc)?到?(xc, H)
  • 右下區域:?放置?img4。根據右下區域大小 ((W - xc) * (H - yc)),縮放?img4,填充該區域。粘貼到?(xc, yc)?到?(W, H)

(6)處理邊界框標注:

對每張原始圖像,應用與其圖像相同的縮放比例偏移量來變換其對應的邊界框坐標。

  • 縮放:?根據圖像被縮放的倍數 (相對于原始尺寸到目標區域尺寸),等比例縮放邊界框的?(x, y, w, h)?坐標。
  • 偏移:?根據該圖像在合成畫布上的起始位置?(x_offset, y_offset),平移邊界框的?(x, y)?坐標。
  • 裁剪:?在縮放和偏移后,邊界框可能有一部分落在其所在區域之外(被相鄰圖像覆蓋)。需要裁剪掉落在區域外的部分邊界框,只保留完全位于其所在區域內部或邊界上的部分。如果一個邊界框被完全裁剪掉(即沒有任何部分留在其所屬區域內),則丟棄該標注。

(7)組合標注:?將處理(縮放、偏移、裁剪)后的 4 張圖像的邊界框和類別標注列表合并,作為這張合成圖像的標注。

(8)應用額外增強 (可選但常見):?在 Mosaic 合成之后,通常還會對這張合成圖像應用其他標準的數據增強,如:

  • 色彩空間變換 (HSV 色調、飽和度、明度抖動)
  • 隨機水平翻轉
  • 隨機旋轉 (角度通常較小)
  • 模糊、噪聲等。

3. 視覺示例與代碼實現

想象一個?640x640?的畫布。隨機中心點?(xc=400, yc=300)

  • 左上角 (0:300, 0:400) 區域:縮放并放置一張包含狗的圖像。

  • 右上角 (0:300, 400:640) 區域:縮放并放置一張包含汽車和樹的圖像。

  • 左下角 (300:640, 0:400) 區域:縮放并放置一張包含人和自行車的圖像。

  • 右下角 (300:640, 400:640) 區域:縮放并放置一張包含貓和沙發的圖像。
    最終得到的合成圖像看起來像一張被分成 4 塊、內容各異的“馬賽克”拼圖,每塊區域內的目標邊界框都根據其位置進行了調整。

import os
import cv2
import numpy as np
import random
from xml.etree import ElementTree as ET
from typing import List, Tuple, Anydef augment_hsv(img: np.ndarray, hgain: float = 0.015, sgain: float = 0.7, vgain: float = 0.4) -> np.ndarray:"""HSV顏色空間增強Args:img: 輸入圖像 (H, W, C)hgain: 色調增益系數sgain: 飽和度增益系數vgain: 明度增益系數Returns:增強后的圖像"""if hgain or sgain or vgain:# 隨機增益系數r = np.random.uniform(-1, 1, 3) * [hgain, sgain, vgain] + 1# 轉換到HSV空間hue, sat, val = cv2.split(cv2.cvtColor(img, cv2.COLOR_BGR2HSV))dtype = img.dtype# 應用隨機增益x = np.arange(0, 256, dtype=np.int16)lut_hue = ((x * r[0]) % 180).astype(dtype)lut_sat = np.clip(x * r[1], 0, 255).astype(dtype)lut_val = np.clip(x * r[2], 0, 255).astype(dtype)# 應用查找表img_hsv = cv2.merge((cv2.LUT(hue, lut_hue), (cv2.LUT(sat, lut_sat)), (cv2.LUT(val, lut_val)))img = cv2.cvtColor(img_hsv, cv2.COLOR_HSV2BGR)return imgdef merge_bboxes(bboxes: List[np.ndarray], cutx: int, cuty: int, min_area: int = 10) -> np.ndarray:"""合并并修正邊界框Args:bboxes: 四張圖像的邊界框列表,每張圖像的邊界框形狀為(N, 4)cutx: 橫向分割點cuty: 縱向分割點min_area: 最小有效區域閾值Returns:合并后的邊界框 (M, 4)"""merged_boxes = []for i, boxes in enumerate(bboxes):for box in boxes:x1, y1, x2, y2 = boxvalid = True# 左上區域if i == 0:# 完全在區域外if x1 > cutx or y1 > cuty:valid = False# 跨越下邊界if y2 > cuty and y1 < cuty:y2 = cuty# 跨越右邊界if x2 > cutx and x1 < cutx:x2 = cutx# 右上區域elif i == 1:if x2 < cutx or y1 > cuty:valid = Falseif y2 > cuty and y1 < cuty:y2 = cutyif x1 < cutx and x2 > cutx:x1 = cutx# 左下區域elif i == 2:if x1 > cutx or y2 < cuty:valid = Falseif y1 < cuty and y2 > cuty:y1 = cutyif x2 > cutx and x1 < cutx:x2 = cutx# 右下區域elif i == 3:if x2 < cutx or y2 < cuty:valid = Falseif y1 < cuty and y2 > cuty:y1 = cutyif x1 < cutx and x2 > cutx:x1 = cutx# 檢查框是否有效if valid:# 確保坐標有效x1, y1 = max(0, x1), max(0, y1)x2, y2 = max(0, x2), max(0, y2)# 檢查面積是否足夠area = (x2 - x1) * (y2 - y1)if area > min_area:merged_boxes.append([x1, y1, x2, y2])return np.array(merged_boxes) if merged_boxes else np.zeros((0, 4))def mosaic_augmentation(image_paths: List[str], annotation_paths: List[str], input_size: Tuple[int, int] = (416, 416),min_offset: float = 0.2,show_result: bool = False) -> Tuple[np.ndarray, np.ndarray]:"""Mosaic數據增強Args:image_paths: 圖像路徑列表annotation_paths: 標注路徑列表input_size: 輸出圖像尺寸 (h, w)min_offset: 最小偏移比例show_result: 是否顯示結果Returns:mosaic_image: 增強后的圖像 (H, W, C)mosaic_boxes: 邊界框數組 (M, 4)"""assert len(image_paths) == 4 and len(annotation_paths) == 4, "需要4張圖像和4個標注文件"h, w = input_sizemin_offset_x, min_offset_y = min_offset, min_offset# 讀取所有圖像和標注images = []all_boxes = []for img_path, ann_path in zip(image_paths, annotation_paths):# 讀取圖像img = cv2.imread(img_path)if img is None:raise FileNotFoundError(f"圖像未找到: {img_path}")# 解析XML標注boxes = []tree = ET.parse(ann_path)root = tree.getroot()for obj in root.findall('object'):bndbox = obj.find('bndbox')x1 = int(bndbox.find('xmin').text)y1 = int(bndbox.find('ymin').text)x2 = int(bndbox.find('xmax').text)y2 = int(bndbox.find('ymax').text)boxes.append([x1, y1, x2, y2])images.append(img)all_boxes.append(np.array(boxes))# 隨機選擇縮放比例scale = random.uniform(0.5, 1.5)# 隨機生成分割點cutx = random.randint(int(w * min_offset_x), int(w * (1 - min_offset_x)))cuty = random.randint(int(h * min_offset_y), int(h * (1 - min_offset_y)))# 創建空白畫布mosaic_img = np.zeros((h, w, 3), dtype=np.uint8)mosaic_boxes = []# 處理每張圖像for i, (img, boxes) in enumerate(zip(images, all_boxes)):ih, iw = img.shape[:2]# 隨機縮放圖像new_ar = w / hnw = int(scale * iw)nh = int(nw / new_ar)# 調整縮放比例防止過大if nw > w or nh > h:ratio = min(w / nw, h / nh)nw = int(nw * ratio)nh = int(nh * ratio)# 縮放圖像img = cv2.resize(img, (nw, nh))# 調整邊界框坐標scale_x = nw / iwscale_y = nh / ihif boxes.size > 0:boxes[:, [0, 2]] = boxes[:, [0, 2]] * scale_xboxes[:, [1, 3]] = boxes[:, [1, 3]] * scale_y# 確定圖像位置if i == 0:  # 左上x1a, y1a, x2a, y2a = 0, 0, min(nw, cutx), min(nh, cuty)img = img[:y2a, :x2a]if boxes.size > 0:boxes[:, [0, 2]] = boxes[:, [0, 2]]boxes[:, [1, 3]] = boxes[:, [1, 3]]elif i == 1:  # 右上x1a, y1a, x2a, y2a = cutx, 0, w, min(nh, cuty)img = img[:y2a, (x1a - (w - nw)):x2a - (w - nw)]if boxes.size > 0:boxes[:, [0, 2]] = boxes[:, [0, 2]] + w - nwboxes[:, [1, 3]] = boxes[:, [1, 3]]elif i == 2:  # 左下x1a, y1a, x2a, y2a = 0, cuty, min(nw, cutx), himg = img[(y1a - (h - nh)):y2a - (h - nh), :x2a]if boxes.size > 0:boxes[:, [0, 2]] = boxes[:, [0, 2]]boxes[:, [1, 3]] = boxes[:, [1, 3]] + h - nhelse:  # 右下x1a, y1a, x2a, y2a = cutx, cuty, w, himg = img[(y1a - (h - nh)):y2a - (h - nh), (x1a - (w - nw)):x2a - (w - nw)]if boxes.size > 0:boxes[:, [0, 2]] = boxes[:, [0, 2]] + w - nwboxes[:, [1, 3]] = boxes[:, [1, 3]] + h - nh# 將圖像放置到mosaic畫布上mosaic_img[y1a:y2a, x1a:x2a] = imgmosaic_boxes.append(boxes)# 合并并修正邊界框final_boxes = merge_bboxes(mosaic_boxes, cutx, cuty)# 應用HSV增強mosaic_img = augment_hsv(mosaic_img)# 可選:顯示結果if show_result:display_img = mosaic_img.copy()for box in final_boxes:x1, y1, x2, y2 = map(int, box)cv2.rectangle(display_img, (x1, y1), (x2, y2), (0, 255, 0), 2)# 繪制分割線cv2.line(display_img, (cutx, 0), (cutx, h), (255, 0, 0), 2)cv2.line(display_img, (0, cuty), (w, cuty), (255, 0, 0), 2)cv2.imshow('Mosaic Augmentation', display_img)cv2.waitKey(0)cv2.destroyAllWindows()return mosaic_img, final_boxesif __name__ == '__main__':# 數據集路徑base_dir = 'VOCdevkit/VOC2007'image_dir = os.path.join(base_dir, 'JPEGImages')annotation_dir = os.path.join(base_dir, 'Annotations')# 獲取所有圖像和標注文件all_images = [f for f in os.listdir(image_dir) if f.endswith('.jpg')]all_annotations = [f for f in os.listdir(annotation_dir) if f.endswith('.xml')]# 確保圖像和標注匹配image_stems = [os.path.splitext(f)[0] for f in all_images]annotation_stems = [os.path.splitext(f)[0] for f in all_annotations]valid_stems = set(image_stems) & set(annotation_stems)# 創建完整路徑image_paths = [os.path.join(image_dir, f"{stem}.jpg") for stem in valid_stems]annotation_paths = [os.path.join(annotation_dir, f"{stem}.xml") for stem in valid_stems]# 隨機選擇4張圖像進行Mosaic增強if len(image_paths) >= 4:indices = random.sample(range(len(image_paths)), 4)selected_images = [image_paths[i] for i in indices]selected_annotations = [annotation_paths[i] for i in indices]# 執行Mosaic增強mosaic_img, mosaic_boxes = mosaic_augmentation(selected_images, selected_annotations,input_size=(640, 640),  # 更大的輸入尺寸min_offset=0.3,  # 更大的最小偏移show_result=True  # 顯示結果)# 保存結果cv2.imwrite('mosaic_result.jpg', mosaic_img)print(f"Mosaic增強完成! 檢測框數量: {len(mosaic_boxes)}")else:print("需要至少4張帶標注的圖像進行Mosaic增強")

4. 關鍵優勢

  • 提升小目標性能:?如前所述,這是其最顯著的優勢之一。

  • 數據利用效率高:?一張合成圖包含 4 張圖的標注信息,相當于增大了有效批大小。

  • 學習復雜上下文:?模型被迫理解不同場景片段拼合在一起的上下文。

  • 增強幾何魯棒性:?大幅度的縮放和裁剪模擬了現實世界目標的尺度變化和部分遮擋。

  • 降低訓練成本:?可以在較小的物理批大小下達到接近使用更大批大小的效果(尤其在顯存受限時)。

5. 潛在缺點與注意事項

  • 不自然的圖像:?合成的圖像在視覺上可能非常不自然(如天空和地板相接),雖然這有助于魯棒性,但過于離奇的組合可能引入噪聲。通常實踐中利大于弊。

  • 標注噪聲:?邊界框裁剪可能導致部分目標信息丟失(如只保留半個目標),或者裁剪邊緣目標時可能引入輕微的定位噪聲。需要仔細實現裁剪邏輯。

  • 訓練后期可能不穩定:?一些研究發現,在訓練后期繼續使用高概率的 Mosaic 可能導致優化困難或性能震蕩。常見的策略是隨著訓練進行線性衰減 Mosaic 的應用概率(例如,從第 N 個 Epoch 開始,每個 Epoch 將 Mosaic 的概率乘以一個衰減因子,最終降為 0)。

  • 計算開銷:?合成圖像和變換標注需要額外的計算,但通常這個開銷被其帶來的訓練效率提升所抵消。

  • 與其他增強的協調:?Mosaic 通常作為增強流水線的第一步,其后應用其他像素級或輕量幾何增強。過強的后續增強可能破壞 Mosaic 帶來的好處。

6. 應用場景

  • 目標檢測 (Object Detection):?這是 Mosaic 最主要的應用領域,尤其適用于 YOLO 系列、SSD 等單階段檢測器。

  • 實例分割 (Instance Segmentation):?理論上也可用,但需要額外處理掩碼 (mask) 的縮放、偏移和裁剪,實現更復雜。不如在目標檢測中普及。

  • 其他密集預測任務 (如語義分割):?較少使用,因為拼接可能導致語義邊界嚴重不連續,合成圖像過于離奇。

7. 總結

Mosaic 數據增強是一種通過拼接 4 張隨機圖像及其標注來創建新訓練樣本的強大技術。它通過顯著增加圖像中目標的密度和多樣性、強制模型學習不同尺度和上下文、以及提高小目標檢測能力,在目標檢測任務(特別是基于 YOLO 的模型)中取得了巨大成功。盡管會生成視覺上不自然的圖像并帶來一些實現復雜性,但其在提升模型性能、特別是對小目標的魯棒性方面的優勢使其成為現代目標檢測訓練流程中一個不可或缺的組件。合理使用(如訓練后期衰減其概率)可以最大化其收益。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/90057.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/90057.shtml
英文地址,請注明出處:http://en.pswp.cn/web/90057.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

LINUX 722 邏輯卷快照

邏輯卷快照 lvcreate -L 128M -s -n lv1-snap /dev/vg1/lv1 lvs lvscan mount -o ro /dev/vg1/lv1 /mmt/lv1-snap dmsetup ls --tree 測試 lvs /dev/vg1/lv1-snap dd if/dev/zero of/uc1/test bs1M count40 lvs /dev/vg1/lv1-snap 問題 [rootweb ~]# cd /mnt [rootweb mnt]# m…

Springboot+vue個人健康管理系統的設計與實現

文章目錄前言詳細視頻演示具體實現截圖后端框架SpringBoot前端框架Vue持久層框架MyBaits成功系統案例&#xff1a;代碼參考數據庫源碼獲取前言 博主介紹:CSDN特邀作者、985高校計算機專業畢業、現任某互聯網大廠高級全棧開發工程師、Gitee/掘金/華為云/阿里云/GitHub等平臺持續…

數據結構 --棧和隊鏈

一.棧的概念一種特殊的線性表&#xff0c;只能從固定的一端插入和刪除元素。棧中元素遵循先進后出的原則。二.模擬實現public class MyStack {public int size;public int[] array;public MyStack(){array new int[10];}private void grow(){array Arrays.copyOf(array,array…

文檔處理控件TX Text Control系列教程:使用 C# .NET 將二維碼添加到 PDF 文檔

PDF 文檔通常是合同、發票、證書和報告的最終格式。盡管它們在設計上是靜態的&#xff0c;但用戶現在希望能夠與它們交互、驗證信息并直接從這些文件訪問數字服務。這時&#xff0c;二維碼就變得至關重要。 PDF 文檔中的二維碼將印刷或數字內容與動態在線體驗連接起來。用戶只需…

Google Chrome 谷歌瀏覽器全部版本集合

Google Chrome 谷歌瀏覽器全部版本集合 Collection of all software versions of Google Chrome. 項目介紹 本項目為Google Chrome谷歌瀏覽器的全部版本集合&#xff0c;方便大家下載舊版本使用。 因為Gitee項目限制倉庫1G大小&#xff0c;所以許多谷歌瀏覽器版本無法上傳。…

論文略讀:Towards Safer Large Language Models through Machine Unlearning

ACL 2024大型語言模型&#xff08;LLMs&#xff09;的迅猛發展展現了其在多個領域的巨大潛力&#xff0c;這主要得益于其廣泛的預訓練知識和出色的泛化能力。然而&#xff0c;當面對問題性提示&#xff08;problematic prompts&#xff09;時&#xff0c;LLMs 仍然容易生成有害…

深度學習 ---參數初始化以及損失函數

深度學習 —參數初始化以及損失函數 文章目錄深度學習 ---參數初始化以及損失函數一&#xff0c;參數初始化1.1 固定值初始化1.1.1 全0初始化1.1.2 全1初始化1.3 任意常數初始化1.2 隨機初始化一&#xff0c;參數初始化 神經網絡的參數初始化是訓練深度學習模型的關鍵步驟之一…

JS--M端事件

移動端&#xff08;Mobile 端&#xff0c;簡稱 M 端&#xff09;開發中&#xff0c;由于設備特性&#xff08;觸摸屏、手勢操作等&#xff09;&#xff0c;需要處理一些與桌面端不同的事件。這些事件主要針對觸摸交互、手勢識別等場景 一、觸摸事件&#xff08;Touch Events&am…

Linux網絡編程-tcp

tcp、udp對比&#xff1a;UDP1. 特點無連接&#xff1a;無需建立連接即可發送數據。不可靠&#xff1a;不保證數據順序或完整性。低延遲&#xff1a;適合實時性要求高的場景。2. 應用場景視頻/音頻流傳輸&#xff08;如直播&#xff09;。DNS 查詢、在線游戲。TCP1. 特點面向連…

記一次flink資源使用優化

一.現狀分析 現有任務的資源配置如下&#xff0c;根據ui監控中Garbage Collection可以發現&#xff0c;此任務頻繁的發生GC&#xff0c;且老年代GC時間較久二.整體memory使用分析如下Framework Heap&#xff08;框架堆內存&#xff09;用于Flink框架自身的堆內存&#xff08;如…

Vue底層換成啥了?如何更新DOM的?

摘要&#xff1a;之前的vue是使用虛擬 DOM的&#xff0c;但是Vue 3.6 帶來了一個意義重大的更新&#xff1a; Vapor Mode 渲染模式。Vue 渲染策略的演進&#xff1a; Vue 1.x&#xff1a; 基于模板渲染策略&#xff0c;直接將模板轉換為DOM元素&#xff0c;并為每個DOM元素創建…

0722 數據結構順序表

Part 1.順序表的代碼一.順序表的內存申請head.h: typedef int datatype;typedef struct sqlist {//數據元素datatype data[MAXSIZE];//順序表長度int len;}*sqlist; //*sqlist的作用: //sqlist:struct Sqlist * sqlist create();head.c: sqlist create() {sqlist list (sqlist)…

為何在 Vue 的 v-model 指令中不能使用可選鏈(Optional Chaining)?

Vue 的 v-model 是實現組件與數據雙向綁定的核心指令之一&#xff0c;它本質上是一個語法糖&#xff0c;用于簡化對表單元素和組件 props 的同步更新。然而&#xff0c;在 Vue 3&#xff08;以及 Vue 2 的某些模式下&#xff09;&#xff0c;開發者嘗試在 v-model 中使用 JavaS…

基于單片機智能藥盒/智能藥箱/定時吃藥系統

傳送門 &#x1f449;&#x1f449;&#x1f449;&#x1f449;其他作品題目速選一覽表 &#x1f449;&#x1f449;&#x1f449;&#x1f449;其他作品題目功能速覽 概述 本設計實現了一種基于單片機的智能藥盒&#xff0c;系統以微控制器&#xff08;如STM32&#xff…

(25)python+playwright自動化處理單選和多選按鈕-中

1.簡介上一篇中講解和介紹的單選框有點多&#xff0c;而且由于時間的關系&#xff0c;決定今天講解和分享復選框的相關知識。2.什么是單選框、復選框&#xff1f;單選按鈕一般叫raido button&#xff0c;就像我們在電子版的單選答題過程一樣&#xff0c;單選只能點擊一次&#…

Nginx IP授權頁面實現步驟

目標&#xff1a;一、創建白名單文件sudo mkdir -p /usr/local/nginx/conf/whitelist sudo touch /usr/local/nginx/conf/whitelist/temporary.conf二、創建Python認證服務文件路徑&#xff1a;/opt/script/auth_server.pyimport os import time from flask import Flask, requ…

2025年7月中科院一區-向光生長優化算法Phototropic growth algorithm-附Matlab免費代碼

引言 本期介紹一種新的元啟發式算法——向光生長優化算法Phototropic growth algorithm&#xff0c;PGA。靈感來自植物細胞在陽光下的生長模式。于2025年7月最新發表在JCR 1區&#xff0c;中科院1區 SCI 期刊 Knowledge-Based Systems。 該算法將生物學啟發的確定性生長行為與…

poi-excel-添加水印

1、官網快速指南 https://poi.apache.org/components/spreadsheet/quick-guide.html 訪問如上地址可以查看到poi的相關操作方式&#xff1a; How to create a new workbookHow to create a sheetHow to create cellsHow to create date cellsWorking with different types of…

STM32 開發的鼠標:技術詳解與實現指南

概述基于STM32微控制器開發的鼠標是一種高度可定化的輸入設備解決方案&#xff0c;廣泛應用于工業控制、嵌入式系統、特殊人機交互等領域。相比傳統鼠標&#xff0c;STM32鼠標具有以下優勢&#xff1a;高度可定制性&#xff1a;可添加特殊功能按鍵、傳感器集成低功耗設計&#…

GoLang教程007:打印空心金字塔

4.6 案例一&#xff1a;打印金字塔編寫一個程序&#xff0c;可以接收一個整數&#xff0c;表示層數&#xff0c;打印出金字塔。1??第一步&#xff1a;打印一個矩形 package mainimport "fmt"func main() {// i表示層數for i : 1; i < 3; i {// j表示每層打印多少…