OpenCV 2 学习笔记(18): 反向投影

来源:互联网 发布:淘宝客哪个软件好 编辑:程序博客网 时间:2024/06/09 19:58

代码见:http://download.csdn.net/download/u010525655/6228687


原理:反向投影是一种记录给定图像中的像素点如何适应直方图模型像素分布的方式。

所谓反向投影就是首先计算某一特征的直方图模型,然后使用模型去寻找图像中存在的该特征。

假设你已经通过下图得到一个肤色直方图(Hue-Saturation), 旁边的直方图就是 模型直方图 ( 代表手掌的皮肤色调).你可以通过掩码操作来抓取手掌所在区域的直方图:

我们要做的就是使用 模型直方图 (代表手掌的皮肤色调) 来检测测试图像中的皮肤区域。以下是检测的步骤

  1. 对测试图像中的每个像素 ( p(i,j) ),获取色调数据并找到该色调(( h_{i,j}, s_{i,j} ) )在直方图中的bin的位置。

  2. 查询 模型直方图 中对应的bin - ( h_{i,j}, s_{i,j} ) - 并读取该bin的数值。

  3. 将此数值储存在新的图像中(BackProjection)。 你也可以先归一化 模型直方图 ,这样测试图像的输出就可以在屏幕显示了。


以上转载自:http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/histograms/back_projection/back_projection.html#back-projection


直方图可以说是图像内容的一个重要特征。如果图片的某一部分有一个特殊的纹理或者某个物体。那么这部分的直方图就可以用来检测像素是否属于这个纹理或者物体。

反向投影方法为

voidcalcBackProject(const Mat* images, int nimages, const int* channels, InputArray hist,OutputArraybackProject, const float** ranges, double scale=1, booluni-form=true)


Parameters
images– Source arrays. They all should have the same depth,CV_8U 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 numer-ated 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).

channels是和hist中的每一维是对应的。指的是使用哪一个信道来进行反向投影,如果channels的元素多余hist的维数不会出现错误,不知道hist的维数多余channels的元素数会不会出错。

hist可以是普通矩阵,也可以是稀疏矩阵,当图像时彩色的时候,在不减少图像位深的情况下,使用稀疏矩阵可以节省内存空间,提高效率,所以在代码中使用了一个模板类,使矩阵类型是通用的,提升了代码的利用率。

不管图像有几个信道,hist是几维的,backProject都是单通道的。由于输出的scale是概率值,不会超过一,所以使用scale来进行放大,scale是多少,最后的像素值就乘以多少,一般我们使用255.


还有比较重要的一点。那就是你利用哪个特征的直方图,在比较时就要使用哪个特征进行比较。例如,你使用HSV颜色空间图中某部分的的Hue分量来识别特征,那么在比较时,就要使用整张图像的Hue分量。如果你利用RGB的R分量进行比较时,那么就要用整张图的R分量。这样子很容易就把人给整晕了,特别是利用HSV颜色空间时。比较简单的做法就是首先用imread读进来一个灰度图像,这样就变得简单多了。

还有在得到直方图时最好将直方图进行归一化。例如归一化到0.0-1.0之间,正好在进行反向投影时需要计算概率。


下图是试验的图片:






其中第一幅是原图,其中可以看到ROI,第二张图先对图像减位深,位深减少为3,利用ROI的RGB特征进行反向投影,位深减少了,每一个像素值出现的概率自然变大了,所以看到的结果比较满意,该亮的地方都亮了。第三张图是利用HSV颜色空间的Hue特征进行反向投影,虽然看起来结果不如第二张图好,但是这说明Hue检测的结果比较细腻。

我们所做的实验非常的简单,这个功能可以使用阈值分割很简单的就实现了,但是我觉得在反向投影的时候,应该可以使用多个特征进行投影,这样检测的结果会更加的准确。这个还有待进一步的研究