基于 OpenCV 的圖像亮度、對比度與銳度調節

? ? 圖像亮度、對比度和銳度是圖像質量感知的重要參數,調節這些屬性常用于圖像增強、圖像美化或圖像分析的預處理階段。本文將基于 OpenCV 實現這三項基礎圖像處理功能,并提供滑動條交互界面與直方圖可視化分析,方便調試和理解效果。

亮度調整

? ? 圖像亮度調整使得圖像整體變亮或變暗,其數學表達式為:dst(x,y)=src(x,y) + beta。圖像亮度調整本質上改變了圖像像素灰度分布。如亮度加30使得其灰度分布向正方向平移30,反之則向負方向平移30。這里的灰度分布我們稱之為圖像直方圖。我們使用眼底圖像作為示例來展示效果:

左:眼底原圖? ? ? ? ? ? ? ? ? ? ? ?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?右:圖像亮度降低30
上:眼底原圖直方圖? ? ? ? ? ? ? ? ? ?下:亮度降低30后直方圖

? ? 從直方圖上我們可以清晰看出,亮度調整會導致直方圖左右平移。我們需要注意的是,當亮度調整到飽和狀態,如調整后亮度大于255或者小于0,可能會因為階段而改變直方圖形狀。

? ? 如何使用代碼實現圖像亮度調整,直觀代碼如下:

for (int row = 0; row < src.rows; ++row)
{uchar* data = src.ptr<uchar>(row);for (int col = 0; col < src.cols * src.channels(); ++col){// 遍歷所有點,對每個點執行亮度調整adj_brightness操作int val = data[col] + adj_brightness;if (val < 0) val = 0;if (val > 255) val = 255;data[col] = val;}
}

? ? 以上代碼從原理上給出了一個實現邏輯,有利于我們理解具體實現。但該代碼效率較低,主要原因包括:

? ? 1)內層for循環的條件語句可能打斷流水線優化,流水線優化利用CPU的指令流水線結構實現多個指令并行處理。

? ? 2)可能沒有有效利用SIMD指令,CPU通過SIMD指令可以實現多條數據同時處理的效果,也稱作向量化。

? ? 由于OpenCV經過了大量的優化,通過調用OpenCV接口,在絕大多數情況下可以獲得極佳的性能,因此我們會盡量使用OpenCV提供的接口來構造功能。

? ?通過cv::Mat提供的接口convertTo可以實現圖像亮度的調整,該函數的核心功能包括:

? ?1)數據類型轉換,如從CV_8U轉換為CV_32F。

? ?2)在轉換過程中執行dst = src * alpha + beta操作,我們將alpha參數設置為1,beta參數設置為亮度調整參數即可實現亮度的調整。

? ? 為什么要調用convertTo實現亮度調整,而不是直接使用cv::add或者直接mat=mat+offset呢?

? ? 其實以上方法都可以實現亮度調整,這里使用convertTo的主要原因是該函數可以同步提高亮度調整與數據類型轉換功能。通過一個函數實現兩個功能,可以避免內存的多次拷貝,從而提升運行效率。

? ? 那么,為什么我們需要做數據類型轉換呢?主要有兩點理由:

? ? 1)我們一般將原始的8位無符號整數(CV_8U)圖像轉換為32位(CV_32F)浮點圖像。在后續圖像處理運算中,不可避免會產生浮點數值。如果仍舊使用整形表示則會產生階段誤差,從而降低調整后圖像的信噪比。

? ? 2)在某些運算中可能產生負數,CV_8U類型無法有效表示負數,從而產生運算錯誤。

? ?以下是亮度調整與類型轉換的代碼:

 cv::Mat img_src_f;img_src.convertTo(img_src_f, CV_32F, 1., adj_brightness);

對比度調整?

? ??對比度控制圖像的明暗差異,通常用一個比例因子alpha控制像素的擴展或壓縮,其數學表達式可寫作:dst(x,y) = src(x,y) * alpha。當alpha>1時對比度增強,當alpha<1時對比度降低。

? ? 通過以上方法,我們會發現調整后圖像的對比度會顯著影響圖像亮度。如增強對比度時也同樣增強了圖像亮度。如下圖:

左:眼底原圖? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 右:對比度增加1.5(亮度也同步增強)

?

上:原圖直方圖? ? ? ? ? ? ? ? ? ? ? 下:對比度增強后直方圖

? ? 從直方圖上來看,圖像平均亮度確實增加了50%,同時直方圖的寬度也有所增加(即動態范圍更大)。在現實應用中,我們在增加對比度時更加希望圖像平均亮度基本保持不變,那么應該如何處理呢?

改進的對比度調整

? ? 為了保持圖像亮度基本不變,我們可以引入一些對稱性操作。在上一節內容中,圖像對比度的擴張是以0點為原點進行縮放,即dst(x,y)=[src(x,y) - 0] * alpha。如果我們以圖像均值為原點進行對比度縮放,則可以確保對比度縮放后的圖像平均亮度基本保持不變,其表達式為:dst(x,y)=(src(x,y) -mean)*alpha + mean,這里的mean為圖像的統計均值。

? ? 使用該改進后方案,我們的對比度調整有如下效果:

左:眼底原圖? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 右:對比度增加1.5(保持亮度不變)
上:原圖直方圖? ? ? ? ? ? ?下:對比度增強直方圖(亮度保持)

? ? 以上直方圖表明,由于對比度增加使得直方圖動態范圍增加,但確保持了平均亮度。這正是我們在對比度調整時所期望的效果。

? ? 另外,對比度調整參數的取值范圍理論上為[0,+\infty ]。實際應用中,我們可能將其限制在[0.5,5]或者[1,5]

銳度調整

? ? 我們之前討論的圖像亮度與圖像對比度都是從全局角度來控制圖像效果。因此,每一個有效的條件都會改變直方圖的基本形態,如導致直方圖平移或者縮放等。關于圖像銳度的調整主要改變圖像邊緣清晰程度,這是一個鄰域操作。也就是說,每一個像素變換后的值僅與其相鄰的像素相關。

? ?如果我們可以獲取圖像上每一個點的邊緣強度信息,那么我們就可以通過對該位置的強度進行疊加,從而獲得邊緣更強的圖像。因此,一個核心點就是如何獲得每個點的邊緣強度信息。

? ? 我們這里使用一個反銳化掩膜方式(Unsharp Masking)來獲取每個點的邊緣強度。公式如下:

?UnsharpMask=Image-Gaussian(Image),通過原圖減去高斯模糊圖像獲取高頻信息,作為每個點的邊緣強度表征。

? ? 然后再在原圖上疊加邊緣強度信息,并通過參數控制疊加強度,如:

Sharpness = Image + UnsharpMask * \lambda\lambda為增強系數,其范圍為[0,+\infty]

左:眼底原圖? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 右:銳度增強圖像
上:原圖直方圖? ? ? ? ? ? ? ? ? ? ? 下:銳度增強直方圖

? ? 從以上直方圖來看,銳度增強基本沒有改變直方圖的動態范圍與均值,這也進一步驗證圖像銳化操作是一個鄰域操作而非全局變換。同時,我們的銳化效果似乎也比較理想。然而仔細觀察會發現:圖像邊緣雖然得到了有效增強,但圖像噪聲似乎也被增強了。我們需要進一步接近該問題。

改進的銳度調整

? ? 要想抑制銳化增強后的噪聲,我們首先需要明白噪聲的特點。噪聲相對于信號來說比較弱,在一個完美信號上疊加隨機噪聲有如下效果:

? ? 如上圖所示,上半部分是一個理想的階躍信息和疊加隨機噪聲的階躍信號,下圖是疊加隨機噪聲階躍信號的梯度響應。我們在做圖像增強時,期望增強的邊緣顯然是0坐標附近的階躍邊緣,而在非零附近區域的噪聲響應是我們期望忽略掉的。?從梯度響應上來看(紅色曲線),階躍信號有一個很強的響應,噪聲信號的響應較弱,這就帶給給我們一個自適應邊緣增強的啟示。

? ? 如果我們將每個點的梯度響應強度作為其增強系數因素,則可以通過選擇合適的策略在增強信號同時抑制噪聲。具體如下:

? ? 1)將梯度響應歸一化到(0,1)區間;

? ? 2)對現有銳度增強方案添加適當的控制因子,以實現增強信號同時抑制噪聲,公式如下:Sharpness=UnsharpMask * norm(gradint) * \lambda + Image

? ? 以下為改進后銳化增強結果:??

左:銳化增強? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 右:改進后的銳化增強(降低了噪聲)

? ? 很明顯,通過引入梯度響應權值,我們能夠獲得更加理想的銳化增強圖像。

基于OpenCV的圖像調整實現?

? ? 下面給出一個完整的基于OpenCV圖像調整實現,通過引入Trackbar,我們可以做一個簡單的實時調節交互。具體代碼如下:

#include "opencv2/highgui/highgui_c.h"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"// 設置滑動條綁定參數變量,該變量必須為整數類型
// 同時分別設置滑塊的取值范圍,如下:
// 亮度[0,512], 對比度[0,500], 銳度[0,1000]
int bar_brightness = 256;
int bar_contrast = 0;
int bar_sharpness = 0;cv::Mat img_src, img_dst;void applyAdjustment(int, void*)
{// 根據對應滑塊的取值范圍換算出不同類型圖像調整的參數值// 換算后的取值范圍為:亮度[-256,256], 對比度[1.,6.],銳度[0.,10.]float adj_brightness = bar_brightness - 256;float adj_contrast = bar_contrast / 100. + 1.;float adj_sharpness = bar_sharpness / 100.;// 通過convertTo函數同步實現了浮點類型轉換和亮度調整,使得計算效率更高cv::Mat img_src_f;img_src.convertTo(img_src_f, CV_32F, 1., adj_brightness);// 對比度增強// 注意:以下矩陣img_src_f, img_diff, img_con均公用數據區(淺拷貝)cv::Scalar m = cv::mean(img_src_f);cv::Mat img_diff = img_src_f - m;cv::Mat img_con = img_diff * adj_contrast + m;// 計算自適應增強系數cv::Mat img_green;cv::extractChannel(img_con, img_green, 1);cv::GaussianBlur(img_green, img_green, cv::Size(3, 3), 0);cv::Mat grad_dx, grad_dy, grad_mag, grad_magc3;cv::Sobel(img_green, grad_dx, CV_32F, 1, 0, 3);cv::Sobel(img_green, grad_dy, CV_32F, 0, 1, 3);cv::magnitude(grad_dx, grad_dx, grad_mag);cv::normalize(grad_mag, grad_mag, 0.0, 1.0, cv::NORM_MINMAX);cv::cvtColor(grad_mag, grad_magc3, CV_GRAY2BGR);// 銳化增強cv::Mat img_blur;cv::GaussianBlur(img_con, img_blur, cv::Size(15, 15), 0);cv::Mat img_diff2 = cv::Mat::zeros(img_con.size(), img_con.type());img_diff2 = img_con - img_blur;cv::Mat img_con2= cv::Mat::zeros(img_con.size(), img_con.type());img_con2 = img_con + img_diff2.mul(grad_magc3) * adj_sharpness;// 轉換為8位深度圖像,用于顯示img_con2.convertTo(img_dst, CV_8U);cv::imshow("調整圖像", img_dst);
}void briConSharpAdjust()
{img_src = cv::imread("fundus3.png", cv::IMREAD_COLOR);if (img_src.empty()) return;  // 檢查是否成功讀取圖像// 打開圖像調整窗口cv::namedWindow("調整圖像", cv::WINDOW_NORMAL);// 創建Trackbarcv::createTrackbar("亮度", "調整圖像", &bar_brightness, 512, applyAdjustment);cv::createTrackbar("對比度", "調整圖像", &bar_contrast, 500, applyAdjustment);cv::createTrackbar("銳度", "調整圖像", &bar_sharpness, 1000, applyAdjustment);applyAdjustment(0, 0);cv::waitKey(0);}int main()
{briConSharpAdjust();return 0;
}

結語

? ? 本文深入淺出的講解了圖像調整的基本算法,通過啟發式的方式引入一些深入問題研究。同時給出了一個完整的Demo,該Demo基于OpenCV進行UI交互,可以實現基本的圖像調整演示。通過對Demo改進可以快速落地一些相關應用。

? ? 另外,我們將所有的圖像處理均放在一個函數中,包括圖像亮度對比度,圖像銳度處理。對于小圖像來說,這樣做當然沒有太多問題。當我們在項目中要求更高的實時性,或者所處理圖像的尺寸特別大(如4000*3000),那么我們可以拆分每項處理,從而達到更好的實時性。主要策略包括:

? ? 1)拆分對比度與銳度處理,每次調整僅做一項調整,這也是用戶交互的一個自然邏輯;

? ? 2)保存中間圖像,如第一次實現銳度增強后,第二次進行對比度調整時基于銳度增強圖像即可;

? ? 3)所保存的中間圖像一定為浮點類型,盡可能規避整形圖像的截斷誤差累積;

? ? 4)在用戶拉動滑塊時(如銳度調整),一些公用數據僅需要計算一次即可,如自適應增強系數,差分圖等。?

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

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

相關文章

WAF(web應用防火墻)的簡單了解

WAF稱之為Web應用防火墻&#xff0c;是一種專門設計用于保護web應用程序免受惡意攻擊的安全設備&#xff0c;能實時監控過濾和攔截可能對網站造成危害的網絡流量&#xff0c;從而避免網絡服務器被惡意入侵導致性能異常、數據泄露、服務中斷這些問題 (WAF是通過執行一系列針對HT…

跟著AI學習C# Day28

&#x1f4c5; Day 28&#xff1a;C# 源生成器&#xff08;Source Generators&#xff09;與編譯時元編程 ? 學習目標&#xff1a; 理解什么是 源生成器&#xff08;Source Generator&#xff09;&#xff1b;掌握如何在 編譯階段生成 C# 代碼&#xff0c;而不是運行時動態處…

設計模式精講 Day 4:建造者模式(Builder Pattern)

【設計模式精講 Day 4】建造者模式&#xff08;Builder Pattern&#xff09; 文章簡述&#xff1a; 在軟件開發中&#xff0c;對象的構造過程往往復雜且容易出錯&#xff0c;尤其是在對象包含多個可選參數或構建步驟時。建造者模式&#xff08;Builder Pattern&#xff09;正是…

如何輕松地將聯系人從 iPhone 轉移到 iPhone?

也許您升級到最新的 iPhone 型號&#xff0c;或者需要切換到另一部 iPhone 來工作。無論如何&#xff0c;您不能錯過您的聯系人&#xff0c;這對每個人來說都是最重要的數據。因此&#xff0c;今天我們將分享 5 種如何將聯系人從 iPhone 轉移到 iPhone 的方法&#xff0c;幫助您…

【51單片機簡單的流水燈程序問題】2022-5-24

1.利用單片機的P2口接8個發光二極管。簡單的流水燈程序問題-編程語言-CSDN問答 2&#xff0e;發光二極管自由閃爍&#xff08;自己設計兩種模式&#xff09;。 3&#xff0e;可通過按鍵實現暫停、啟動以及不用模式的切換。 4. 利用Proteus繪制電路原理圖 5. 元件選型&#xff1…

第七節:Vben Admin 最新 v5.0 (vben5) 快速入門 - 用戶管理(上)

Vben5 系列文章目錄 ?? 基礎篇 ? 第一節:Vben Admin 最新 v5.0 (vben5) 快速入門 ? 第二節:Vben Admin 最新 v5.0 (vben5) 快速入門 - Python Flask 后端開發詳解(附源碼) ? 第三節:Vben Admin 最新 v5.0 (vben5) 快速入門 - 對接后端登錄接口(上) ? 第四節:Vben Ad…

1572. 矩陣對角線元素的和

給你一個正方形矩陣 mat&#xff0c;請你返回矩陣對角線元素的和。 請你返回在矩陣主對角線上的元素和副對角線上且不在主對角線上元素的和。 示例 1&#xff1a; 輸入&#xff1a;mat [[1,2,3],[4,5,6],[7,8,9]] 輸出&#xff1a;25 解釋&#xff1a;對角線的和為&#xf…

供應鏈場景使用ClickHouse最佳實踐

一、概述 ClickHouse是一款由俄羅斯公司Yandex開發的開源列式數據庫管理系統&#xff0c;以其高性能的分析查詢能力和高壓縮比著稱。供應鏈場景中&#xff0c;數據量大且數據類型復雜&#xff0c;需要高效的數據存儲和快速的查詢性能&#xff0c;ClickHouse在這些方面具有顯著…

RA4M2開發IOT(0)----安裝e2 studio

RA4M2開發IOT.0--安裝e studio 概述視頻教學樣品申請安裝 概述 瑞薩電子靈活配置軟件包 (FSP) 是用于嵌入式系統設計的高質量增強型軟件包&#xff0c;支持瑞薩電子 RA 產品家族 Arm 微控制器&#xff0c;提供用戶友好的界面且可靈活擴展&#xff0c;確保從入門級到高性能的整…

【Ambari3.0.0 部署】Step2—免密登陸認證-適用于el8

如果有其他系統部署需求可以參考原文 戳我->所有組件編譯教程 戳我->獲取部署源代碼 一、免密登錄認證 &#x1f510; 在多臺服務器協同工作的環境中&#xff0c;免密登錄&#xff08;SSH 免密認證&#xff09;是一種常見的優化手段&#xff0c;能夠極大地提升運維效率&…

網站自助廣告投放系統源碼 附安裝教程(源碼下載)

網站自助廣告投放系統源碼 全自動無人化出售網站廣告位 站長必備 源碼測試可用&#xff0c;部分加密。感興趣自行下載 源碼下載&#xff1a;https://download.csdn.net/download/m0_66047725/91093092 更多資源下載&#xff1a;關注我 圖片&#xff1a;

日常運維問題匯總-15

42.SD開票計劃產生的預收款在正式開票時未自動清賬 統馭科目&#xff08;應收、預收&#xff09;對應的字段狀態組中附加科目設置銷售訂單字段設置為了隱藏導致&#xff0c;更改為“可選輸入項” 43.MIGO取消憑證時&#xff0c;用戶反饋發現除一行外&#xff0c;其它都不能取消…

【設計模式】6.原型模式

every blog every motto: You can do more than you think. https://blog.csdn.net/weixin_39190382?typeblog 0. 前言 原型模式 1. 基礎 import copyclass Resume:def __init__(self, name):self.name nameself.sex Noneself.age Noneself.time_area Noneself.compan…

【算法 day08】LeetCode 151.翻轉字符串里的單詞 |卡碼網:55.右旋轉字符串

151.翻轉字符串里的單詞 題目鏈接 | 文檔講解 |視頻講解 : 鏈接 1.思路&#xff1a; 1.去除字符串頭尾的空格 &#xff0c;使用庫函數 trim&#xff08;&#xff09; 2.對字符串進行分割&#xff0c;使用庫函數split&#xff08;&#xff09; 3.創建StringBuilder sb&#x…

【WordPress優化插件】WPOPT v2.4.7

WPOPT插件,是由本站開發的一款WordPress優化插件,能對WordPress底層功能進行優化,支持功能開關,系統加速等功能。 2.0版本全新發布,采用vite打包,界面采用Vue3+element-plus制作。無論是外觀,還是框架功能,都是空前的強大。 功能更多,更強,是所有WordPress網站都值得…

如何使用 mkimage 工具生成 uImage 文件(RISC-V 環境)

一、mkimage 命令參數詳解 在 RISC-V Linux 環境下&#xff0c;使用 U-Boot 的 mkimage 工具生成 uImage 的基本命令格式如下&#xff1a; mkimage -A riscv -O linux -T kernel -C compression -a load_addr -e entry_addr -n "描述信息" -d Image uImage核心參數…

React Native 搭建iOS與Android開發環境

目錄 第一步 第二步 一、必須安裝的工具 二、具體安裝步驟 1. 安裝 Homebrew 切換國內源和其他配置&#xff1a; 2. 安裝 node 3.下載watchman 4. Ruby 5.CocoaPods 配置環境 6. jdk 7. 配置git 開發環境 第三步——啟動項目&#xff08;可以忽略&#xff09; 1…

Vue 簡寫形式全解析:清晰記憶指南

Vue 簡寫形式全解析:清晰記憶指南 Vue 中的各種簡寫形式確實容易混淆,我將它們系統化整理,并提供了多種記憶方法,幫助你輕松掌握! 一、核心簡寫形式匯總表 完整形式簡寫形式適用場景記憶技巧v-bind:attribute:attribute動態綁定屬性: 像鏈條,表示"綁定"v-on:…

車載電子電器架構 --- 電子電氣架構設計方案

我是穿拖鞋的漢子,魔都中堅持長期主義的汽車電子工程師。 老規矩,分享一段喜歡的文字,避免自己成為高知識低文化的工程師: 做到欲望極簡,了解自己的真實欲望,不受外在潮流的影響,不盲從,不跟風。把自己的精力全部用在自己。一是去掉多余,凡事找規律,基礎是誠信;二是…

MVCC中read_view的核心參數解析與讀操作流程實戰

在數據庫并發控制領域&#xff0c;MVCC&#xff08;多版本并發控制&#xff09;是實現高性能讀寫并發的關鍵技術。其中&#xff0c;read_view作為MVCC判斷數據可見性的核心組件&#xff0c;其內部參數的設計直接影響著并發訪問的行為。本文將深入解析read_view的三個核心參數&a…