Posted on

AI大師論壇:人工智慧如何形塑人類未來

YOUTUBE連結: https://www.youtube.com/watch?v=k7aFffQn5vU

本篇文章所有圖片皆來自於永齡基金會 YouTube

講者介紹

吳恩達(1976-,英文名:Andrew Ng),華裔美國人,是斯坦福大學計算機科學系和電子工程系副教授,人工智能實驗室主任。吳恩達是人工智能和機器學習領域國際上最權威的學者之一。吳恩達也是在線教育平台Coursera的聯合創始人(with Daphne Koller),DeepLearning.AI創始人。

他的其他分享

AI 大神吳恩達降臨──告訴你如何成為創新者

【ChatGPT 之父來台】Sam Altman、吳恩達重磅開講!談 AI 將如何顛覆世界

現在AI應用的狀況

兩個重要的概念

  1. 監督式學習:需要label,從2015起大多的應用都是監督式學習,即便是不同的應用但大多屬於監督式學習
  2. 生成AI: 而現在則到了生成式AI的時代,CHATGPT利用不停地去預測下一個字來完成文字的生成,可以產生非常長的文字。
現在監督式學習模型為最大宗應用

大模型的時代

從2010-2020,進入了GPU加速的大模型的時代。這是因為GPU的支持,讓模型可以學習更多的資料,這也讓生成式AI有機會發展起來

AI的革命 – 生成式AI的發展

CHATGPT利用不停地去預測下一個字來完成文字的生成,可以產生非常長的回應文字。吳恩達認為這樣的生成式模型會很大的改變現有的模型生態

生成式AI如何改變建模的過程

以前的監督式學習需要
拿到label資料->建模->部屬
現在則只需要
指定prompt->部屬

吳恩達在現場分享,不同的 AI 分屬不同領域,包含生成式 AI、監督式學習等。他指出,過去 10 年是生成式 AI 的 10 年,如今生成式 AI 僅處於早期的成功階段,未來潛力仍大,如果要達到真正的通用,至少還要 30,甚至 50 年。

他認為,或許現在大家已看到很多生成式 AI 的消費端應用,但更讓他興奮的是開發端的發展。過去很多 AI 應用需要花 6 個月打造,現在已可以讓成千上萬的人,透過生成式 AI 將開發過程降低至幾天內。他認為 AI 的未來,還有許多機會是給開發者的。

Generative AI 的課程很重要

他認為企業應該賦能員工,因為生成式AI會是下一個顛覆AI產業的應用,可以讓員工在這些地方學習Generative AI

三年內生成式AI的數量會增長一倍

他認為現在雖然監控式模型是大多數的應用,而生成很少,但未來會改變,三年內預計生成式AI會大增。而他認為監督式學習的應用成長幅度則會減低,因為未來的建模會更偏向廣泛化功能的建模(生成模型)

雖然生成式 AI 要追上發展已久的監督式 AI 的產值還有一段距離,但其成長速度驚人。台灣的開發者團隊在全球人工智慧領域也做出了重要貢獻。他也舉例自己從共同創辦人那裡獲得將 AI 導入船運業的點子,同理也期望在台灣激發如農業、工業領域更多類似的 AI 創業點子。

他舉出一個APP就是可以把你的照片變成太空人的照片的APP,叫做LENSA,他們的營收在去年12月到最高,然後就掉下去了,這是因為這是一個很單純的APP,很快地就會風潮過去。而大多數能夠屹立不搖、一直被使用的軟體,都要經過很多時間的考驗

為什麼在台灣AI還沒有廣泛被採用

為什麼在台灣AI還沒有廣泛被採用,這是因為還很難使用no code/low code的方式去建模,他還舉了披薩工廠的例子,說明未來很可能建模就會像是在產生一個披薩。未來自己建模的機率會大幅降低,因為客製化建模很可能no code就可以達成,只需要做prompts。不再需要大量的標註資料

他指出,有許多領域專案本身具有高價值的生意,例如廣告、搜尋業務,自然吸引許多工程師投入;不過有些總價值沒那麼高、較為長尾的小型生意,例如餐廳,對於大型科技公司來說投入的吸引力較低。

這是AI應用上非常重大的一個革命,未來企業將可以用非常省成本的方式採用AI

The AI stack

企業要使用AI所需要擁有的資源

他提到 AI 的基礎架構、開發者工具市場已經有一些贏家、高度競爭,也獲得了大量外界關注;但還有一塊是 AI 未來的發展重點── App 應用程式,而這高度需要合作夥伴。人工智慧(AI)被認為將成為未來社會的基礎設施,就像水和電網一樣不可或缺。監督式學習和生成式 AI 是兩個關鍵領域。

AI的危機

  • 偏見、歧視、不正確的資訊=>這些部分正在快速改進中
  • 職業被自動化取代=>但是要取代所有人類的工作還要很久很久
  • 國際化會變得非常的快速、資訊更加爆炸,但在一些突發狀況中,如瘟疫、氣候改變等,AI的腳色會變得十分關鍵

新創如何使用生成式AI

https://bearing.ai/

這個吳恩達投資的公司在很短很短的時間建立了航運預測的AI軟體,猛猛搭~

擁有生成式AI的技術可以更快速的建立所需要的模型

Posted on

使用現有模型標記新圖片

Auto Labeling

因為在標記時常會花費很多的時間和力氣,現在市面上有許多auto labeling的工具,例如前一陣子meta有發表一個模型,還引起注目叫做SAM: https://segment-anything.com/

以下為一個簡單的使用範例

from segment_anything import sam_model_registry, SamAutomaticMaskGenerator, SamPredictor
import matplotlib.pyplot as plt
import cv2
import numpy as np
def show_anns(anns):
    if len(anns) == 0:
        return
    sorted_anns = sorted(anns, key=(lambda x: x['area']), reverse=True)
    ax = plt.gca()
    ax.set_autoscale_on(False)

    img = np.ones((sorted_anns[0]['segmentation'].shape[0], sorted_anns[0]['segmentation'].shape[1], 4))
    img[:,:,3] = 0
    for ann in sorted_anns:
        m = ann['segmentation']
        color_mask = np.concatenate([np.random.random(3), [0.35]])
        img[m] = color_mask
    ax.imshow(img)
    
image = cv2.imread('./train/IMG_5208_jpg.rf.d85b8d233845117f0362c17ca2222c21.jpg')
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

sam_checkpoint = "sam_vit_h_4b8939.pth"
model_type = "vit_h"

device = "cpu"

sam = sam_model_registry[model_type](checkpoint=sam_checkpoint)
sam.to(device=device)

mask_generator = SamAutomaticMaskGenerator(sam)
masks = mask_generator.generate(image)
print(len(masks))
print(masks[0].keys())

plt.figure(figsize=(20,20))
plt.imshow(image)
show_anns(masks)
plt.axis('off')
plt.show() 

成果如下:

Roboflow的智慧圈選工具

在Roboflow也有類似的智慧圈選工具,可以自動為我們圈選目標的形狀,使用方式如下

使用現有模型標記YOLO格式label

但是若我們想要使用既有的模型訓練一些新的圖片,在新的圖片,若要標記一些常見的物品,如汽車、人、機車等…。這些東西因為在YOLO這種模型,預設的偵測狀況就很不錯了,有的時候為了要讓標記更快速,可以使用現有模型把預測的結果轉為標記檔案,再匯入Roboflow等標記軟體檢視標記狀況並修正錯誤的標記,會可以使標記工作更輕鬆。

預測結果轉標記程式碼

這邊是預測的result的相關文件: https://docs.ultralytics.com/reference/engine/results/#ultralytics.engine.results.Results.tojson

我真的覺得yolov8做的很用心的點,在於他的說明超級清楚,尤其是在程式碼本身上面,我們可以單單藉由下面程式碼印出詳細返回的物件結構,然後就可以了解該如何取得我們所需的物件資訊

from ultralytics import YOLO

# Load a model
model = YOLO('yolov8n.pt')  # pretrained YOLOv8n model

# Run batched inference on a list of images
results = model(['im1.jpg', 'im2.jpg'])  # return a list of Results objects

# Process results list
for result in results:
    boxes = result.boxes  # Boxes object for bbox outputs
    masks = result.masks  # Masks object for segmentation masks outputs
    keypoints = result.keypoints  # Keypoints object for pose outputs
    probs = result.probs  # Probs object for classification outputs
    print(masks )

從API我們可以得知,若我們使用的是yolo-seg,則吐回的座標資訊可參考這個返回值

完整預測結果轉標記的程式範例

設定folder_path到images的資料夾,label會放到相對應的labels資料夾下

from ultralytics import YOLO
from PIL import Image
import cv2
import os

# 資料夾路徑
folder_path = './datasets/coco8-seg/images/train'
images = []
# 確保資料夾存在
if not os.path.exists(folder_path):
    print("資料夾不存在")
else:
    # 取得資料夾內所有檔案
    file_list = os.listdir(folder_path)
    
    # 遍歷每個檔案
    for filename in file_list:
        # 確保檔案是圖片檔案(可根據您的需求調整)
        if filename.lower().endswith(('.png', '.jpg', '.jpeg')):
            # 構建完整的檔案路徑
            file_path = os.path.join(folder_path, filename)
            
            images.append(file_path)

# Load a model
model = YOLO('yolov8n-seg.pt')  # pretrained YOLOv8n model

# Run batched inference on a list of images
results = model(images)  # return a list of Results objects


# Show the results
for r in results:
    formatted_string = ""
    if r is not None and r.masks is not None:
        for i in range(len(r.masks.xyn)):
            mask = r.masks.xyn[i]
            cls = int(r.boxes.cls[i].item())
            formatted_rows = []
            formatted_rows.append(cls)
            for row in mask:
                formatted_rows.append(row[0])
                formatted_rows.append(row[1])

            formatted_string = ((formatted_string + '\n') if formatted_string != "" else "") + " ".join(str(x) for x in formatted_rows)
        with open(r.path.replace('.jpg', '.txt').replace('images', 'labels'), "a") as file:
            file.write(formatted_string)

把YOLO格式轉為COCO格式

請參考此專案: https://github.com/Taeyoung96/Yolo-to-COCO-format-converter/tree/master

Posted on

尋找pretrain model的好地方

https://paperswithcode.com/sota

“SOTA” 是 “State-of-the-Art” 的縮寫,意為 “最先進技術”。在計算機科學和人工智能領域,SOTA模型指的是當前被認為是在某個特定任務或領域內表現最優秀的模型或方法。這些模型通常代表了當前領域內的最高水平,並在諸如自然語言處理、計算機視覺、語音識別等各種任務中發揮著重要作用。

Posted on

如何把docker image推到AKS

請參考此說明: https://docs.docker.com/cloud/aci-integration/

首先請登入Azure

會跳出瀏覽器登入Azure的帳號和docker做連接

docker login azure

接著創立aci的context

docker context create aci myacicontext

使用docker context ls可以檢視現在有哪些context

接著這樣就可以把image部屬上AKS了

docker --context myacicontext run -p 80:80 nginx

推送自建的container

https://learn.microsoft.com/zh-tw/training/modules/intro-to-containers/7-exercise-deploy-docker-image-to-container-instance

1.建立容器

2. 改名並推送上去

docker tag reservationsystem:latest <registry-name>.azurecr.io/reservationsystem:latest
docker image ls
docker login <login-server>
docker push <registry-name>.azurecr.io/reservationsystem:latest
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