Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 国产高清在线精品二区一,韩剧网免费韩国电视剧在线观看,成人精品视频网站

          整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          為什么要學習HTML?HTML會過時嗎?

          編程有沒有必要學 HTML 呢?這是編程初學者中非常普遍的問題,而且在網上意見分歧很大。關于初學者在學習 HTML 前的一些常見問題,編程獅W3Cschool整理了以下資料希望對你有所幫助:

          學編程不需要學習HTML?

          那些說不需要 HTML 知識的人要么不了解 Web 設計,要么別有用心。雖然現在哪怕不會 HTML 也有其他方法可以解決 web 設計相關問題,但絕大多數資深前端開發者還是會建議你最好還是要學習它的。

          沒有時間學習HTML?

          通常了解基本知識只需要20到40分鐘?;◣讉€小時學習 w3cschool官網 的《HTML 教程 》和《HTML 微課 》,你就可以制作一個簡單而完整的網頁。如果你愿意每周花幾個小時,學習幾個月的 《前端開發體系課程 _ 》,那么您將對網站的工作方式有一個很好的了解。這種時間上的投資將獲得很大的回報比。試想下,如果你本周花在學習上一小時,未來的工作上每個月都將永遠節省一個小時。盡管投資回收期在開始時比較緩慢,但你最終可以只需要花費一小部分時間用來完成工作,你覺得值得嗎?

          編寫HTML太慢?

          這是勸退很多人的一個原因,但實際上這個問題是不存在的。因為大多數情況下我們不需要編寫 HTML 代碼,只需了解它即可。

          我有一個很好的所見即所得編輯器,所以我不需要HTML

          市面上有很多可視化的工具如 WYSIWYG 、Dreamweaver及現在越來越多的”低代碼“云開發工具等,它可以幫助你更高效地工作。如前所述,你并不是要手動輸入 HTML 代碼,而是要了解 HTML 的工作原理。

          例如:射釘槍能比錘子更快地幫助您建造房屋,但是如果你不知道如何搭建框架以及將釘子釘在何處,造出來的房屋很可能會倒塌。我們需要了解如何手動構造 HTML,然后使用所見即所得工具更快地工作。

          PS:所見即所得的編輯器永遠不會是完美的,總有時候是需要我們手動來調整 HTML。。

          我不擅長學習計算機語言

          放心,雖然我們時常把它稱為語言,但其實 HTML 并不是一種編程語言(從技術上講,HTML 被稱為“mark up”語言,也就是標記語言,英文全稱是“HyperText Markup Language”。)。從難度上講,它就像是小孩子們的“密碼”游戲。真正難點在于要學習的東西太多了,但是請記住,你不必全部都學會!只要按照自己的步調學習盡可能多的知識即可。

          不要將費時困難混淆。HTML 很耗時,但是并不難。另外,你不需要學會全部知識點,即使只花費幾個小時來學習基本結構也將極大地幫助你。

          HTML會過時嗎?

          不會。其他編程語言一直在發展中,并且很可能最終會取代 HTML,但是 HTML 將在很長一段時間內繼續作為幾乎所有網站的基礎。在任何情況下,HTML 都會為您提供堅實的基礎,然后再采用 XML 等新語言。

          HTML對我而言太過局限了

          如果您的目的是創建網頁,那么很抱歉告訴你,無論你喜不喜歡,你只能選擇 HTML,因為他是構成網絡構成的基礎。如果你真的想以其他格式(例如PDF)來傳送,請注意,它并不是一個網頁,所以它不能實現我們在網頁中的一些常見功能。

          以上就是編程獅W3Cschool為你整理的關于《為什么要學習HTML?HTML會過時嗎?》的全部內容,現在你要開始學習 HTML 了嗎?

          能每一個前端工程師都想要理解瀏覽器的工作原理。

          我們希望知道從在瀏覽器地址欄中輸入 url 到頁面展現的短短幾秒內瀏覽器究竟做了什么;

          我們希望了解平時常常聽說的各種代碼優化方案是究竟為什么能起到優化的作用;

          我們希望更細化的了解瀏覽器的渲染流程。

          瀏覽器的多進程架構

          一個好的程序常常被劃分為幾個相互獨立又彼此配合的模塊,瀏覽器也是如此,以 Chrome 為例,它由多個進程組成,每個進程都有自己核心的職責,它們相互配合完成瀏覽器的整體功能,每個進程中又包含多個線程,一個進程內的多個線程也會協同工作,配合完成所在進程的職責。

          對一些前端開發同學來說,進程和線程的概念可能會有些模糊,為了更好的理解瀏覽器的多進程架構,這里我們簡單討論一下進程和線程。

          進程(process)和線程(thread)


          進程就像是一個有邊界的生產廠間,而線程就像是廠間內的一個個員工,可以自己做自己的事情,也可以相互配合做同一件事情。

          當我們啟動一個應用,計算機會創建一個進程,操作系統會為進程分配一部分內存,應用的所有狀態都會保存在這塊內存中,應用也許還會創建多個線程來輔助工作,這些線程可以共享這部分內存中的數據。如果應用關閉,進程會被終結,操作系統會釋放相關內存。更生動的示意圖如下:

          一個進程還可以要求操作系統生成另一個進程來執行不同的任務,系統會為新的進程分配獨立的內存,兩個進程之間可以使用 IPC (Inter Process Communication)進行通信。很多應用都會采用這樣的設計,如果一個工作進程反應遲鈍,重啟這個進程不會影響應用其它進程的工作。

          如果對進程及線程的理解還存在疑惑,可以參考下述文章:

          http://www.ruanyifeng.com/blog/2013/04/processes_and_threads.html

          瀏覽器的架構

          有了上面的知識做鋪墊,我們可以更合理的討論瀏覽器的架構了,其實如果要開發一個瀏覽器,它可以是單進程多線程的應用,也可以是使用 IPC 通信的多進程應用。


          不同瀏覽器的架構模型

          不同瀏覽器采用了不同的架構模式,這里并不存在標準,本文以 Chrome 為例進行說明 :

          Chrome 采用多進程架構,其頂層存在一個 Browser process 用以協調瀏覽器的其它進程。


          Chrome 的不同進程

          具體說來,Chrome 的主要進程及其職責如下:

          Browser Process:

          • 負責包括地址欄,書簽欄,前進后退按鈕等部分的工作;
          • 負責處理瀏覽器的一些不可見的底層操作,比如網絡請求和文件訪問;

          Renderer Process:

          • 負責一個 tab 內關于網頁呈現的所有事情

          Plugin Process:

          • 負責控制一個網頁用到的所有插件,如 flash
          • GPU Process
          • 負責處理 GPU 相關的任務



          不同進程負責的瀏覽器區域示意圖

          Chrome 還為我們提供了「任務管理器」,供我們方便的查看當前瀏覽器中運行的所有進程及每個進程占用的系統資源,右鍵單擊還可以查看更多類別信息。

          通過「頁面右上角的三個點點點 — 更多工具 — 任務管理器」即可打開相關面板。

          Chrome 多進程架構的優缺點

          優點

          某一渲染進程出問題不會影響其他進程

          更為安全,在系統層面上限定了不同進程的權限

          缺點

          由于不同進程間的內存不共享,不同進程的內存常常需要包含相同的內容。

          為了節省內存,Chrome 限制了最多的進程數,最大進程數量由設備的內存和 CPU 能力決定,當達到這一限制時,新打開的 Tab 會共用之前同一個站點的渲染進程。

          測試了一下在 Chrome 中打開不斷打開知乎首頁,在 Mac i5 8g 上可以啟動四十多個渲染進程,之后新打開 tab 會合并到已有的渲染進程中。

          Chrome 把瀏覽器不同程序的功能看做服務,這些服務可以方便的分割為不同的進程或者合并為一個進程。以 Broswer Process 為例,如果 Chrome 運行在強大的硬件上,它會分割不同的服務到不同的進程,這樣 Chrome 整體的運行會更加穩定,但是如果 Chrome 運行在資源貧瘠的設備上,這些服務又會合并到同一個進程中運行,這樣可以節省內存,示意圖如下。

          iframe 的渲染 – Site Isolation

          在上面的進程圖中我們還可以看到一些進程下還存在著 Subframe,這就是 Site Isolation 機制作用的結果。

          Site Isolation 機制從 Chrome 67 開始默認啟用。這種機制允許在同一個 Tab 下的跨站 iframe 使用單獨的進程來渲染,這樣會更為安全。


          iframe 會采用不同的渲染進程

          Site Isolation 被大家看做里程碑式的功能, 其成功實現是多年工程努力的結果。Site Isolation 不是簡單的疊加多個進程。這種機制在底層改變了 iframe 之間通信的方法,Chrome 的其它功能都需要做對應的調整,比如說 devtools 需要相應的支持,甚至 Ctrl + F 也需要支持。關于 Site Isolation 的更多內容可參考下述鏈接:

          https://developers.google.com/web/updates/2018/07/site-isolation

          介紹完了瀏覽器的基本架構模式,接下來我們看看一個常見的導航過程對瀏覽器來說究竟發生了什么。

          導航過程發生了什么

          也許大多數人使用 Chrome 最多的場景就是在地址欄輸入關鍵字進行搜索或者輸入地址導航到某個網站,我們來看看瀏覽器是怎么看待這個過程的。

          我們知道瀏覽器 Tab 外的工作主要由 Browser Process 掌控,Browser Process 又對這些工作進一步劃分,使用不同線程進行處理:

          • UI thread : 控制瀏覽器上的按鈕及輸入框;
          • network thread: 處理網絡請求,從網上獲取數據;
          • storage thread: 控制文件等的訪問;



          瀏覽器主進程中的不同線程

          回到我們的問題,當我們在瀏覽器地址欄中輸入文字,并點擊回車獲得頁面內容的過程在瀏覽器看來可以分為以下幾步:

          1. 處理輸入

          UI thread 需要判斷用戶輸入的是 URL 還是 query;

          2. 開始導航

          當用戶點擊回車鍵,UI thread 通知 network thread 獲取網頁內容,并控制 tab 上的 spinner 展現,表示正在加載中。

          network thread 會執行 DNS 查詢,隨后為請求建立 TLS 連接。


          UI thread 通知 Network thread 加載相關信息

          如果 network thread 接收到了重定向請求頭如 301,network thread 會通知 UI thread 服務器要求重定向,之后,另外一個 URL 請求會被觸發。

          3. 讀取響應

          當請求響應返回的時候,network thread 會依據 Content-Type 及 MIME Type sniffing 判斷響應內容的格式。


          判斷響應內容的格式

          如果響應內容的格式是 HTML ,下一步將會把這些數據傳遞給 renderer process,如果是 zip 文件或者其它文件,會把相關數據傳輸給下載管理器。

          Safe Browsing 檢查也會在此時觸發,如果域名或者請求內容匹配到已知的惡意站點,network thread 會展示一個警告頁。此外 CORB 檢測也會觸發確保敏感數據不會被傳遞給渲染進程。


          4. 查找渲染進程

          當上述所有檢查完成,network thread 確信瀏覽器可以導航到請求網頁,network thread 會通知 UI thread 數據已經準備好,UI thread 會查找到一個 renderer process 進行網頁的渲染。


          收到 Network thread 返回的數據后,UI thread 查找相關的渲染進程

          由于網絡請求獲取響應需要時間,這里其實還存在著一個加速方案。當 UI thread 發送 URL 請求給 network thread 時,瀏覽器其實已經知道了將要導航到那個站點。UI thread 會并行的預先查找和啟動一個渲染進程,如果一切正常,當 network thread 接收到數據時,渲染進程已經準備就緒了,但是如果遇到重定向,準備好的渲染進程也許就不可用了,這時候就需要重啟一個新的渲染進程。

          5. 確認導航

          進過了上述過程,數據以及渲染進程都可用了, Browser Process 會給 renderer process 發送 IPC 消息來確認導航,一旦 Browser Process 收到 renderer process 的渲染確認消息,導航過程結束,頁面加載過程開始。

          此時,地址欄會更新,展示出新頁面的網頁信息。history tab 會更新,可通過返回鍵返回導航來的頁面,為了讓關閉 tab 或者窗口后便于恢復,這些信息會存放在硬盤中。


          6. 額外的步驟

          一旦導航被確認,renderer process 會使用相關的資源渲染頁面,下文中我們將重點介紹渲染流程。當 renderer process 渲染結束(渲染結束意味著該頁面內的所有的頁面,包括所有 iframe 都觸發了 onload 時),會發送 IPC 信號到 Browser process, UI thread 會停止展示 tab 中的 spinner。


          Renderer Process 發送 IPC 消息通知 browser process 頁面已經加載完成。

          當然上面的流程只是網頁首幀渲染完成,在此之后,客戶端依舊可下載額外的資源渲染出新的視圖。

          在這里我們可以明確一點,所有的 JS 代碼其實都由 renderer Process 控制的,所以在你瀏覽網頁內容的過程大部分時候不會涉及到其它的進程。不過也許你也曾經監聽過 beforeunload 事件,這個事件再次涉及到 Browser Process 和 renderer Process 的交互,當當前頁面關閉時(關閉 Tab ,刷新等等),Browser Process 需要通知 renderer Process 進行相關的檢查,對相關事件進行處理。


          瀏覽器進程發送 IPC 消息給渲染進程,通知要離開當前網站了

          如果導航由 renderer process 觸發(比如在用戶點擊某鏈接,或者 JS 執行 window.location = "http://newsite.com" ) renderer process 會首先檢查是否有 beforeunload 事件處理器,導航請求由 renderer process 傳遞給 Browser process。

          如果導航到新的網站,會啟用一個新的 render process 來處理新頁面的渲染,老的進程會留下來處理類似 unload 等事件。

          關于頁面的生命周期,更多內容可參考 Page Lifecycle API 。


          瀏覽器進程發送 IPC 消息到新的渲染進程通知渲染新的頁面,同時通知舊的渲染進程卸載。

          除了上述流程,有些頁面還擁有 Service Worker (服務工作線程),Service Worker 讓開發者對本地緩存及判斷何時從網絡上獲取信息有了更多的控制權,如果 Service Worker 被設置為從本地 cache 中加載數據,那么就沒有必要從網上獲取更多數據了。

          值得注意的是 service worker 也是運行在渲染進程中的 JS 代碼,因此對于擁有 Service Worker 的頁面,上述流程有些許的不同。

          當有 Service Worker 被注冊時,其作用域會被保存,當有導航時,network thread 會在注冊過的 Service Worker 的作用域中檢查相關域名,如果存在對應的 Service worker,UI thread 會找到一個 renderer process 來處理相關代碼,Service Worker 可能會從 cache 中加載數據,從而終止對網絡的請求,也可能從網上請求新的數據。


          Service Worker 依據具體情形做處理。

          關于 Service Worker 的更多內容可參考:

          https://developers.google.com/web/fundamentals/primers/service-workers/lifecycle

          如果 Service Worker 最終決定通過網上獲取數據,Browser 進程 和 renderer 進程的交互其實會延后數據的請求時間 。Navigation Preload 是一種與 Service Worker 并行的加速加載資源的機制,服務端通過請求頭可以識別這類請求,而做出相應的處理。

          更多內容可參考:

          https://developers.google.com/web/updates/2017/02/navigation-preload

          渲染進程是如何工作的?

          渲染進程幾乎負責 Tab 內的所有事情,渲染進程的核心目的在于轉換 HTML CSS JS 為用戶可交互的 web 頁面。渲染進程中主要包含以下線程:


          渲染進程包含的線程

          1. 主線程 Main thread

          2. 工作線程 Worker thread

          3. 排版線程 Compositor thread

          4. 光柵線程 Raster thread

          后文我們將逐步介紹不同線程的職責,在此之前我們先看看渲染的流程。

          1. 構建 DOM

          當渲染進程接收到導航的確認信息,開始接受 HTML 數據時,主線程會解析文本字符串為 DOM。

          渲染 html 為 DOM 的方法由 HTML Standard 定義。

          2. 加載次級的資源

          網頁中常常包含諸如圖片,CSS,JS 等額外的資源,這些資源需要從網絡上或者 cache 中獲取。主進程可以在構建 DOM 的過程中會逐一請求它們,為了加速 preload scanner 會同時運行,如果在 html 中存在 <img><link> 等標簽,preload scanner 會把這些請求傳遞給 Browser process 中的 network thread 進行相關資源的下載。

          3.JS 的下載與執行

          當遇到 <script> 標簽時,渲染進程會停止解析 HTML,而去加載,解析和執行 JS 代碼,停止解析 html 的原因在于 JS 可能會改變 DOM 的結構(使用諸如 documwnt.write()等 API)。

          不過開發者其實也有多種方式來告知瀏覽器應對如何應對某個資源,比如說如果在<script> 標簽上添加了 async 或 defer 等屬性,瀏覽器會異步的加載和執行 JS 代碼,而不會阻塞渲染。更多的方法可參考 Resource Prioritization – Getting the Browser to Help You。

          4. 樣式計算

          僅僅渲染 DOM 還不足以獲知頁面的具體樣式,主進程還會基于 CSS 選擇器解析 CSS 獲取每一個節點的最終的計算樣式值。即使不提供任何 CSS,瀏覽器對每個元素也會有一個默認的樣式。


          渲染進程主線程計算每一個元素節點的最終樣式值

          5. 獲取布局

          想要渲染一個完整的頁面,除了獲知每個節點的具體樣式,還需要獲知每一個節點在頁面上的位置,布局其實是找到所有元素的幾何關系的過程。其具體過程如下:

          通過遍歷 DOM 及相關元素的計算樣式,主線程會構建出包含每個元素的坐標信息及盒子大小的布局樹。布局樹和 DOM 樹類似,但是其中只包含頁面可見的元素,如果一個元素設置了 display:none ,這個元素不會出現在布局樹上,偽元素雖然在 DOM 樹上不可見,但是在布局樹上是可見的。


          6. 繪制各元素

          即使知道了不同元素的位置及樣式信息,我們還需要知道不同元素的繪制先后順序才能正確繪制出整個頁面。在繪制階段,主線程會遍歷布局樹以創建繪制記錄。繪制記錄可以看做是記錄各元素繪制先后順序的筆記。


          主線程依據布局樹構建繪制記錄

          7. 合成幀

          熟悉 PS 等繪圖軟件的童鞋肯定對圖層這一概念不陌生,現代 Chrome 其實利用了這一概念來組合不同的層。

          復合是一種分割頁面為不同的層,并單獨柵格化,隨后組合為幀的技術。不同層的組合由 compositor 線程(合成器線程)完成。

          主線程會遍歷布局樹來創建層樹(layer tree),添加了 will-change CSS 屬性的元素,會被看做單獨的一層。


          主線程遍歷布局樹生成層樹

          你可能會想給每一個元素都添加上 will-change,不過組合過多的層也許會比在每一幀都柵格化頁面中的某些小部分更慢。為了更合理的使用層,可參考 堅持僅合成器的屬性和管理層計數 。

          一旦層樹被創建,渲染順序被確定,主線程會把這些信息通知給合成器線程,合成器線程會柵格化每一層。有的層的可以達到整個頁面的大小,因此,合成器線程將它們分成多個磁貼,并將每個磁貼發送到柵格線程,柵格線程會柵格化每一個磁貼并存儲在 GPU 顯存中。


          柵格線程會柵格化每一個磁貼并存儲在 GPU 顯存中

          一旦磁貼被光柵化,合成器線程會收集稱為繪制四邊形的磁貼信息以創建合成幀。

          合成幀隨后會通過 IPC 消息傳遞給瀏覽器進程,由于瀏覽器的 UI 改變或者其它拓展的渲染進程也可以添加合成幀,這些合成幀會被傳遞給 GPU 用以展示在屏幕上,如果滾動發生,合成器線程會創建另一個合成幀發送給 GPU。


          合成器線程會發送合成幀給 GPU 渲染

          合成器的優點在于,其工作無關主線程,合成器線程不需要等待樣式計算或者 JS 執行,這就是為什么合成器相關的動畫 最流暢,如果某個動畫涉及到布局或者繪制的調整,就會涉及到主線程的重新計算,自然會慢很多。

          瀏覽器對事件的處理

          瀏覽器通過對不同事件的處理來滿足各種交互需求,這一部分我們一起看看從瀏覽器的視角,事件是什么,在此我們先主要考慮鼠標事件。

          在瀏覽器的看來,用戶的所有手勢都是輸入,鼠標滾動,懸置,點擊等等都是。

          當用戶在屏幕上觸發諸如 touch 等手勢時,首先收到手勢信息的是 Browser process, 不過 Browser process 只會感知到在哪里發生了手勢,對 tab 內內容的處理是還是由渲染進程控制的。

          事件發生時,瀏覽器進程會發送事件類型及相應的坐標給渲染進程,渲染進程隨后找到事件對象并執行所有綁定在其上的相關事件處理函數。


          事件從瀏覽器進程傳送給渲染進程

          前文中,我們提到過合成器可以獨立于主線程之外通過合成柵格化層平滑的處理滾動。如果頁面中沒有綁定相關事件,組合器線程可以獨立于主線程創建組合幀。如果頁面綁定了相關事件處理器,主線程就不得不出來工作了。這時候合成器線程會怎么處理呢?

          這里涉及到一個專業名詞「理解非快速滾動區域(non-fast scrollable region)」由于執行 JS 是主線程的工作,當頁面合成時,合成器線程會標記頁面中綁定有事件處理器的區域為 non-fast scrollable region ,如果存在這個標注,合成器線程會把發生在此處的事件發送給主線程,如果事件不是發生在這些區域,合成器線程則會直接合成新的幀而不用等到主線程的響應。


          涉及 non-fast scrollable region 的事件,合成器線程會通知主線程進行相關處理。

          web 開發中常用的事件處理模式是事件委托,基于事件冒泡,我們常常在最頂層綁定事件:

          復制代碼

          document.body.addEventListener('touchstart', 
          event => {
           if (event.target === area) {
           event.preventDefault();
           }
          }
          );
           
          

          上述做法很常見,但是如果從瀏覽器的角度看,整個頁面都成了 non-fast scrollable region 了。

          這意味著即使操作的是頁面無綁定事件處理器的區域,每次輸入時,合成器線程也需要和主線程通信并等待反饋,流暢的合成器獨立處理合成幀的模式就失效了。


          由于事件綁定在最頂部,整個頁面都成為了 non-fast scrollable region。

          為了防止這種情況,我們可以為事件處理器傳遞 passive: true 做為參數,這樣寫就能讓瀏覽器即監聽相關事件,又讓組合器線程在等等主線程響應前構建新的組合幀。

          復制代碼

          document.body.addEventListener('touchstart', 
          event => {
           if (event.target === area) {
           event.preventDefault()
           }
           }, {passive: true}
          );
           
          

          不過上述寫法可能又會帶來另外一個問題,假設某個區域你只想要水平滾動,使用 passive: true 可以實現平滑滾動,但是垂直方向的滾動可能會先于event.preventDefault()發生,此時可以通過 event.cancelable 來防止這種情況。

          復制代碼

          document.body.addEventListener('pointermove', event => {
           if (event.cancelable) {
           event.preventDefault(); // block the native scroll
           /*
           * do what you want the application to do here
           */
           } 
          }, {passive: true});
           
          

          也可以使用 css 屬性 touch-action 來完全消除事件處理器的影響,如:

          復制代碼

          #area { 
           touch-action: pan-x; 
          }
           
          

          查找到事件對象

          當組合器線程發送輸入事件給主線程時,主線程首先會進行命中測試(hit test)來查找對應的事件目標,命中測試會基于渲染過程中生成的繪制記錄( paint records )查找事件發生坐標下存在的元素。


          主線程依據繪制記錄查找事件相關元素。

          事件的優化

          一般我們屏幕的刷新速率為 60fps,但是某些事件的觸發量會不止這個值,出于優化的目的,Chrome 會合并連續的事件 (如 wheel, mousewheel, mousemove, pointermove, touchmove ),并延遲到下一幀渲染時候執行 。

          而如 keydown, keyup, mouseup, mousedown, touchstart, 和 touchend 等非連續性事件則會立即被觸發。


          Chrome 會合并連續事件到下一幀觸發。

          合并事件雖然能提示性能,但是如果你的應用是繪畫等,則很難繪制一條平滑的曲線了,此時可以使用 getCoalescedEvents API 來獲取組合的事件。示例代碼如下:

          復制代碼

          window.addEventListener('pointermove', event => {
           const events = event.getCoalescedEvents();
           for (let event of events) {
           const x = event.pageX;
           const y = event.pageY;
           // draw a line using x and y coordinates.
           }
          });
           
          



          花了好久來整理上面的內容,整理的過程收獲還挺大的,也希望這篇筆記能對你有所啟發,如果有任何疑問,歡迎一起來討論。

          本文經作者授權轉載,原文鏈接為:

          https://zhuanlan.zhihu.com/p/47407398

          參考鏈接

          • https://developers.google.com/web/updates/2018/09/inside-browser-part1
          • https://developers.google.com/web/updates/2018/09/inside-browser-part2
          • https://developers.google.com/web/updates/2018/09/inside-browser-part3
          • https://developers.google.com/web/updates/2018/09/inside-browser-part4
          • https://www.html5rocks.com/zh/tutorials/internals/howbrowserswork/#Layered_representation

          解一定的技術原理,對產品經理而言是有益處的。本文講述的圖像處理的基本思路,希望大家能夠對當前圖像處理技術有一定了解。

          現在有個概念叫泛產品經理,這個概念本身是好的,核心說的是產品思維,但是在工作上我認為還是有一定誤導性。產品經理在工作中要突出自己的核心價值與職業壁壘,如果無法構建良好的職業壁壘,就會面臨中年危機帶來的挑戰。

          人工智能相對的技術內容是塑造職業壁壘的有力武器,并非要求產品經理能夠自己寫代碼開發產品,而且在了解技術原理后,能夠將業務快速高效的轉化為可實施的產品問題,對于人工智能相關的產品更加重要。所有了解一定的技術原理,對產品經理而言是有益處的。本文講述的圖像處理的基本思路,希望大家能夠對當前圖像處理技術有一定了解。

          卷積神經網絡(Convolutional Neural Network, CNN)是一種前饋神經網絡,是當今圖像處理的主流技術。說起CNN卷積網絡,不得不說2012 年Alex Krizhevsky 憑借它們贏得了那一年的 ImageNet 大賽(由斯坦福大學李飛飛發起的世界級人工智能大賽),AlexNet將圖像分類誤差記錄從 26% 降低到 15%,之后很多公司開始將深度學習作為的核心技術發展。Facebook、谷歌、亞馬遜等知名公司都利用卷積網絡進行圖像識別,商品推送等工作。

          CNN卷積神經網絡是一個大家族,對圖像而言主要有以下4個關鍵技術應用。

          1. 物體定位:預測包含主要物體的圖像區域,以便識別區域中的物體。
          2. 物體識別:針對分割好的目標進行分類。
          3. 目標分割:將圖像目標分割出來,針對圖像上的像素進行歸屬,例中如人類、建筑物等。
          4. 關鍵點檢測:從圖像中檢測目標物體上某關鍵點的位置,例如人類面部關鍵點信息。

          CNN網絡訓練數據集是公開的,支持全球的開發者進行下載訓練模型數據集:

          (1)MNIST:最受歡迎的深度學習數據集之一。手寫數字數據集,包含一組60,000個示例的訓練集和一個包含10,000個示例的測試集。http://deeplearning.net/tutorial/gettingstarted.html

          (2)ImageNet:李飛飛創立的全球視覺識別挑戰賽數據集(ILSVRC)。http://image-net.org/index

          (3)PASCAL:標準化的優秀的數據集,數據集可以用于圖像分類、目標檢測、圖像分割。http://host.robots.ox.ac.uk/pascal/VOC/

          (4)MS-COCO:COCO是一個大型的、豐富的物體檢測,分割和字幕數據集。http://cocodataset.org/

          為什么要用CNN來處理圖像呢?

          原因很簡單,因為能在短時間內提取圖像特征。

          一般來講,普通神經網絡將輸入層和隱含層進行全連接(Full Connected),從而保證系統能夠提取張圖像的特征。從算力的角度來分析,較小的圖像從整幅圖像中計算特征是可行的。比如提取一張28×28的小照片的特征,當前CPU還夠用。

          但是,如果提取大的圖像(如 96×96 的圖像),要使用這種普通神經網絡全全連接方法來學習整幅圖像上的特征,將變得非常耗時。需要設計個輸入單元,如果要學習 100 個特征,那么就有個參數需要進行運算。

          相比之下,96×96 的圖像計算過程比28×28圖像的處理過程慢100倍。大家都明白當前的相片動不動就是高清大圖,普通神經網絡按照全連接的方式無法預計何時才能處理完。

          下面的內容是本節的重點部分,我們具體來講述一下CNN網絡的實現過程。

          1. 圖像的輸入

          我們首先要搞清楚一張照片是如何輸入到神經網絡中的。眾所周知,計算機適合處理的是矩陣運算,所以必須要把圖片轉換成矩陣后計算機才能認識。所有的彩色圖像都由紅綠藍(RGB)疊加而成,成為圖像的三個通道,一張圖片在計算機中存儲也是通過這三個矩陣完成的。

          圖4-23圖的色彩通道

          如圖4-23所示,一張64*64個像素大小的圖片(例如白色可以表示成RGB(255,255,255),可以用3個64*64大小的矩陣來代表這個圖。上面指畫三個5 * 4的矩陣來代表64*64的全尺寸矩陣。RGB這三個矩陣稱為為圖像的3個通道,也作為神經網絡的輸入數據。

          2. 卷積神經網絡的組成

          與其他神經網絡相同,CNN網絡同樣也包含輸入層、隱藏層、輸出層幾大部分,卷積神經網絡的主要運算過程如圖4-24所示。

          圖4-24卷積神經網絡處理過程

          卷積層(Convolutional layer):卷積層由多個卷積單元組成,每個卷積單元的參數都是通過反向傳播算法優化得到的。卷積運算主要為了提取圖像的特征,隨著卷積層的增加,多層網絡可以提取更為復雜的圖像特征。

          線性整流(Rectified Linear Units layer, ReLU layer):主要指的是激活函數運算(Activation function)使用線性整流的ReLu函數(Rectified Linear Units, ReLU)。

          池化層(Pooling layer):在卷積之后圖像的維度特征依然很多,將特征矩陣分割成幾個單個區塊,取其最大值或平均值,起到了降維的作用。

          全連接層(Fully-Connected layer):把所有局部特征以及各通道的特征矩陣結合變為向量代表,計算最后每一類的得分。

          3. 計算過程

          CNN網絡的計算過程如圖XXX,每個組成模塊代表了不同的計算內容。

          (1)數據規則化

          彩色圖像的輸入通常先要分解為R(紅)G(綠)B(藍)三個通道,其中每個值介于0~255之間。

          (2)卷積運算(Convolution)

          前面講到,由于普通的神經網絡對于輸入與隱層采用全連接的方式進行特征提取,在處理圖像時,稍微大一些的圖將會導致計算量巨大而變得十分緩慢。卷積運算正是為了解決這一問題,每個隱含單元只能連接輸入單元的一部分,我們可以理解為是一種特征的提取方法。

          首先我們來明確幾個基礎概念:深度(depth)、步長(stride)、補零(zero-padding)、卷積核(convolution kernel)。

          深度(depth):深度指的是圖的深度與它控制輸出單元的深度,也表示為連接同一塊區域的神經元個數。

          步幅(stride):用來描述卷積核移動的步長。

          補零(zero-padding):通過對圖片邊緣補零來填充圖片邊緣,從而控制輸出單元的空間大小。

          卷積核(convolution kernel):在輸出圖像中每一個像素是輸入圖像中一個小區域中像素的加權平均的權值函數。卷積核可以有多個,卷積核參數可以通過誤差反向傳播來進行訓練。

          如圖4-25為步長=1的卷積計算過程,卷積核依次向右移動進行卷積運算得到相應結果。

          圖4-25 卷積運算過程

          為圖像計算可以對邊緣進行補零,可見這個過程改變了圖像的運算大小,如圖4-26所示。

          卷積運算的過程其實非常簡單,過程如圖4-27描述,可以概括為公式(4.3.6)。其中B代表卷積后的結果,K是卷積核,A為圖像的輸入矩陣。

          圖4-27 卷積運算過程

          如圖4-27所示,可見卷積核K為2*2的卷積核,詳細運算過程如下。

          全部圖像卷積運算可以通過公式(4.3.6)進行。

          (3)激活

          CNN卷積神經網絡在卷積后需要經過激活過程,當前通常使用的激活函數是Relu函數。Relu函數的主要特點在之前的章節已經講過。從函數的圖像上來看,單側抑制,相對寬闊的興奮邊界,具有稀疏激活性的特點。

          (4)池化(Pooling)

          池化的目的是提取特征,減少向下一個階段傳遞的數據量。池化操作相對于對每個深度切片是獨立,池化規模一般為像素的 2*2,與卷積運算相比,池化層運算一般有以下幾種:

          1. 最大池化(Max Pooling):取4個點數值的最大值。這是最常用的池化算法。
          2. 均值池化(Mean Pooling):取4個點數值的均值。
          3. 高斯池化(Gauss Pooling):按照高斯模糊的方法。

          如圖4-28,描述了最大池化的計算方法。

          圖4-28 池化運算過程

          (5)全連接(Fully-connected layer)

          全連接層一般出現最后幾步,在卷積神經網絡中起到“分類器”的作用。如果說卷積層、池化層和激活函數層等操作是將原始數據映射到隱層特征空間的話,全連接層則起到將學到的“分布式特征表示”映射到樣本標記空間的作用。全連接過程是對矩陣的展開過程,也可以理解為輸出矩陣與一個1*1的卷積核進行卷積運算,最后展開為一個1*n的向量。

          在卷積神經網絡中,全連接層一般使用Softmax函數來進行分類。Softmax函數適用于數據分類,用于保證每個分類概率總和為1。

          卷積神經網絡(CNN)的計算過程雖然講解繁瑣,但對于了解深刻理解神經網絡算法非常有益。卷積神經網絡經過近30年的發展擁有多條網絡發展分支,并且持續高速發展之中。其中有網絡層數加深的VGG16與VGG19等,有卷積模塊增強的NIN網絡等,從分類任務向目標檢測任務過度的新型網絡R-CNN等,圖4-29展示了卷積神經網絡的不同發展分支。

          #專欄作家#

          白白,人人都是產品經理專欄作家。公眾號:白白說話(xiaob-talk)。醫藥行業資深產品專家,負責人工智能行業類產品綜合架構與技術開發。在行業云產品架構,藥物設計AI輔助、醫療知識圖譜等領域有深入研究。

          本文原創發布于人人都是產品經理。未經許可,禁止轉載。

          題圖來自Unsplash,基于 CC0 協議


          主站蜘蛛池模板: 国产一区二区精品| 国产在线一区二区杨幂| 国产一区二区三区播放心情潘金莲| 无码国产精品一区二区免费式影视 | 国产精品女同一区二区| 成人久久精品一区二区三区| 日韩一区二区在线观看视频| 亚洲熟女乱综合一区二区| 91精品一区二区三区在线观看| 国产熟女一区二区三区四区五区| 波多野结衣一区在线| 国产精品一区二区电影| 四虎成人精品一区二区免费网站 | 免费无码一区二区三区蜜桃| 亚洲一区二区三区丝袜| 亚洲一区精彩视频| 精品无码国产一区二区三区AV| 国产成人精品无码一区二区| 丝袜人妻一区二区三区网站| 一本色道久久综合一区| aⅴ一区二区三区无卡无码| 国产拳头交一区二区| 国产精品视频一区国模私拍| 久久久无码精品人妻一区| 亚洲国产欧美一区二区三区| 成人无号精品一区二区三区 | 亚洲AV无码一区二三区| 国产伦一区二区三区免费| 日韩美女在线观看一区| 日本精品一区二区三区四区| 久久精品无码一区二区日韩AV| 国产在线观看一区二区三区精品| 国产一区二区三区高清在线观看| 中文字幕一区二区三| 精品无码一区二区三区爱欲| 国产免费一区二区三区| 日韩高清一区二区三区不卡| 免费在线观看一区| 国产一区二区三区久久精品| 久久久久人妻精品一区| 日韩一区二区a片免费观看|