python+OpenCV反投影圖像的實現(xiàn)示例詳解
一、前言
如果對直方圖或者直方圖均衡化的概念比較模糊的話,建議先了解直方圖的基本原理及概念:
python+OpenCv筆記(十二):直方圖(灰度直方圖、掩膜的應(yīng)用、直方圖均衡化、自適應(yīng)直方圖均衡化)
二、什么是反投影圖像
我們先不談反投影圖像抽象的概念,可以先用示例做一個簡單且清晰的了解:
1.
例如,現(xiàn)在有一張手掌的圖片,我們對其進行直方圖繪制(假設(shè)bins設(shè)置為4),如圖:
這是之前做過的一個示例,而且很容易理解,直方圖中清晰地展示了如果將灰度0~255劃分為4個區(qū)間(bins),那么這張手掌灰度圖按照這4個區(qū)間劃分都有多少個像素點,這就是圖像到直方圖的一個過程。
反投影圖像恰恰是這一步的逆過程,即通過直方圖又生成了一張圖像,但生成的圖像只有4種顏色(即直方圖有多少個bins,生成的反投影圖像就有多少種顏色),比如說原圖中某一塊區(qū)域的灰度值都在0到20這個區(qū)間內(nèi),如果bins=4,那么反投影圖像中那一塊區(qū)域的顏色是同一種顏色。
并且,一個bins(區(qū)間)內(nèi)像素越多,在反投影圖像中呈現(xiàn)出的顏色就越亮,反之越暗。
現(xiàn)在,我們設(shè)置bins=12,在代碼中運行的結(jié)果如下:
歸一化后的直方圖:
反投影圖像:
由上面可知,反投影圖像由12種灰度值組成,且落在同一個區(qū)間內(nèi)的像素值越多,那么反投影后原區(qū)域就會越亮,比如整個手掌部分由于灰度值接近,且像素很多,那么反投影后手掌部分就會變得很亮,像素點很少的bins反投影后甚至?xí)尸F(xiàn)黑色。
(注:由于示例原因,直方圖中很多bins的像素點數(shù)為0,所以反投影后的圖像看起來不像是由12種灰度值組成,其實是因為那些區(qū)間并不存在像素點)
2.
但是,反投影圖像更常見的用途是查找特征,在meanshift算法中會用到。
比如說我們現(xiàn)在有模板圖像以及生成的模板圖像的直方圖(見上),我們需要在原圖像中用上面的結(jié)果來檢測特征,先看一下結(jié)果:
在原圖像中反投影后:
可以看到,一個手掌已經(jīng)被清晰地展現(xiàn)了出來。
使用統(tǒng)計學(xué)的語言, 新圖像中儲存的數(shù)值代表了測試圖像中該像素屬于皮膚區(qū)域的 概率 。比如以上圖為例, 亮起的區(qū)域是皮膚區(qū)域的概率更大(事實確實如此),而更暗的區(qū)域則表示更低的概率(注意手掌內(nèi)部和邊緣的陰影影響了檢測的精度)。
這其中涉及backproject算法,具體算法以及流程可以閱讀后文。
總結(jié):
原圖像————直方圖————反投影圖像
三、反投影圖像的概念
現(xiàn)在,我們可以理解一下反投影圖像的抽象概念:
- 反向投影是一種記錄給定圖像中的像素點如何適應(yīng)直方圖模型像素分布的方式。
- 簡單的講, 所謂反向投影就是首先計算某一特征的直方圖模型,然后使用模型去尋找圖像中存在的該特征(即查找特征)。
四、反向投影的工作原理
一、利用反向投影backproject查找特征的大致流程:
- 輸入模板圖像
- 得到模板圖像的直方圖
- 輸入源圖像,依據(jù)源圖像的每個像素的值,在模板圖像的直方圖中找到對應(yīng)的值,然后將直方圖的值賦給新的圖像
二、具體細化的流程
直方圖反向投影流程
假設(shè)我們有一張100x100的輸入圖像,有一張10x10的模板圖像,查找的過程是這樣的: |
1.從輸入圖像的左上角(0,0)開始,切割一塊(0,0)至(10,10)的臨時圖像 |
2.生成臨時圖像的直方圖 |
3.用臨時圖像的直方圖和模板圖像的直方圖對比,對比結(jié)果記為c |
4.直方圖對比結(jié)果c,就是結(jié)果圖像(0,0)處的像素值 |
5.切割輸入圖像從(0,1)至(10,11)的臨時圖像,對比直方圖,并記錄到結(jié)果圖像 |
6.重復(fù)1~5步直到輸入圖像的右下角,就形成了直方圖的反向投影。 |
三、計算過程示例
(1)模板灰度圖像的矩陣如下:
(2)模板灰度圖像的直方圖為:
bin指定的區(qū)間為:[0,3), [4,7), [8,11), [12,16)
Histogram = 4 4 6 2
(3)反向投影圖為的矩陣為:
例如位置(0,0)上的像素值為0,對應(yīng)的bin為[0,3), 所以反向直方圖在該位置上的值為這個bin的值4。
五、反向投影需注意的細節(jié)
- 反投影圖像能夠在圖像內(nèi)定位感興趣的對象,同時反投影圖像總是單通道圖像,其中每一個像素的值都是從直方圖中其對應(yīng)的bin獲取的。
- 生成的反投影圖像實際上是一張概率圖。
- 輸入的原圖像需要轉(zhuǎn)換為HSV顏色空間,然后方可計算直方圖,同時由于一般的直方圖的bin很容易溢出0到255,所以在計算反投影之前,需要對直方圖的結(jié)果進行標(biāo)準化,將所有值縮放到從最小值0到最大值255的范圍內(nèi),用到的是cv2.normalize()函數(shù)。
- 再重復(fù)一次,必須在calBackProject函數(shù)之前調(diào)用該函數(shù)。
- 為什么使用HSV顏色空間?
- 例如,對于一張還有紅玫瑰的圖像,在RGB圖像中,我們不能只根據(jù)一個閾值濾除紅色通道,因為它可能太亮或太暗。但它仍然可能是紅色的不同陰影。另外,可能想要考慮與紅色極其相似的顏色,以確保盡可能精確的得到玫瑰。在這種情況下,以及在需要處理顏色的類似情況下,最好是用色調(diào)、飽和度、值(三者簡稱HSV)顏色空間,其中顏色保存在單個通道(hue 或 h 通道)中。
- 在HSV顏色空間中,色調(diào)單獨負責(zé)每一個像素的顏色,飽和度和值通道可以用來得到相同顏色的更亮(使用飽和度通道)和更暗(使用值通道)的變化。
- 另外與RGB不同,色調(diào)是0~360之間的值,這是因為色調(diào)被建模為一個圓,因此只要其值溢出,顏色就會回到起點。
- 但是在open CV中,色調(diào)通常除以2以滿足8位(除非我們使用16或更多位)的像素數(shù)據(jù),所以顏色的值在0~180之間變化。
六、代碼編寫
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() # 計算直方圖 # 轉(zhuǎn)換色彩空間 hsv_roi = cv.cvtColor(img, cv.COLOR_BGR2HSV) # 計算直方圖 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)
模板圖像與原圖像:
模板圖像的直方圖:
在原圖像中檢測的特征:
到此這篇關(guān)于python+OpenCV反投影圖像的文章就介紹到這了,更多相關(guān)python OpenCV反投影內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
pandas調(diào)整列的順序以及添加列的實現(xiàn)
這篇文章主要介紹了pandas調(diào)整列的順序以及添加列的實現(xiàn)操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-03-03python爬取NUS-WIDE數(shù)據(jù)庫圖片
本文給大家分享的是使用Python制作爬蟲爬取圖片的小程序,非常的簡單,但是很實用,有需要的小伙伴可以參考下2016-10-10Python 中的判斷語句,循環(huán)語句,函數(shù)
這篇文章主要介紹了Python 中的判斷語句,循環(huán)語句,函數(shù),文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-08-08擴展Django admin的list_filter()可使用范圍方法
今天小編就為大家分享一篇擴展Django admin的list_filter()可使用范圍方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2019-08-08