openh264 降噪功能源碼分析

文件位置

openh264/codec/processing/denoise/denoise.cpp
openh264/codec/processing/denoise/denoise_filter.cpp

代碼流程

在這里插入圖片描述

  • 說明:從代碼流程可以看到,實現降噪的核心功能主要就是BilateralDenoiseLumaWaverageDenoiseChroma兩個函數。

原理

  • 參數開關控制:(bool) bEnableDenoise

BilateralDenoiseLuma函數

  1. 功能:實現圖像亮度分量的雙邊濾波降噪
  2. 過程
  • 將亮度指針pSrcY向前移動m_uiSpaceRadius行,跳過圖像邊緣的噪聲處理區域;
  • 外層循環遍歷圖像的高度,從m_uiSpaceRadius開始,到iHeight - m_uiSpaceRadius,跳過邊緣區域;
    • 內層循環遍歷圖像的寬度,從m_uiSpaceRadius開始,每次增加8(為了利用SIMD指令集進行優化),直到iWidth - m_uiSpaceRadius - TAIL_OF_LINE8;
      • 對當前8個像素塊使用雙邊濾波器pfBilateralLumaFilter8函數(指向具體的BilateralLumaFilter8_c函數)進行去噪;
    • for 循環處理剩余的像素,這些像素不能被8整除,因此需要單獨處理;
      • 調用Gauss3x3Filter函數對單個像素使用高斯濾波器進行去噪;
    • 將指針pSrcY向下移動一行,準備處理下一行的數據;
  1. 原理圖
    在這里插入圖片描述
  2. 相關源碼
  • BilateralDenoiseLuma函數
void CDenoiser::BilateralDenoiseLuma (uint8_t* pSrcY, int32_t iWidth, int32_t iHeight, int32_t iStride) {int32_t w;pSrcY = pSrcY + m_uiSpaceRadius * iStride;for (int32_t h = m_uiSpaceRadius; h < iHeight - m_uiSpaceRadius; h++) {for (w = m_uiSpaceRadius; w < iWidth - m_uiSpaceRadius - TAIL_OF_LINE8; w += 8) {m_pfDenoise.pfBilateralLumaFilter8 (pSrcY + w, iStride);}for (; w < iWidth - m_uiSpaceRadius; w++) {Gauss3x3Filter (pSrcY + w, iStride);}pSrcY += iStride;}
}
  • pfBilateralLumaFilter8函數(指向具體的BilateralLumaFilter8_c函數)
void BilateralLumaFilter8_c (uint8_t* pSample, int32_t iStride) {int32_t nSum = 0, nTotWeight = 0;int32_t iCenterSample = *pSample;uint8_t* pCurLine = pSample - iStride - DENOISE_GRAY_RADIUS;int32_t x, y;int32_t iCurSample, iCurWeight, iGreyDiff;uint8_t aSample[8];for (int32_t i = 0; i < 8; i++) {nSum = 0;nTotWeight = 0;iCenterSample = *pSample;pCurLine = pSample - iStride - DENOISE_GRAY_RADIUS;for (y = 0; y < 3; y++) {for (x = 0; x < 3; x++) {if (x == 1 && y == 1) continue; // except center pointiCurSample = pCurLine[x];iCurWeight = WELS_ABS (iCurSample - iCenterSample);iGreyDiff = 32 - iCurWeight;if (iGreyDiff < 0) continue;else iCurWeight = (iGreyDiff * iGreyDiff) >> 5;nSum += iCurSample * iCurWeight;nTotWeight +=  iCurWeight;}pCurLine += iStride;}nTotWeight = 256 - nTotWeight;nSum += iCenterSample * nTotWeight;aSample[i] = nSum >> 8;pSample++;}WelsMemcpy (pSample - 8, aSample, 8);
}
  • Gauss3x3Filter函數
/***************************************************************************
edge of y/uv use a 3x3 Gauss filter, radius = 1:
1   2   1
2   4   2
1   2   1
***************************************************************************/
void Gauss3x3Filter (uint8_t* pSrc, int32_t iStride) {int32_t nSum = 0;uint8_t* pCurLine1 = pSrc - iStride - 1;uint8_t* pCurLine2 = pCurLine1 + iStride;uint8_t* pCurLine3 = pCurLine2 + iStride;nSum =  pCurLine1[0]       + (pCurLine1[1] << 1) +  pCurLine1[2]       +(pCurLine2[0] << 1) + (pCurLine2[1] << 2) + (pCurLine2[2] << 1) +pCurLine3[0]       + (pCurLine3[1] << 1) +  pCurLine3[2];*pSrc = nSum >> 4;
}

WaverageDenoiseChroma函數

  1. 功能:實現圖像色度分量的降噪功能
  2. 過程
  • 將指針pSrcUV向前移動UV_WINDOWS_RADIUS行,跳過圖像邊緣的噪聲處理區域;
  • 外層循環遍歷圖像的高度,從UV_WINDOWS_RADIUS開始,到iHeight - UV_WINDOWS_RADIUS,跳過邊緣區域;
    • 內層循環遍歷圖像的寬度,從UV_WINDOWS_RADIUS開始,每次增加8(為了利用SIMD指令集進行優化),直到iWidth - UV_WINDOWS_RADIUS - TAIL_OF_LINE8,用于確保在處理行尾時不會超出邊界;
      • 對當前8個像素塊使用加權平均濾波器pfWaverageChromaFilter8函數(指向WaverageChromaFilter8_c函數)進行去噪;
    • 調用Gauss3x3Filter函數處理剩余的像素,這些像素不能被8整除,因此需要單獨處理;
    • 將指針pSrcUV向下移動一行,準備處理下一行的數據。
  1. 原理圖
    在這里插入圖片描述
  2. 相關源碼
  • WaverageDenoiseChroma函數
void CDenoiser::WaverageDenoiseChroma (uint8_t* pSrcUV, int32_t iWidth, int32_t iHeight, int32_t iStride) {int32_t w;pSrcUV = pSrcUV + UV_WINDOWS_RADIUS * iStride;for (int32_t h = UV_WINDOWS_RADIUS; h < iHeight - UV_WINDOWS_RADIUS; h++) {for (w = UV_WINDOWS_RADIUS; w < iWidth - UV_WINDOWS_RADIUS - TAIL_OF_LINE8; w += 8) {m_pfDenoise.pfWaverageChromaFilter8 (pSrcUV + w, iStride);}for (; w < iWidth - UV_WINDOWS_RADIUS; w++) {Gauss3x3Filter (pSrcUV + w, iStride);}pSrcUV += iStride;}
}
  • WaverageChromaFilter8_c函數
/***************************************************************************
5x5 filter:
1   1   2   1   1
1   2   4   2   1
2   4   20  4   2
1   2   4   2   1
1   1   2   1   1
***************************************************************************/
#define SUM_LINE1(pSample)       (pSample[0]     +(pSample[1])    +(pSample[2]<<1)  + pSample[3]     + pSample[4])
#define SUM_LINE2(pSample)       (pSample[0]     +(pSample[1]<<1) +(pSample[2]<<2)  +(pSample[3]<<1) + pSample[4])
#define SUM_LINE3(pSample)      ((pSample[0]<<1) +(pSample[1]<<2) +(pSample[2]*20)  +(pSample[3]<<2) +(pSample[4]<<1))
void WaverageChromaFilter8_c (uint8_t* pSample, int32_t iStride) {int32_t sum;uint8_t* pStartPixels = pSample - UV_WINDOWS_RADIUS * iStride - UV_WINDOWS_RADIUS;uint8_t* pCurLine1 = pStartPixels;uint8_t* pCurLine2 = pCurLine1 + iStride;uint8_t* pCurLine3 = pCurLine2 + iStride;uint8_t* pCurLine4 = pCurLine3 + iStride;uint8_t* pCurLine5 = pCurLine4 + iStride;uint8_t aSample[8];for (int32_t i = 0; i < 8; i++) {sum = SUM_LINE1 ((pCurLine1 + i)) + SUM_LINE2 ((pCurLine2 + i)) + SUM_LINE3 ((pCurLine3 + i))+ SUM_LINE2 ((pCurLine4 + i)) + SUM_LINE1 ((pCurLine5 + i));aSample[i] = (sum >> 6);pSample++;}WelsMemcpy (pSample - 8, aSample, 8);
}
  • Gauss3x3Filter 函數
/***************************************************************************
edge of y/uv use a 3x3 Gauss filter, radius = 1:
1   2   1
2   4   2
1   2   1
***************************************************************************/
void Gauss3x3Filter (uint8_t* pSrc, int32_t iStride) {int32_t nSum = 0;uint8_t* pCurLine1 = pSrc - iStride - 1;uint8_t* pCurLine2 = pCurLine1 + iStride;uint8_t* pCurLine3 = pCurLine2 + iStride;nSum =  pCurLine1[0]       + (pCurLine1[1] << 1) +  pCurLine1[2]       +(pCurLine2[0] << 1) + (pCurLine2[1] << 2) + (pCurLine2[2] << 1) +pCurLine3[0]       + (pCurLine3[1] << 1) +  pCurLine3[2];*pSrc = nSum >> 4;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/24090.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/24090.shtml
英文地址,請注明出處:http://en.pswp.cn/web/24090.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

SOA主要協議和規范

Web服務作為實現SOA中服務的最主要手段。首先來了解Web Service相關的標準。它們大多以“WS-”作為名字的前綴&#xff0c;所以統稱“WS-*”。Web服務最基本的協議包括UDDI、WSDL和SOAP&#xff0c;通過它們&#xff0c;可以提供直接而又簡單的Web Service支持&#xff0c;如圖…

代碼隨想錄算法訓練營第十五天| 110.平衡二叉樹、 257. 二叉樹的所有路徑、404.左葉子之和

110.平衡二叉樹 題目鏈接&#xff1a;110.平衡二叉樹 文檔講講&#xff1a;代碼隨想錄 狀態&#xff1a;還可以 思路&#xff1a;計算左右子樹的深度差&#xff0c;遞歸判斷左右子樹是否符合平衡條件 題解&#xff1a; public boolean isBalanced(TreeNode root) {if (root n…

覆蓋路徑規劃經典算法 The Boustrophedon Cellular Decomposition 詳解

2000年一篇論文 Coverage of Known Spaces: The Boustrophedon Cellular Decomposition 橫空出世&#xff0c;解決了很多計算機和機器人領域的覆蓋路徑問題&#xff0c;今天我來詳細解讀這個算法。 The Boustrophedon Cellular Decomposition 算法詳解 這篇論文標題為"C…

nginx配置正向代理忽略證書!!!!!

要繞過證書驗證并忽略SSL證書檢查&#xff0c;可以使用curl的-k或--insecure選項。這允許curl在連接到HTTPS站點時忽略證書錯誤。你可以這樣做&#xff1a; curl -k https://220.181.49.193:10010/sms/11011200002020000001/flv/hls/11010000021321001788_1101000002132100178…

數字模擬EDA研發環境搭建

中小企業數字模擬EDA研發環境部署、集群搭建、網絡配置、硬件咨詢、數據備份、技術指導、環境生命周期維護等&#xff0c;Cadence、Synopsys、Mentor、Keysight、ANSYS&#xff0c;MATLAB、Xilinx等廠商軟件工具安裝調試。 EDA研發環境搭建經驗交流&#xff0c;請加V

【Neo4j】Windows11使用Neo4j導入CSV數據可視化知識圖譜

Windows11使用Neo4j導入CSV數據可視化知識圖譜 序1. 安裝JDK21&#xff08;1&#xff09;下載&#xff08;2&#xff09;安裝&#xff08;3&#xff09;環境配置 2. 安裝Neo4j&#xff08;1&#xff09;下載&#xff08;2&#xff09;解壓安裝&#xff08;3&#xff09;環境配置…

初識C++ · 模板進階

目錄 前言&#xff1a; 1 非類型模板參數 2 按需實例化 3 模板特化 4 模板的分離編譯 前言&#xff1a; 前面模板我們會了簡單的使用&#xff0c;這里帶來模板的進階&#xff0c;當然&#xff0c;也就那么幾個知識點&#xff0c;并不太難。 1 非類型模板參數 先來看這樣…

嵌入式移植jpeglib--Linux交叉編譯ARM平臺

一 、交叉編譯jpeg庫 1.下載源碼tar.gz 2. 源碼目錄下執行 jpeglib配置文件 ./configure CCarm-none-linux-gnueabihf-gcc LDarm-none-linux-gnueabihf-ld --prefix/work/jpeg_arm_lib --exec-prefix/work/jpeg_arm_lib --enable-shared --enable-static --hostarm-none-linu…

經典文獻閱讀之--MGS-SLAM(單目稀疏跟蹤和高斯映射與深度平滑正則化)

Tip: 如果你在進行深度學習、自動駕駛、模型推理、微調或AI繪畫出圖等任務&#xff0c;并且需要GPU資源&#xff0c;可以考慮使用UCloud云計算旗下的Compshare的GPU算力云平臺。他們提供高性價比的4090 GPU&#xff0c;按時收費每卡2.6元&#xff0c;月卡只需要1.7元每小時&…

CiteScore 2023發布,AI Open斬獲45分,位列全球計算機領域前1%

與影響因子&#xff08;IF&#xff09;一樣&#xff0c;引用分數&#xff08;CiteScore&#xff09;同樣是衡量學術期刊影響力的重要指標之一&#xff0c;且大有趕超前者的勢頭。 6 月 6 日&#xff0c;CiteScore 2023 正式發布&#xff0c;人工智能領域可自由訪問的期刊平臺 …

Java 8 中的 Stream API,用于處理集合數據

Java 8 引入了 Stream API&#xff0c;使得處理集合數據變得更加簡潔和高效。Stream API 允許開發者以聲明式編程風格操作數據集合&#xff0c;而不是使用傳統的迭代和條件語句。 一、基本概念 1.1 什么是 Stream Stream 是 Java 8 中的一個新抽象&#xff0c;它允許對集合數…

CSRF 令牌的生成過程和檢查過程

在 Django 中,CSRF 令牌的生成和檢查過程是通過 Django 的 CSRF 中間件 (CsrfViewMiddleware) 和模板標簽 ({% csrf_token %}) 自動處理的。以下是詳細的生成和檢查過程: CSRF 令牌的生成過程 用戶訪問頁面: 當用戶第一次訪問頁面時,Django 會為用戶創建一個會話。如果用戶…

人工智能、深度學習和機器學習的前世今生

人工智能、深度學習和機器學習的前世今生 引言 在當今科技飛速發展的時代&#xff0c;人工智能&#xff08;AI&#xff09;、機器學習&#xff08;ML&#xff09;和深度學習&#xff08;DL&#xff09;已經成為引領第四次工業革命的重要力量。這些技術不僅在學術界和工業界掀…

C++ 數據共享與保護學習記錄【代碼】

一.項目一 1.頭文件.h //A.h #pragma once //防止頭文件被重復包含&#xff08;重復包含會被重復編譯&#xff0c;也就是該類會被重復定義&#xff09; #ifndef HEAD_H //等價于&#xff08; #if !defined(HEAD_H) ) //defined是一個預處理操作符&#xff0c;相當于一個表達式…

整理好了!2024年最常見 20 道分布式、微服務面試題(二)

上一篇地址&#xff1a;整理好了&#xff01;2024年最常見 20 道分布式、微服務面試題&#xff08;一&#xff09;-CSDN博客 三、請解釋CAP定理及其含義。 CAP定理是分布式計算領域的一個基本概念&#xff0c;由計算機科學家Eric Brewer在2000年提出&#xff0c;并由科學家Se…

力扣76.最小覆蓋子串

力扣76.最小覆蓋子串 用哈希表記錄每個字母出現次數 枚舉右端點 判斷是否能全覆蓋如果可以 并且更短 就更新 j 縮小區間再判斷 class Solution {bool is_covered(int cnt_s[], int cnt_t[]) {for (int i A; i < Z; i) {if (cnt_s[i] < cnt_t[i]) {return false;}}fo…

上網操作的必要條件

一、 網卡 1、 為什么需要網卡 計算機為了實現網絡通信&#xff0c;必須都要有網卡這個東西&#xff0c;網卡是計算機眾多外部設備之一&#xff08;其它還有硬盤、鍵盤等&#xff09;&#xff0c;計算機將數據發給網卡&#xff0c;網卡負責將數據往外發送&#xff0c;通過IP定…

技術團隊的沖突管理: 谷歌亞里士多德項目的啟示

有效的沖突管理對于技術團隊保持高效和創新的工作環境至關重要。谷歌的亞里士多德項目是一項內部研究&#xff0c;旨在了解成功團隊的因素&#xff0c;強調了心理安全和開放溝通在促進團隊成員之間的合作和解決分歧方面的重要性。本文將探討受谷歌的亞里士多德項目和其他數據點…

工廠生產計劃難以執行的真正原因及對策

在制造業中&#xff0c;生產計劃的執行對于企業的運營至關重要。然而&#xff0c;許多工廠在生產計劃執行過程中面臨著諸多挑戰&#xff0c;尤其是物料齊套率低的問題。本文將探討工廠生產計劃難以執行的真正原因&#xff0c;并提出相應的解決對策。 一、生產計劃難以執行的真…

mysql optimizer_switch : 查詢優化器優化策略深入解析

碼到三十五 &#xff1a; 個人主頁 在 MySQL 數據庫中&#xff0c;查詢優化器是一個至關重要的組件&#xff0c;它負責確定執行 SQL 查詢的最有效方法。為了提供DBA和開發者更多的靈活性和控制權&#xff0c;MySQL 引入了 optimizer_switch 系統變量。這個強大的工具允許用戶開…