OpenCV中反向投影
首先要说的可能要说的就是反向投影,用一个看到的例子来说可能更直观一些。
[
1
2
3
4
5
6
7
8
9
10
11
12
9
10
13
15
]
\begin{bmatrix}1&2&3&4 \\ 5&6&7&8 \\ 9&10&11&12 \\ 9&10&13&15 \end{bmatrix}
⎣⎢⎢⎡1599261010371113481215⎦⎥⎥⎤
假设该矩阵为一个图像的像素分布,首先我们根据该矩阵找到图像的直方图,假设图像的bin值范围为
[
1
,
4
]
,
[
5
,
8
]
,
[
9
,
11
]
,
[
12
,
15
]
[1,4],[5,8],[9,11],[12,15]
[1,4],[5,8],[9,11],[12,15]
可以得到图像的各个像素的个数:
[
1
,
4
]
:
4
[1,4]:4
[1,4]:4
[ 5 , 8 ] : 4 [5,8]:4 [5,8]:4
[ 9 , 11 ] : 5 [9,11]:5 [9,11]:5
[ 12 , 15 ] : 3 [12,15]:3 [12,15]:3
我们得到了各个像素的在图像中出现的次数,然后遍历原图像,例如第一个像素点,像素值为1在
[
1
,
4
]
[1,4]
[1,4]这个范围内,所以将该点的像素值改为该范围统计的频值即是4,对所有的像素执行上述的操作,可以得到如下矩阵:
[
4
4
4
4
4
4
4
4
5
5
5
3
5
5
3
3
]
\begin{bmatrix}4&4&4&4\\4&4&4&4 \\5&5&5&3\\5&5&3&3 \end{bmatrix}
⎣⎢⎢⎡4455445544534433⎦⎥⎥⎤
这个过程就是我们所说的反向投影。
第二个需要知道的是HSV图像。HSV表示一个色彩空间,也是三通道的,类似与RGB图像,在RGB图像中每个通道代表的是三原色之一,而在HSV中每个通道代表的意思与RGB完全不同。
H通道表示色调在OpenCV中取值范围为0-180,
S为饱和度,取值范围为0-255表示颜色接近光谱的程度,一种颜色可以看成时光谱色与白色混合的结果。其中光谱色占的比例越大,颜色的饱和度也就越高。
V为亮度,取值范围为0-255。
HSV通道的获取,利用mixChannels函数来实现:
hue.create(hsv.size(),hsv.depth());
int ch[] = {0,0};
mixChannels(&hsv,1,&hue,1,ch,1);
hsv.depth();在OpenCV中该函数用来显示图像的深度,什么叫图像的深度呢?作为小白的我去求助了度娘,例如灰度图,每个像素的值的范围为0-255,需要8位二进制数才能表示255,所以叫该图的位深为8。
mixChannels(
输入图像,
矩阵的数量,
输出图像,深度和大小必须和输入图像0通道相同
矩阵的数量,
被复制通道和要复制到的位置组成索引对,例如从原图的0通道到0通道
索引对的数目。
);
分离通道时需要注意,HSV中,H在0通道,S在1通道,V在2通道。
在
这
个
地
方
,
有
一
个
疑
惑
,
之
前
我
们
对
图
像
通
道
分
离
都
是
采
用
s
p
l
i
t
这
个
函
数
来
进
行
,
\color{#f00}在这个地方,有一个疑惑,之前我们对图像通道分离都是采用split这个函数来进行,
在这个地方,有一个疑惑,之前我们对图像通道分离都是采用split这个函数来进行,
这
里
没
有
使
用
,
那
么
s
p
l
i
t
是
否
可
以
呢
所
以
我
就
试
了
一
下
,
发
现
可
以
。
\color{#f00}这里没有使用,那么split是否可以呢所以我就试了一下,发现可以。
这里没有使用,那么split是否可以呢所以我就试了一下,发现可以。
vector<Mat> v;
split(hsv,v);
hue = v[0];
下面就是由OpenCV提供的反向投影的API函数:
calcBackProjection(
输入图像,深度必须为cv_8u、cv_16u、cv_32f的一种
输入图像的数量,
用于反向投影的通道列表
输入的直方图,
输出的单通道反向投影的图像,
直方图中每个维度bin的取值范围
double scale=1:可选输出反向投影的比例因子
直方图是否均匀分布的标识符,默认为true
);
下面看一个手敲的小demo:
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
Mat src,hsv,hue;
int bins = 25;
void Hist_and_Backproj(int,void*)
{
Mat hist;
int histSize = MAX(bins,2);
float hue_range[] = {0,180};
const float* ranges = {hue_range};
calcHist(&hue,1,0,Mat(),hist,1,&histSize,&ranges,true,false);
normalize(hist,hist,0,255,NORM_MINMAX,-1,Mat());
Mat backproj;
calcBackProject(&hue,1,0,hist,backproj,&ranges,1,true);
imshow("backproj",backproj);
}
int main(int argc, char *argv[])
{
src = imread("/home/dynamicw/Project/C++_Project/opencvtest/src/lesson01/source/map.png");
cvtColor(src,hsv,CV_BGR2HSV);
hue.create(hsv.size(),hsv.depth());
int ch[] = {0,0};
mixChannels(&hsv,1,&hue,1,ch,1);
//vector<Mat> v;
//split(hsv,v);
//hue = v[0];
namedWindow("Test",CV_WINDOW_AUTOSIZE);
createTrackbar("Test","Test",&bins,180,Hist_and_Backproj);
Hist_and_Backproj(0,0);
waitKey(0);
return 0;
}