python+OpenCV反投影圖像的實(shí)現(xiàn)示例詳解
一、前言
如果對(duì)直方圖或者直方圖均衡化的概念比較模糊的話,建議先了解直方圖的基本原理及概念:
python+OpenCv筆記(十二):直方圖(灰度直方圖、掩膜的應(yīng)用、直方圖均衡化、自適應(yīng)直方圖均衡化)
二、什么是反投影圖像
我們先不談反投影圖像抽象的概念,可以先用示例做一個(gè)簡(jiǎn)單且清晰的了解:
1.
例如,現(xiàn)在有一張手掌的圖片,我們對(duì)其進(jìn)行直方圖繪制(假設(shè)bins設(shè)置為4),如圖:


這是之前做過(guò)的一個(gè)示例,而且很容易理解,直方圖中清晰地展示了如果將灰度0~255劃分為4個(gè)區(qū)間(bins),那么這張手掌灰度圖按照這4個(gè)區(qū)間劃分都有多少個(gè)像素點(diǎn),這就是圖像到直方圖的一個(gè)過(guò)程。
反投影圖像恰恰是這一步的逆過(guò)程,即通過(guò)直方圖又生成了一張圖像,但生成的圖像只有4種顏色(即直方圖有多少個(gè)bins,生成的反投影圖像就有多少種顏色),比如說(shuō)原圖中某一塊區(qū)域的灰度值都在0到20這個(gè)區(qū)間內(nèi),如果bins=4,那么反投影圖像中那一塊區(qū)域的顏色是同一種顏色。
并且,一個(gè)bins(區(qū)間)內(nèi)像素越多,在反投影圖像中呈現(xiàn)出的顏色就越亮,反之越暗。
現(xiàn)在,我們?cè)O(shè)置bins=12,在代碼中運(yùn)行的結(jié)果如下:
歸一化后的直方圖:

反投影圖像:

由上面可知,反投影圖像由12種灰度值組成,且落在同一個(gè)區(qū)間內(nèi)的像素值越多,那么反投影后原區(qū)域就會(huì)越亮,比如整個(gè)手掌部分由于灰度值接近,且像素很多,那么反投影后手掌部分就會(huì)變得很亮,像素點(diǎn)很少的bins反投影后甚至?xí)尸F(xiàn)黑色。
(注:由于示例原因,直方圖中很多bins的像素點(diǎn)數(shù)為0,所以反投影后的圖像看起來(lái)不像是由12種灰度值組成,其實(shí)是因?yàn)槟切﹨^(qū)間并不存在像素點(diǎn))
2.
但是,反投影圖像更常見(jiàn)的用途是查找特征,在meanshift算法中會(huì)用到。
比如說(shuō)我們現(xiàn)在有模板圖像以及生成的模板圖像的直方圖(見(jiàn)上),我們需要在原圖像中用上面的結(jié)果來(lái)檢測(cè)特征,先看一下結(jié)果:
在原圖像中反投影后:

可以看到,一個(gè)手掌已經(jīng)被清晰地展現(xiàn)了出來(lái)。
使用統(tǒng)計(jì)學(xué)的語(yǔ)言, 新圖像中儲(chǔ)存的數(shù)值代表了測(cè)試圖像中該像素屬于皮膚區(qū)域的 概率 。比如以上圖為例, 亮起的區(qū)域是皮膚區(qū)域的概率更大(事實(shí)確實(shí)如此),而更暗的區(qū)域則表示更低的概率(注意手掌內(nèi)部和邊緣的陰影影響了檢測(cè)的精度)。
這其中涉及backproject算法,具體算法以及流程可以閱讀后文。
總結(jié):
原圖像————直方圖————反投影圖像
三、反投影圖像的概念
現(xiàn)在,我們可以理解一下反投影圖像的抽象概念:
- 反向投影是一種記錄給定圖像中的像素點(diǎn)如何適應(yīng)直方圖模型像素分布的方式。
- 簡(jiǎn)單的講, 所謂反向投影就是首先計(jì)算某一特征的直方圖模型,然后使用模型去尋找圖像中存在的該特征(即查找特征)。
四、反向投影的工作原理
一、利用反向投影backproject查找特征的大致流程:
- 輸入模板圖像
- 得到模板圖像的直方圖
- 輸入源圖像,依據(jù)源圖像的每個(gè)像素的值,在模板圖像的直方圖中找到對(duì)應(yīng)的值,然后將直方圖的值賦給新的圖像
二、具體細(xì)化的流程
直方圖反向投影流程
| 假設(shè)我們有一張100x100的輸入圖像,有一張10x10的模板圖像,查找的過(guò)程是這樣的: |
| 1.從輸入圖像的左上角(0,0)開(kāi)始,切割一塊(0,0)至(10,10)的臨時(shí)圖像 |
| 2.生成臨時(shí)圖像的直方圖 |
| 3.用臨時(shí)圖像的直方圖和模板圖像的直方圖對(duì)比,對(duì)比結(jié)果記為c |
| 4.直方圖對(duì)比結(jié)果c,就是結(jié)果圖像(0,0)處的像素值 |
| 5.切割輸入圖像從(0,1)至(10,11)的臨時(shí)圖像,對(duì)比直方圖,并記錄到結(jié)果圖像 |
| 6.重復(fù)1~5步直到輸入圖像的右下角,就形成了直方圖的反向投影。 |
三、計(jì)算過(guò)程示例
(1)模板灰度圖像的矩陣如下:

(2)模板灰度圖像的直方圖為:
bin指定的區(qū)間為:[0,3), [4,7), [8,11), [12,16)
Histogram = 4 4 6 2
(3)反向投影圖為的矩陣為:

例如位置(0,0)上的像素值為0,對(duì)應(yīng)的bin為[0,3), 所以反向直方圖在該位置上的值為這個(gè)bin的值4。
五、反向投影需注意的細(xì)節(jié)
- 反投影圖像能夠在圖像內(nèi)定位感興趣的對(duì)象,同時(shí)反投影圖像總是單通道圖像,其中每一個(gè)像素的值都是從直方圖中其對(duì)應(yīng)的bin獲取的。
- 生成的反投影圖像實(shí)際上是一張概率圖。
- 輸入的原圖像需要轉(zhuǎn)換為HSV顏色空間,然后方可計(jì)算直方圖,同時(shí)由于一般的直方圖的bin很容易溢出0到255,所以在計(jì)算反投影之前,需要對(duì)直方圖的結(jié)果進(jìn)行標(biāo)準(zhǔn)化,將所有值縮放到從最小值0到最大值255的范圍內(nèi),用到的是cv2.normalize()函數(shù)。
- 再重復(fù)一次,必須在calBackProject函數(shù)之前調(diào)用該函數(shù)。
- 為什么使用HSV顏色空間?
- 例如,對(duì)于一張還有紅玫瑰的圖像,在RGB圖像中,我們不能只根據(jù)一個(gè)閾值濾除紅色通道,因?yàn)樗赡芴粱蛱?。但它仍然可能是紅色的不同陰影。另外,可能想要考慮與紅色極其相似的顏色,以確保盡可能精確的得到玫瑰。在這種情況下,以及在需要處理顏色的類似情況下,最好是用色調(diào)、飽和度、值(三者簡(jiǎn)稱HSV)顏色空間,其中顏色保存在單個(gè)通道(hue 或 h 通道)中。
- 在HSV顏色空間中,色調(diào)單獨(dú)負(fù)責(zé)每一個(gè)像素的顏色,飽和度和值通道可以用來(lái)得到相同顏色的更亮(使用飽和度通道)和更暗(使用值通道)的變化。
- 另外與RGB不同,色調(diào)是0~360之間的值,這是因?yàn)樯{(diào)被建模為一個(gè)圓,因此只要其值溢出,顏色就會(huì)回到起點(diǎn)。
- 但是在open CV中,色調(diào)通常除以2以滿足8位(除非我們使用16或更多位)的像素?cái)?shù)據(jù),所以顏色的值在0~180之間變化。
六、代碼編寫(xiě)
import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np
# 輸入模板圖像與原圖像
src = cv.imread("E:\\hand.jpg")
img = src.copy()
src2 = cv.imread("E:\\hand2.jpg")
img2 = src2.copy()
# 計(jì)算直方圖
# 轉(zhuǎn)換色彩空間
hsv_roi = cv.cvtColor(img, cv.COLOR_BGR2HSV)
# 計(jì)算直方圖
roi_hist = cv.calcHist([hsv_roi], [0], None, [13], [0, 180])
# 歸一化
cv.normalize(roi_hist, roi_hist, 0, 255, cv.NORM_MINMAX)
# 原圖像轉(zhuǎn)換色彩空間
hsv_roi2 = cv.cvtColor(img2, cv.COLOR_BGR2HSV)
# 反投影
dst = cv.calcBackProject([hsv_roi2], [0], roi_hist, [0, 255], 1)
# 顯示圖像
plt.figure(figsize=(10, 6), dpi=100)
plt.plot(roi_hist)
plt.grid()
plt.show()
cv.imshow("backProject", dst)
cv.waitKey(0)模板圖像與原圖像:

模板圖像的直方圖:

在原圖像中檢測(cè)的特征:

到此這篇關(guān)于python+OpenCV反投影圖像的文章就介紹到這了,更多相關(guān)python OpenCV反投影內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python項(xiàng)目文件中安裝?setup.py的步驟
大家都知道setup.py是python模塊分發(fā)與安裝的指導(dǎo)文件,這篇文章主要介紹了Python項(xiàng)目文件中如何安裝?setup.py,需要的朋友可以參考下2023-05-05
Python如何生成指定區(qū)間中的隨機(jī)數(shù)
這篇文章主要介紹了Python如何生成指定區(qū)間中的隨機(jī)數(shù),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07
pandas調(diào)整列的順序以及添加列的實(shí)現(xiàn)
這篇文章主要介紹了pandas調(diào)整列的順序以及添加列的實(shí)現(xiàn)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-03-03
python爬取NUS-WIDE數(shù)據(jù)庫(kù)圖片
本文給大家分享的是使用Python制作爬蟲(chóng)爬取圖片的小程序,非常的簡(jiǎn)單,但是很實(shí)用,有需要的小伙伴可以參考下2016-10-10
Python 中的判斷語(yǔ)句,循環(huán)語(yǔ)句,函數(shù)
這篇文章主要介紹了Python 中的判斷語(yǔ)句,循環(huán)語(yǔ)句,函數(shù),文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-08-08
擴(kuò)展Django admin的list_filter()可使用范圍方法
今天小編就為大家分享一篇擴(kuò)展Django admin的list_filter()可使用范圍方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-08-08

