OpenCV實(shí)現(xiàn)圖像背景虛化效果原理詳解
0 寫(xiě)在前面
相信用過(guò)相機(jī)的同學(xué)都知道虛化特效,這是一種使焦點(diǎn)聚集在拍攝主題上,讓背景變得朦朧的效果,例如本文最后實(shí)現(xiàn)的背景虛化效果
相機(jī)虛化特效背后的原理是什么?和計(jì)算機(jī)視覺(jué)有什么關(guān)系?本文帶你研究這些問(wèn)題。
1 小孔成像
小學(xué)我們就知道,沒(méi)有光就不存在圖像,為了產(chǎn)生圖像,場(chǎng)景必須有一個(gè)或多個(gè)、直接或間接的光源。
如圖所示,光照主要分為三類:
- 散射
- 直接光照
- 漫反射
在獲得光源后,將產(chǎn)生從物體到檢測(cè)平面的光線。
由于從物體上某點(diǎn)A出發(fā)存在無(wú)數(shù)條四散的光線到達(dá)檢測(cè)平面,因此可以認(rèn)為A的成像點(diǎn)A’均勻地分布在成像平面上,同理其他點(diǎn)亦然。所以這種情況下,檢測(cè)平面上是無(wú)數(shù)張物體圖像的混疊,導(dǎo)致成像模糊甚至無(wú)法成像。
面對(duì)一張白紙上看不到你的臉,不是因?yàn)榘准埳蠜](méi)有來(lái)自于你的光線,而是因?yàn)閬?lái)自于你不同部分的光線在白紙上產(chǎn)生了重疊,不信你試試?
那如何在白紙上成像?
其實(shí)非常簡(jiǎn)單,采用小學(xué)就嘗試過(guò)的小孔成像
本質(zhì)上小孔相當(dāng)于一個(gè)濾光器,僅保留從物點(diǎn)發(fā)出的少數(shù)光線,此時(shí)應(yīng)能獲得清晰的圖像。
2 光學(xué)成像
小孔成像的缺陷是成像光線較少,亮度低。為了既能獲得較多光線,又不讓像點(diǎn)四散在檢測(cè)面上造成影像重疊,引入具有聚光性的透鏡。透鏡成像與小孔成像的本質(zhì)都是避免因像點(diǎn)四散導(dǎo)致的無(wú)法成像,前者利用聚光,后者則利用濾光。
現(xiàn)代相機(jī)在應(yīng)用上通常使用透鏡成像,但不管是透鏡成像還是小孔成像,都是計(jì)算機(jī)視覺(jué)研究的基本模型和假設(shè),例如透視幾何、相機(jī)內(nèi)參矩陣、畸變修正等等,因此本節(jié)對(duì)于建立機(jī)器視覺(jué)的研究思維很有幫助。
3 虛化效果
介紹完前面的基礎(chǔ)知識(shí),終于開(kāi)始圖像虛化特效的原理啦!
理想透鏡應(yīng)保證光線聚焦于一點(diǎn)——焦點(diǎn),這個(gè)點(diǎn)不會(huì)產(chǎn)生任何成像混疊,圖像最清晰。在焦點(diǎn)前后光線開(kāi)始四散,形成不同程度的成像重疊區(qū)域,稱為彌散圓,對(duì)于人眼而言,在一定范圍內(nèi)影象產(chǎn)生的模糊是不能辨認(rèn)的,不能辨認(rèn)的彌散圓范圍稱為容許彌散圓
當(dāng)對(duì)被攝主體平面調(diào)焦時(shí),因?yàn)槿菰S彌散圓的存在,在一定離焦范圍內(nèi),成像仍然清晰,這個(gè)范圍稱為焦深。調(diào)整成像面和鏡頭距離,使成像面處于焦深內(nèi),物體可以清晰成像的過(guò)程,稱為對(duì)焦。
類似地,對(duì)被攝物體而言,位于調(diào)焦物平面前后的能相對(duì)清晰成像的景物間縱深距離稱為景深。圖像虛化效果就和這個(gè)景深有關(guān)系!
- 景深越小,被攝物體前后能清晰成像的范圍越小,也就相應(yīng)地出現(xiàn)朦朧虛化的效果
- 景深越大,被攝物體前后能清晰成像的范圍越大,也就沒(méi)有虛化效果
如何調(diào)節(jié)景深?記住一句話:光圈越大景深越小,所以拿手機(jī)拍照的時(shí)候,大光圈也就代表了虛化效果!
所以下次有機(jī)會(huì)給女生拍照的話,請(qǐng)先確認(rèn)
“請(qǐng)問(wèn)你喜歡小景深還是大景深?”
4 代碼實(shí)戰(zhàn)
相機(jī)背景虛化特效在圖像處理中可以采用引導(dǎo)濾波器實(shí)現(xiàn),源碼如下。
//引導(dǎo)濾波器 Mat guidedFilter(Mat& srcMat, Mat& guidedMat, int radius, double eps) { srcMat.convertTo(srcMat, CV_64FC1); guidedMat.convertTo(guidedMat, CV_64FC1); // 計(jì)算均值 Mat mean_p, mean_I, mean_Ip, mean_II; boxFilter(srcMat, mean_p, CV_64FC1, Size(radius, radius)); // 生成待濾波圖像均值mean_p boxFilter(guidedMat, mean_I, CV_64FC1, Size(radius, radius)); // 生成引導(dǎo)圖像均值mean_I boxFilter(srcMat.mul(guidedMat), mean_Ip, CV_64FC1, Size(radius, radius)); // 生成互相關(guān)均值mean_Ip boxFilter(guidedMat.mul(guidedMat), mean_II, CV_64FC1, Size(radius, radius)); // 生成引導(dǎo)圖像自相關(guān)均值mean_II // 計(jì)算相關(guān)系數(shù)、Ip的協(xié)方差cov和I的方差var------------------ Mat cov_Ip = mean_Ip - mean_I.mul(mean_p); Mat var_I = mean_II - mean_I.mul(mean_I); // 計(jì)算參數(shù)系數(shù)a、b Mat a = cov_Ip / (var_I + eps); Mat b = mean_p - a.mul(mean_I); // 計(jì)算系數(shù)a、b的均值 Mat mean_a, mean_b; boxFilter(a, mean_a, CV_64FC1, Size(radius, radius)); boxFilter(b, mean_b, CV_64FC1, Size(radius, radius)); // 生成輸出矩陣 Mat dstImage = mean_a.mul(srcMat) + mean_b; return dstImage; }
關(guān)于引導(dǎo)濾波器的相關(guān)原理我們下次再開(kāi)新的章節(jié)闡述。
主函數(shù)內(nèi)調(diào)用濾波器即可,效果如文首所示。
int main() { Mat resultMat; Mat vSrcImage[3], vResultImage[3]; Mat vResultImage[3]; Mat srcImage = imread("1.jpg"); imshow("源圖像", srcImage); // 對(duì)源圖像進(jìn)行通道分離,并對(duì)每個(gè)分通道進(jìn)行引導(dǎo)濾波 split(srcImage, vSrcImage); for (int i = 0; i < 3; i++) { Mat tempImage; vSrcImage[i].convertTo(tempImage, CV_64FC1, 1.0 / 255.0); Mat cloneImage = tempImage.clone(); Mat resultImage = guidedFilter(tempImage, cloneImage, 5, 0.3); vResultImage[i] = resultImage; } // 將分通道導(dǎo)向?yàn)V波后結(jié)果合并 merge(vResultImage, 3, resultMat); imshow("背景虛化特效", resultMat); waitKey(0); return 0; }
一個(gè)小小的圖像虛化特效,背后牽扯出光學(xué)成像的各種原理,構(gòu)建了計(jì)算機(jī)視覺(jué)模型的地基。正如我們每個(gè)人一樣,也許你覺(jué)得自己很渺小,說(shuō)不定也是別人的中流砥柱呢!
到此這篇關(guān)于OpenCV實(shí)現(xiàn)圖像背景虛化效果原理詳解的文章就介紹到這了,更多相關(guān)OpenCV圖像背景虛化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語(yǔ)言數(shù)據(jù)類型枚舉enum全面詳解示例教程
生活中有很多地方會(huì)用到枚舉,比如一周有7天,可以一一枚舉;性別有男、女...等等都可以可以一一枚舉,今天來(lái)和筆者一起學(xué)習(xí)一下c語(yǔ)言枚舉吧2021-10-10C語(yǔ)言實(shí)現(xiàn)BMP圖像處理(直方圖均衡化)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)BMP圖像直方圖均衡化處理,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10C語(yǔ)言編程之初識(shí)數(shù)組線性查找和二分查找
本篇文章是C語(yǔ)言編程篇,主要為大家介紹C語(yǔ)言編程中數(shù)組的線性查找及二分查找分析講解,有需要的朋友可以借鑒參考下,希望可以有所幫助2021-09-09C++實(shí)現(xiàn)LeetCode(104.二叉樹(shù)的最大深度)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(104.二叉樹(shù)的最大深度),本篇文章通過(guò)簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07用C語(yǔ)言模仿Python函數(shù)的一種簡(jiǎn)單實(shí)現(xiàn)方法
這篇文章主要介紹了用C語(yǔ)言模仿Python函數(shù)的一種簡(jiǎn)單實(shí)現(xiàn)方法,需要的朋友可以參考下2017-05-05C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易通訊錄完整流程
這篇文章主要為大家介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易通訊錄的完整流程,每個(gè)環(huán)節(jié)都有完整代碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助2022-02-02基于Matlab實(shí)現(xiàn)數(shù)字音頻分析處理系統(tǒng)
這篇文章主要為大家介紹了如何利用Matlab制作一個(gè)帶GUI的數(shù)字音頻分析與處理系統(tǒng)。文中的示例代碼講解詳細(xì),感興趣的小伙伴可以學(xué)習(xí)一下2022-02-02