多媒體技術及應用(第3版) 課件第8-10章 網絡多媒體技術及其應用、多媒體技術拓展應用、多媒體技術展望_第1頁
多媒體技術及應用(第3版) 課件第8-10章 網絡多媒體技術及其應用、多媒體技術拓展應用、多媒體技術展望_第2頁
多媒體技術及應用(第3版) 課件第8-10章 網絡多媒體技術及其應用、多媒體技術拓展應用、多媒體技術展望_第3頁
多媒體技術及應用(第3版) 課件第8-10章 網絡多媒體技術及其應用、多媒體技術拓展應用、多媒體技術展望_第4頁
多媒體技術及應用(第3版) 課件第8-10章 網絡多媒體技術及其應用、多媒體技術拓展應用、多媒體技術展望_第5頁
已閱讀5頁,還剩114頁未讀 繼續免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領

文檔簡介

多媒體技術與應用

第8章網絡多媒體技術及其應用8.1.1網絡多媒體基礎8.1.2網絡多媒體傳輸技術—流媒體8.1網絡多媒體概述1.網絡多媒體的發展互聯網普及之前

通過廣播電視節目獲取音視頻直播或者點播服務;

通過電話獲取語音即時通信服務;

通過手機短信業務獲取文字即時通信服務;互聯網早期

提供新聞瀏覽、電子郵箱、電子公告板(BBS)等服務;

ICQ:互聯網的即時消息軟件,用于文字聊天的在線工具;互聯網和數字化時代廣播電視網、電話通訊網和互聯網三網融合,促成了網絡多媒體的快速發展網絡電話(VoIP)網絡視頻會議2.網絡多媒體的應用(1)點播(VOD):根據觀眾要求播放指定節目的音頻和視頻點播系統,系統可以把用戶所點擊或選擇的視頻內容傳輸給所請求的用戶,如愛課程的MOOC/SPOC在線學習視頻、網易公開課、優酷影視點播等。(2)直播:服務端實時采集和上傳音頻和視頻流,支持大量客戶端同時從服務器下拉并播放這些實時的音視頻流,如體育賽事直播、泛娛樂直播節目、在線銷售直播、手術直播等。(3)實時交互:支持音視頻的實時交互,常用于在線會議系統。允許多個用戶通過互聯網進行即時語音或視頻交流,交流過程中可以發送文字和表情符號、共享桌面和文檔等,如騰訊會議、ZOOM會議、遠程醫療會診等。3.網絡多媒體系統架構4.網絡多媒體的壓縮編碼方法(1)網絡音頻編碼常見的網絡音頻編碼器包括Opus、AAC、Vorbis、MP3、Speex、AMR,ILBC和G.7xx系列等,目前最常用是Opus和AAC,延遲小,壓縮率高。①

AAC(Advanced

Audio

Coding):基于MPEG-2和MPEG-4的音頻編碼格式,壓縮比為18倍左右,音質佳,文件小,目前廣泛應用于娛樂直播。②

Opus:是一個有損聲音編碼格式,由互聯網工程任務組制定,適用于網絡上低延遲的即時聲音傳輸。大多數主流瀏覽器都支持,實時互動系統較多地使用Opus,如在線教育、視頻會議系統等,其中WebRTC(網頁即時通信)是一個支持網頁瀏覽器進行實時語音對話或視頻會議的API,使用的音頻編碼就是Opus。常見音頻編碼器4.網絡多媒體的壓縮編碼方法(2)網絡視頻編解碼標準

AVC(高級視頻編碼),用于高精度視頻的錄制、壓縮和發布,這是一種面向塊的基于運動補償的編解碼器標準,被廣泛用于網絡流媒體服務,如YouTube、iTunesStore、AdobeFlashPlayer、MicrosoftSilverlight以及各種高清晰度電視廣播系統。

SVC(可伸縮視頻編碼),是傳統H.264/MPEG-4AVC編碼的改進,具有更大的編碼彈性,具有時間可伸縮、空間可伸縮及信噪比可伸縮,使視頻傳輸更適應不同的網絡帶寬。4.網絡多媒體的壓縮編碼方法(2)網絡視頻編解碼標準

③HEVC即H.265,是ITU-T繼H.264之后所制定的高壓縮率的視頻壓縮格式,最高分辨率可達8192×4320。HEVC面向下一代HDTV設計,使用幀掃描,采樣分辨率支持4K高清視頻,具有增強的動態范圍調整和噪聲抑制等功能。

VP8/VP9,都是Google發布的開放視頻編解碼標準,VP8與H.264一樣采用混合編碼框架,采用libvpx來進行編解碼,VP9則支持更低的碼率,VP9比H.265有更好的編碼效率。4.網絡多媒體的壓縮編碼方法●mp4格式:是一種標準的多媒體容器格式,保存了視頻和音頻數據流、海報、字幕和元數據等,MP4格式屬于MPEG-4標準的第14部分,目前流行的AVC/H.264視頻編碼格式則定義在MPEG-4第10部分中。●mkv格式:是一種標準的多媒體容器格式,能夠在一個文件中容納無限數量的視頻、音頻、圖片或字幕軌道,可以作為一種統一格式保存常見的電影和電視節目。●webm格式:由Google推出的一個開放、免費的多媒體文件格式,其實是以mkv容器格式為基礎而開發的,支持用瀏覽器播放。4.網絡多媒體的壓縮編碼方法●wmv格式:微軟推出的一種采用獨立編碼方式并且可以直接在網上實時觀看視頻節目的文件壓縮格式。●mov格式:蘋果構思推出的一種流式視頻格式,用QuickTime播放,為了適應網絡多媒體應用,QuickTime為多個流行的瀏覽器提供了QuickTimeViewer插件,能夠在瀏覽器中實現mov文件的實時回放。●flv、f4v格式:Adobe公司推出的一種視頻格式,在網絡上傳輸的流媒體數據存儲容器格式,由于移動端瀏覽器大多不支持Flash播放器,已逐步被mp4和webm等格式所取代。4.網絡多媒體的壓縮編碼方法●wmv格式:微軟推出的一種采用獨立編碼方式并且可以直接在網上實時觀看視頻節目的文件壓縮格式。●mov格式:蘋果構思推出的一種流式視頻格式,用QuickTime播放,為了適應網絡多媒體應用,QuickTime為多個流行的瀏覽器提供了QuickTimeViewer插件,能夠在瀏覽器中實現mov文件的實時回放。●flv、f4v格式:Adobe公司推出的一種視頻格式,在網絡上傳輸的流媒體數據存儲容器格式,由于移動端瀏覽器大多不支持Flash播放器,已逐步被mp4和webm等格式所取代。8.1.1網絡多媒體基礎8.1.2網絡多媒體傳輸技術—流媒體8.1網絡多媒體概述1.流媒體簡介流式傳輸技術:就是將多媒體數據壓縮編碼后,在網絡上分段發送,實時傳輸數據,把數據包像流水一樣源源不斷地發送到用戶端,用戶無需等待整個影音文件全部下載到本地,可以一邊下載一邊播放。流式傳輸主要有兩種方式

順序流式傳輸(Progressivestreaming)

實時流式傳輸(Realtimestreaming)(1)順序流式傳輸

用戶在觀看在線媒體的同時下載文件,只能觀看已下載部分,不能觀看未下載部分。

HTTP服務器就可以發送這種形式的文件,稱為HTTP流式傳輸

順序流式傳輸能夠較好地保證節目播放的質量,比較適合供用戶點播的高質量的短片段,如片頭、片尾和廣告,不適合有隨機訪問要求的視頻,如講座、演說與演示,也不支持現場廣播。(2)實時流式傳輸

數據實時傳送,用戶可以實時觀看,對網絡帶寬有較高的要求,在觀看過程中用戶可以任意快進或快退,如果網絡傳輸狀況不理想,則收到的圖像質量就會比較差。

實時流式傳輸需要專用的流媒體服務器與流式傳輸協議

Nodejs是基于ChromeJavaScript的多媒體網絡服務平臺 SRS(SimpleRtmpServer)一個簡單高效的實時視頻服務器實時流式傳輸協議:RTSP(Real-timeStreaming

Protocol)實時流傳輸協議)HLS(HTTP

Live

Streaming)蘋果制定的基于HTTP的流媒體傳輸協議TCP/IP協議層2.網絡協議基礎3.網絡多媒體協議8.2.1

點播服務8.2.2直播服務8.2非交互式網絡多媒體服務1.點播基礎

點播的前提是音視頻文件已經錄制或制作完成且已上傳到了網絡服務器上,用戶按照需求,向服務器發出請求,服務器一般通過流式傳輸方式響應用戶的請求,教學中的錄播即屬于這樣的應用場景。2.點播節目制作

制作點播或錄播節目最常用的是用帶有攝像頭的設備進行視頻錄制,如手機、平板、電腦、照相機和攝像機等,也可以通過視頻軟件制作生成,如Premiere與AfterEffects等。

一般的直播軟件和視頻會議系統都同時提供了云錄制或本地錄制功能,可以將直播現場或視頻會議直接錄制為mp4或mkv格式的視頻文件,方便用戶后期點播觀看。3.點播應用

在線教學音視頻在線點播:優酷、芒果TV、YouTube8.2.1

點播服務8.2.2直播服務8.2非交互式網絡多媒體服務1.網絡直播概述

網絡直播是通過互聯網進行傳輸的,允許用戶接收從世界上任何角落發送來的廣播和電視節目。

有許多用戶同時接收相同的實時音頻、視頻節目。

對數據包延遲和抖動的要求不像互聯網電話和實時視頻會議那樣嚴格。從用戶點擊一個鏈接到音頻/視頻播放開始,幾十秒的延遲是可以容忍的。

通過組播方式將實時音頻/視頻分配給許多接收者2.直播推流與拉流推流指的是把采集階段封包好的內容傳輸到服務器的過程,其實就是將現場的視頻信號傳到網絡的過程。推流對網絡要求比較高,如果網絡不穩定,直播效果就會很差,觀看直播時就會發生卡頓等現象,觀眾體驗會很糟糕。拉流是指服務器已有直播內容,根據協議類型(如RTMP、RTP、RTSP、HTTP等),與服務器建立連接、接收數據、進行拉取的過程。3.網絡直播軟件用來對直播內容進行管理OBS(OpenBroadcasterSoftware)是一個用于錄制和網絡直播的自由開源軟件包8.3.1交互式網絡多媒體基礎8.3.2網絡視頻會議系統8.3交互式網絡多媒體服務1.交互式網絡多媒體概述交互式網絡多媒體首先是通過網絡實時傳輸多媒體信息,包括文字、圖像、聲音和視頻等多種媒體信息,同時允許用戶與用戶之間進行實時的互動溝通。Skype、GoogleTalk、騰訊QQ遠程辦公遠程教育電商直播遠程醫療2.交互式網絡多媒體服務的應用8.3.1交互式網絡多媒體基礎8.3.2網絡視頻會議系統8.3交互式網絡多媒體服務1.網絡視頻會議系統的組成會議終端

通常以網頁瀏覽器、計算機軟件或移動應用程序的方式給用戶提供服務。會議終端一般自帶音視頻采集功能,也可以外接采集設備。服務器

為會議各終端提供數據交換、音視頻處理和轉發、會議控制管理等服務傳輸網絡

會議終端通過有線或者無線的方式接入網絡,服務器一般通過有線方式接入網絡,數據包通過網絡在各終端與服務器之間傳送。2.網絡視頻會議系統的性能指標(1)帶寬:

參加一個視頻會議常常要保證有1Mbps以上的接入帶寬,更高的帶寬帶來更清晰的畫面。(2)丟包:數據包無法到達目的地即丟包,出現丟包的原因是多方面的,包括網絡中的信號衰減、通道阻塞、損壞的數據包被拒絕通過、有缺陷的網絡硬件、網絡驅動故障等。(3)延遲:用于衡量數據從一個端點傳送到另一個端點所需的時間,端點的位置、數據包的大小以及流量大小都會對網絡延遲造成影響。(4)抖動:接收端收到數據包序列的時序和發送端不同,比如間隔時長變化、順序錯位等都會引起抖動。(4)抖動接收端收到數據包序列的時序和發送端不同,比如間隔時長變化、順序錯位等都會引起抖動。3.服務質量

質量服務(QoS,QualityofService)策略的主要任務就是對抗各種因素對數據傳輸帶來的影響。(1)自動重傳請求(ARQ,AutomaticRepeat-reQuest)(2)前向糾錯(FEC,ForwardErrorCorrection)(3)抖動緩沖(JitterBuffer)(4)擁塞控制(CongestionControl)8.4網絡多媒體技術綜合應用遠程醫療是一種正在發展中的醫療技術,是計算機技術、網絡通信技術、醫療技術與醫療設備的結合,醫師可以與病人遠距離互動,達到診療的目的。多用于克服距離障礙及改善偏遠地區的醫療服務。遠程醫療使得偏遠地區的病患無需長途跋涉到醫院就診,他們可以就近得到相對較好的醫療服務。隨著移動設備和網絡技術的快速發展,不同地區的醫護人員能夠彼此分享資料、討論病情、監測遠端病患、在線開處方,顯著降低了患者的就醫成本,對于行動不便的病患更有益處。此外,利用遠程醫療系統,偏遠地區的醫護人員也可與大醫院專家即時互動,獲取便捷的咨詢和培訓機會。遠程醫療診斷系統多媒體技術與應用

第9章多媒體技術拓展應用9.1.1神經網絡的發展9.1.2感知機9.1.3神經網絡9.1.4卷積神經網絡9.1深度學習概述生物神經元的結構9.1.1神經網絡的發展M-P模型:1943年美國心理學家McCulloch(麥卡洛克)和數學家Pitts(皮茨)最先在論文《神經活動中所蘊含思想的邏輯活動》中提出的第一個神經元數學模型,將接收到的一個輸入中多個分量加權求和后通過硬限幅函數處理后再輸出。第一代:感知機,1950年左右被提出來,算法分為輸入層和輸出層,輸入和輸出之間為線性關系,感知機無法處理非線性模型;第二代:多層感知機(MLP),又叫人工神經網絡(ANN),在中間加了多個隱含層,隱含層可以引入非線性結構,能夠處理非線性問題;第三代:深度神經網絡,主要包括深度神經網絡(DNN)、循環神經網絡(RNN)、卷積神經網絡(CNN)等。9.1.1神經網絡的發展9.1.2感知機9.1.3神經網絡9.1.4卷積神經網絡9.1深度學習概述9.1.2感知機感知機是一個簡單的二分類線性分類模型,可以接收多個輸入信號并輸出一個結果信號。1.感知機模型

2.感知機的特點只有1層輸入信號的感知機稱為單層感知機,適合于線性分類當權重參數b=-0.5,ω1=ω2=1.0時,感知機可表示為由直線?0.5+x1+x2=0分割成的兩個空間單層感知機的缺陷:無法實現非線性可分空間如右圖所示的圓圈和三角標志無法畫一條直線來分隔只能繪制一條曲線來進行分隔9.1.1神經網絡的發展9.1.2感知機9.1.3神經網絡9.1.4卷積神經網絡9.1深度學習概述1.神經網絡就是把多個單層感知機進行組合,形成一個多層感知機,可實現更復雜的功能。神經網絡的特點:①

神經網絡包括輸入層、中間層和輸出層,中間層又稱為隱含層;②

該網絡由3層神經元構成,但只有2層神經元有權重,一般稱之為2層網絡;③

信號從輸入到輸出都是單向的,整個網絡中無反饋,稱為前饋神經網絡;輸入層輸出層中間層2.激活函數將輸入信號的總和轉換為輸出信號,設x=b+ω1x1+ω2x2,則y=h(x)函數h(x)稱之為激活函數,即決定如何來激活輸入信號的總和。

激活函數實質是一種非線性的數學變換,用于對上一層神經元的輸出進行某種數學變換,將變換后的結果作為下一層神經元的輸入。如果使用線性激活函數時,不管神經網絡有幾層,最終輸出還是一個線性變換,無法發揮多層網絡疊加帶來的優勢,所以激活函數都使用非線性的激活函數。2.常用非線性激活函數(1)ReLU激活函數(RectifiedLinearUnit,線性整流函數):該函數以閾值為界,一旦輸入超過某個閾值,就輸出,這就是感知機中的激活函數,又叫階躍函數

2.常用非線性激活函數(2)Sigmoid激活函數:當輸入信號x較小時,輸出接近為0,隨著輸入信號x的增大,輸出向1靠近,對每個神經元的輸出進行了歸一化處理。一般用于將預測概率作為輸出的模型,主要用于輸出為二分類的神經網絡模型。

(3)tanh激活函數(雙曲正切函數):輸出以0為中心,范圍在-1和+1之間,與Sigmoid相比,tanh的梯度下降作用更強在一般的二分類問題中,tanh函數用于隱含層,而Sigmoid函數則用于輸出層2.常用非線性激活函數(4)Softmax激活函數:對于神經網絡具有K個信號的輸出向量,Softmax可以將其變換到K個數值位于(0,1)之間的實數,剛好可以對應每個輸出結果出現的概率,并且各項輸出的總和為1,輸出值中概率值最大的即為對應的結果,一般用于多分類問題。2.常用非線性激活函數機器學習就是要從訓練數據中獲得最優權重參數的過程。神經網絡中參數的數量超多,需要在學習過程中通過反向傳播的方式不斷地調整網絡中的權重參數,使模型中的權重參數盡可能達到最優。3.損失函數損失函數就是用來評價模型的預測值和真實值不一樣的程度,用于衡量神經網絡性能一個指標,模型訓練過程中損失函數的值越來越小,說明模型的性能越來越好常見的損失函數(1)均方誤差(MSE,MeanSquaredError)(2)交叉熵誤差(CrossEntropyError)

交叉熵就是用來判定實際的輸出與期望輸出的接近程度

優化器就是在深度學習的反向傳播過程中,通過損失函數來指引如何調整各個權重參數往正確的方向更新到合適的大小,更新后的各個權重參數使損失函數的值不斷逼近全局最小。4.優化器①

批量梯度下降(BGD):使用所有樣本計算梯度并更新權重參數,計算工作量大,訓練速度慢,能夠更準確地逼近最優解。②

隨機梯度下降法(SGD):每輪迭代都是針對一個樣本而不是全部樣本,更新速度大大加快,但是得到的可能只是局部最優而不是全局最優解。③

小批量梯度下降(MBGD):每輪迭代都是針對一個小樣本集合,既可以加快訓練速度,又可以避免只能得到局部最優,如手寫數字識別batch_size=32。4.優化器④

自適應梯度下降(AdaGrad):對不同的權重參數調整不同的學習率α,對頻繁變化的權重參數以更小的步長進行更新,而稀疏的權重參數以更大的步長進行更新,一般默認學習率α=0.01。⑤

均方根傳遞(RMSProp):采用指數加權移動平均(累計局部梯度和)來替代AdaGrad中的累計平方梯度和,能夠在不穩定的目標函數情況下很好地收斂,可克服AdaGrad梯度急劇減小的問題。5.模型的評價預測值真實值正類負類正類ab負類cd(1)準確率(Accuracy):(a+d)/(a+b+c+d),所有樣本中被正確預測的比例;(2)精確率(Precision):a/(a+c),所有被預測為正類的樣本中,預測正確的比例(3)召回率(Recall):a/(a+b),所有真實類別為正類的樣本中,被正確預測出來的比例;(4)F1得分:2a/(2a+b+c),是準確率和召回率的一種調和均值;混淆矩陣其他評價方法泛化能力:是指機器學習算法處理訓練集之外未知樣本的適應能力,即把未知樣本作為測試集,檢測已訓練好的模型在測試集上的適應能力。擬合(fit):模型在訓練集與測試集上的表現都好欠擬合:就是模型在訓練集與測試集上的表現都不好過擬合:模型在訓練數據集上表現很好,但在未知數據集上卻表現欠佳模型出現欠擬合或過擬合的話,建議增加訓練樣本數,調整超參數,包括Epcho、batch-size(小批量的大小)、學習率等,對訓練集與測試集數據做歸一化預處理等。9.1.1神經網絡的發展9.1.2感知機9.1.3神經網絡9.1.4卷積神經網絡9.1深度學習概述卷積神經網絡的結構(1)輸入層卷積神經網絡的輸入層可以處理多維數據,如四維數組【0,0,0,0】可理解為第1張圖片的第0行第0列的第0個通道的像素值通常在數據輸入卷積神經網絡前,需對數據進行歸一化處理,若輸入數據為像素,原始像素值【0,255】會被歸一化處理為【0,1】之間的實數,有利于提升卷積神經網絡的學習效率和性能。

隱含層又叫隱藏層,一般包含了卷積層、池化層和全連接層(2)隱含層卷積計算過程②

池化層:每個卷積層輸出的特征圖會被傳遞至池化層進行特征選擇和信息過濾,仿照人的視覺系統進行降維(又叫降采樣),可以提取出圖像更高層的抽象特征。③

全連接層:是卷積神經網絡隱含層的最后部分,特征圖在全連接層中會失去空間拓撲結構,被展平為一個向量,對提取的特征進行非線性組合得到最后的輸出結果使用邏輯函數或Softmax函數輸出分類標簽,對于物體識別問題,輸出層將輸出物體的中心坐標、大小(尺寸)和分類信息等。(2)隱含層(3)輸出層9.2.1基于按鈕交互的動畫實現9.2.2基于圖像識別的動畫實現9.2拓展應用案例—剪刀石頭布簡單交互動畫的運行結果界面設計思路(1)準備好代表剪刀石頭布的圖片;(2)機器出的圖片用一個標簽顯示,由系統時鐘控制其隨機出現;(3)我出的是哪個,通過單擊圖片按鈕實現;(4)當我單擊某個按鈕時,系統時鐘暫停,機器標簽顯示的圖片即為機器出結果;(5)根據游戲規則判別輸贏,并對贏的次數進行累計;(6)游戲采用5局3勝制,當某一方獲勝時,彈出對話框,顯示最后的結果;(7)點按“下一局”,開始新一輪的比賽。9.2.1基于按鈕交互的動畫實現9.2.2基于圖像識別的動畫實現9.2拓展應用案例—剪刀石頭布剪刀石頭布——采用圖像識別(神經網絡模型)1)我和機器隨機出的剪刀石頭布圖片動畫顯示在界面上面;2)左下角顯示當前攝像頭采集的圖像畫面;3)單擊按鈕“開始識別”,視頻采集畫面靜止,將當前識別出的圖片顯示在上面我出的圖片位置,同時動畫停止,并與當前機器出的圖片按游戲規則判別輸贏,動畫圖片下方顯示當前輸贏次數;4)單擊“繼續出拳”按鈕,繼續視頻采集,游戲采用5局3勝制,游戲結束彈出贏了的對話框;5)單擊“下一局”按鈕,繼續下一輪的游戲Step1,設計思路剪刀石頭布——采用圖像識別(神經網絡簡單建模)首先采集剪刀石頭布的圖像,并按規律保存為圖像文件,本例采集了3000*3=9000張訓練用的原始jpg格式的圖像(大小為640*480),采用外接USB攝像頭,背景為黑色的屏幕背景。采集了2000*3=6000張測試用jpg圖像文件。三種圖片分三次采集,分別保存在指定目錄下,本例為當前目錄。準備工作1:采集原始圖像importimageio#圖像輸入輸出處理importvisvisasvv#計算機視覺庫fc,i=0,-100#圖片起始編號為負,便于將來采用時從1開始success=Truecapt=imageio.get_reader('<video3>')#ThinkPad中打開外接USB攝像頭,0~2為內置攝像頭#windowssurface:0為前置攝像頭,1對于后置攝像頭,2對應外接USB攝像頭frame=capt.get_next_data()#讀取幀數據t=vv.imshow(frame,clim=(0,255))#將幀數據顯示在VV的視頻窗口t中,clim控制顏色的范圍forimincapt:#循環控制讀取cessEvents()#vv處理事件t.SetData(im)#刷新t窗口中的圖像fc=fc+1#累計幀數iffc%5==0:#設置截取的幀頻,這里每隔5幀保存一次i+=1#給需要保存的圖像文件編號vv.imwrite("jd_%d.jpg"%i,im)#將圖像保存為指定的jpg文件ifi==6000:#當保存的文件數為6000時停止采集capt.close()#關閉攝像頭break#退出循環app=vv.use()#開始消息循環app.Run()vv.closeAll()#關閉采集窗口剪刀石頭布——采用圖像識別(神經網絡簡單建模)分別讀取三種圖像文件,按照訓練模型中的格式要求進行處理,同時對其進行標注(對應剪刀石頭布的序號)準備工作2:制作數據集importnumpyasnpfromPILimportImageimportrandom#初始化一個二維的圖像數組,默認為空,第1維是高度,第2維是寬度TrainImage=np.array([],dtype=np.uint8,ndmin=2)#存放打亂順序的圖像TrainLabel=[0]*9000TrainImg=np.array([],dtype=np.uint8,ndmin=2)#順序添加圖像數據TrainLbl=[]foriinrange(3000):#讀取3000張訓練用剪刀圖像

TrainLbl.append(0)#剪刀的標記為0

fileName=r"F:\sjb_recog\trainphoto\jd_"+str(i)+'.jpg'#打開圖像文件并轉換為灰度圖像,數據類型為np的二維數組

img=np.array(Image.open(fileName).convert("L"))#再從數組類型轉換成圖像,然后縮放圖像大小,本例是縮小了10倍

imgResize=Image.fromarray(img.astype('uint8')).resize((64,48))#將所有訓練圖像數據(二維數組)依次添加到用于存儲訓練圖像的三維數組中

TrainImg=np.append(TrainImg,imgResize)

TrainImage=np.append(TrainImage,imgResize)foriinrange(3000):#讀取3000張訓練用石頭圖像

TrainLbl.append(1)#石頭標記為1

fileName=r"F:\sjb_recog\trainphoto\st_"+str(i)+'.jpg'

img=np.array(Image.open(fileName).convert("L"))

imgResize=Image.fromarray(img.astype('uint8')).resize((64,48))

TrainImg=np.append(TrainImg,imgResize)

TrainImage=np.append(TrainImage,imgResize)

foriinrange(3000):#讀取3000張訓練用布圖像

TrainLbl.append(2)#布標記為2

fileName=r"F:\sjb_recog\trainphoto\bu_"+str(i)+'.jpg'

img=np.array(Image.open(fileName).convert("L"))

imgResize=Image.fromarray(img.astype('uint8')).resize((64,48))

TrainImg=np.append(TrainImg,imgResize)

TrainImage=np.append(TrainImage,imgResize)#再將訓練圖像數據改成三維數組,依次表示圖像的序號,像素的高度和寬度TrainImg=TrainImg.reshape(9000,48,64)#有序的圖像數組TrainImage=TrainImage.reshape(9000,48,64)#有序的圖像數組xh=random.sample(range(0,9000),9000)#隨機生成9000個不一樣的隨機整數0~9000,打亂圖像順序random.shuffle(xh)foriinrange(9000):k=xh[i]

TrainImage[k]=TrainImg[i]

TrainLabel[k]=TrainLbl[i]準備工作2:制作數據集(續)準備工作2:制作數據集(續)TestImg=np.array([],dtype=np.uint8,ndmin=2)TestLbl=[]TestImage=np.array([],dtype=np.uint8,ndmin=2)#存放打亂順序的圖像TestLabel=[0]*6000foriinrange(2000):#讀取2000張訓練用剪刀圖像TestLbl.append(0)#剪刀的標記為0fileName=r"F:\sjb_recog\trainphoto\jd_"+str(3000+i)+'.jpg'#打開圖像文件并轉換為灰度圖像,數據類型為np的二維數組img=np.array(Image.open(fileName).convert("L"))#再從數組類型轉換成圖像,然后縮放圖像大小,本例是縮小了10倍imgResize=Image.fromarray(img.astype('uint8')).resize((64,48))#將所有訓練圖像數據(二維數組)依次添加到用于存儲訓練圖像的三維數組中TestImg=np.append(TestImg,imgResize)TestImage=np.append(TestImage,imgResize)準備工作2:制作數據集(續)foriinrange(2000):#讀取2000張訓練用石頭圖像TestLbl.append(1)#石頭標記為1fileName=r"F:\sjb_recog\trainphoto\st_"+str(3000+i)+'.jpg'

img=np.array(Image.open(fileName).convert("L"))imgResize=Image.fromarray(img.astype('uint8')).resize((64,48))TestImg=np.append(TestImg,imgResize)TestImage=np.append(TestImage,imgResize)foriinrange(2000):#讀取2000張訓練用布圖像TestLbl.append(2)#布標記為2fileName=r"F:\sjb_recog\trainphoto\bu_"+str(3000+i)+'.jpg'img=np.array(Image.open(fileName).convert("L"))imgResize=Image.fromarray(img.astype('uint8')).resize((64,48))TestImg=np.append(TestImg,imgResize)TestImage=np.append(TestImage,imgResize)準備工作2:制作數據集(續)#再將訓練圖像數據改成三維數組,依次表示圖像的序號,像素的高度和寬度TestImg=TestImg.reshape(6000,48,64)TestImage=TestImage.reshape(6000,48,64)xh1=random.sample(range(0,6000),6000)random.shuffle(xh1)foriinrange(6000):kk=xh1[i]TestImage[kk]=TestImg[i]TestLabel[kk]=TestLbl[i]#用savez函數將訓練集和測試集的圖像數據以及標簽數據寫入sjb.npz數據集文件中np.savez(r'C:\Users\lxm\.keras\datasets\sjb.npz',TrainImage=TrainImage,TrainLabel=TrainLabel,TestImage=TestImage,TestLabel=TestLabel)#訪問該數據集中的數據用#data=np.load(r'C:\Users\lxm\.keras\datasets\sjb.npz')#data['TrainImage']獲取訓練圖像數據,data['TrainLabel']獲取訓練標簽準備工作3:訓練神經網絡模型importnumpyasnpdata=np.load(r'C:\Users\lxm\.keras\datasets\sjb.npz')train_images=data['TrainImage']test_images=data['TestImage']train_labels=data['TrainLabel'].astype(np.uint8)test_labels=data['TestLabel'].astype(np.uint8)(1)讀取數據集train_images=train_images.reshape((9000,64*48))test_images=test_images.reshape((6000,64*48))train_images=train_images.astype('float32')/255test_images=test_images.astype('float32')/255(2)準備圖像數據:變換數據維度,并將圖像數據轉化為[0~1]準備工作3:訓練神經網絡模型fromtensorflow.kerasimportmodelsfromtensorflow.kerasimportlayersnetwork=models.Sequential()network.add(layers.Dense(512,activation='relu',input_shape=(64*48,)))network.add(layers.Dense(3,activation='softmax'))(3)創建訓練模型并添加層pile(optimizer='rmsprop',loss='categorical_crossentropy',metrics=['accuracy'])(4)指定模型的優化器、損失函數和評價方法準備工作3:訓練神經網絡模型fromtensorflow.keras.utilsimportto_categoricaltrain_labels=to_categorical(train_labels)test_labels=to_categorical(test_labels)(5)處理訓練標簽和測試標簽network.fit(train_images,train_labels,epochs=6,batch_size=32)(6)開始模型的訓練,指定輪數和每輪數據批量的大小network.save("F:\sjb_recog\sjb-2.h5")(7)保存訓練好的模型(8)查看測試結果test_loss,test_acc=network.evaluate(test_images,test_labels)模型的改進fromtensorflow.kerasimportlayersfromtensorflow.kerasimportmodelssjbModel=models.Sequential()sjbModel.add(layers.Conv2D(32,(3,3),activation='relu',input_shape=(48,64,1)))sjbModel.add(layers.MaxPooling2D((2,2)))sjbModel.add(layers.Conv2D(64,(3,3),activation='relu'))sjbModel.add(layers.MaxPooling2D((2,2)))sjbModel.add(layers.Conv2D(64,(3,3),activation='relu'))sjbModel.add(layers.Flatten())sjbModel.add(layers.Dense(512,activation='relu'))sjbModel.add(layers.Dense(3,activation='softmax'))importnumpyasnpdata=np.load(r'C:\Users\lxm\.keras\datasets\sjb.npz')train_images=data['TrainImage'].reshape(9000,48,64,1)train_images=train_images.astype('float32')/255test_images=data['TestImage'].reshape(6000,48,64,1)test_images=test_images.astype('float32')/255train_labels=data['TrainLabel'].astype(np.uint8)test_labels=data['TestLabel'].astype(np.uint8)模型的改進(續)fromtensorflow.keras.utilsimportto_categoricaltrain_labels=to_categorical(train_labels)test_labels=to_categorical(test_labels)sjbMpile(optimizer='rmsprop',loss='categorical_crossentropy',metrics=['accuracy'])模型的改進(續)sjbModel.fit(train_images,train_labels,epochs=5,batch_size=64)sjbModel.save("F:\sjb_recog\sjb-4.h5")test_loss,test_acc=sjbModel.evaluate(test_images,test_labels)print('test_acc:',test_acc)importtkinterastkimportrandomimportthreadingastrimporttkinter.messagebox#importmatplotlib.pyplotaspltimportcv2fromPILimportImage,ImageTkfromtensorflow.keras.modelsimportload_modelimportnumpyasnpStep2,導入必要的庫,全局變量初始化root=tk.Tk()root.title("游戲:剪刀石頭布")root.geometry('600x600')random.seed()#隨機數種子jqNo=1#機器默認出剪刀meWin,jqWin=0,0#我贏的次數和機器贏的次數初始化為0imgtk=None#控制畫布上顯示的圖片im1=None#控制圖像的數據傳遞conCapture=True#控制視頻是否繼續采集Step3,界面控件設計#定義兩個標簽,時鐘開始后隨機顯示我和機器出的圖片jqLabel=tk.Label(root,text=‘機器出的’)#機器出的圖片,標簽顯示jqLabel.place(x=220,y=60,width=150,height=50)myLabel=tk.Label(root,text='我出的')#我出的圖片,標簽顯示myLabel.place(x=20,y=60,width=120,height=50)#下面先加載用于顯示的圖片對象,分別控制機器和我出的圖片jqph=[None,None,None]#初始化圖像文件對象,兩個語句不能合在一起賦值,否則引用的圖片是一樣的myph=[None,None,None]foriinrange(3):jqph[i]=tk.PhotoImage(file='r'+str(i+1)+'.gif')#每個圖像文件必須單獨保存,不能迭代賦值myph[i]=tk.PhotoImage(file='l'+str(i+1)+'_2.gif')jq_disp=tk.Label(root,image=jqph[0])#機器默認出的剪刀石頭布jq_disp.place(x=250,y=120,width=70,height=50)my_disp=tk.Label(root,image=myph[0])#我默認出的剪刀石頭布my_disp.place(x=50,y=120,width=70,height=50)Step3,界面控件設計(續)#下面定義兩個標簽。分別顯示我和機器贏的次數,文本可動態變化varMe=tkinter.StringVar()lbMe=tk.Label(root,textvariable=varMe)lbMe.place(x=50,y=200,width=70,height=30)varJq=tkinter.StringVar()lbjq=tk.Label(root,textvariable=varJq)lbjq.place(x=250,y=200,width=70,height=30)#定義一個下一局按鈕,單擊開始下一輪比賽nextbt=tk.Button(root,text="下一局",command=nextClick)nextbt.place(x=450,y=400,width=70,height=30)nextbt.config(state="disabled")#在圖片上方放2個提示性的文字標簽tsLb1=tk.Label(root,text="我")tsLb1.place(x=40,y=30,width=90,height=30)tsLb2=tk.Label(root,text="機器")tsLb2.place(x=240,y=30,width=90,height=30)Step3,界面控件設計(續)#定義一塊畫布,用于顯示采集的視頻圖像canvas=tk.Canvas(root,width=400,height=300)canvas.place(x=10,y=250)#定義兩個按鈕,控制開始圖像識別和繼續出拳

recogBt=tk.Button(root,text="開始識別",command=startRecog)recogBt.place(x=450,y=300,width=70,height=30)conCaptBt=tk.Button(root,text="繼續出拳",command=conCapt)conCaptBt.place(x=450,y=350,width=70,height=30)conCaptBt.config(state="disabled")#繼續出拳按鈕默認為灰Step4,主程序設計#0是內置攝像頭,1是外接USB攝像頭,capt.read()將開啟攝像頭capt=cv2.VideoCapture(1,cv2.CAP_DSHOW)#定義一個全局的定時器,調用Fun_timer處理相應的事件,機器默認顯示第1張圖片timer1=tr.Timer(0.1,Fun_timer,['1'])timer1.start()#開啟定時器t=tr.Thread(target=dispVideo)#通過線程控制執行自定義函數t.start()#啟動線程model=load_model(r".\sjb-2.h5")#載入訓練好的模型root.focus_set()#獲取焦點root.mainloop()#開始事件循環Step5,隨機顯示圖片的動畫設計def

Fun_timer(n):#時鐘觸發時,將三張照片隨機顯示

globaljqNo,timer1,myph,jqph,my_disp,jq_disp

i=eval(n)-1

jqNo=i+1#記住當前機器出的圖片序號

jq_disp=tk.Label(root,image=jqph[i])#image指定機器要打開的圖片文件

jq_disp.place(x=250,y=120,width=70,height=50)

my_disp=tk.Label(root,image=myph[i])#image指定我要打開的圖片文件

my_disp.place(x=50,y=120,width=70,height=50)timer1=tr.Timer(0.1,Fun_timer,args=[str(random.randint(1,3))])

#每隔0.1秒調用一次Fun_timer函數,參數為隨機生成的文件序號(字符)

timer1.start()#啟動時鐘

root.update()#刷新窗體Step6,采集視頻的顯示def

dispVideo():#控制視頻的顯示

globalcanvas,capt,imgtk,im1,conCapture,timer1

capt=cv2.VideoCapture(1,,cv2.CAP_DSHOW)#0對應內置,1對應USB外置攝像頭

conCapture=True#控制攝像頭是否繼續捕獲圖像

defcapture():#捕獲攝像頭的圖像并顯示

globalcanvas,capt,imgtk,im1whileTrue:

rval,frame=capt.read()#從攝像頭讀取圖像保存在frame中,rval保存是否讀取成功

ifconCaptureandrval:#conCapture=True表示攝像頭繼續捕獲圖像

im=Image.fromarray(frame)#轉換圖像的數據類型,im可顯示為圖像

im1=im.convert("L")#將其轉換為灰度圖像

imgtk=ImageTk.PhotoImage(image=im1)#將讀取到的圖像轉換為image屬性支持的類型

canvas.create_image(200,150,image=imgtk)#200,150指定圖像的中心

canvas.image=imgtk#該語句用于解決圖像顯示時候的閃爍

rval,frame=capt.read()#繼續從攝像頭讀取圖像

t1=tr.Thread(target=capture)#創建一個線程t,指向函數capturet1.start()Step7,開始識別圖像def

startRecog():#單擊開始識別按鈕執行的功能

globalcanvas,capt,imgtk,im1,conCapture,model,timer1,myph,jqph,jqNo,my_disp,jq_dispglobalconCapture=False#通過該邏輯變量控制攝像頭停止捕獲視頻

timer1.cancel()#定時器停止,使機器出拳畫面靜止

conCaptBt.config(state="active")#繼續出拳按鈕變亮

recogBt.config(state="disabled")#開始識別按鈕變灰

imgRecognized=np.array([],dtype=np.uint8,ndmin=2)#初始化圖像列表,一個二維的空列表

canvas.create_image(200,150,image=imgtk)#當前畫布顯示待識別的圖像

imGray=np.array(im1)#先將待識別的圖像im1轉換成灰度圖像

imgRec=Image.fromarray(imGray.astype('uint8')).resize((64,48))#將圖像縮小10倍

imgRecognized=np.append(imgRecognized,imgRec)#將圖像添加到圖像列表imgRecognized

imgRecognized=imgRecognized.reshape(1,48,64)#將該圖像列表變成三維

imgRecognized=imgRecognized.reshape((1,64*48))#繼續變換為二維數組

imgRecognized=imgRecognized.astype('float32')/255#將所有像素點的值變換到【0,1】區間

result=model.predict_classes(imgRecognized)#調用訓練好的模型開始預測,結果保存在result中ifresult==0:

rk=0

elifresult==1:

rk=1

elifresult==2:

rk=2

my_disp.config(text='',image=myph[rk])#我出的圖片標簽替換顯示為圖片

root.update()#更新照片必須刷新窗體才能顯示

Judge(rk+1,jqNo)#調用判別輸贏的函數model=load_model(r".\sjb-2.h5")defstartRecog():#單擊開始識別按鈕執行的功能globalcanvas,capt,imgtk,im1,conCapture,modelglobaltimer1,myph,jqph,jqNo,my_disp,jq_dispconCapture=False#通過該邏輯變量控制攝像頭停止捕獲視頻timer1.cancel()#定時器停止,使機器出拳畫面靜止conCaptBt.config(state="active")#繼續出拳按鈕變亮recogBt.config(state="disabled")#開始識別按鈕變灰imgRecognized=np.array([],dtype=np.uint8,ndmin=3)#初始化圖像列表,一個四維的空列表canvas.create_image(200,150,image=imgtk)#當前畫布顯示待識別的圖像imGray=np.array(im1)#先將待識別的圖像im1轉換為np數組imgRec=Image.fromarray(imGray.astype('uint8')).resize((64,48))#將圖像縮小10倍

imgRec=np.array(imgRec).reshape(48,64,1)imgRecognized=np.append(imgRecognized,imgRec)#將圖像添加到圖像列表imgRecognizedimgRecognized=imgRecognized.reshape(1,48,64,1)#將該圖像列表變成四維imgRecognized=imgRecognized.astype(‘float32’)/255#將所有像素點的值變換到【0,1】區間result=model.predict_classes(imgRecognized)#調用訓練好的模型開始預測,結果保存在result中ifresult==0:rk=0elifresult==1:rk=1elifresult==2:rk=2Step7,開始識別圖像(使用改進的模型)

my_disp.config(text='',image=myph[rk])#我出的圖片標簽替換顯示為圖片

root.update()#更新照片必須刷新窗體才能顯示

Judge(rk+1,jqNo)#調用判別輸贏的函數model=load_model(r".\sjb-4.h5")Step8,判別輸贏defJudge(x,y):#x對應我出的圖片序號,y對應機器出

globalmeWin,jqWin,timer1ifx!=y:#根據圖片序號判輸贏

ifx==1andy==2:#我出剪刀,機器出石頭

jqWin+=1ifx==1andy==3:#我出剪刀,機器出布

meWin+=1ifx==2andy==1:#我出石頭,機器出剪刀

meWin+=1ifx==2andy==3:#我出石頭,機器出布

jqWin+=1ifx==3andy==1:#我出布,機器出剪刀

jqWin+=1ifx==3andy==2:#我出布,機器出石頭

meWin+=1

varMe.set('我贏了'+str(meWin)+'次')

varJq.set('機器贏了'+str(jqWin)+'次')ifmeWin==3andmeWin>jqWin:#jxbt.config(state="disabled")#繼續按鈕失效

tkinter.messagebox.showinfo("結果","我贏了!")

nextbt.config(state="active")#下一局按鈕變亮

conCaptBt.config(state="disabled")#繼續出拳變灰

timer1.cancel()ifjqWin==3andjqWin>meWin:#jxbt.config(state="disabled")#繼續按鈕失效

tkinter.messagebox.showinfo("結果","機器贏了!")

nextbt.config(state="active")#下一局按鈕變亮

conCaptBt.config(state="disabled")#繼續出拳變灰

timer1.cancel()Step9,繼續出拳def

conCapt():#單擊繼續出拳按鈕執行的功能

globalconCapture,timer1

conCapture=Truetimer1=tr.Timer(0.1,Fun_timer,args=[str(random.randint(1,3))])#每隔0.1秒調用一次Fun_timer函數,參數為隨機生成的文件序號(字符)

timer1.start()#啟動時鐘

recogBt.config(state="active")#開始識別按鈕變亮

conCaptBt.config(state="disabled")#繼續出拳按鈕變灰Step10,繼續下一局def

nextClick():#單擊下一局按鈕

globaltimer,meWin,jqWin,timer1,my_disp,jq_disp,myLabel,jqLabel,conCapture

meWin=0;jqWin=0

recogBt.config(state="active")

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
  • 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
  • 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論