圖像閾值


0 引

圖像閾值,即圖像的分割基準,基於此可完成圖像的二值化。圖像二值化可用於OCR成圖像的分割(也是最爲簡單的一種)。這種分割是基於圖像像素值級別的差異,且一般的對象是灰度圖像。

1 圖像二值化

如上所述,圖像閾值的進一步處理就是二值化,二值化包含但不限於“大於閾值爲255,小於閾值爲0”的處理模式。具體如下所示。其實個人理解這些方法只是提供了一種在處理圖像時的思路,並不一定要死記住方法的名字。

爲了更好解釋,假設待處理圖像的直方圖如下。


1.1二進制閾值化

1.2反二進制閾值化

1.3截段閾值化

1.4閾值化0

1.5 反閾值化0

2 OpenCV API

       double cvThreshold( const void* srcarr, void*dstarr, double thresh, double maxval, int type );

       srcarr源數組,dstarr爲目標數組,thresh爲閾值,maxval爲欲設最大值,type爲閾值處理的類型,有如下幾種:

CV_THRESH_BINARY,表示dsti=(srci>T)?M:0。

CV_THRESH_BINARY_INV,表示dsti=(srci>T)?0:M。

CV_THRESH_TRUNC,表示dsti=(srci>T)?M:srci。

CV_THRESH_TOZERO_INV,表示dsti=(srci>T)?0:srci。

CV_THRESH_TOZERO,表示dsti=(srci>T)?srci:0。

另外,type值還有兩個選擇,可以指定thresh值,此時傳入參數thresh不會起作用。

       CV_THRESH_OTSU        使用大津法選擇最優的thresh;

       CV_THRESH_TRIANGLE 使用三角法確定thresh;

3 閾值的選擇

       上文中介紹API的同時,也介紹了兩種算法確定的thresh:大津法和三角法。

3.1 大津法

大津法又稱爲最大類間方差法。優點計算簡單且不受亮度和對比度的影響。算法的基本思想是找到的閾值滿足low(即低於選擇的閾值)部分與high(即高於閾值部分)的類方差是最大的。

類方差是一個新概念,在正式解釋之前先補充另外一個在算法中使用的概念即前景與後景,前景與後景是根據閾值區分的,即上述的low部分與high部分,至於哪個是前景哪個是後景,需要根據圖像的特徵確定(例如黑背景白字的圖片,那麼前景就是指high部分的白字)。

假設圖像背景是黑色時,且分辨率爲M*N,閾值爲T,記小於T的像素個數爲N0且其平均灰度爲μ0,大於的個數記爲N1且其平均灰度爲μ1,則類方差g的計算公式如下。

ω0=N0/ M×N (1)

ω1=N1/ M×N (2)

N0+N1=M×N (3)

ω0+ω1=1 (4)

μ=ω0*μ0+ω1*μ1 (5)

g=ω0(μ0-μ)^2+ω1(μ1-μ)^2 (6)

將式(5)代入式(6),得到等價公式:
   g=ω0ω1(μ0-μ1)^2    (7) 這就是類間方差

而OTSU算法則是找到使類間方差最大的像素值,作爲閾值。代碼演示如下。

int GetOTUSThresh(cv::Matimg) {

  assert(img.channels() == 1);

  int gray_cnt[256] = { 0 };

  // stastics

  for (inti = 0; i < img.rows; i++) {

    for (intj = 0; j < img.cols; j++) {

      gray_cnt[img.at<unsignedchar>(i, j)]++;

    }

  }

  // otus

  double max_delta = 0.0;

  double delta;

  int thresh;

  double weight_l, weight_h;

  double u_l, u_h, u;

  int cnt_l, cnt_h;

  for (inti = 0; i < 256; i++) {

    cnt_l = cnt_h = 0;

    u_l = u_h = 0.0;

    for (intj = 0; j < 256; j++) {

      if (j <i) {

        cnt_l += gray_cnt[j];

        u_l += j * gray_cnt[j];

      }

      else {

        cnt_h += gray_cnt[j];

        u_h += j*gray_cnt[j];

      }

    }

    u_l = u_l / cnt_l;

    u_h = u_h / cnt_h;

    weight_l = (double)cnt_l / (img.rows*img.cols);

weight_h = 1 - weight_l;

delta = weight_h*weight_l*(u_h -u_l)*(u_h - u_l);

    if (delta >max_delta) {

      max_delta =delta;

      thresh = i;

    }

  }

  return thresh;

}

3.2 三角法

4 自適應圖像閾值

       所謂自適應,即將圖像分爲若干個大小相同的block,每個block的閾值會根據周圍局部像素值動態改變待比較的閾值。這樣做的好處是亮處較亮的地方二值化閾值通常較高,而亮度較低的則更低,對噪聲不會那麼敏感。具體的分爲兩種方法,局部鄰域塊的均值和局部鄰域塊的高斯加權和。事實上對於成像效果不好的圖,往往自適應閾值法更加適用。

       OPENCV中的API

       void adaptiveThreshold(InputArray src,OutputArray dst, double maxValue, int adaptiveMethod, int thresholdType, int blockSize, double param)

       參數 adaptiveMethod:採用的算法兩個取值ADAPTIVE_THRESH_MEAN_C 和 ADAPTIVE_THRESH_GAUSSIAN_C分別對應局部鄰域塊的均值和局部鄰域塊的高斯加權和。

       參數param:引入的微調參數,最終的閾值等於通過adpativeMethod得到的值與param的差值,也可以負數。

5 參考

http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/threshold/threshold.html

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