Posted on

高壓縮比編碼格式的介紹 – HEVC

HEVC(H265)介紹

HEVC(High Efficiency Video Coding),也稱為H.265,是一種先進的視頻編解碼標準,是H.264/MPEG-4 AVC的後繼者。相較於H.264,HEVC可以提供更高的視頻質量、更少的碼率和更高的壓縮效率。
HEVC採用更高級的壓縮算法,通過增加更多的預測模式、增加更多的參考幀以及使用更高級別的變換和量化技術,實現了更高的壓縮比。在同樣的視頻質量下,HEVC可以減少50%以上的比特率。
HEVC支持分辨率高達8192×4320的超高清視頻,可以處理各種類型的視頻內容,包括高速運動、低比特率和高動態範圍內容。 HEVC還可以支持多種顏色空間、高級色彩映射和多視點視頻。
由於HEVC壓縮效率高,可以在更低的比特率下提供更高的視頻質量,因此被廣泛用於高清和超高清視頻的傳輸和存儲,例如藍光光盤、在線視頻流媒體、視頻會議等。

瀏覽器對於HEVC的支持


上面若有不支持的瀏覽器,只要支持webassembly,就可以透過webassembly來實現解碼的部分
使用webassembly來達成全平台HEVC的播放器

支持推流端的HEVC透過RTMP推流

OBS在版本29版之後增加的新的編碼支持(H265及AV1)
現在可以透過OBS來推送HEVC格式的流了。

https://blog.csdn.net/karamos/article/details/103508790
FLV規範不支持HEVC(H.265)/AV1,FFmpeg社區對FLV的新視頻編碼算法CodecID也沒有新增定義支持,騰訊視頻雲T-FFmpeg(騰訊視頻雲的FFmpeg維護版本)正在推動社區支持封裝/解封H.265/AV1的FLV的補丁。目前,國內各直播CDN廠商基本支持H.265的封裝和解封,而騰訊視頻雲則針對FLV支持AV1進行了一系列優化。

go2rtc

go2rtc
因為WebRTC是一個非常低延遲的封裝格式,有人寫了這個工具,可以把所有封裝格式的串流轉為WebRTC格式,但是現在WEBRTC對H265的支持仍不高
以下為支持表

Safari 支持 WebRTC,如果您通過以下方式啟用它:

英文版:Develop > Experimental Features > WebRTC H265 codec
中文版:开发 > 实验性功能 > WebRTC H265 codec

Posted on

高壓縮比編碼格式的介紹 – AV1

高壓縮比編碼格式AV1介紹

AV1是一種免費、開源的視頻編解碼器,由Alliance for Open Media(AOMedia)聯盟開發。它是H.265(HEVC)的競爭對手,旨在提供更高的壓縮效率和更好的視頻質量。
AV1使用了許多新技術來提高壓縮效率,例如可變帶寬預測、可變塊大小和可變熵編碼等。與H.265相比,AV1在相同的比特率下可以提供更高的視頻質量。同時,AV1還具有更好的自適應流媒體性能,可以更好地適應網絡帶寬的變化。
AV1可以支持多種分辨率和色彩空間,包括8位、10位和12位色彩深度。此外,它還可以支持HDR(高動態範圍)和WCG(廣色域)等高級視頻格式,以提供更真實的圖像質量。
由於AV1是一種開放標準,並且沒有專利費用,因此它被廣泛用於在線視頻流媒體服務和其他應用,例如YouTube、Netflix、Amazon Prime Video等。同時,AV1還適用於各種類型的視頻內容,包括電影、電視節目、動畫和遊戲。

常見的編碼器

SVT-AV1和AOM-AV1

SVT-AV1和AOM-AV1都是AV1編碼器,不過它們有幾個不同之處:

  • 開發者:SVT-AV1是由英特爾開發的,而AOM-AV1是由Alliance for Open Media(AOM)開發的。
  • 編碼質量:SVT-AV1相對於AOM-AV1來說,可以提供更高的編碼質量,尤其是在高比特率下。
  • 編碼速度:AOM-AV1的編碼速度相對於SVT-AV1來說更快,這對於需要實時編碼的場景非常重要。
  • 適用範圍:SVT-AV1更適用於需要高質量視頻編碼的場景,如影片後期製作等;而AOM-AV1更適用於實時編碼的場景,如視頻通話、視頻會議等。

甚麼是AV1 SVC

AV1 SVC中的SVC是指可伸縮視頻編碼(Scalable Video Coding)。可伸縮視頻編碼是一種視頻編碼技術,可以將視頻數據分成多個層級,每個層級可以根據不同的要求進行編碼和解碼。這種編碼技術可以在不同的設備和網絡帶寬上提供不同的視頻質量和分辨率。在AV1 SVC中,視頻數據被分成多個空間和時間層級。空間層級是根據空間分辨率進行編碼的,例如低分辨率圖像和高分辨率圖像。時間層級是根據時間分辨率進行編碼的,例如低幀率和高幀率圖像。這些層級可以按需選擇和合併,以提供適合設備和網絡帶寬的最佳視頻質量。+

AV1 SVC可以提供更高的編碼效率和更好的視頻質量,同時可以適應不同的設備和網絡環境。這使得它非常適合用於實時視頻流傳輸、視頻會議和移動通信等應用場景。AV1是第一個支持SVC的編解碼器。對於那些對關於SVC是如何發揮作用的更多細節感興趣的人,Alex E.博士在2016年寫了一篇很好的解釋性博文。寫的是關於VP9,大多數點對AV1有效的內容。

SVT-AV1和AOM-AV1都支持可伸縮視頻編碼(SVC),但是它們支持的SVC規格略有不同。具體而言:

  • SVT-AV1支持SVC的規格是MPEG-5 Part 2 LCEVC(Low Complexity Enhancement Video Coding),這是一種用於增強現有編碼器的規格,可以提高編碼效率和視頻質量。
  • AOM-AV1支持的SVC規格是AV1 Scalable Video Technology(SVT),這是一種基於AV1的可伸縮視頻編碼技術,可以實現在不同的網絡帶寬和終端設備之間動態調整視頻質量和分辨率。

非常適合用於會議場合

AV1旨在與下一波WebRTC視頻創新集成:端到端加密,SVC和獨立於編解碼器的轉發。因此,這與視頻編解碼器無關,而與下一代架構有關。

1. 隨著WebRTC現在通過可插入流(和SFrame)合併了E2E加密,並且NSA現在推薦E2E安全性,由於有效負載可能是不透明的,因此會議系統需要RTP標頭擴展來轉發數據包。因此,如果瀏覽器和編解碼器不支持可插入流或與下一代編解碼器集成的轉發頭擴展名,則將無法滿足NSA的要求,並且會議供應商將無法提供完整的功能。

2. SVC支持對於會議很重要。AV1內置了SVC;在HEVC中,它是一個擴展。Dependency Descriptor(在AV1 RTP有效負載規範中定義)優於用於空間可伸縮性模式的Framemarking RTP標頭擴展。如果瀏覽器(和下一代編解碼器)不支持帶有轉發頭擴展名的SVC,那麼它就沒有競爭力。

3. AV1包含屏幕編碼工具作為基本功能,而不是像HEVC中的擴展。這是會議的主要競爭優勢。”

屏幕共享

對於文本內容以及超高動態內容,在對屏幕內容進行編碼時,AV1都非常高效。實際上,AV1實時的性能非常優越,以至於像Cisco在Webex中所做的那樣,AV1實時可能只部署在單個使用案例中。

在共享屏幕或應用程序時,如果選擇了“優化運動和視頻”,並且您所在的機器至少有四個內核,則支持傳輸AV1。任何至少有兩個內核的機器都支持接收AV1。只要會議的所有參與者都支持AV1,AV1就會自動用於共享此類屏幕內容,否則它將自動恢復為H.264。

有趣的是,這里分別提到了4和2個內核的約束條件。思科在2019年6月的大蘋果大會上進行現場演示時也發表了同樣的觀點。

我們將在下一個部分中繼續討論性能的問題,但是為了提供相關的背景信息,MacBook Air自2008年以來一直使用具有2個內核的Intel core-2芯片,並且自2011年以來在MacBook Pro中具有4個或更多內核的Intel i7或更高版本。就筆記本電腦和台式機而言,預計擁有4個內核並不是一個大問題。

端到端加密

E2EE是下一件值得關注的問題。也許是因為這是webrtc最初許下的承諾之一。又或許是因為它成為了一個過度使用的營銷術語,而Zoom已經變得遍體鱗傷。也許是因為大多數人仍然聲稱擁有它,實際上卻沒有。

關於E2EE,對這個問題最好的回應之一是Emil Ivov的這篇演講。

雖然許多人認為E2EE加密只是一種視頻會議或聊天應用程序功能,但它在整個媒體行業中都以縮寫“DRM”(數字版權管理)的形式使用。然而,傳統的DRM在瀏覽器和媒體播放器中的實現並不是真正的端到端的,只涵蓋了交付這一模塊。當人們上傳他們的內容到一個平台時仍然需要信任這個平台(以及任何可以合法訪問或不合法訪問該平台的人)與他們的原始內容。

真正的E2EE要求在對媒體進行編碼時在源處對媒體進行加密,並且僅在播放時對其進行解密。它允許內容提供商不信任該平台。

WebRTC可通過插入流API方案來得到了廣泛的應用,因為它可以用於很多方面。它是使您能夠訪問媒體的API,也是啟用E2EE的必要步驟。但是,它本身沒有加密功能或加密密鑰管理功能。

推流端支持AV1的相關資料

SRS在4.0.91開始支持經過WebRTC去推流AV1
RTC: Support av1 for Chrome M90 enabled it. 4.0.91
事實上,這已經是瀏覽器內建就可以做到的了。針對WEBRTC而言,Chrome已經在90版之後支持AV1編碼
Google Chrome 90 正式版發佈,支援 AV1 解碼

另外騰訊雲則可支持使用AV1格式推流
實現直播AV1 編碼

解碼端支持AV1的相關資料

騰訊雲有自己開發出可支援AV1透過FLV格式來解碼
播放AV1格式視頻

播放AV1視頻

通過支持AV1的播放器,按播放步驟3中生成的地址進行播放即可。在播放器的選擇上,可以選擇已支持AV1的播放器,也可以對自有播放器進行改造。

已支持AV1的播放器

App 客戶端

1. ExoPlayer已支持AV1,用的libgav1
2. ijkplayer FFmpeg 版本陳舊,可以升級FFmpeg 並集成dav1d

Web 端

1. dash.js已經支持(解碼取決於瀏覽器,Chrome 支持)
2. shaka-player已經支持(解碼取決於瀏覽器,Chrome 支持)

PC 端

VLC PC 版,支持AV1 in FLV、HEVC in FLV, 可按需下載Windowos 版& MacOS 版

Posted on 1 Comment

OBS在版本29版之後增加的新的編碼支持(H265及AV1)

OBS支持HEVC推流

OBS在v29版本之後支持了HEVC推流,支持利用RTMP的封裝方式來推送H265編碼的串流格式,若電腦沒有可支持硬編碼的GPU,其CPU編碼所採取的編碼方案是QuickSync HEVC。

若是電腦有可支持硬編碼的GPU,則下拉選單會增加該硬件編碼的編碼選項

支持AV1及HEVC的錄影格式

並且可以錄製SVT-AV1、AOM-AV1和HEVC的格式的影片

Posted on

為SRS6編譯支持HTTP-FLV的FFMPEG檔案

SRS介紹

SRS是一個簡單高效的實時視頻服務器,支持RTMP/WebRTC/HLS/HTTP-FLV/SRT/GB28181。
是一個運營級的互聯網直播服務器集群並發7.5k+,支持多種轉碼,RTMP->HLS,RTMP->FLV等,支持HTTP回調,RTMP0.1s延時
在HTTP-FLV的低延遲實踐方案上,可以說是繼FMS之後,非常有用心地在更新、維護的一個開源專案

主要開發者很熱心地回答問題,相關的文件也隨著時間越來越完整,使用的人數也越來越多,是一個高效能且穩定的開源串流服務器。

SRS6.0已支持H.265編碼格式

在SRS 6.0之中,很開心我們終於看到SRS支持H265了,這其中很重要的一個工作就是我們需要在推流端能夠讓RTMP的FLV格式推流能夠支持H265。
但是,若我們使用從FFMPEG官網下載的.EXE檔案,即便我們使用ffmpeg -version顯示支持H265,在實際推H265的流時仍然會發生錯誤。

錯誤訊息如下圖

這個錯誤代表說,官方所提供的版本雖然支持H.265,但是卻不支持使用FLV來封裝H.265的編碼格式。

為FFmpeg增加支持HEVC over RTMP的補丁

對於SRS6.0支持HEVC over RTMP的詳細說明於此: https://github.com/ossrs/srs/issues/465

支持 HEVC over RTMP 或 FLV 的規範和用法。runner365為FFmpeg提供了FFmpeg 4.1/5.1/6.0 的補丁,以支持通過 RTMP 或 FLV 的 HEVC。Intel也有針對此功能的補丁。

這裡面提到說,SRS 6之所以能夠支持H265 over RTMP是因為使用了runner365自己為ffmpeg所增加的補丁功能。官方的版本並不支持HEVC over RTMP,若我們希望使用RTMP來推流H265,則需要重新編譯包含這份補丁的FFMPEG執行檔案。

另外要注意的是,雖然,但是應該是它們採用HEVC支持RTMP的實作方式與SRS6.0使用的FFMPEG方案並不一致,若是使用OBS的v29.0.2推H265的流到SRS伺服器,伺服器並沒有辦法正確的解析串流內容,因此,在推流時,一定要使編譯過的(runner365的補丁版本)、可支援HEVC over RTMP的FFMPEG來推流,才可以正確把H265的流推送到SRS。

這邊是官方如何編譯ffmpeg的教學:
https://github.com/ossrs/srs/issues/465#ffmpeg-tools

使用ffmpeg推流HEVC格式的影片,其重點在於將vcodec指定為libx265

ffmpeg -i sample.mp4 -c:v libx265 -b:v 350k -f flv rtmp://127.0.0.1/live/livestream

以下指令可推送極低延遲的H.265影片

ffmpeg -i sample.mp4 -c:v libx265 -crf 28 -x265-params profile=fast -preset veryfast -tune zerolatency -b:v 300k -minrate 300k -maxrate 300k -f flv rtmp://127.0.0.1/live/livestream

如何在linux裡面編譯支持H265 over rtmp的ffmpeg

支持 HEVC over RTMP 或 FLV 的規範和用法。 runner365 為 FFmpeg 提供了 FFmpeg 4.1/5.1/6.0 的補丁,以支持通過 RTMP 或 FLV 的 HEVC。

在編譯ffmpeg之前,要先編譯libx264

cd ~/git
git clone https://code.videolan.org/videolan/x264.git
cd ~/git/x264
./configure --prefix=$(pwd)/build --disable-asm --disable-cli --disable-shared --enable-static
make -j10
make install


以及libx265

cd ~/git
git clone https://bitbucket.org/multicoreware/x265_git.git
cd ~/git/x265_git/build/linux
cmake -DCMAKE_INSTALL_PREFIX=$(pwd)/build -DENABLE_SHARED=OFF ../../source
make -j10
make install


接著載入HEVC over RTMP/FLV的補丁:

cd ~/git
git clone -b 5.1 https://github.com/runner365/ffmpeg_rtmp_h265.git
cp ~/git/ffmpeg_rtmp_h265/flv.h ~/git/FFmpeg/libavformat/
cp ~/git/ffmpeg_rtmp_h265/flv*.c ~/git/FFmpeg/libavformat


然後編譯ffmpeg

cd ~/git/FFmpeg
env PKG_CONFIG_PATH=~/git/x264/build/lib/pkgconfig:~/git/x265_git/build/linux/build/lib/pkgconfig \
./configure \
  --prefix=$(pwd)/build \
  --enable-gpl --enable-nonfree --enable-pthreads --extra-libs=-lpthread \
  --disable-asm --disable-x86asm --disable-inline-asm \
  --enable-decoder=aac --enable-decoder=aac_fixed --enable-decoder=aac_latm --enable-encoder=aac \
  --enable-libx264 --enable-libx265 \
  --pkg-config-flags='--static'
make -j10


嘗試推流

./ffmpeg -stream_loop -1 -re -i ~/srs/doc/source.flv -acodec copy -vcodec libx265 \
  -f flv rtmp://localhost/live/livestream
Posted on

使用OpenCV判別圖像清晰度

3種清晰度評價方法

  • Tenengrad梯度方法: Tenengrad梯度方法利用Sobel算子分別計算水平和垂直方向的梯度,同一場景下梯度值越高,圖像越清晰。以下是具體實現,這裡衡量的指標是經過Sobel算子處理後的圖像的平均灰度值,值越大,代表圖像越清晰。
  • Laplacian梯度方法: Laplacian()變換不需要區分圖像的x和y方向計算梯度,從上圖的2種kernel也可以看到其x和y方向是對稱的。
  • 方差方法: 方差是概率論中用來考察一組離散數據和其期望(即數據的均值)之間的離散(偏離)成都的度量方法。方差較大,表示這一組數據之間的偏差就較大,組內的數據有的較大,有的較小,分佈不均衡;方差較小,表示這一組數據之間的偏差較小,組內的數據之間分佈平均,大小相近。

圖像清晰度識別之Laplacian算子

Laplacce算子是一種各向同性算子,二階微分算子,在只關心邊緣的位置而不考慮其周圍的像素灰度差值時比較合適。Laplace算子對孤立像素的響應要比對邊緣或線的響應要更強烈,因此只適用於無噪聲圖像。存在噪聲情況下,使用Laplacian算子檢測邊緣之前需要先進行低通濾波。所以,通常的分割算法都是把Laplacian算子和平滑算子結合起來生成一個新的模板。

從模板形式容易看出,如果在圖像中一個較暗的區域中出現了一個亮點,那麼用拉普拉斯運算就會使這個亮點變得更亮。因為圖像中的邊緣就是那些灰度發生跳變的區域,所以拉普拉斯銳化模板在邊緣檢測中很有用。一般增強技術對於陡峭的邊緣和緩慢變化的邊緣很難確定其邊緣線的位置。但此算子卻可用二次微分正峰和負峰之間的過零點來確定,對孤立點或端點更為敏感,因此特別適用於以突出圖像中的孤立點、孤立線或線端點為目的的場合。

在圖像處理中,圖像的清晰程度可以被表示為圖像的邊緣和顏色變化的強度。圖像的清晰度越強,邊緣和顏色變化的強度就越高。因此,通過評估圖像的清晰度,可以檢測圖像是否模糊。

使用範例和結果

import numpy as np
import cv2
from os import listdir
import re
files = [f for f in listdir('./wrong2/') if re.match(r'.*\.jpg', f)]
for i in range(len(files)):
    image = cv2.imread("./wrong2/"+files[i])
    image = cv2.resize(image, (100, 120))
    image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
    # Calculate the Laplacian of the image
    laplacian = cv2.Laplacian(image, cv2.CV_64F)
    score = np.var(laplacian)
    print(files[i], score)
cv2.waitKey(0)

下面這張圖片的分數為1099.5216466388888

而這張為2966.9266674375

所以可以知道,由於拉普拉斯是在求邊緣,而模糊偵測就會是一種比較級的狀況,也就是說,如果一個動態的影片,前一偵的邊緣多,後一偵突然變少,有可能就是因為正在移動而造成的模糊導致邊緣變少

Posted on

建立模型與並使用模型來預測資料

從本機圖片建立模型的簡單範例

以下為從classify資料夾內載入圖片並建構分類模組的範例。圖片資料夾的結構如下:

其中daisy、dandelion、roses、sunflowers、tulips為標籤名稱,在各個資料夾內為圖片

然後使用 image_dataset_from_directory 函數載入圖片,需要傳遞以下參數:

  • directory:包含圖片的目錄。
  • labels:標籤的名稱。預設情況下,每個圖片所在的子目錄將被當作標籤。
  • class_names:標籤的名稱列表。
  • label_mode:標籤的格式。可以是 ‘int’(預設值)、’binary’ 或 ‘categorical’。
  • batch_size: 用於指定每個批次中包含的圖片數量。

在載入圖片時,tf.keras.utils.image_dataset_from_directory 函數會使用 RGB 色彩空間。

tf.keras.utils.image_dataset_from_directory 函數中的 seed 參數用於設置隨機數生成器的種子。

如果指定了 seed 參數,則在載入資料集時,將使用指定的種子初始化隨機數生成器,這樣可以保證每次載入資料集的順序都是一致的。

# TensorFlow and tf.keras
import tensorflow as tf
import pathlib
# Helper libraries
import numpy as np
import matplotlib.pyplot as plt
from keras.callbacks import Callback
print(tf.__version__)

batch_size = 32
img_height = 150
img_width = 150

data_dir = pathlib.Path('flower_photos')
# 從資料集中取出訓練資料,需要將 subset 參數設置為 'training'。
train_ds = tf.keras.utils.image_dataset_from_directory(
    data_dir,
    validation_split=0.2,
    subset="training",
    seed=123,
    image_size=(img_height, img_width),
    batch_size=batch_size)
# 同時設定了 subset 參數和 validation_split 參數,則會從資料集中取出指定的子集作為驗證集。
val_ds = tf.keras.utils.image_dataset_from_directory(
    data_dir,
    validation_split=0.2,
    subset="validation",
    seed=123,
    image_size=(img_height, img_width),
    batch_size=batch_size)

class_names = train_ds.class_names
print(class_names)

image_batch, label_batch = next(iter(train_ds))

num_classes = len(class_names)

model = tf.keras.Sequential([
    # 對輸入的張量進行縮放。將輸入的張量除以 255,這將會將輸入的值縮放到 0 到 1 之間。
    tf.keras.layers.Rescaling(1./255),
    tf.keras.layers.Conv2D(32, 3, activation='relu'),
    tf.keras.layers.MaxPooling2D(),
    tf.keras.layers.Conv2D(32, 3, activation='relu'),
    tf.keras.layers.MaxPooling2D(),
    tf.keras.layers.Conv2D(32, 3, activation='relu'),
    tf.keras.layers.MaxPooling2D(),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(128, activation='relu'),
    tf.keras.layers.Dense(num_classes)
])
model.compile(
    optimizer='adam',
    loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
    metrics=['accuracy'])

model.fit(
    train_ds,
    validation_data=val_ds,
    epochs=3
)

model.save('model.h5')

然後按下complier之後,會有下面的樣建模的資訊

因為我們在model.compile的metrics選擇了accuracy,因此評估模型的評估方式會以accuracy作為標準

將資料集分割為訓練集和測試集

上面的程式碼我們呼叫了兩次image_dataset_from_directory來分別載入訓練集和測試集
但也可以只載入一次,然後再將資料集分割為訓練集和測試集

範例程式如下

import tensorflow as tf

# 建立圖片資料集
dataset = tf.keras.utils.image_dataset_from_directory(
    'image_directory',
    labels='inferred',
    class_names=None,
    label_mode='int'
)

# 計算資料集的大小
dataset_size = tf.data.experimental.cardinality(dataset).numpy()

# 計算訓練集和測試集的大小
test_size = int(0.2 * dataset_size)
train_size = dataset_size - test_size

# 將資料集分割為訓練集和測試集
train_dataset = dataset.take(train_size)
test_dataset = dataset.skip(train_size)

用 Keras 載入模型並預測答案

以下為一個簡單範例,使用keras.preprocessing.image.load_img所載入的圖片預設格式為 RGB 圖片

import numpy as np
import tensorflow as tf
from tensorflow import keras
import os
import re
import pathlib
# 載入模型
rank_model = keras.models.load_model('model.h5')
# 讓模型輸出的機率值分布在0-1之間
probability_rank_model = tf.keras.Sequential([rank_model, tf.keras.layers.Softmax()])

class_names = ['daisy','dandelion','roses','sunflowers','tulips']

img = keras.preprocessing.image.load_img('./test.jpg', target_size=(150, 150))
if img is None:
    continue
x = keras.preprocessing.image.img_to_array(img)
x = np.expand_dims(x, axis=0)
pred = probability_rank_model.predict(x)[0]
print(path)
top_inds = pred.argsort()[::-1][:5]
if pred[top_inds[0]] > 0.8:
    print('result is: ' + class_names[top_inds[0]])
# 印出機率分布
for data in top_inds:
    print('    {:.3f}  {}'.format(pred[data], class_names[data]))

上面是使用keras.preprocessing.image.load_img來載入圖片
我們也可以使用OpenCV來載入圖片使用

# 使用 OpenCV 讀取圖片
image = cv2.imread('image.jpg')

# 將圖片轉換為 RGB 格式
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
image = PIL.Image.fromarray(image)
x = keras.preprocessing.image.img_to_array(image)
probability_rank_model.predict(x.tolist())

如何關掉預測時吐出的log

在使用 predict 方法進行預測時,Keras 模型可能會輸出一些訓練過程中的訊息,如果你想要避免輸出這些訊息,則可以在建立模型時設置 verbose 參數。

例如,如果你想要在預測時停止輸出訓練過程中的訊息,則可以在建立模型時使用以下代碼:

# 預測
predictions = model.predict(x_test, verbose=0)

這樣,在進行預測時就不會再輸出任何訓練過程中的訊息了。

Posted on

TensorFlow Extended (TFX) 介紹

功能介紹

TensorFlow Extended (TFX) 是Google 開發的一個開源框架,用於在TensorFlow 中構建機器學習管道。TFX 的目標是簡化機器學習管道的構建過程,使其能夠更容易地部署和維護。

其中TFX 管道是TFX 中的一個重要部分,它是一種用於組織和管理機器學習工作流的方式。TFX 管道由多個組件組成,每個組件負責執行特定的任務,如數據預處理、訓練、評估等。TFX 管道中的組件可以由TFX 提供的組件使用,也可以使用自定義組件。

TFX 管道通過使用Apache Airflow 或Kubeflow Pipelines 在組件之間傳遞數據來實現自動化的機器學習工作流。這樣可以在一個可視化的界面上監控和管理管道執行過程,並且在管道中的每個步驟之間自動傳遞數據。

強大的資料處理工具

TFDV 結合開源的 Facets ,是可以幫助理解和分析機器學習數據集的開源可視化工具,在 Google AI Blog 中展示了透過 Facets 視覺化抓出 CIFAR-10 資料集中一個錯誤分為貓咪的青蛙的圖片。

TFDV 容許兩個資料及之間的分布對照,例如訓練資料與測試資料,迅速抓出資料飄移與偏斜情形,而 TFDV 更進一步可以做到修正與納入新特徵,以及整合在筆記本及 TFX 之中。

PS: 以上資料來自於Day 14 : 資料驗證 TensorFlow Data Validation (TFDV)

安裝TFX

pip install tfx
pip install -i https://pypi-nightly.tensorflow.org/simple --pre tfx

上文命令會安裝 TFX 的主要依賴項的軟件包,例如 TensorFlow 模型分析 (TFMA)、TensorFlow 數據驗證 (TFDV)、TensorFlow 轉換 (TFT)、TFX 基本共享庫 (TFX-BSL)、ML 元數據 ( MLMD)。

這些組件之間的數據流


下圖說明了TFX庫與流水線組之間的關係:

研究感想

這個工具組裡面的TFDV非常的吸引我,但是後來發現若要使用TFDV去驗證資料,前面還是需要把資料集先經過前面FTX的流水線處理過後,才有辦法使用Facets去可視化已經經過驗證後的資料結果。Facets並沒有辦法直接讀入未經TFX流水線處理過的原始資料集,而FTX對現在的我還有一點複雜,所以先大概知道有這個工具,然後以後再來慢慢摸索。

Posted on

用兩張圖片來偵測圖像是否在靜止狀態

實踐概念

使用 TensorFlow 的圖像處理函數,將兩張圖片讀入並進行比對。

比如您可以使用 OpenCV 庫將圖片讀入,然後使用 TensorFlow 庫對兩張圖片進行比對。 您可以使用 TensorFlow 的圖像處理函數,例如圖像縮放、旋轉和鏡像轉換等,對兩張圖片進行預處理。接著您可以使用 TensorFlow 中的數值計算函數,例如 mean square error (MSE) 或 structural similarity index (SSIM)等,對兩張圖片進行比對。

如果比對結果的值非常小,則可以認為兩張圖片非常相似,反之則表示兩張圖片不相似。

Structural Similarity Index (SSIM)

Structural Similarity Index (SSIM) 是一種用於評估圖像相似度的指標。它是基於人眼視覺系統的特性,模擬人眼對圖像質量的敏感度,並使用三個要素來評估圖像相似度:亮度、對比度和結構。

亮度(luma): 表示圖像中所有像素的平均亮度
對比度(contrast): 表示圖像中各像素亮度值的差異程度
結構(structure): 表示圖像中各像素之間的相關性
SSIM 使用這三個要素的加權和來計算圖像之間的相似度,其值介於 -1 到 1 之間,值越大則表示圖像相似度越高。

SSIM 有很好的相似度表示能力,在圖像壓縮、還原和質量評估等領域有著廣泛的應用。

使用Tensorflow實現SSIM的簡單範例

以下是使用 TensorFlow 實現 SSIM 的簡單範例,該範例使用兩張圖片來比較它們的相似度:

import tensorflow as tf

# 讀入兩張圖片
img1 = tf.io.read_file('image1.jpg')
img2 = tf.io.read_file('image2.jpg')
img1 = tf.image.decode_jpeg(img1, channels=3)
img2 = tf.image.decode_jpeg(img2, channels=3)

# 計算兩張圖片的 SSIM
ssim = tf.image.ssim(img1, img2, max_val=255)

# 顯示 SSIM 值
print(ssim)

這個範例中,我們使用 TensorFlow 的 I/O 函數來讀入兩張圖片,使用 decode_jpeg 函數將圖片解碼為 Tensor,然後使用 ssim 函數對兩張圖片進行比對,最終顯示 SSIM 值。

注意: 這個範例中,由於是在計算兩張圖片的 SSIM,所以需要兩張圖片大小相同,如果不同需要先對兩張圖片進行resize或pad。

Posted on

Tensorflow裡Estimator介紹

tf.estimator.Estimator 介紹

官方介紹頁面: https://www.tensorflow.org/guide/estimator
tf.estimator.Estimator tf.keras.Model 類似,estimator是模型級別的抽象。tf.estimator提供了一些目前仍在為 tf.keras 開發中的功能。包括:

  • 基於參數服務器的訓練
  • 完整的TFX集成

使用預製Estimator,能夠在比基礎TensorFlow API 高很多的概念層面上工作。您無需再擔心創建計算圖或會話,因為Estimator 會替您完成所有“基礎工作”。此外,使用預製Estimator,您只需改動較少代碼就能試驗不同的模型架構。例如,tf.estimator.DNNClassifier是一個預製Estimator 類,可基於密集的前饋神經網絡對分類模型進行訓練。

它提供了一種統一的方式來實現和使用各種不同類型的機器學習模型。它提供了一些預定義的模型類型,如線性迴歸、決策樹、KNN等,可以讓開發者更輕鬆的實現常見的機器學習模型。

主要功能

tf.estimator 是 TensorFlow 的一個高級 API,它提供了一種統一的方式來實現和使用各種不同類型的機器學習模型。它的主要用途是簡化建立、訓練和使用模型的流程,使開發人員能夠更輕鬆地實現常見的機器學習模型。

其主要功能如下:

  • 提供預定義的模型類型, 如線性迴歸,決策樹和KNN等
  • 提供一組工具,可以幫助您訓練,評估和預測模型
  • 提供一個統一的界面,使得用戶能夠更容易地訓練、評估和使用模型
  • 支持模型訓練和預測的分布式計算
  • 具有模型檢查点和恢復功能,可以將模型訓練過程中的狀態保存到磁盤上

優點

  • 提供了一個統一的界面,使開發人員能夠更輕鬆地實現常見的機器學習模型
  • 提供了一組工具,可以幫助您訓練,評估和預測模型
  • 支持模型訓練和預測的分布式計算
  • 具有模型檢查点和恢復功能,可以將模

在2.0裡被標註為棄用

在官網的API文件裡可以發現這個類別旁邊被註記了【棄用標籤】

在 TensorFlow 2.0 中,tf.estimator 被宣布即將棄用是因為它與 TensorFlow 的其他部分存在一些不一致性。隨著 TensorFlow 進化,其他部分,特別是 Keras API,已經成為了更簡單,更直接的機器學習模型構建選項。

Keras API 提供了一個統一的界面,可以用於創建和調用各種不同類型的模型,並且與 TensorFlow 的其他部分(如 TensorFlow 的低級計算圖 API)更加一致。

另外,Keras API 更加易於學習和使用,並且支持更多的高級功能,如自動微調。因此,TensorFlow 的開發團隊決定將重點轉移到 Keras API 上,並將 tf.estimator 標記為即將棄用。

學習 Keras API 更簡單,並且與其他 TensorFlow 特性更加一致,因此官方才會建議將重點轉向學習 Keras API。

使用Keras API來取代tf.estimator.Estimator的範例

tf.estimator.LinearRegressor 的使用範例

import tensorflow as tf

# Define the input function
def input_fn(features, labels, batch_size):
    dataset = tf.data.Dataset.from_tensor_slices((features, labels))
    dataset = dataset.shuffle(1000).batch(batch_size)
    return dataset

# Define the feature columns
feature_columns = [tf.feature_column.numeric_column("x", shape=[1])]

# Define the LinearRegressor
regressor = tf.estimator.LinearRegressor(feature_columns=feature_columns)

# Define the training inputs
train_input_fn = lambda: input_fn(x_train, y_train, batch_size=batch_size)

# Train the model
regressor.train(input_fn=train_input_fn, steps=1000)

# Define the testing inputs
test_input_fn = lambda: input_fn(x_test, y_test, batch_size=batch_size)

# Evaluate the model
metrics = regressor.evaluate(input_fn=test_input_fn)
print("Mean squared error: ", metrics["average_loss"])

把上面的程式碼使用Keras API改寫

from tensorflow import keras

# Define the model
model = keras.Sequential()
model.add(keras.layers.Dense(1, input_shape=[1]))

# Compile the model
model.compile(optimizer='sgd', loss='mean_squared_error')

# Train the model
model.fit(x_train, y_train, epochs=100)

在上面的程式碼之中,線性回歸的設定是來自於以下compile所設定的參數
model.compile(optimizer='sgd', loss='mean_squared_error')
使用 ‘sgd’ 作為優化器和 ‘mean_squared_error’ 作為損失函數是常用於實現線性迴歸模型的設定。

‘SGD’ 是隨機梯度下降的縮寫,它是一種優化算法,用於尋找最小化損失函數的權重值。’mean_squared_error’ 是一種常用的損失函數,用於計算預測值和實際值之間的差距。

在線性迴歸中, 我們嘗試找到一組權重和偏差, 使得預測值和實際值之間的差距最小, 而 mean_squared_error 是計算預測值和實際值之間差距的常用方法, 所以使用 mean_squared_error 作為損失函數是適當的.

tf.estimator.train_and_evaluate

tf.estimator.train_and_evaluate是TensorFlow Estimator API 中的一個函數,用於在訓練和評估模型時自動管理訓練循環。

它接受兩個參數:一個是估計器對象,另一個是一個字典,其中包含訓練和評估所需的所有配置信息。

在訓練期間,該函數會自動調用估計器的train() 方法,並在訓練過程中記錄訓練步驟和損失值。在評估期間,該函數會自動調用估計器的evaluate() 方法,並在評估過程中記錄評估指標。

通過使用tf.estimator.train_and_evaluate可以簡化訓練和評估模型的流程,避免手動管理訓練循環和評估過程中的各種細節。這樣可以讓開發人員專注於模型的構建和調優,而不必擔心訓練和評估的細節實現。

使用示例如下:

# Define the estimator
estimator = tf.estimator.LinearClassifier(feature_columns=feature_columns)

# Define the training and evaluation specs
train_spec = tf.estimator.TrainSpec(input_fn=train_input_fn, max_steps=1000)
eval_spec = tf.estimator.EvalSpec(input_fn=eval_input_fn)

# Train and evaluate the estimator
tf.estimator.train_and_evaluate(estimator, train_spec, eval_spec)

可以使用Keras API 來使用tf.estimator.train_and_evaluate。
使用TensorFlow 的Keras API 和Estimator API 來構建模型時,可以使用 tf.keras.estimator.model_to_estimator() 函數將Keras 模型轉換為Estimator,然後使用 tf.estimator.train_and_evaluate() 函數訓練和評估模型。

示例如下:

import tensorflow as tf
from tensorflow import keras

# Define the Keras model
def build_model():
    model = keras.Sequential([
        keras.layers.Dense(64, activation='relu', input_shape=(784,)),
        keras.layers.Dense(64, activation='relu'),
        keras.layers.Dense(10, activation='softmax')
    ])
    model.compile(optimizer=tf.keras.optimizers.Adam(),
                  loss=tf.keras.losses.categorical_crossentropy,
                  metrics=[tf.keras.metrics.categorical_accuracy])
    return model

# Convert the Keras model to an Estimator
estimator = tf.keras.estimator.model_to_estimator(keras_model=build_model())

# Define the input function for training
def train_input_fn():
    pass  # return training data

# Define the input function for evaluation
def eval_input_fn():
    pass  # return evaluation data

# Train and evaluate the Estimator
tf.estimator.train_and_evaluate(estimator,
                                train_spec=tf.estimator.TrainSpec(train_input_fn),
                                eval_spec=tf.estimator.EvalSpec(eval_input_fn))
Posted on

梯度下降法介紹

梯度下降法

梯度下降法(英語:Gradient descent)是一個一階最佳化算法,通常也稱為最陡下降法,但是不該與近似積分的最陡下降法(英語:Method of steepest descent)混淆。 要使用梯度下降法找到一個函數的局部極小值,必須向函數上當前點對應梯度(或者是近似梯度)的反方向的規定步長距離點進行疊代搜索。如果相反地向梯度正方向疊代進行搜索,則會接近函數的局部極大值點;這個過程則被稱為梯度上升法。

既然在變量空間的某一點處,函數沿梯度方向具有最大的變化率,那麼在優化目標函數的時候,自然是沿著負梯度方向去減小函數值,以此達到我們的優化目標。
如何沿著負梯度方向減小函數值呢?既然梯度是偏導數的集合,如下:

同時梯度和偏導數都是向量,那麼參考向量運算法則,我們在每個變量軸上減小對應變量值即可,梯度下降法可以描述如下:

描述


甚麼是梯度消失

梯度是一種數學概念,用於描述一個函數的變化率。在機器學習中,我們會使用梯度下降法來最小化損失函數。

損失函數是用來衡量模型預測結果與實際結果之間的差異的函數。通過最小化損失函數,我們可以讓模型的預測結果越來越接近實際結果。

梯度下降法是一種基於梯度的最優化算法,它會不斷計算損失函數的梯度,並根據梯度的大小和方向來更新模型的參數。當梯度越大,就意味著模型的預測結果與實際結果的差異越大,所以需要更大的步長來進行更新。當梯度越小,就意味著模型的預測結果與實際結果的差異越小,所以可以使用較小的步長來進行更新。

隨著層數的增加,梯度有可能會越來越小。這是因為在深度神經網路中,每個層的輸入都是前一層的輸出,因此如果前一層的輸出有變化,那麼這層的輸入也會有變化。如果前一層的輸出有很大的變化,那麼這層的輸入也有可能有很大的變化,導致梯度變小。而如果前一層的輸出沒有太大變化,那麼這層的輸入也不會有太大變化,梯度就不會變小。

當梯度變得非常小時,梯度下降法就無法有效地更新模型的參數、有可能陷入局部最小值,使得模型無法有效地學習。

這就是深度神經網路中的梯度消失問題。殘差網路就是為了解決這個問題而設計的。這是因為梯度下降法是通過梯度的大小和方向來決定步長的,如果梯度變得非常小,那麼步長也會變得非常小,導致更新參數的幅度非常小。

這篇文章對梯度下降法有很詳細的解釋: https://ithelp.ithome.com.tw/articles/10273302
更多關於CNN殘差學習介紹: https://zhuanlan.zhihu.com/p/31852747