唉,再再再学一下直方图:直方图反投影

之前写过一篇【opencv】带你再学一遍直方图,里面的内容可以看下图。所以今天还要再再再学一个直方图的API:直方图反投影。
在这里插入图片描述
直方图反向投影是干啥的呢,它用于图像分割或在图像中查找感兴趣的对象。用什么来查找呢?用直方图。

直方图在一定程度上可以反应图像的特征,我们截取一个有固定特征的样例,比如草地,然后计算该块草地的直方图,然后用这个直方图去和整幅图像的直方图做对比,根据一定的判断条件,就能得出相似的即为草地。
在这里插入图片描述
看着就像是语义分割,其实一定意义上这就是语义分割,这不过直方图反向分割的依据是人为计算的(直方图),后者分割的依据是靠在神经网络中学习得来的。

我们先看一下opencv直方图反向计算得API:


void cv::calcBackProject(
  const Mat *  images, //要进行投影的输入图像的地址,注意该API要求输入的是地址
  int          nimages,//输入图像的数目
  const int *  channels,//要进行投影的通道数
  InputArray   hist,//样本得直方图
  OutputArray  backProject,//输出得反向投影,为Mat类型
  const float ** ranges, //输入直方图得特征空间的取值范围
  double         scale = 1,
  bool          uniform = true
)

一:该API得实现原理是什么呢

假设我们现在有一个四行四列得灰度图,它得灰度值如下图:

在这里插入图片描述

说这幅图有什么特征呢?直观上看类似于一个边角,但这是直观上,怎么表示出来呢?深度学习是靠神经网络黑箱计算出来得,我们可以用直方图。

那我们就计算这幅灰度图得直方图,如果以组距为1计算直方图并反向投影到原图,得到得为下图:

在这里插入图片描述

可以大概表述一下边角得特征:左下角有6个像素值相同得三角形区域,中间斜向下有四个像素值相同得边界线,以此类推。这就是用直方图得到得边角得特征。

那如果以组距为2计算直方图呢?反向投影后为:

在这里插入图片描述

扫描二维码关注公众号,回复: 11549727 查看本文章

可以看到特征描述得更为广泛了,就像深度学习里,提取更高层次得特征,虽然更为普适,但也会忽略掉一些细节特征。

我们就是拿这个反向投影所表达得特征信息,去和整幅图做对比,来得到特征相似得部分,达到分割得效果。

二:利用反向投影进行语义分割

先看一下我们今天要处理得图片:
在这里插入图片描述
我们今天要做得就是将这条公路给提取出来。

1,先读取原图以及样本图,并转换为HSV格式。


  //【1】读取图片
  Mat srcImage = imread("风景图.jpg");
  Mat RoiImage = imread("公路2.png"); 
  //【2】转换为HSV图像
  Mat HsvImage, RoiImage_HSV;
  cvtColor(srcImage, HsvImage, COLOR_BGR2HSV);
  cvtColor(RoiImage, RoiImage_HSV, COLOR_BGR2HSV);

为什么转HSV呢?因为HSV表达颜色更为方便区分,我们今天用到得只有前两个通道:H(色调)和S(饱和度),不用V(亮度)。

来看一下我们截取得样本图:
在这里插入图片描述
这是我们在公路上随便截取得一块儿样本,可以看到整条公路大概都是这个样子。

2,计算样本图得直方图并进行归一化

  //【3】计算公路的直方图
  MatND roiHist; //直方图对象
  int dims = 2;  //特征数目(直方图维度)
  float hranges[] = { 0,180 }; //特征空间的取值范围
  float Sranges[] = { 0,256 };
  const float *ranges[] = { hranges,Sranges };
  int size[] = { 20,32 };  //存放每个维度的直方图的尺寸的数组
  int channels[] = {0,1};  //通道数
  calcHist(&RoiImage_HSV,1, channels, Mat(), roiHist, dims, size, ranges);
  //【4】直方图归一化
  normalize(roiHist, roiHist, 0, 255, NORM_MINMAX);

代码第7行,我们计算H和S通道直方图的组距分别为20和32,我们采用更小的组距来抓取更大的特征区域。

为什么要归一化呢,直方图反向投影到原图后,原图各位置表示的是整幅图中等于该点像素值的数量,归一化后就变成概率了。
在这里插入图片描述
3,将计算的归一化后的直方图进行反向投影


  //【5】反向投影
  Mat proImage; //投影输出图像
  calcBackProject(&HsvImage, 1, channels, roiHist, proImage, ranges);

反向投影后的原图:
在这里插入图片描述
可以大概看出公路的轮廓了吧?

4,上一篇图像腌膜Mask的常规操作你真的信手拈来吗?介绍了掩码操作,这里我们就要用掩码将公路给抠出来显示:
在这里插入图片描述
效果并不是想象中那么好是吧哈,感觉还是语义分割要更准确些。但准确能当女朋友吗?

后期再加上些边缘检测和霍夫直线变换,和一些其他骚操作,就可以提取公路啊,车道线啥的了。

如果觉的有帮助,就点个赞再走吧~
另外我分享了近6G视觉各门类电子书,公众号后台回复【电子书资源】自取呀。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_43667130/article/details/106605281