Posted on

Swift初探

條件編譯

這是 Swift 的條件編譯(Conditional Compilation)的一個示例,它允許你根據特定的條件選擇性地編譯代碼。在這段代碼中,它確定代碼是在 iOS 模擬器中運行還是在實際的 iOS 裝置上運行。

    #if targetEnvironment(simulator)
    self.videoCapturer = RTCFileVideoCapturer(delegate: videoSource)
    #else
    self.videoCapturer = RTCCameraVideoCapturer(delegate: videoSource)
    #endif

判斷變數是否存在

Swift的空值會是nil

什麼 是 Protocol 與 Delegate

1. Protocol

在 Swift 中,協議(Protocol)定義了一套規範或合約,但不提供具體的實現。任何型別(如 classstructenum)都可以遵循(implement)這些協議,並為協議中的要求提供具體的實現。

例如,我們可以定義一個表示可序列化對象的 Serializable 協議:

protocol Serializable {
    func serialize() -> String
}

然後,我們可以讓某個 structclass 遵循這個協議:

struct Person: Serializable {
    var name: String
    var age: Int

    func serialize() -> String {
        return "\(name),\(age)"
    }
}

2. Delegate

Delegate 是一種設計模式,允許一個物件將某些決策或功能外包給另一個物件。在 Swift 中,Delegate 通常是通過協議來實現的。這意味著當一個類想要成為另一個類的代理時,它必須遵循一個特定的協議。

例如,假設我們有一個 Downloader 類,當下載完成時,我們希望通知另一個物件。我們可以定義一個 DownloaderDelegate 協議:

protocol DownloaderDelegate: AnyObject {
    func didFinishDownloading(data: Data)
}

然後,Downloader 類可以有一個 delegate 屬性:

class Downloader {
    weak var delegate: DownloaderDelegate?

    func download() {
        // 下載過程...
        // 完成後通知代理:
        delegate?.didFinishDownloading(data: someData)
    }
}

其他類(例如 ViewController)可以遵循 DownloaderDelegate 協議並成為 Downloader 的代理,以響應下載完成事件。

這兩個概念在 iOS 和 Swift 開發中都是核心的,用於很多不同的場景和功能。

強大的extension

在 Swift 中,類別 (class)、結構體 (struct)、列舉 (enum)、或者協定 (protocol) 都可以使用 extension 來增加功能。這是 Swift 中一個非常強大的功能,使得你可以將類別或結構體的定義分散到多個區塊,使其更具組織性和可讀性。

以下是使用 extension 的一些常見原因:

  1. 組織性: 你可以使用 extension 來組織你的程式碼,將相似的功能或者與某個特定主題相關的方法放在一起。
  2. 遵循協定: 如果你的類別需要遵循某個協定 (protocol),你可以使用 extension 來隔離所有與該協定相關的實現。
  3. 可讀性: 將類別或結構體分成小區塊可以提高程式碼的可讀性。
  4. 重用和模組化: 你可以定義多個 extension,並將它們放在不同的檔案中,以便於重用或者模組化。

在你給出的例子中,原始的 WebRTCClient 類別可能已經有了一些基本功能。然後,通過使用 extension,增加了關於視頻控制的功能。這種方式可以讓每個 extension 專注於一個特定的功能或者主題,從而使得整體的程式碼更加清晰和有組織性。

總的來說,Swift 中的 extension 功能允許我們對既有的類別或其他資料結構進行進一步的擴展,這樣可以使得程式碼更具組織性、可讀性,並且更容易維護。

分開寫 extension 和將其寫在一起,從功能的角度來看,並沒有區別。不過,程式碼的組織方式往往是為了達到更好的可讀性和易於維護。將不同的功能或與特定主題相關的方法分開在不同的 extension 中,可以幫助讀者和開發者更快地了解該區塊的主要功能,也更容易定位和修改相關的代碼。

使用guard控制流結構

guard 是 Swift 語言中的一個控制流結構,用於提前退出(early exit)方法或函數的執行,當某些條件不成立時。它是為了減少嵌套(nested)的深度和提高程式碼的可讀性。

以下是 guard 的一些特點:

  1. guard 之後必須跟一個條件,如果這個條件為 false,則執行 else 裡面的代碼。
  2. else 裡面必須有一個轉移控制語句,例如 returnbreakcontinuethrow,以確保退出當前的執行流程。
  3. 如果 guard 的條件為 true,則會繼續執行 guard 之後的代碼。

例如:

guard let dataToSend = alert.textFields?.first?.text?.data(using: .utf8) else {
    return
}

這段代碼試圖從 alert 的第一個文本欄位中獲取文本,然後將其轉換為 UTF-8 編碼的 Data 對象。如果其中任何一步失敗(例如,文本欄位為 nil、文本為空或轉換失敗),則整個條件為 false,並執行 else 裡面的 return 語句,從當前函數或方法中提前退出。

使用 guard 而不是嵌套的 if-let 可以使程式碼更加整潔、易讀,特別是當有多個條件需要檢查時。

在Swift中使用閉包

在Swift中,$0, $1, $2, … 是在閉包中使用的隱式名稱,代表閉包的第一個、第二個、第三個…參數。

peerConnection.transceivers
    .compactMap { return $0.sender.track as? T }
    .forEach { $0.isEnabled = isEnabled }

這裡有兩個閉包:一個是用於 compactMap 的閉包,另一個是用於 forEach 的閉包。

  1. 對於 compactMap 的閉包:$0 代表 peerConnection.transceivers 集合中的每一個元素,即每一個 RTCRtpTransceiver 對象。在這個閉包中,它試圖取出每個 transceiver 的 sender 的 track 並嘗試將其轉型為指定的 T 類型。
  2. 對於 forEach 的閉包:在 compactMap 運行之後,我們獲得一個包含符合指定類型 T 的軌道的集合。在 forEach 的閉包中,$0 代表這些軌道。閉包的作用是設置這些軌道的 isEnabled 屬性。
Posted on

常見的Computer Vision Tasks

下面是四種常見的計算機視覺任務的簡要介紹:

分類(Classification)

分類任務是將輸入圖像分為不同的類別或類別之一。例如,給定一張圖像,分類任務的目標是確定圖像中顯示的對像是什麼,比如貓、狗、汽車、飛機等。這通常涉及訓練一個分類器,以便它能夠識別圖像中的特定特徵並將其歸類到正確的類別中。

語義分割(Semantic Segmentation)

語義分割任務是為圖像中的每個像素分配一個類別標籤,從而實現像素級別的分類。與分類任務不同,語義分割不僅關注對象的類型,還考慮了對象的位置和邊界。這在許多應用中很有用,比如圖像分割、醫學圖像分析等。

語義分割是一種計算機視覺任務,旨在將圖像中的每個像素分配給預定義的語義類別。在語義分割中,每個像素都被標記為屬於某個特定的類別,如人、車、樹等。語義分割遵循像素級別的分類,因此通常使用像素級別的掩碼(即”masks”)來表示圖像中每個類別的區域。這些分割掩碼是二進製圖像,其中每個像素要嘛屬於某個類別,要嘛不屬於。

有名模型: U-Net 

和實例分割最大的不同是他的輸入會是兩張圖片,一張為原圖,一張為掩碼的圖

目標檢測(Object Detection)

目標檢測任務涉及在圖像中識別並定位多個不同類別的對象。相比於分類任務,目標檢測不僅需要標識對象的類別,還需要確定它們的位置和邊界框。常見的目標檢測算法可以提供每個檢測到的對象的邊界框和類別信息。具代表性的演算法包括Faster R-CNN, YOLO, SSD等

這篇文章介紹了許多我們常用的物件偵測模型: https://zhuanlan.zhihu.com/p/38709522

實例分割(Instance Segmentation)

實例分割任務結合了目標檢測和語義分割的概念,不僅要對每個對象進行分類,還需要在像素級別區分出每個對象的邊界。實例分割旨在識別圖像中的每個獨立實例並為每個實例分配獨特的標籤,從而在一個圖像中區分出不同的對象。

例如: COCO Segmentation
COCO(Common Objects in Context)是一個廣泛使用的圖像識別和分割數據集,其中包含了多種物體類別的圖像以及每個圖像中物體的分割標註。 COCO Segmentation 數據集中的分割信息通常是用多邊形輪廓來表示物體的形狀。這種分割方法在標註上更靈活,可以準確地表示物體的複雜形狀,但同時也需要更多的標註工作。

Posted on

使用ffmpeg濾鏡功能做影片合成

下載ffmpeg

https://ffmpeg.org/download.html

推一個時鐘文字的影片

ffmpeg的指令如下

ffmpeg  -f lavfi -i color=c=0x00ff00:s=800x450 -vf "settb=AVTB, setpts='trunc(PTS/1K)*1K+st(1,trunc(RTCTIME/1K))-1K*trunc(ld(1)/1K)', drawtext=text='STREAM2-%{localtime}.%{eif\:1M*t-1K*trunc(t*1K)\:d}':x=100:y=100:fontsize=32:fontcolor=white" -c:v libx264 -f flv rtmp://192.168.189.11/live/test2
  1. -f lavfi -i color=c=0x00ff00:s=800×450:這部分使用lavfi作為輸入來源,並創建一個顏色填充的視頻流。 c=0x00ff00指定填充的顏色為綠色,s=800×450指定分辨率為 800×450。
  2. -vf “settb=AVTB, setpts=’trunc(PTS/1K)1K+st(1,trunc(RTCTIME/1K))-1Ktrunc(ld(1)/1K)’, drawtext=text=’STREAM2 -%{localtime}.%{eif\:1Mt-1Ktrunc(t*1K)\:d}’:x=100:y=100:fontsize=32:fontcolor=white”:這部分使用- vf標誌來應用視頻過濾器。其中有兩個主要的過濾器:
    • settb=AVTB, setpts=’trunc(PTS/1K)1K+st(1,trunc(RTCTIME/1K))-1Ktrunc(ld(1)/1K)’:這個過濾器設置視頻時間戳。 settb=AVTB設置時間基準,setpts用於計算新的時間戳,其中包括根據PTS(顯示時間戳)和RTCTIME(實時時鐘時間)進行一些計算。
    • drawtext=text=’STREAM2-%{localtime}.%{eif\:1Mt-1Ktrunc(t1K)\:d}’:x=100:y=100:fontsize=32:fontcolor=white “:這個過濾器使用drawtext來在視頻上繪製文本。它在視頻左上角繪製了一個文本,其中包含了時間戳信息。%{localtime}插入本地時間,%{eif\:1Mt-1K* trunc(t*1K)\:d}用於插入一個經過格式化的時間戳。
  3. -c:v libx264:這部分設置視頻編碼器為libx264,用於將視頻編碼為H.264格式。
  4. -f flv rtmp://192.168.189.11/live/test2:這部分設置輸出格式為FLV,並指定RTMP服務器的地址。視頻會通過RTMP流式傳輸到指定的地址。在這裡,rtmp://192.168.189.11/live/test2是RTMP服務器的地址。

使用虛擬鏡頭來推流

ffmpeg -f dshow -rtbufsize 200M -i video=OBS-Camera -pix_fmt yuv420p -c:v libx264 -profile:v baseline -level:v 3.1 -preset:v ultrafast -s 480x270 -g 240 -an -f flv -y rtmp://172.16.46.89/live/0101_dealerPC1 
  1. -f dshow -rtbufsize 200M -i video=OBS-Camera:這部分設置輸入來源為DirectShow,並指定攝像頭的名稱為 “OBS-Camera”。 -rtbufsize 200M 設置了實時緩衝區的大小為 200MB。
  2. -pix_fmt yuv420p:這部分設置輸出視頻的像素格式為YUV 4:2:0,這是常見的視頻格式。
  3. -c:v libx264 -profile:v baseline -level:v 3.1 -preset:v ultrafast:這部分設置視頻編碼器為libx264,使用baseline配置文件,3.1級別,並設置預設(編碼速度)為ultrafast,這意味著編碼速度非常快。
  4. -s 480×270:這部分設置輸出視頻的分辨率為 480×270,即寬度為480,高度為270。
  5. -g 240:這部分設置關鍵幀(I幀)之間的間隔為 240 幀,用於控制視頻的GOP結構。
  6. -an:這部分錶示不捕獲音頻。
  7. -f flv:這部分設置輸出格式為FLV格式。
  8. -y:這部分錶示在輸出文件存在時覆蓋已存在的文件。
  9. rtmp://172.16.46.89/live/0101_dealerPC1:這部分是輸出URL,指定了通過RTMP傳輸的目標地址。視頻將會通過RTMP協議傳輸到 rtmp://172.16.46.89/live/0101_dealerPC1 這個地址。

極低延遲播放串流

ffplay -fflags nobuffer -flags low_delay -rtmp_buffer 0 -rtmp_live live -framedrop -infbuf %desc%
  1. -fflags nobuffer: 禁用緩衝。這意味著ffplay將盡可能地減少緩衝,以減少播放的延遲。
  2. -flags low_delay: 啟用低延遲模式。這將優化播放以減少延遲,適用於實時音視頻流。
  3. -rtmp_buffer 0: 設置 RTMP 緩衝大小為 0。 RTMP 是一種流媒體協議,這個選項設置緩衝大小為 0 表示盡可能地減少緩衝,從而減少延遲。
  4. -rtmp_live live: 表示要播放的是實時流。
  5. -framedrop: 如果幀太多,ffplay 將刪除一些幀以避免播放過慢。這有助於保持播放的實時性。
  6. -infbuf: 禁用緩衝輸入。與 -fflags nobuffer 相似,這有助於減少延遲。
  7. %desc%: 這可能是一個佔位符,用於指定音視頻流的 URL 或描述符。

把虛擬鏡頭和某個線上串流做綠幕合成

ffmpeg -f dshow -rtbufsize 1M -i video="OBS Virtual Camera" -f flv -i rtmp://172.17.22.89/live/test1 -filter_complex "[0:v]colorkey=0x00ff00:0.3:0.2[keyed];[1:v][keyed]overlay[o]" -map "[o]" -c:v h264_nvenc -f flv rtmp://127.0.0.1/live/test3
  1. -f dshow: 指定輸入的多媒體設備類型為 DirectShow(Windows 平台上的多媒體框架)。
  2. -rtbufsize 1M: 設置輸入緩衝區大小為 1MB。這可能有助於減少輸入的延遲。
  3. -i video=”OBS Virtual Camera”: 指定輸入的視頻設備名稱為 “OBS Virtual Camera”。這是一個虛擬攝像頭,通常由 OBS(Open Broadcaster Software)等軟件創建,用於虛擬攝像頭設備的捕獲。
  4. -f flv -i rtmp://172.17.22.89/live/test1: 指定輸入的媒體流為 RTMP 流,其 URL 為 rtmp://172.17.22.89/live/test1。這是從另一個 RTMP 流獲取的視頻。
  5. -filter_complex “[0:v]colorkey=0x00ff00:0.3:0.2[keyed];[1:v][keyed]overlay[o]”: 使用濾鏡複雜處理,這裡進行了以下操作:
  6. [0:v]colorkey=0x00ff00:0.3:0.2[keyed]:應用顏色鍵(chroma key)效果來移除綠色(0x00ff00)背景。生成一個帶有透明背景的圖像。
    [1:v][keyed]overlay[o]:將第一個輸入流(來自虛擬攝像頭)與經過顏色鍵處理的圖像進行疊加,產生混合後的圖像。
    -map “[o]”: 從混合後的圖像中選擇 [o] 這個輸出流。
  7. -c:v h264_nvenc: 使用 NVIDIA GPU 的硬件編碼器 h264_nvenc 進行視頻編碼。這將利用 GPU 進行加速,提高編碼效率。
  8. -f flv rtmp://172.17.22.89/live/test3: 指定輸出為 RTMP 流,其 URL 為 rtmp://172.17.22.89/live/test3。這是輸出混合後的視頻流。

更多詳細設置串流的方式

set ffmpegBin=C:\apps\ffmpeg\
set PATH=%PATH%;%ffmpegBin%

set camName="OBS Virtual Camera"
set camBufferSize=1000
set desc=rtmp://127.0.0.1:1935/live/demo

set codec=libx264
set fps=24
set /a "keyint=%fps%*5"
set x264opts=keyint=120:min-keyint=%fps%:scenecut=0
set preset=medium
set profile=baseline
set level=3.1
set resolution=800x450
set bitrate=700

:: publish stream
ffmpeg -f dshow -rtbufsize %camBufferSize%M -i video=%camName% ^
       -vf format=yuv420p ^
       -vcodec %codec% -x264-params %x264opts% ^
       -preset %preset% -profile:v %profile% -level:v %level% ^
       -tune:v zerolatency ^
       -s %resolution% ^
       -r %fps% ^
       -b:v %bitrate%k -minrate %bitrate%k -maxrate %bitrate%k -bufsize %bitrate%k ^
       -an ^
       -f flv %desc%

`-r` 轉成多少 fps

`-y` (global) Overwrite output files without asking.

`-i` 輸入檔案

`-c:v` video codec

`-profile:v` video profile, streaming 用 baseline

`-level:v` video level, streaming 用 3.1

`-preset:v` 編碼速度 streaming 用 ultrafast

`-b:v` 設定 bitrate, 例如 700k 486k

`-s` 尺寸

`-g` GOP size (-4 24 -g 240 相當於 Keyframe frequency = 10s)

`-an` 不需要 audio

`-f flv` flv 格式

`-f dshow -i video=OBS-Camera` window 使用 direct show來抓 camera

`-rtbufsize 200M` 設定 buffer size 避免 drop frame

`-re` 串流轉碼會變慢 因為要求 encoder 根據 native frame rate 讀檔按維持品值,要做串流轉發不要延遲時要拿掉。

https://www.wowza.com/docs/how-to-restream-using-ffmpeg-with-wowza-streaming-engine

FFREPORT 環境變數設好 ffmpeg 就會根據設定存log

linux format for date
https://www.opencli.com/linux/linux-date-format-shell-script

偵測 video frame 資訊

取得 stream 資訊

ffprobe -v quiet -show_streams -select_streams v:0 input.flv

抓出所有 i-frame

ffprobe -show_frames input.flv | grep pict_type | grep -n I

FME 設定 24fps, keyframe frequency = 10s
在理想狀況,會每 240 frame 插入一個 i-frame

example:

1:pict_type=I
241:pict_type=I
481:pict_type=I
721:pict_type=I
961:pict_type=I
1201:pict_type=I
Posted on

conda無法安裝套件,缺少OpenSSL解決方案

錯誤訊息

Collecting package metadata (current_repodata.json): failed CondaSSLError: OpenSSL appears to be unavailable on this machine. OpenSSL is required to download and install packages. Exception: HTTPSConnectionPool(host=’conda.anaconda.org’, port=443): Max retries exceeded with url: /conda-forge/win-64/current_repodata.json (Caused by SSLError(“Can’t connect to HTTPS URL because the SSL module is not available.”))

使用pip install/conda install跳出的錯誤

解決方法

在anaconda3>Library>bin尋找這兩個檔案

  • libcrypto-1_1-x64.dll
  • libssl-1_1-x64.dll

然後複製到anaconda3>DLLs.

相關討論串

https://github.com/conda/conda/issues/11982

Posted on

資料增強好工具 – Albumentations

官方資訊

GITHUB: https://github.com/albumentations-team/albumentations

官方文檔: https://albumentations.ai/docs/getting_started/transforms_and_targets/

官方範例: https://github.com/albumentations-team/albumentations_examples/blob/master/notebooks/pytorch_semantic_segmentation.ipynb

Albumentations介紹

Albumentations 是一個流行的計算機視覺數據增強庫,專門設計用於圖像分類、目標檢測、分割等任務。它提供了豐富的圖像增強技術,可以幫助您在訓練深度學習模型時提升模型的性能和魯棒性。 Albumentations 支持多種常用的深度學習框架,如PyTorch和TensorFlow。

以下是 Albumentations 的一些特點和功能:

  • 多樣的增強技術: Albumentations 提供了大量的圖像增強技術,包括但不限於旋轉、翻轉、裁剪、縮放、亮度調整、對比度調整、顏色變換、模糊效果、噪聲添加等。
  • 高性能: Albumentations 以速度和內存效率為目標,因此它在圖像增強方面表現出色。這使得您能夠在訓練過程中高效地應用增強,不會成為訓練的瓶頸。
  • 靈活性: 您可以通過組合不同的增強操作來構建自定義的數據增強流水線。這使得您能夠根據任務和數據集的特點選擇適合的增強操作。
  • 易於集成: Albumentations 支持多種主流深度學習框架,可以方便地與您的模型訓練流程集成,無需複雜的配置。
  • 實時預覽: Albumentations 提供了實時預覽功能,可以在應用增強之前查看圖像的效果,以確保增強操作設置正確。
  • 多線程支持: 對於大規模數據集,Albumentations 支持多線程應用增強,加速數據準備過程。
  • 大量示例: Albumentations 提供了豐富的示例和文檔,幫助您了解每個增強操作的用法和效果。

使用範例

以下是一個使用 Albumentations 的簡單示例,演示如何將一些常見的增強操作應用於圖像數據:

https://github.com/albumentations-team/albumentations_examples/blob/master/notebooks/pytorch_semantic_segmentation.ipynb

import albumentations as A
from albumentations.pytorch import ToTensorV2
import cv2
import matplotlib.pyplot as plt

# 示例图像路径
image_path = 'path_to_your_image.jpg'
image = cv2.imread(image_path)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

# 定义增强操作
transform = A.Compose([
    A.Resize(width=256, height=256),
    A.HorizontalFlip(p=0.5),
    A.VerticalFlip(p=0.5),
    A.Rotate(limit=30, p=0.5),
    A.RandomBrightnessContrast(p=0.2),
    A.Normalize(),
    ToTensorV2(),
])

# 应用增强
transformed_image = transform(image=image)['image']

# 可视化原始图像和增强后的图像
plt.figure(figsize=(10, 5))
plt.subplot(1, 2, 1)
plt.imshow(image)
plt.title('Original Image')

plt.subplot(1, 2, 2)
plt.imshow(transformed_image[0])  # 转换后的图像是 PyTorch 张量,选择通道 0 进行显示
plt.title('Transformed Image')
plt.show()

Posted on

把標記轉成YOLO格式 – JSON2YOLO

JSON2YOLO介紹

官方網站: https://github.com/ultralytics/JSON2YOLO

JSON2YOLO 是一個用於將JSON格式標註數據轉換為YOLO格式標註數據的工具。 YOLO(You Only Look Once)是一種流行的目標檢測算法,它能夠在單次前向傳遞中同時預測圖像中的多個目標邊界框和類別。

在計算機視覺中,標註數據用於告知模型在圖像中的哪些位置存在目標以及目標的類別。 JSON和YOLO是兩種常用的標註數據格式,其中JSON通常用於描述目標的邊界框和類別,而YOLO格式則將目標的邊界框和類別信息結合在一起,以便更有效地訓練目標檢測模型。

JSON2YOLO 工具的主要目的是簡化將JSON格式標註數據轉換為YOLO格式標註數據的過程。通常,這種轉換涉及將目標的邊界框坐標映射到YOLO格式的網格單元,並將類別信息進行編碼。這使得標註數據能夠更好地適應YOLO模型的訓練和預測需求。

何時會需要做格式轉換

當我們使用別人的資料集,很有可能別人並不是使用YOLO格式去輸出資料集的,如果我們想要使用YOLO做訓練,勢必就得做標註資料的轉換,針對YOLO的狀況,就會需要使用這個轉換工具來將其他格式轉為YOLO標記格式

或者像是roboflow支持的輸出格式並不包含YOLO semgemt,所以也會需要先下載一般JSON格式的標記,再使用這個工具來做轉換

Roboflow支持的輸出格式

如何使用

接著再呼叫JSON2YOLO-master>python general_json2yolo.py

轉換好的資料就會出現在new_dir

Posted on

好用的線上標記工具-Roboflow

Roboflow介紹

官網: https://roboflow.com/

文檔: https://docs.roboflow.com/

Roboflow 是一個用於計算機視覺項目的平台,它旨在幫助開發人員和團隊更輕鬆地構建、訓練和部署計算機視覺模型。 Roboflow 提供了一系列工具和功能,使您能夠有效地處理圖像數據、訓練機器學習模型,並將這些模型集成到您的應用程序中。以下是 Roboflow 的一些主要特點和功能:

  • 數據預處理和清理: Roboflow 提供了數據預處理工具,可以幫助您對圖像數據進行清理、轉換和增強,以提高模型的訓練質量和性能。
  • 數據標註和註釋: 為了訓練計算機視覺模型,您需要標註圖像中的對象和特徵。 Roboflow 提供了圖像標註工具,可幫助您在圖像上繪製邊界框、進行分類標籤等操作。
  • 模型訓練: 您可以使用 Roboflow 訓練您的計算機視覺模型,選擇適當的架構並使用您的數據進行訓練。 Roboflow 支持多種常見的深度學習框架,如TensorFlow和PyTorch。
  • 模型評估和優化: 在訓練完成後,您可以使用 Roboflow 的評估工具來檢查模型在測試數據集上的表現,並進行模型的調優。
  • 模型部署: Roboflow 提供了將訓練好的模型部署到不同環境的選項,包括本地環境、移動設備和雲端。
  • 集成和 API: 您可以使用 Roboflow 的 API 將計算機視覺能力集成到您的應用程序中,以便自動處理圖像數據和執行預測。
  • 教程和資源: Roboflow 提供了豐富的教程、文檔和資源,幫助您了解計算機視覺的基礎知識和最佳實踐。

可讓團隊於線上共同標記圖片

這個功能是我覺得Roboflow大勝labelImg的原因,當團隊有很多人要負責標記時,這個工具可以非常方便的檢視、確認、共同標記。

可匯入現有的資料集及標記

Roboflow可以直接匯入以標記好的檔案,可以在線上去觀察以標記的資料的標記樣態,這些都是labelImg沒有辦法做到的,我們可以直接把含有標記和圖片的資料夾拉近網頁裡面,他會問你是否資料夾內的檔案全部放入,選擇Upload

就會可以看到已經標記好的狀況,我覺得這個功能在使用別人標記的圖檔時非常重要,才可以知道別人是如何去標記圖片的

線上做資料增強

Roboflow 提供了豐富的在線數據增強工具,用於處理圖像數據,改善數據集的多樣性,提高模型的泛化能力。數據增強是在保持圖像語義信息的前提下,通過應用各種變換和處理來生成多樣性的圖像,從而增加模型對於不同場景的適應能力。以下是 Roboflow 在線數據增強工具的一些功能和特點:

  • 旋轉和翻轉: 您可以輕鬆地對圖像進行旋轉、水平翻轉和垂直翻轉,從而生成不同角度和方向的圖像。
  • 縮放和裁剪: Roboflow 允許您調整圖像的尺寸、剪裁圖像以及生成不同分辨率的圖像,以增加模型對於不同大小的物體和場景的適應能力。
  • 亮度和對比度調整: 您可以調整圖像的亮度、對比度和飽和度,從而改變圖像的外觀和光照條件。
  • 噪聲和擾動: 添加噪聲、模糊效果和其他擾動可以幫助模型更好地應對真實世界中的噪聲和不確定性。
  • 顏色變換: 改變圖像的色彩分佈、色調和色溫,使模型能夠在不同的環境下進行準確的預測。
  • 隨機變換: Roboflow 提供了隨機化參數,可以在每次增強時以隨機方式應用不同的變換,從而生成更多樣化的數據。
  • 多模態增強: 對於多通道圖像(如RGB圖像),您可以單獨處理每個通道,或者應用通道之間的特定變換,以增加數據的多樣性。
  • 實時預覽: 在進行數據增強時,Roboflow 提供實時預覽功能,讓您可以在應用增強之前查看變換後的圖像。
  • 保存和導出: 您可以保存增強後的圖像,以便後續在模型訓練中使用。 Roboflow支持將增強後的數據導出到各種格式,如Yolo、COCO等。

按Generate可以做圖像預處理並選擇資料增強的方法,不過這邊圖片要輸出的若太多,就會要升級方案,免費方案沒辦法輸出破千張

線上建模

選擇Deploy頁籤,可以線上建模,並可以看到在測試資料及上的偵測狀況,我覺得最酷的是這一切都完全使用點、按就可以達成,完全no code

Posted on

YOLOv8模型訓練及其指標意義

訓練自定義的YOLOv8模型

以下為官網的一個範例程式

from ultralytics import YOLO

# Load a model
model = YOLO('yolov8n.yaml')  # build a new model from YAML
model = YOLO('yolov8n.pt')  # load a pretrained model (recommended for training)
model = YOLO('yolov8n.yaml').load('yolov8n.pt')  # build from YAML and transfer weights

# Train the model
results = model.train(data='coco128.yaml', epochs=100, imgsz=640)

範例中三種載入方式的比較

  • model = YOLO(‘yolov8n.yaml’):
    這段代碼使用給定的 YAML 配置文件構建一個新的 YOLO 模型。 YAML 配置文件包含了有關模型架構、層設置、超參數等的信息。通過提供 YAML 文件的路徑,可以創建一個全新的 YOLO 模型。(yaml檔案位於: ultralytics\cfg\models\v8)
  • model = YOLO(‘yolov8n.pt’):
    這段代碼加載一個預訓練的 YOLO 模型,該模型以 PyTorch 的 .pt 文件格式保存。預訓練模型已經在某個數據集上進行了訓練,並且包含了在該數據集上學到的權重。這個過程稱為遷移學習,它可以加快在新數據集上訓練模型的收斂速度,同時保留之前任務的特徵提取能力。
  • model = YOLO(‘yolov8n.yaml’).load(‘yolov8n.pt’):
    這段代碼首先使用給定的 YAML 配置文件構建一個 YOLO 模型,然後從預訓練的 .pt 文件中加載權重,將權重遷移到新構建的模型中。這使您可以根據自己的需求創建模型結構,然後將預訓練模型的權重用於該結構。這種方法允許您根據不同的目標任務進行微調或擴展。

YOLOv8 模型的每個類別中有五個模型

YOLOv8nYOLOv8sYOLOv8mYOLOv8lYOLOv8x
YOLOv8 Nano是最快和最小的,而YOLOv8 Extra Large(YOLOv8x)是最準確但最慢的

YOLOv8 使用了以下預訓練模型:

  • 在 COCO 檢測數據集上訓練的對象檢測,圖像分辨率為 640。
  • 在 COCO 分割數據集上訓練的實例分割,圖像分辨率為 640。
  • 在 ImageNet 數據集上預訓練的圖像分類模型,圖像分辨率為 224。

訓練指標分析

Intersection over Union指標

IoU(Intersection over Union)是一個用於評估目標檢測和分割任務的常用指標。它主要用於衡量預測的目標與實際目標之間的重疊程度。在機器學習和計算機視覺領域中,IoU通常用於衡量模型的預測準確度,特別是在處理像目標檢測、物體定位和分割等任務時。

IoU的計算方式是將預測的目標區域(通常是矩形框或分割區域)與實際目標區域的交集面積除以它們的聯集面積。公式如下:

其中,交集是預測區域和實際區域的重疊部分,聯集是預測區域和實際區域的整體合併部分。

在目標檢測中,當模型預測的目標框與實際目標框之間的IoU值越高,表示模型的預測越準確。通常,當IoU超過一個預定的閾值(例如0.5或0.7)時,可以將該預測視為成功檢測。這種指標可以用於計算Precision-Recall曲線以及平均精度(Average Precision)等性能指標。

在分割任務中,IoU用於衡量模型預測的分割區域與實際分割區域之間的相似度。當分割區域的IoU越高,表示模型的分割結果越準確。

mAP50(B)

mAP50(B) 是指”Mean Average Precision at IoU 0.50 for Large Objects”,意思是在IoU(Intersection over Union,重疊度)為0.50 的情況下,針對較大目標計算的平均精度(AP)值的均值。 mAP 是模型在不同類別上的平均精度值,而 mAP50(B) 是針對較大目標計算的平均精度值。

mAP50-95(B)

mAP50-95(B) 是指 “Mean Average Precision across IoU 0.50 to 0.95 for Large Objects”,意思是在 IoU 從 0.50 到 0.95 範圍內,針對較大目標計算的平均精度值的均值。這個指標更全面地評估了模型在不同重疊度下的性能。

precision(B)

precision(B) 是針對較大目標計算的精確率,即模型在預測中有多少是正確的,相對於所有預測中的正確和錯誤。它是衡量模型預測的準確性的指標之一。

recall(B)

recall(B) 是針對較大目標計算的召回率,即模型正確預測的目標數與實際目標數之比。它表示模型能夠檢測到多少實際目標。召回率是衡量模型識別能力的指標之一。

dfl_loss(Detection Focal Loss)

dfl_loss 是一種在YOLO目標檢測中引入的特殊損失函數,它是基於焦點損失(Focal Loss)的改進。焦點損失的主要目標是應對樣本不平衡問題,即正負樣本比例嚴重失衡。在目標檢測中,負樣本(即不含目標的區域)遠遠多於正樣本(含有目標的區域)。 dfl_loss 試圖通過放大難以分類的正樣本的損失,來應對這種不平衡,從而使模型更關注難以識別的目標。

box_loss(Box Regression Loss)

這是用於衡量預測框位置的損失函數。在目標檢測中,模型不僅要預測目標的類別,還要預測框的位置,即邊界框的中心坐標、寬度和高度。 box_loss 的目標是使模型的位置預測更接近真實目標框的位置。這有助於確保檢測到的框與真實目標框的位置相匹配,從而提高目標定位的準確性。

cls_loss(Class Classification Loss)

cls_loss 用於分類目標的類別。在YOLO中,每個檢測框需要預測它所屬的目標類別。 cls_loss 的作用是確保模型的類別預測盡可能準確。這對於準確地將檢測框與正確的目標類別關聯非常重要,從而實現了目標分類的準確性。

我的tensorborad訓練狀況

這邊深藍色的是使用YOLOv8m.pt做預訓練模型、淺藍色的是使用YOLOv8n,深藍色的跑了2個多小時(100次),淺藍色的因為懶得跑完只做了60幾次。橘色的是別人訓練的歷程。

為什麼自己訓練的結果即使所有資料集都一樣卻有不同的狀況,需要進一步去了解。

Posted on

Yolov8 – 物件偵測模型

模型介紹

GitHub位置: https://github.com/ultralytics/ultralytics

官方網站: https://ultralytics.com/

YOLOv8 最初由 Ultralytics 公司的開發人員開發和發布,旨在在目標檢測任務中提供高性能和高效率的解決方案。 基於深度學習和計算機視覺領域的前沿進步而構建,在速度和準確性方面提供無與倫比的性能。其流線型設計使其適用於各種應用程序,並可輕鬆適應從邊緣設備到雲 API 的不同硬件平台。

與之前的 YOLO 版本相比,YOLOv8 引入了一些新的設計思想和技術,以提高模型的精度和速度。它在模型結構、數據增強、網絡設計等方面進行了優化,使得在目標檢測任務中取得了出色的結果。 YOLOv8 不僅可以在通用的目標檢測任務中表現良好,還可以應用於各種應用領域,如自動駕駛、工業檢測、物體識別等。

模型安裝

官方的教學提供了非常明確的指導: https://docs.ultralytics.com/quickstart/

在這邊我選擇了使用pip安裝,只需要打下這一行就可以了

pip install ultralytics

用command line執行的方式如下

yolo predict model=yolov8n.pt source='https://ultralytics.com/images/bus.jpg'

用python執行偵測的方式

from ultralytics import YOLO

# Load a model
model = YOLO("yolov8n.yaml")  # build a new model from scratch
model = YOLO("yolov8n.pt")  # load a pretrained model (recommended for training)

# Use the model
model.train(data="coco128.yaml", epochs=3)  # train the model
metrics = model.val()  # evaluate model performance on the validation set
results = model("https://ultralytics.com/images/bus.jpg")  # predict on an image
path = model.export(format="onnx")  # export the model to ONNX format

官方建議使用的相關工具

建立一個物件偵測模型,需要做標註、影像增強、修改、訓練、佈署,以及將模型整合至使用端的程式。對於這些流程,Yolo提供了很完整的生態鏈去實現這些步驟

支持的任務

自己建立模型

下面是官方網站內一個包含建模、預測、輸出模型的程式碼範例

from ultralytics import YOLO

# Create a new YOLO model from scratch
model = YOLO('yolov8n.yaml')

# Load a pretrained YOLO model (recommended for training)
model = YOLO('yolov8n.pt')

# Train the model using the 'coco128.yaml' dataset for 3 epochs
results = model.train(data='coco128.yaml', epochs=3)

# Evaluate the model's performance on the validation set
results = model.val()

# Perform object detection on an image using the model
results = model('https://ultralytics.com/images/bus.jpg')

# Export the model to ONNX format
success = model.export(format='onnx')

我自己嘗試使用原有的模型訓練新的資料,在訓練過程中,會出現下面這樣的模型訊息

上面那些數值的解釋如下

  • Epoch (迭代輪數): 這是訓練過程中的迭代次數,每次迭代會處理數據集中的一批樣本。
  • GPU_mem (顯存佔用): 顯存是指圖形處理單元(GPU)上的內存,該數字顯示在當前迭代中 GPU 使用了多少顯存。
  • box_loss (框回歸損失): 這是目標檢測模型訓練中的一個損失項,用於優化檢測框的位置。
  • cls_loss (分類損失): 也是目標檢測模型訓練中的損失項之一,用於優化目標的分類預測。
  • dfl_loss (變換損失): 這可能是一種針對目標檢測中檢測框位置變換的損失。
  • Instances (實例數): 在每次迭代中,訓練過程處理的目標實例數量。
  • Size (尺寸): 可能是指輸入圖像的尺寸。
  • Class (類別): 指的是不同的目標類別。
  • Images (圖像數): 在評估模型性能時,所用圖像的數量。
  • Box (框)、P (精確率)、R (召回率): 這些是用於評估目標檢測模型性能的指標。精確率衡量模型在預測為正類的情況下有多少是正確的,召回率衡量模型在所有正類樣本中有多少被正確檢測出來。
  • mAP50、mAP50-95 (平均精確率): 這是在不同閾值下計算的平均精確率。 mAP50 表示在 50% 的 IoU 閾值下的平均精確率,而 mAP50-95 表示在 50% 到 95% 的 IoU 閾值範圍內的平均精確率。

以上圖而言,在第23輪的訓練其精度為48.4%,F1召回率為59%

處理圖片大小的不一致

YOLO原本建模時所使用的是COCO的資料集,在這個資料集裡面,圖片的長、寬皆為640px,但是實際上我們應用上所使用的圖片很可能並不是640×640的尺寸,這時候就要先對圖片做處理。

如果只是要做預測,可以直接使用resize_with_pad來對圖片做縮放,這個函數可以保持長寬比相同且不失真,將圖像大小調整為目標寬度和高度。如果目標尺寸與圖像尺寸不匹配,則會調整圖像大小,然後用零填充以匹配請求的尺寸。

但對於訓練,您還需要相應地調整邊界框的大小和填充邊界框,這並非易事。
這是如何完成此操作的示例https://nbviewer.jupyter.org/github/aleju/imgaug-doc/blob/master/notebooks/B02%20-%20Augment%20Bounding%20Boxes.ipynb

以下為幾個主要手法:

  • 調整輸入尺寸:你可以將攝像機圖像調整為與 YOLO 模型訓練時使用的正方形尺寸相匹配。這可能會導致圖像在寬度或高度上出現一些留白,但能夠與模型兼容。
  • 圖像裁剪:將攝像機圖像進行裁剪,以適應 YOLO 模型所需的正方形尺寸。你可以從圖像的中心或其他感興趣的區域進行裁剪,以確保包含重要的目標信息。
  • 填充:如果圖像的長寬比與模型所需的正方形尺寸不匹配,你可以在圖像的較短邊或較長邊添加填充,使其達到正方形尺寸。填充可以使用一些背景顏色或內容進行填充,以保持圖像比例。
  • 訓練新模型:如果你的攝像機圖像尺寸與標準的 YOLO 輸入尺寸差異較大,並且以上方法不適用,你可能需要考慮訓練一個新的 YOLO 模型,以適應你的攝像機圖像尺寸。這樣可以確保模型在不同尺寸的圖像上都有良好的性能。

無論你選擇哪種方法,都需要注意到調整輸入尺寸可能會對模型性能產生影響,特別是在目標檢測任務中。你可能需要在實際場景中進行測試和調整,以找到最適合你應用的方法。

Posted on

PyTorch於Mac系統下的安裝教學

環境架設

相關教學文章: https://github.com/pytorch/pytorch

首先,PyTorch需要 Python 3.8.1以上的環境,先安裝Anaconda,接著設定一個虛擬環境使用py3.8.1

conda create -n aia16 python=3.8.1
conda activate aia16

切換到新創建的環境之後,就依照下面的步驟下載PyTorch

git clone --recursive https://github.com/pytorch/pytorch
cd pytorch
# if you are updating an existing checkout
git submodule sync
git submodule update --init --recursive

編譯PyTorch

當你運行python setup.py develop來安裝PyTorch(或任何其他Python套件)時,這個命令的目的是在”開發模式”下安裝該套件。這意味著源代碼的更改會立即反映到Python環境中,無需重新安裝。

但是對於像PyTorch這樣的大型項目,這個過程可能會變得相對緩慢。如果你只是想試用PyTorch而不是開發它,那麼通常建議直接從官方渠道安裝預編譯的版本,這樣會快得多。(可以跳過此步驟)

安裝編譯所需工具

conda install cmake ninja
# Run this command from the PyTorch directory after cloning the source code using the “Get the PyTorch Source“ section below
pip install -r requirements.txt
# Add this package on intel x86 processor machines only
conda install mkl mkl-include
# Add these packages if torch.distributed is needed
conda install pkg-config libuv

開始編譯

python3 setup.py develop

直接安裝PyTorch

使用預編譯的二進制檔案安裝PyTorch是相對簡單的。以下是使用pip或conda安裝PyTorch的方法:

使用pip安裝

pip install torch torchvision

使用conda安裝

conda install pytorch torchvision -c pytorch

下載第一個測試專案

https://github.com/pytorch/ios-demo-app

首先要先安裝依賴管理套件cocoapods,安裝指令如下:

sudo gem install cocoapods

cocoapods安裝失敗解決方法

https://stackoverflow.com/questions/69460048/unable-to-install-cocoapods-in-macos-monterey-version-12-0-beta-xcode-13-013a

用homebrew安裝

brew install cocoapods

安裝依賴項

先把目錄切到有PodFile的位置,然後下指令

pod install