唉,再再再學一下直方圖:直方圖反投影

之前寫過一篇【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計算直方圖呢?反向投影后爲:

在這裏插入圖片描述

可以看到特徵描述得更爲廣泛了,就像深度學習裏,提取更高層次得特徵,雖然更爲普適,但也會忽略掉一些細節特徵。

我們就是拿這個反向投影所表達得特徵信息,去和整幅圖做對比,來得到特徵相似得部分,達到分割得效果。

二:利用反向投影進行語義分割

先看一下我們今天要處理得圖片:
在這裏插入圖片描述
我們今天要做得就是將這條公路給提取出來。

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視覺各門類電子書,公衆號後臺回覆【電子書資源】自取呀。
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章