敞开生长之旅!这是我参加「日新方案 2 月更文应战」的第 25 天,点击检查活动详情
方针
在本章中将学习
- 直方图反投影
理论
这是由Michael J. Swain和Dana H. Ballard在他们的论文《 Indexing via color histograms》中提出的。
用简单的话来说,它用于图画切割或在图画中查找感兴趣的方针。简而言之,它创立的图画巨细与输入图画相同(但只有一个通道),其间每个像素对应于该像素归于物体的概率。用更简单的话来说,与其余部分比较,输出图画将在或许有方针的区域具有更多的白色值。直方图反投影与camshift算法等配合运用。
反向投影矩阵中某点的值便是它对应的原图画中的点所在区间的灰度直方图值。所以咱们能够看出,一个区间点越多,在反向投影矩阵中就越亮。
进程如下:
- 首要创立一个图画的直方图,其间包含感兴趣的方针。方针应尽或许填充图画以取得更好的效果。而且色彩直方图比灰度直方图更可取,由于对象的色彩对比灰度强度是定义方针的好办法
- 然后,将该直方图“反投影”到需求找到方针的测验图画上,换句话说,核算出归于背景的每个像素的概率并将其显示出来
- 在适当的阈值下发生的输出成果仅仅是取得背景
从这个进程能够看出,先求出原图画的直方图,再由直方图得到反向投影矩阵,由直方图到反向投影矩阵实际上便是一个反向的进程,所以叫反向。
Numpy中的算法
- 首要,需求核算要查找的方针(使其为
M
)和要查找的图画(使其为I
)的色彩直方图。
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] )
- 然后找到比例,R=MIR=\frac{M} {I}
即 运用R作为调色板,并运用每个像素创立新图画作为其方针的相应概率。
B(x,y) = R[h(x,y),s(x,y)]
, 其间h和s表明像素点(x,y)处的色调(h),饱和度(s)。
h, s, v = cv2.split(hsvt)
B = R[h.ravel(), s.ravel()]
B = np.minimum(B,1)
B = B.reshape(hsvt.shape[:2])
- 现在用圆形核应用卷积, 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)
- 现在最大强度的方位给了物体的方位。如果期望图画中有一个区域,则对合适的值进行阈值处理将取得不错的成果。
ret, thresh = cv2.threshold(B,50,255,0)
OpenCV的反投影
OpenCV供给了一个内建的函数cv2.calcBackProject()
。它的参数简直与cv2.calchist()
函数相同。
dst = cv.calcBackProject( images, channels, hist, ranges, scale[, dst] )
- images Source arrays. They all should have the same depth, CV_8U, CV_16U or CV_32F , and the same size. Each of them can have an arbitrary number of channels.
- nimages Number of source images.
- channels The list of channels used to compute the back projection. The number of channels must match the histogram dimensionality. The first array channels are numerated from 0 to images[0].channels()-1 , the second array channels are counted from images[0].channels() to images[0].channels() + images[1].channels()-1, and so on.
- hist Input histogram that can be dense or sparse.
- backProject Destination back projection array that is a single-channel array of the same size and depth as images[0] .
- ranges Array of arrays of the histogram bin boundaries in each dimension. See calcHist .
- scale Optional scale factor for the output back projection.
- uniform Flag indicating whether the histogram is uniform or not (see above).
在传递给backproject函数之前,应该对方针直方图进行归一化。它返回概率图画。然后咱们用圆盘内核对图画进行卷积并应用阈值。下面是我的代码和成果:
import numpy as np
import cv2
from matplotlib import pyplot as plt
roi = cv2.imread('roi.png') # 感兴趣的图片 绿色草地
hsv = cv2.cvtColor(roi, cv2 .COLOR_BGR2HSV)
target = cv2.imread('messi.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)
cv2.imshow('res', res)
cv2.waitKey()
cv2.destroyAllWindows()
以下是处理过的一个示例。将蓝色矩形内的区域用作示例方针,提取整个地上:
能够用于方针检测和切割
附加资源
- docs.opencv.org/4.1.2/dc/df…
- Indexing via color histograms”, Swain, Michael J. , Third international conference on computer vision,1990.
- docs.opencv.org/4.1.2/d6/dc…
- blog.csdn.net/shuiyixin/a…
- blog.csdn.net/jia20003/ar…