opencv計算圖像亮度調節_OpenCV教程創建Trackbar圖像對比度、亮度值調整

這篇文章中我們一起學習了如何在OpenCV中用createTrackbar函數創建和使用軌跡條,以及圖像對比度、亮度值的動態調整。

文章首先詳細講解了OpenCV2.0中的新版創建軌跡條的函數createTrackbar,并給上一個詳細注釋的示例。

然后講解圖像的對比度、亮度值調整的細節,最后放出了一個利用createTrackbar函數創建軌跡條來輔助進行圖像對比度、亮度值調整的程序源碼。

依然是先放一張運行截圖:

bf38894b7eba16b624fea2214795ded2.png

好了,下面正式開始我們的講解。

一、OpenCV中軌跡條(Trackbar)的創建和使用

<1>創建軌跡條——createTrackbar函數詳解

createTrackbar這個函數我們以后會經常用到,它創建一個可以調整數值的軌跡條,并將軌跡條附加到指定的窗口上,使用起來很方便。首先大家要記住,它往往會和一個回調函數配合起來使用。先看下他的函數原型:

C++: int createTrackbar(conststring& trackbarname, conststring& winname, int* value, int count, TrackbarCallback onChange=0,void* userdata=0);
  • 第一個參數,const string&類型的trackbarname,表示軌跡條的名字,用來代表我們創建的軌跡條。
  • 第二個參數,const string&類型的winname,填窗口的名字,表示這個軌跡條會依附到哪個窗口上,即對應namedWindow()創建窗口時填的某一個窗口名。
  • 第三個參數,int* 類型的value,一個指向整型的指針,表示滑塊的位置。并且在創建時,滑塊的初始位置就是該變量當前的值。
  • 第四個參數,int類型的count,表示滑塊可以達到的最大位置的值。PS:滑塊最小的位置的值始終為0。
  • 第五個參數,TrackbarCallback類型的onChange,首先注意他有默認值0。這是一個指向回調函數的指針,每次滑塊位置改變時,這個函數都會進行回調。并且這個函數的原型必須為void XXXX(int,void*);其中第一個參數是軌跡條的位置,第二個參數是用戶數據(看下面的第六個參數)。如果回調是NULL指針,表示沒有回調函數的調用,僅第三個參數value有變化。
  • 第六個參數,void*類型的userdata,他也有默認值0。這個參數是用戶傳給回調函數的數據,用來處理軌跡條事件。如果使用的第三個參數value實參是全局變量的話,完全可以不去管這個userdata參數。

這個createTrackbar函數,為我們創建一個具有特定名稱和范圍的軌跡條(Trackbar,或者說是滑塊范圍控制工具),指定一個和軌跡條位置同步的變量。而且要指定回調函數onChange(第五個參數),在軌跡條位置改變的時候來調用這個回調函數。并且我們知道,創建的軌跡條顯示在指定的winname(第二個參數)所代表的窗口上。

看完函數講解,先給大家一個函數使用小示例

 //創建軌跡條createTrackbar("對比度:", "【效果圖窗口】",&g_nContrastValue,300,ContrastAndBright );// g_nContrastValue為全局的整型變量,ContrastAndBright為回調函數的函數名(即指向函數地址的指針)

然給大家一個完整的使用示例。這是OpenCV官方的sample示例程序,一個演示了用軌跡條來控制輪廓檢測,輪廓填充的程序。淺墨將其修改、代碼簡潔化和詳細注釋,放出來供大家消化研習。稍后更新的博文會有關于輪廓檢測更詳細的講解。

//-----------------------------------【頭文件包含部分】---------------------------------------//描述:包含程序所依賴的頭文件//---------------------------------------------------------------------------------------------- #include "opencv2/imgproc/imgproc.hpp"#include "opencv2/highgui/highgui.hpp"#include  //-----------------------------------【命名空間聲明部分】---------------------------------------//描述:包含程序所使用的命名空間//-----------------------------------------------------------------------------------------------   using namespace cv;using namespace std; //-----------------------------------【全局函數聲明部分】--------------------------------------//描述:全局函數聲明//-----------------------------------------------------------------------------------------------Mat img;int threshval = 160;//軌跡條滑塊對應的值,給初值160 //-----------------------------【on_trackbar( )函數】------------------------------------//描述:軌跡條的回調函數//-----------------------------------------------------------------------------------------------static void on_trackbar(int, void*){Mat bw = threshval < 128 ? (img < threshval) : (img > threshval); //定義點和向量vector > contours;vector hierarchy; //查找輪廓findContours( bw, contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE );//初始化dstMat dst = Mat::zeros(img.size(), CV_8UC3);//開始處理if( !contours.empty() && !hierarchy.empty() ){//遍歷所有頂層輪廓,隨機生成顏色值繪制給各連接組成部分int idx = 0;for( ; idx >= 0; idx = hierarchy[idx][0] ){Scalar color( (rand()&255), (rand()&255), (rand()&255) );//繪制填充輪廓drawContours( dst, contours, idx, color, CV_FILLED, 8, hierarchy );}}//顯示窗口imshow( "Connected Components", dst );}  //-----------------------------------【main( )函數】--------------------------------------------//描述:控制臺應用程序的入口函數,我們的程序從這里開始//-----------------------------------------------------------------------------------------------int main(  ){system("color 5F");  //載入圖片img = imread("1.jpg", 0);if( !img.data ) { printf("Oh,no,讀取img圖片文件錯誤~! "); return -1; } //顯示原圖namedWindow( "Image", 1 );imshow( "Image", img ); //創建處理窗口namedWindow( "Connected Components", 1 );//創建軌跡條createTrackbar( "Threshold", "Connected Components", &threshval, 255, on_trackbar );on_trackbar(threshval, 0);//軌跡條回調函數 waitKey(0);return 0;}

原圖:

d2026f87c189919f1726cde53389e9c5.png

運行效果圖:

56d279d2c6d0c764ad962b03775a73ba.png

拖動滾動條,改變threshval(閾值)的值,得到效果迥異的圖片:

acfa7409903f85014565a567f9eb1589.png

另外,在OpenCV路徑opencv_source_code/samples/cpp/connected_components.cpp下,可以找到原版的官方代碼。

接著順便講一個配合createTrackbar使用的函數,用于獲取當前軌跡條的位置的getTrackbarPos函數吧。

<2>獲取當前軌跡條的位置——getTrackbarPos函數

這個函數用于獲取當前軌跡條的位置并返回。

C++: int getTrackbarPos(conststring& trackbarname, conststring& winname);
  • 第一個參數,const string&類型的trackbarname,表示軌跡條的名字。
  • 第二個參數,const string&類型的winname,表示軌跡條的父窗口的名稱。

這部分大概就是這些了。馬不停蹄地向下一部分進發吧:)

二、亮度和對比度調整的理論依據

首先我們給出算子的概念。一般的圖像處理算子都是一個函數,它接受一個或多個輸入圖像,并產生輸出圖像。下式給出了算子的一般形式

4fe98153dda7fe6cea1616ef2a6b7f6f.png

或者

177b81e083c80106315d09dcbe69bcdb.png

今天我們所講解的圖像亮度和對比度的調整操作,其實屬于圖像處理變換中比較簡單的一種——點操作(pointoperators)。點操作有一個特點,僅僅根據輸入像素值(有時可加上某些全局信息或參數),來計算相應的輸出像素值。這類算子包括亮度(brightness)和對比度(contrast)調整,以及顏色校正(colorcorrection)和變換(transformations)。

最兩種常用的點操作(或者說點算子),很顯然,是乘上一個常數(對應對比度的調節)以及加上一個常數(對應亮度值的調節)。用公式表示出來就是這樣:

1b8ba9076bef3cb3ab6727552f63a5d9.png

看到這個式子,我們關于圖像亮度和對比度調整的策略就呼之欲出了。

其中:

參數f(x)表示源圖像像素。

參數g(x) 表示輸出圖像像素。

參數a(需要滿足a>0)被稱為增益(gain),常常被用來控制圖像的對比度。

參數b通常被稱為偏置(bias),常常被用來控制圖像的亮度。

而更近一步,我們這樣改寫這個式子:

b3caf94438d58b839e82859ed9acddc2.png

其中,i 和 j 表示像素位于第i行 和 第j列 。

那么,這個式子就可以用來作為我們在OpenCV中控制圖像的亮度和對比度的理論公式了。

三、關于訪問圖片中的像素

訪問圖片中的像素有很多種方式,以后有機會淺墨會用個專題來講解。目前我們可以先了解下面的這一種。

而為了執行

cae42ff67284949666eb9dc7b56fb217.png

這個運算 ,我們需要訪問圖像的每一個像素。因為是對GBR圖像進行運算,每個像素有三個值(G、B、R),所以我們必須分別訪問它們(PS:OpenCV中的圖像存儲模式為GBR)。以下是訪問像素的代碼片段,三個for循環解決問題:

       //三個for循環,執行運算 new_image(i,j) =a*image(i,j) + b       for(int y = 0; y < image.rows; y++ )       {              for(int x = 0; x < image.cols; x++ )              {                     for(int c = 0; c < 3; c++ )                     {                            new_image.at(y,x)[c]= saturate_cast( (g_nContrastValue*0.01)*(image.at(y,x)[c] ) + g_nBrightValue );                     }              }       }

讓我們分三個方面進行講解:

  • 為了訪問圖像的每一個像素,我們使用這樣的語法: image.at(y,x)[c]
  • 其中,y是像素所在的行, x是像素所在的列, c是R、G、B(對應0、1、2)其中之一。
  • 因為我們的運算結果可能超出像素取值范圍(溢出),還可能是非整數(如果是浮點數的話),所以我們要用saturate_cast對結果進行轉換,以確保它為有效值。
  • 這里的a也就是對比度,一般為了觀察的效果,取值為0.0到3.0的浮點值,但是我們的軌跡條一般取值都會整數,所以在這里我們可以,將其代表對比度值的nContrastValue參數設為0到300之間的整型,在最后的式子中乘以一個0.01,這樣就可以完成軌跡條中300個不同取值的變化。所以在式子中,我們會看到saturate_cast( (g_nContrastValue*0.01)*(image.at(y,x)[c] ) + g_nBrightValue )中的g_nContrastValue*0.01。

四、圖像對比度、亮度值調整示例程序

依然是每篇文章都會配給大家的一個詳細注釋的博文配套示例程序,把這篇文章中介紹的知識點以代碼為載體,展現給大家。

這個示例程序用兩個軌跡條分別控制對比度和亮度值,有一定的可玩性。廢話不多說,上代碼吧:

//-----------------------------------【程序說明】----------------------------------------------//  程序名稱::【OpenCV入門教程之四】 創建Trackbar&圖像對比度、亮度值調整 配套博文源碼// VS2010版  OpenCV版本:2.4.8//  2014年3月18 日 Create by 淺墨//------------------------------------------------------------------------------------------------  //-----------------------------------【頭文件包含部分】---------------------------------------//     描述:包含程序所依賴的頭文件//----------------------------------------------------------------------------------------------#include #include#include"opencv2/imgproc/imgproc.hpp"#include  //-----------------------------------【命名空間聲明部分】---------------------------------------//     描述:包含程序所使用的命名空間//-----------------------------------------------------------------------------------------------  using namespace std;using namespace cv;  //-----------------------------------【全局函數聲明部分】--------------------------------------//     描述:全局函數聲明//-----------------------------------------------------------------------------------------------static void ContrastAndBright(int, void *); //-----------------------------------【全局變量聲明部分】--------------------------------------//     描述:全局變量聲明//-----------------------------------------------------------------------------------------------int g_nContrastValue; //對比度值int g_nBrightValue;  //亮度值Mat g_srcImage,g_dstImage;//-----------------------------------【main( )函數】--------------------------------------------//     描述:控制臺應用程序的入口函數,我們的程序從這里開始//-----------------------------------------------------------------------------------------------int main(  ){       //改變控制臺前景色和背景色       system("color5F");         //讀入用戶提供的圖像       g_srcImage= imread( "pic1.jpg");              if(!g_srcImage.data ) { printf("Oh,no,讀取g_srcImage圖片錯誤~!"); return false; }       g_dstImage= Mat::zeros( g_srcImage.size(), g_srcImage.type() );        //設定對比度和亮度的初值       g_nContrastValue=80;       g_nBrightValue=80;        //創建窗口       namedWindow("【效果圖窗口】", 1);        //創建軌跡條       createTrackbar("對比度:", "【效果圖窗口】",&g_nContrastValue,300,ContrastAndBright );       createTrackbar("亮   度:","【效果圖窗口】",&g_nBrightValue,200,ContrastAndBright );             //調用回調函數       ContrastAndBright(g_nContrastValue,0);       ContrastAndBright(g_nBrightValue,0);             //輸出一些幫助信息       cout<(y,x)[c]= saturate_cast( (g_nContrastValue*0.01)*(g_srcImage.at(y,x)[c] ) + g_nBrightValue );                     }              }       }        //顯示圖像       imshow("【原始圖窗口】", g_srcImage);       imshow("【效果圖窗口】", g_dstImage);}

最后看一下運行截圖,運行這個程序會得到兩個圖片顯示窗口。第一個為原圖窗口,第二個為效果圖窗口。在效果圖窗口中可以調節兩個軌跡條,來改變當前圖片的對比度和亮度。

原圖:

a46d704880719fdd86387727071a4410.png

可調節的效果圖:

02803cdc94ee47020084ef51223300e3.png
2211ef82c16085bee9cdc26d1be7a155.png

本文轉載于https://blog.csdn.net/zhmxy555/category_9262318.html

作者:淺墨_毛星云

對OpenCV感興趣的可以去看原作者的其他文章

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

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

相關文章

TCP與UDP的區別(未完成,待補充)

TCP&#xff1a;Transport Control Protocol UDP&#xff1a;User Data Protocol TCP相較于UDP有更高的可靠性。TCP相較于UDP需要更多的存儲空間。因為TCP的頭部有20個字節&#xff0c;UDP的頭部只有8個字節。UDP相較于TCP有更高的實時性。TCP基于連接&#xff0c;UDP基于不連…

find linux 目錄深度_浪里淘沙,詳解Linux系統中Find命令的實用技巧

知了小巷&#xff1a;浪里淘沙&#xff0c;詳解Linux系統中Find命令的實用技巧。啊哈&#xff0c;找到了&#xff01;當我們需要在Linux系統上定位某個文件或目錄時&#xff0c;find命令通常是必備之選。它使用起來非常簡單&#xff0c;但有許多不同的可選項&#xff0c;允許我…

劍指offer之從上到下打印二叉樹

從上到下打印出二叉樹的每個節點&#xff0c;同一層的節點按照從左到右的順序打印。 例如: 給定二叉樹: [3,9,20,null,null,15,7], 返回&#xff1a; [3,9,20,15,7] 來源&#xff1a;力扣&#xff08;LeetCode&#xff09; 鏈接&#xff1a;https://leetcode-cn.com/problem…

小米真藍牙耳機說明書_小米真無線藍牙耳機Air2 SE評測:僅需169元,享受隨心暢聽體驗...

繼小米真無線藍牙耳機Air 2、小米真無線藍牙耳機Air 2S之后&#xff0c;小米公司又于2020年5月19日再次推出了一款售價更為親民的真無線藍牙耳機新品——小米真無線藍牙耳機Air2 SE&#xff0c;該機不僅延續了小米真無線藍牙耳機Air 2系列的外觀設計&#xff0c;支持開盒彈窗、…

引用與指針的區別

雖然指針和引用都可以完成對其他對象的間接訪問&#xff0c;但是還是有很多不同之處&#xff1a; 1.本身是否是對象 指針本身就是一個對象&#xff0c;而引用本身不是一個對象。因此允許對指針賦值和拷貝&#xff0c;可以定義對指針的引用&#xff0c;已經指向指針的指針&#…

三點外接圓_故地重游偽切圓——偽外接圓的基本性質

在思考一個有關于偽外接圓的等角線問題時&#xff0c;我回想起偽外接圓的一道小題目&#xff0c;這是2012年羅馬尼亞大師杯的第六題&#xff0c;這道題目直接以結論的形式呈現出了偽外接圓的基本性質&#xff0c;是一道入門偽外接圓必做的精巧小題。當然有些讀者可能從未見過&q…

C++的const限定符

const限定符總是讓人很頭疼&#xff0c;下面講解一下幾個比較容易混淆的概念&#xff1a; 對常量的引用&#xff08;常量引用&#xff09;&#xff1a; 一般情況下&#xff0c;引用的類型要與其所引用的對象的類型一致&#xff0c;其中的例外情況就是&#xff0c;當初始化常量…

Linux學習:第五章-Linux用戶和用戶組管理

一用戶管理命令用戶信息文件&#xff1a;/etc/passwd aa:x:501:501::/home/aa:/bin/bash 第一列&#xff1a;用戶名 第二列&#xff1a;密碼標志 第三列&#xff1a;UID用戶ID 0管理員 1-499系統用戶&#xff08;偽用戶&#xff09; 500普通用戶 第四列&#xff1a;GID初始組ID…

一點等于多少厘米_馬桶知識介紹,你了解馬桶多少

我們可能并不了解我們經常運用的馬桶&#xff0c;認為馬桶便是簡簡單單的規劃&#xff0c;沒什么技術含量。其實不然&#xff0c;馬桶的規劃也包含了不少物理學原理。假如你家里的馬桶出現毛病&#xff0c;首先要排查毛病的原因&#xff0c;但是假如不了解馬桶結構圖那就很難把…

動態內存分配與智能指針

內存分配&#xff1a; 靜態存儲區&#xff1a; 局部static對象類的static數據成員定義在任何函數之外的變量 棧區&#xff1a; 函數內的非static對象 動態內存分配的方式有&#xff1a; new和delete智能指針&#xff08;shared_ptr、unique_ptr、weak_ptr&#xff09;all…

1151壓力變送器型號_日本進口橫河EJA530E壓力變送器型號解讀!

橫河EJA變送器對大家來說也許不陌生&#xff0c;但是對于EJA變送器的型號很多人還不是很懂&#xff0c;因為一個全型號代表這很多參數&#xff0c;每一個字母和每一個數字背后都是一個準確的參數&#xff0c;我們在選型的時候要提供必要的參數&#xff0c;更具參數選出合適的型…

plc控制可調節閥流程圖_PLC控制的水箱液位控制系統畢業論文

內容介紹原文檔由會員 莎士比亞 發布論文標準WORD格式排版40頁摘要在人們生活以及工業生產等諸多領域經常涉及到液位和流量的控制問題, 例如居民生活用水的供應, 飲料、食品加工, 溶液過濾, 化工生產等多種行業的生產加工過程, 通常需要使用蓄液池, 蓄液池中的液位需要維持合適…

idea繼承后重新方法快捷鍵_idea 查看類繼承關系的快捷鍵

類似eclipse ctrlt的快捷鍵,idea中是ctrlH…找到對應的類 查看類關系圖…1.在想要查看的類上按 Ctrl H -> Diagrams -> Show Diagrams -> Java Class Diagrams -> Show Implementations -> Ctrl A -> 右擊一下 -> Enter .…打開想要查看的接口或者類文件…

怎樣在數組末尾添加數據_如何利用C++實現可變長的數組?

應該執行什么功能&#xff1f;假設我們要實現一個將自動擴展的數組類&#xff0c;是否需要實現函數&#xff1f;讓我們從下面主要功能使用的功能開始&#xff0c;看看我們需要實現哪些功能。輸出結果&#xff1a;0 1 2 3 40 1 2 100 4您需要做什么才能實現上述功能&#xff1f;…

Linux學習:第六章-Linux服務和進程管理

一進程查看 1psaux查看當前系統所有運行的進程 -a顯示前臺所有進程 -u顯示用戶名 -x顯示后臺進程 user&#xff1a; 用戶名 pid&#xff1a;進程id。PID1init系統啟動的第一個進程 %CPUcpu占用百分比 %MEM內存占用百分比 VSZ虛擬內存占用量KB RSS固定內存占有量 tty登錄終端tty…

覆蓋索引與聯合索引_淺析MySQL的索引覆蓋和索引下推

寫在前面在MySQL數據庫中&#xff0c;索引對查詢的速度有著至關重要的影響&#xff0c;理解索引也是進行數據庫性能調優的起點&#xff0c;索引就是為了提高數據查詢的效率。今天我們來聊聊在MySQL索引優化中兩種常見的方式&#xff0c;索引覆蓋和索引下推索引覆蓋要了解索引覆…

python3 輸入輸出_Python3基礎之輸入和輸出實例分析

通常來說&#xff0c;一個Python程序可以從鍵盤讀取輸入&#xff0c;也可以從文件讀取輸入&#xff1b;而程序的結果可以輸出到屏幕上&#xff0c;也可以保存到文件中便于以后使用。本文就來介紹Python中最基本的I/O函數。一、控制臺I/O1.讀取鍵盤輸入內置函數input([prompt])&…

redis 哨兵 異步_突破Java面試(23-8) - Redis哨兵主備切換的數據丟失問題-阿里云開發者社區...

1 數據丟失的兩個場景主備切換的過程&#xff0c;可能會導致數據丟失1.1 異步復制由于 master > slave的復制是異步的&#xff0c;所以可能有部分數據還沒復制到slave&#xff0c;master就宕機&#xff0c;于是這些數據就丟失了1.2 腦裂導致腦裂&#xff0c;也就是說&#x…

vue 斷開正在發送的請求_vue 發送請求頻繁時取消上一次請求

前言&#xff1a;在項目中經常有一些場景會連續發送多個請求&#xff0c;而異步會導致最后得到展示的結果可能不是最后一次發送請求返回的結果&#xff0c;且對性能也有非常大的影響。場景&#xff1a;列表式切換商品&#xff0c;有時候上一次請求的結果非常慢&#xff0c;而我…

Linux學習:第六章-Linux網絡配置

上一章的補充&#xff1a; 常見網絡端口&#xff1a; 2021ftp服務文件共享 22ssh服務安全遠程網絡管理 23telnet服務 25smtp&#xff1a;簡單郵件傳輸協議發信 110pop3&#xff1a;郵局協議收信 80www網頁服務 3306mysql端口 3389windows終端服務 53DNS端口 /etc/services所有系…