主頁 >  其他 > U-Net學習筆記及Pytorch實戰訓練細節

U-Net學習筆記及Pytorch實戰訓練細節

2021-10-27 09:00:30 其他

文章目錄

  • 前言
  • 一、卷積和核(Convolution and Kernels)
    • 1.什么是卷積
    • 2.什么是核
  • 二、卷積層與全連接層的共同點
    • 1.全連接層(Fully-connection)
    • 2.卷積層1×1
  • 三、U-Net
    • 1.反卷積
    • 2.U-Net結構
  • 四、U-Net實戰(Pytorch)
    • 1.專案描述
    • 2.搭建U-Net
      • 2.1卷積層
      • 2.2上采樣層
      • 2.3完成U-Net結構搭建
    • 3.資料集定義
    • 4.訓練
    • 5.預測
  • 參考鏈接


前言

因為畢設需要針對遙感影像進行語意分割,在這里記錄一下自己學習的心路歷程,


提示:以下是本篇文章正文內容,下面案例可供參考

一、卷積和核(Convolution and Kernels)

1.什么是卷積

??卷積和加法、乘法一樣,只是一種數學運算,選擇不同的內核,如“銳化”、“邊緣檢測”、“濾波”等,通過內核與原影像進行卷積,便能實作相應的功能,
??例如,讓我們找下圖A的輪廓(邊緣),
這是一張圖片

A

??給出一個內核如下:
在這里插入圖片描述

查找垂直方向(Finds verticals)
??卷積運算如下:將核所覆寫的像素值與相應的核值相乘,乘積相加后作為新影像中與核中心相對應的點的值,具體如下圖:

在這里插入圖片描述

卷積第一步
??之后,藍色區域(核)開始移動,根據不同的步幅(stride)能得到不同尺寸的結果影像,當stride=1時,藍色區域每次移動一個格子,從左往右從上往下,直到遍歷完原始影像:

在這里插入圖片描述

卷積運算完整程序
??觀察上圖,發現原影像大小為5×5,卷積后的影像大小為3×3,這是由于卷積運算后的求和值只放置在內核中心點導致的,如果你想得到尺寸與原始影像相同的結果影像,可以使用填充(padding)操作,下圖用0像素將原始影像padding為7×7,經過卷積后,得到結果影像為5×5,

在這里插入圖片描述

使用0填充,結果影像與填充前的原始影像有同樣大小
??現在回到圖A(上面的安卓標志),采用Vertical Sobel(核)卷積后的結果如下:

在這里插入圖片描述

Vertical Sobel

2.什么是核

??感謝前人的大量研究,我們有了很多功能明確的核,例如上文的Vertical Sobel,可以提取影像的垂直資訊,但是我們應該思考兩個問題:
??①我們并不知道需要用到怎樣的核;
??②假設你知道需要怎樣功能的核,但并不是所有我們需要的核都被明確的開發出來了
??因此,核中的值應該是被當做引數,通過誤差反向傳播、優化“學”出來的,就和簡單的神經網路一樣,
??
具體怎么理解呢?
??首先,我們應該有這么一個認識:一個8×8的影像,一共有64個像素點,每個像素點的值都是它的一個特征,也就是輸入的一個節點,通過卷積,結果會被放入到另一些節點,即隱藏節點,而核中的每個值對應著輸入節點與隱藏節點的聯系,即權重,這些權重以與普通神經網路完全相同的方式學習:首先隨機初始化核值,將卷積后的結果與實際輸出進行比較(然后對其進行誤差反向傳播和優化),最終迭代出新的核值,如果輸入影像是二維的(即單通道),那么針對某一個功能的核(例如下圖的綠色核)也是二維的,當你想提取四類特征時候,就應該采用4個二維核:在這里插入圖片描述

輸入為單通道影像
??當輸入影像為多通道時(如正常的RGB三通道影像),不同功能核的尺寸也應該變成三維(核的不同顏色代表不同功能,如邊緣、銳化、或其他不知名特征類),針對某一個功能核(如綠色核)對應通道分別卷積,再最終求和(三個通道對應位置相加),得到的最終結果依舊是單通道的, 這個單通道結果矩陣的每一個值,代表的是輸入影像的某個像素或某些像素在綠色核所代表的高維特征中的情況,下圖最侄訓輸出四個單通道結果(綠、黃、藍、粉),表示的是原影像在不同高維特征中的情況,

在這里插入圖片描述

輸入為三通道影像
?? 在pytorch構建卷積層時,in_channels代表輸入影像通道數,out_channels代表卷積產生的通道數,即高維特征數,在上圖中分別為:in_channels=3,out_channels=4. `torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode='zeros', device=None, dtype=None)`

二、卷積層與全連接層的共同點

??在一個識別X與O的任務中,我們輸入一張影像,經過一系列卷積層、池化層后,得到了3×2×2的特征圖:
在這里插入圖片描述

得到3×2×2的特征圖

1.全連接層(Fully-connection)

??全連接層所扮演的角色是主要建構單元,當我們向這個單元輸入圖片時,它會將所有像素的值當成一個一維清單,而不是前面的二維矩陣,清單里的每個值都可以決定圖片中的符號是O還是X,不過這場選舉并不全然民主,由于某些值可以更好地判別叉,有些則更適合用來判斷圈,這些值可以投的票數會比其他值還多,所有值對不同選項所投下的票數,將會以權重(weight)的方式來表示,下圖連接線的不同粗細代表權重的高低,
在這里插入圖片描述

全連接層

2.卷積層1×1

?? 全連接層的結果是輸入影像歸屬某類的強度,但很多時候我們需要得到的是輸入影像中各個像素歸屬某類的強度,此時可以用1×1的卷積層來等價代替全連接層,
??下圖展示了1×1卷積核的計算,輸出中的每個元素來自輸入中在高和寬上相同位置的元素在不同通道間的按權重累加,這與上文的卷積運算相同,假設我們將通道維當作特征維,每個像素位置當成一個資料樣本,那么一個樣本是1×3,共有9個樣本,輸入為9×3,于是下圖實際上是9個全連接層的組合,每組樣本與核的卷積輸出就相當于一個全連接層輸出,下圖的兩個通道維對應著兩個輸出類別,
在這里插入圖片描述

1×1卷積層

三、U-Net

1.反卷積

?? 經過上面的學習我們知道,卷積會導致尺寸變小,為了使得輸入輸出影像有相同的尺寸,我們會填充原影像(padding),
在這里插入圖片描述

原圖(藍)填充后再卷積輸出同尺寸結果(綠)
??如果將原圖繼續往外擴大,結果影像比原圖尺寸更大,這就是反卷積,也稱為 上采樣

2.U-Net結構

U-Net: Convolutional Networks for Biomedical Image Segmentation

在這里插入圖片描述

U-net結構(以最低解析度的32x32像素為例),每個藍盒對應于一個多通道的特征圖,通道的數量表示在盒子的頂部,X-Y尺寸在盒子的左下角提供,白框代表復制的特征圖,箭頭表示不同的操作,

??U形的結構非常簡潔優雅,灰色的箭頭是Skip Connection,是將不同深度的下采樣層的輸出裁剪后與同深度的上采樣層的輸入疊加,疊加結果為通道數加倍,目的在于保留下采樣中部分損失的特征資訊,綠色的箭頭是反卷積,產生的結果是通道數減半但尺寸加倍,最后一層采用了1×1卷積層,目的是二分類,

??為什么最終輸出圖片尺寸與輸入圖片尺寸不同呢?原論文中首先對資料進行了鏡像填充,可以減少有效資料的損失,此外,有些影像尺寸較大(如遙感影像),需要分塊輸入,之后再拼接結果,這樣做還可以避免拼接程序中邊緣部分不連接問題,
在這里插入圖片描述

無縫分割策略
?? 為什么卷積核數量是64、128、...、1024?這是根據實驗結果好壞人為設定的,卷積核越多特征提取越充分,但計算量也會越大,也可能產生冗余資訊, 為什么會翻倍增長呢?因為下采樣時影像高寬縮小一倍,將卷積核增多一倍也是為了保留更多資訊,

??為什么是四層深網路,而不是五層、六層,網路越深精度會越高嗎?針對不同的訓練資料,會有不同的最佳網路深度,網路過深會出現“退化”現象,即隨著網路層數變多,訓練誤差反而降低了,

強烈推薦閱讀:研習U-Net

四、U-Net實戰(Pytorch)

1.專案描述

??復現原論文中的醫學影像分割實驗,共有30張原始影像,解析度為512×512,
在這里插入圖片描述

原始影像(左),對應標簽(右)

2.搭建U-Net

??根據U-Net的結構,首先重現卷積池化層與上采樣層,最后再在Unet中按順序連接起來,

2.1卷積層

??匯入模塊,實作卷積層

import torch
import torch.nn as nn
import torch.nn.functional as F
from torchsummary import summary

#1.模型搭建
#***資料tensor是四維的(N,C,H,W)
#①卷積層
class Unetconv(nn.Module):
    def __init__(self,in_channels,out_channels):
        super(Unetconv,self).__init__()
        
        self.conv1=nn.Sequential(
            nn.Conv2d(in_channels,out_channels,kernel_size=3,stride=1,padding=0),
            nn.ReLU(inplace=True),#inplace=True,節省記憶體開銷
        )
        self.conv2=nn.Sequential(
            nn.Conv2d(out_channels,out_channels,kernel_size=3,stride=1,padding=0),
            nn.ReLU(inplace=True),
        )
    
    def forward(self,X):
        X=self.conv1(X)
        outputs=self.conv2(X)
        return outputs

2.2上采樣層

??Attention 1:在最后一行的torch.cat()中,我們需要資料在通道維進行疊加,而網路中的資料是四維的,(批大小,通道數,高,寬),dim=0時按批疊加,dim=1時按通道數疊加,大家可以動手實作下面這個例子來加深理解,

x=torch.randn(1,2,3)
print("x.shape:",x.shape)
print("dim1.shape:",torch.cat((x,x),dim=1).shape)
print("dim2.shape:",torch.cat((x,x),dim=2).shape)

輸出:
x.shape: torch.Size([1, 2, 3])
dim1.shape: torch.Size([1, 4, 3])
dim2.shape: torch.Size([1, 2, 6])

??Attention 2:反卷積層的輸出通道數為in_channels//2(//為向下取整除法),但進入卷積層的張量是torch.cat()后的,因此Unetconv的輸入通道數是in_channels.

??Attention 3:torch.cat()要求待疊加張量在除疊加維度外的其他維相同,例如按通道維疊加,那么另外三個維度應該完全相同(批大小、高、寬),批大小是人為給定一定相同,高和寬是不同的,因此需要對高、寬進行裁剪(crop),也就是U-Net結構中的copy and crop,pad=[左,右,上,下],陣列中的數大于0為填充,小于0為裁剪,例如“左=-2”則原影像裁剪兩列,詳細見:functional.pad()說明檔案

#②上采樣層
class upconv(nn.Module):
    def __init__(self,in_channels, out_channels):
        super(upconv,self).__init__()
        
        self.conv=Unetconv(in_channels, out_channels)
        #①反卷積
        self.upconv1=nn.ConvTranspose2d(in_channels, in_channels//2, kernel_size=2, stride=2)
        #②skip connection,資料合并
    def forward(self,inputs_R,inputs_U):
        #self,x2,x1
        outputs_U=self.upconv1(inputs_U)
        offset=outputs_U.size()[-1]-inputs_R.size()[-1]
        pad=[offset//2,offset-offset//2,offset//2,offset-offset//2]        # 2*[1,1]=[1,1,1,1]
        outputs_R=F.pad(inputs_R,pad)
        
        #這里教程寫的dim=1,但torch(c,h,w),我覺得dim=0的時候才是通道相加
        #tensor是四維的,所以dim=1,即按三維拼接
        return self.conv(torch.cat((outputs_U,outputs_R),dim=1))

2.3完成U-Net結構搭建

??在最后的1×1卷積層中,為了使得輸出結果與原始影像有相同尺寸,使用了Upsample層,這并不是最好的辦法,

#③完成U-net構建
#in_channels:圖片維度
#n_classes:最終分類數
class Unet(nn.Module):
    def __init__(self,in_channels=3,n_classes=1):
        super(Unet,self).__init__()
        self.in_channels=in_channels
        
        filters=[64,128,256,512,1024]  
        
        #下采樣
        self.conv1=Unetconv(self.in_channels,filters[0])
        self.maxpool1=nn.MaxPool2d(kernel_size=2)
        
        self.conv2=Unetconv(filters[0],filters[1])
        self.maxpool2=nn.MaxPool2d(kernel_size=2)
        
        self.conv3=Unetconv(filters[1],filters[2])
        self.maxpool3=nn.MaxPool2d(kernel_size=2)
        
        self.conv4=Unetconv(filters[2],filters[3])
        self.maxpool4=nn.MaxPool2d(kernel_size=2)

        self.center=Unetconv(filters[3],filters[4])
        #上采樣
        self.upnet4=upconv(filters[4],filters[3])
        self.upnet3=upconv(filters[3],filters[2])
        self.upnet2=upconv(filters[2],filters[1])
        self.upnet1=upconv(filters[1],filters[0])
        #
        self.final=nn.Sequential(
            nn.Conv2d(filters[0],n_classes,kernel_size=1),
            ######為了使得輸出與label同尺寸,這里加入了一個Upsample層,但為什么是2D而不是4D呢?
            nn.Upsample(size=(512, 512)),
            )
        
    def forward(self,inputs):
        #下
        conv1=self.conv1(inputs)
        maxpool1=self.maxpool1(conv1)

        conv2=self.conv2(maxpool1)
        maxpool2=self.maxpool2(conv2)

        conv3=self.conv3(maxpool2)
        maxpool3=self.maxpool3(conv3)

        conv4=self.conv4(maxpool3)
        downputs=self.maxpool4(conv4)

        centerputs=self.center(downputs)
        #上
        up4=self.upnet4(conv4,centerputs)
        up3=self.upnet3(conv3,up4)
        up2=self.upnet2(conv2,up3)
        up1=self.upnet1(conv1,up2)
        #1×1
        final=self.final(up1)

        return final

3.資料集定義

??Pytorch提供了自定義資料集的框架,我們需要重構dataset,然后用dataloader讀取,框架如下:
??對Dataloader感興趣的話推薦看一下這個:Dataloader講解-Miracle8070

# ================================================================== #
#                Input pipeline for custom dataset                 #
# ================================================================== #
 
# You should build your custom dataset as below.
class CustomDataset(torch.utils.data.Dataset):
    def __init__(self):
        # TODO
        # 1. Initialize file paths or a list of file names. 
        pass
    def __getitem__(self, index):
        # TODO
        # 1. Read one data from file (e.g. using numpy.fromfile, PIL.Image.open).
        # 2. Preprocess the data (e.g. torchvision.Transform).
        # 3. Return a data pair (e.g. image and label).
        pass
    def __len__(self):
        # You should change 0 to the total size of your dataset.
        return 0 
 
# You can then use the prebuilt data loader. 
custom_dataset = CustomDataset()
train_loader = torch.utils.data.DataLoader(dataset=custom_dataset,
                                           batch_size=64, 
                                           shuffle=True)

??于是我們自定義資料集如下,我的理解是:在__init__()中得到一個串列,這個串列中的每個元素是一個圖片的路徑,即[圖片路徑1,圖片路徑2,…],在__getitem__(index)中,用index來挨個讀取某一個圖片路徑,從而能得到一張圖片資料,及其對應標簽資料,再return即可,

from torch.utils.data import Dataset
from matplotlib import pyplot as plt
import os
import glob
import cv2
import random
class MyDataset(Dataset):
    def __init__(self,data_dir,transform=None):
        # TODO
        # 1. Initialize file paths or a list of file names. 
        self.data_dir=data_dir
        #img_dir為圖片路徑串列
        self.img_dir=glob.glob(os.path.join(data_dir,'image/*.png'))
        
    def __getitem__(self, index):
        # TODO
        # 1. Read one data from file (e.g. using numpy.fromfile, PIL.Image.open).
        # 2. Preprocess the data (e.g. torchvision.Transform).
        # 3. Return a data pair (e.g. image and label).
        #先傳入圖片的路徑串列
        img_path=self.img_dir[index]
        #修改后得到了對應標簽的路徑串列
        label_path=img_path.replace('image','label')
        #得到圖片和標簽資料
        image = cv2.imread(img_path)
        label = cv2.imread(label_path)
        #資料轉換為單通道
        image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        label = cv2.cvtColor(label, cv2.COLOR_BGR2GRAY)
        image = image.reshape(1, image.shape[0], image.shape[1])
        label = label.reshape(1, label.shape[0], label.shape[1])
        #把標簽從[0,255]變到[0,1]
        if label.max()>1:
            label=label/255
        flipCode = random.choice([-1, 0, 1, 2])
        if flipCode != 2:
            ## 使用cv2.flip進行資料增強,filpCode為1水平翻轉,0垂直翻轉,-1水平+垂直翻轉
            image = cv2.flip(image, flipCode)
            label=cv2.flip(label,flipCode)        
        return image,label
    def __len__(self):
        # You should change 0 to the total size of your dataset.
        return len(self.img_dir)

4.訓練

??損失函式采用了論文中的交叉熵損失函式,優化演算法采用了RMSprop,訓練中保存了best_model.pth,它是loss最小時保存的模型引數,并不是最后一次迭代的模型引數,

from torch import optim
def train_net(net, device, data_path, epochs=10, batch_size=15, lr=0.001):
    # 加載訓練集
    isbi_dataset = MyDataset(data_path)
    train_loader = torch.utils.data.DataLoader(dataset=isbi_dataset,
                                               batch_size=batch_size, 
                                               shuffle=True)
    # 定義RMSprop演算法
    optimizer = optim.RMSprop(net.parameters(), lr=lr, weight_decay=1e-8, momentum=0.9)
    # 定義Loss演算法
    criterion = nn.BCEWithLogitsLoss()
    # best_loss統計,初始化為正無窮
    best_loss = float('inf')
    # 訓練epochs次
    for epoch in range(epochs):
        # 訓練模式
        net.train()
        # 按照batch_size開始訓練
        for image, label in train_loader:
            optimizer.zero_grad()
            # 將資料拷貝到device中
            image = image.to(device=device, dtype=torch.float32)
            label = label.to(device=device, dtype=torch.float32)
            # 使用網路引數,輸出預測結果
            pred = net(image)
            # 計算loss
            loss = criterion(pred, label)
            print('Loss/train', loss.item())
            # 保存loss值最小的網路引數
            if loss < best_loss:
                best_loss = loss
                torch.save(net.state_dict(), 'best_model.pth')
            # 更新引數
            loss.backward()
            optimizer.step()
            
        
    print("訓練結束")

5.預測

# 選擇設備,有cuda用cuda,沒有就用cpu
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
# 加載網路,圖片單通道1,分類為1,
net = Unet(in_channels=1, n_classes=1)
# 將網路拷貝到deivce中
net.to(device=device)
# 指定訓練集地址,開始訓練
data_path = "C:/Users/tc/Desktop/lesson-2/data/train/"
train_net(net, device, data_path)

參考鏈接

How do Convolutional Neural Networks work?
Dive into Pytorch
Convolutional Neural Networks - Basics

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/337582.html

標籤:AI

上一篇:如何同時執行djangorunserver和python腳本(在cmd中的一行)

下一篇:LSTM詳解

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 網閘典型架構簡述

    網閘架構一般分為兩種:三主機的三系統架構網閘和雙主機的2+1架構網閘。 三主機架構分別為內端機、外端機和仲裁機。三機無論從軟體和硬體上均各自獨立。首先從硬體上來看,三機都用各自獨立的主板、記憶體及存盤設備。從軟體上來看,三機有各自獨立的作業系統。這樣能達到完全的三機獨立。對于“2+1”系統,“2”分為 ......

    uj5u.com 2020-09-10 02:00:44 more
  • 如何從xshell上傳檔案到centos linux虛擬機里

    如何從xshell上傳檔案到centos linux虛擬機里及:虛擬機CentOs下執行 yum -y install lrzsz命令,出現錯誤:鏡像無法找到軟體包 前言 一、安裝lrzsz步驟 二、上傳檔案 三、遇到的問題及解決方案 總結 前言 提示:其實很簡單,往虛擬機上安裝一個上傳檔案的工具 ......

    uj5u.com 2020-09-10 02:00:47 more
  • 一、SQLMAP入門

    一、SQLMAP入門 1、判斷是否存在注入 sqlmap.py -u 網址/id=1 id=1不可缺少。當注入點后面的引數大于兩個時。需要加雙引號, sqlmap.py -u "網址/id=1&uid=1" 2、判斷文本中的請求是否存在注入 從文本中加載http請求,SQLMAP可以從一個文本檔案中 ......

    uj5u.com 2020-09-10 02:00:50 more
  • Metasploit 簡單使用教程

    metasploit 簡單使用教程 浩先生, 2020-08-28 16:18:25 分類專欄: kail 網路安全 linux 文章標簽: linux資訊安全 編輯 著作權 metasploit 使用教程 前言 一、Metasploit是什么? 二、準備作業 三、具體步驟 前言 Msfconsole ......

    uj5u.com 2020-09-10 02:00:53 more
  • 游戲逆向之驅動層與用戶層通訊

    驅動層代碼: #pragma once #include <ntifs.h> #define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,0x800,METHOD_BUFFERED,FILE_ANY_ACCESS) /* 更多游戲逆向視頻www.yxfzedu.com ......

    uj5u.com 2020-09-10 02:00:56 more
  • 北斗電力時鐘(北斗授時服務器)讓網路資料更精準

    北斗電力時鐘(北斗授時服務器)讓網路資料更精準 北斗電力時鐘(北斗授時服務器)讓網路資料更精準 京準電子科技官微——ahjzsz 近幾年,資訊技術的得了快速發展,互聯網在逐漸普及,其在人們生活和生產中都得到了廣泛應用,并且取得了不錯的應用效果。計算機網路資訊在電力系統中的應用,一方面使電力系統的運行 ......

    uj5u.com 2020-09-10 02:01:03 more
  • 【CTF】CTFHub 技能樹 彩蛋 writeup

    ?碎碎念 CTFHub:https://www.ctfhub.com/ 筆者入門CTF時時剛開始刷的是bugku的舊平臺,后來才有了CTFHub。 感覺不論是網頁UI設計,還是題目質量,賽事跟蹤,工具軟體都做得很不錯。 而且因為獨到的金幣制度的確讓人有一種想去刷題賺金幣的感覺。 個人還是非常喜歡這個 ......

    uj5u.com 2020-09-10 02:04:05 more
  • 02windows基礎操作

    我學到了一下幾點 Windows系統目錄結構與滲透的作用 常見Windows的服務詳解 Windows埠詳解 常用的Windows注冊表詳解 hacker DOS命令詳解(net user / type /md /rd/ dir /cd /net use copy、批處理 等) 利用dos命令制作 ......

    uj5u.com 2020-09-10 02:04:18 more
  • 03.Linux基礎操作

    我學到了以下幾點 01Linux系統介紹02系統安裝,密碼啊破解03Linux常用命令04LAMP 01LINUX windows: win03 8 12 16 19 配置不繁瑣 Linux:redhat,centos(紅帽社區版),Ubuntu server,suse unix:金融機構,證券,銀 ......

    uj5u.com 2020-09-10 02:04:30 more
  • 05HTML

    01HTML介紹 02頭部標簽講解03基礎標簽講解04表單標簽講解 HTML前段語言 js1.了解代碼2.根據代碼 懂得挖掘漏洞 (POST注入/XSS漏洞上傳)3.黑帽seo 白帽seo 客戶網站被黑帽植入劫持代碼如何處理4.熟悉html表單 <html><head><title>TDK標題,描述 ......

    uj5u.com 2020-09-10 02:04:36 more
最新发布
  • 2023年最新微信小程式抓包教程

    01 開門見山 隔一個月發一篇文章,不過分。 首先回顧一下《微信系結手機號資料庫被脫庫事件》,我也是第一時間得知了這個訊息,然后跟蹤了整件事情的經過。下面是這起事件的相關截圖以及近日流出的一萬條資料樣本: 個人認為這件事也沒什么,還不如關注一下之前45億快遞資料查詢渠道疑似在近日復活的訊息。 訊息是 ......

    uj5u.com 2023-04-20 08:48:24 more
  • web3 產品介紹:metamask 錢包 使用最多的瀏覽器插件錢包

    Metamask錢包是一種基于區塊鏈技術的數字貨幣錢包,它允許用戶在安全、便捷的環境下管理自己的加密資產。Metamask錢包是以太坊生態系統中最流行的錢包之一,它具有易于使用、安全性高和功能強大等優點。 本文將詳細介紹Metamask錢包的功能和使用方法。 一、 Metamask錢包的功能 數字資 ......

    uj5u.com 2023-04-20 08:47:46 more
  • vulnhub_Earth

    前言 靶機地址->>>vulnhub_Earth 攻擊機ip:192.168.20.121 靶機ip:192.168.20.122 參考文章 https://www.cnblogs.com/Jing-X/archive/2022/04/03/16097695.html https://www.cnb ......

    uj5u.com 2023-04-20 07:46:20 more
  • 從4k到42k,軟體測驗工程師的漲薪史,給我看哭了

    清明節一過,盲猜大家已經無心上班,在數著日子準備過五一,但一想到銀行卡里的余額……瞬間心情就不美麗了。最近,2023年高校畢業生就業調查顯示,本科畢業月平均起薪為5825元。調查一出,便有很多同學表示自己又被平均了。看著這一資料,不免讓人想到前不久中國青年報的一項調查:近六成大學生認為畢業10年內會 ......

    uj5u.com 2023-04-20 07:44:00 more
  • 最新版本 Stable Diffusion 開源 AI 繪畫工具之中文自動提詞篇

    🎈 標簽生成器 由于輸入正向提示詞 prompt 和反向提示詞 negative prompt 都是使用英文,所以對學習母語的我們非常不友好 使用網址:https://tinygeeker.github.io/p/ai-prompt-generator 這個網址是為了讓大家在使用 AI 繪畫的時候 ......

    uj5u.com 2023-04-20 07:43:36 more
  • 漫談前端自動化測驗演進之路及測驗工具分析

    隨著前端技術的不斷發展和應用程式的日益復雜,前端自動化測驗也在不斷演進。隨著 Web 應用程式變得越來越復雜,自動化測驗的需求也越來越高。如今,自動化測驗已經成為 Web 應用程式開發程序中不可或缺的一部分,它們可以幫助開發人員更快地發現和修復錯誤,提高應用程式的性能和可靠性。 ......

    uj5u.com 2023-04-20 07:43:16 more
  • CANN開發實踐:4個DVPP記憶體問題的典型案例解讀

    摘要:由于DVPP媒體資料處理功能對存放輸入、輸出資料的記憶體有更高的要求(例如,記憶體首地址128位元組對齊),因此需呼叫專用的記憶體申請介面,那么本期就分享幾個關于DVPP記憶體問題的典型案例,并給出原因分析及解決方法。 本文分享自華為云社區《FAQ_DVPP記憶體問題案例》,作者:昇騰CANN。 DVPP ......

    uj5u.com 2023-04-20 07:43:03 more
  • msf學習

    msf學習 以kali自帶的msf為例 一、msf核心模塊與功能 msf模塊都放在/usr/share/metasploit-framework/modules目錄下 1、auxiliary 輔助模塊,輔助滲透(埠掃描、登錄密碼爆破、漏洞驗證等) 2、encoders 編碼器模塊,主要包含各種編碼 ......

    uj5u.com 2023-04-20 07:42:59 more
  • Halcon軟體安裝與界面簡介

    1. 下載Halcon17版本到到本地 2. 雙擊安裝包后 3. 步驟如下 1.2 Halcon軟體安裝 界面分為四大塊 1. Halcon的五個助手 1) 影像采集助手:與相機連接,設定相機引數,采集影像 2) 標定助手:九點標定或是其它的標定,生成標定檔案及內參外參,可以將像素單位轉換為長度單位 ......

    uj5u.com 2023-04-20 07:42:17 more
  • 在MacOS下使用Unity3D開發游戲

    第一次發博客,先發一下我的游戲開發環境吧。 去年2月份買了一臺MacBookPro2021 M1pro(以下簡稱mbp),這一年來一直在用mbp開發游戲。我大致分享一下我的開發工具以及使用體驗。 1、Unity 官網鏈接: https://unity.cn/releases 我一般使用的Apple ......

    uj5u.com 2023-04-20 07:40:19 more