OpenCV-Python教程:26.Histogram 4 Histogram 向后投影

理論

Michael J. Swain , Dana H. Ballard?發(fā)表的Indexing via color histograms

用來在圖片分割或者在圖像里找感興趣的目標(biāo),簡(jiǎn)單說來,它創(chuàng)建了一個(gè)和輸入圖像一樣大小的圖像,但是是單通道的。輸出圖像會(huì)有我們感興趣的目標(biāo),但是它比其他部分更白。

我們?cè)趺醋瞿兀课覀儎?chuàng)建一個(gè)圖像的histogram,包含我們感興趣的目標(biāo)。彩色的histogram比灰度的要好,因?yàn)椴噬繕?biāo)更好被定義。然后我們“向后投影”這個(gè)histogram到我們的測(cè)試圖像上,我們計(jì)算每個(gè)像素的可能性,并顯示它。

Numpy里的算法

1.首先我們需要計(jì)算我們要找的目標(biāo)(假設(shè)叫M)和我們要搜索的圖像(假設(shè)叫I)的彩色histogram。

import cv2
import numpy as np
from matplotlib import pyplot as plt

#roi is the object or region of object we need to find
roi = cv2.imread('rose_red.png')
hsv = cv2.cvtColor(roi,cv2.COLOR_BGR2HSV)

#target is the image we search in
target = cv2.imread('rose.png')
hsvt = cv2.cvtColor(target,cv2.COLOR_BGR2HSV)

# Find the histograms using calcHist. Can be done with np.histogram2d also
M = cv2.calcHist([hsv],[0, 1], None, [180, 256], [0, 180, 0, 256] )
I = cv2.calcHist([hsvt],[0, 1], None, [180, 256], [0, 180, 0, 256] )

2.找到 R = M / I .然后向后投影R, 用R當(dāng)調(diào)色板創(chuàng)建一個(gè)新圖像,圖像的每個(gè)像素和它的目標(biāo)對(duì)應(yīng)的像素點(diǎn)可能性。B(x, y) = R[h(x, y), s(x,y)], h 是色調(diào),s是飽和度,然后B(x, y) = min[B(x, y), 1]

h, s, v = cv2.split(hsvt)
B = R[h.ravel(), s.ravel()]
B = np.minimum(B, 1)
B = B.reshape(hsvt.shape[:2])

3.現(xiàn)在用卷積, B = D * B,D是核

disc = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
cv2.filter2D(B,-1,disc,B)
B=np.uint8(B)
cv2.normalize(B,B,0,255,cv2.NORM_MINMAX)

4.現(xiàn)在最大強(qiáng)度的位置告訴我們目標(biāo)的位置,我們?nèi)绻氲玫綀D像的一個(gè)區(qū)域,可以用合適的閾值得到:

ret,thresh=cv2.threshold(B,50,255,0)

OpenCV里的向后映射

OpenCV提供了內(nèi)置函數(shù)cv2.calcBackProject()。它的參數(shù)和calcHist()一樣,一個(gè)參數(shù)是histogram,目標(biāo)的histogram應(yīng)該標(biāo)準(zhǔn)化,然后再傳給向后投影函數(shù)。它返回可能性圖片。然后我們用disc 核卷積,接著用閾值。

import cv2
import numpy as np

roi = cv2.imread('rose_red.png')
hsv = cv2.cvtColor(roi,cv2.COLOR_BGR2HSV)

target = cv2.imread('rose.png')
hsvt = cv2.cvtColor(target,cv2.COLOR_BGR2HSV)

# calculating object histogram
roihist = cv2.calcHist([hsv],[0, 1], None, [180, 256], [0, 180, 0, 256] )

# normalize histogram and apply backprojection
cv2.normalize(roihist,roihist,0,255,cv2.NORM_MINMAX)
dst = cv2.calcBackProject([hsvt],[0,1],roihist,[0,180,0,256],1)

# Now convolute with circular disc
disc = cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
cv2.filter2D(dst,-1,disc,dst)

# threshold and binary AND
ret,thresh = cv2.threshold(dst,50,255,0)
thresh = cv2.merge((thresh,thresh,thresh))
res = cv2.bitwise_and(target,thresh)

res = np.vstack((target,thresh,res))
cv2.imwrite('res.jpg',res)

下面是一個(gè)例子,我使用了藍(lán)色矩形的區(qū)域作為樣本對(duì)象,我想提取整個(gè)草皮

END

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容