1. 程式人生 > >opencv學習(二十八)之基本影象閾值操作threshold

opencv學習(二十八)之基本影象閾值操作threshold

在二維數字影象中,其每個畫素點對應了不同的畫素值,其畫素值各不相同。可以對畫素值特定範圍內的影象影象進行操作,劃分這個範圍的值就被稱為影象閾值,它不是一個固定的量級,是根據每幅影象和處理要求動態改變。例如我們可以從影象中利用閾值分割出我們需要的部分,利用其畫素值與背景在灰度特性上的差異,影象具有了不同的灰度等級,可據此指定一個合理的閾值從而確定影象中的畫素值是否屬於這個區域。所以其是畫素操作的一種形式。
opencv官方檔案中給出的解釋是:為了從一幅影象中提取我們需要的部分,應該用影象中的每一個畫素點的灰度值與選取的閾值進行比較,並作出相應的判斷(閾值的選取依賴於具體的問題,物體在不同的影象中可能會有不同的灰度值)。
一旦找到了需要分割的物體畫素點,我們可以對這些畫素點設定一些特定的值來標識(例如:可以將物體的畫素點的灰度值設定為:’0’黑色,其他的畫素點灰度值設定為:’255’白色;當然畫素點的灰度值可以任意,但最好設定兩種顏色對比度較強,方便觀察結果)。
這裡寫圖片描述

給出一個簡單的有關畫素灰度的圖片,如下:

這裡寫圖片描述

圖中的藍色水平線代表著具體的一個閾值。
opencv提供了threshold()函式對影象的閾值進行處理,threshold()共支援五中型別的閾值化方式,分別是二進位制閾值化、反二進位制閾值化、截斷閾值化、閾值化為0和反閾值化為0。
1.二進位制閾值化
二進位制閾值化的數學公式如下:

這裡寫圖片描述

在運用二進位制閾值化操作時,首先指定一個閾值量即畫素的灰度值,遍歷影象中畫素值,大於這個閾值的畫素均設定為最大畫素值(如8位灰度值最大為255),灰度值小於設定閾值的畫素點畫素值重新賦值為0.得到如下圖所示影象,借用二進位制概念,超過該閾值即為1,否則為0.

這裡寫圖片描述

2.反二進位制閾值化
反二進位制閾值化顧名思義就是與第一個閾值化型別相反,其數學公式如下:

這裡寫圖片描述

與二進位制閾值化相同的是也要首先指定一個閾值,不同的是在對影象進行閾值化操作時正好與二進位制閾值化相反,當影象畫素點超過這個閾值的時候畫素點重新賦值為0,當畫素值低於該閾值時即賦值為最大值,其閾值化後示意圖如下所示:

這裡寫圖片描述

3.截斷閾值化
截斷閾值化數學模型公式如下:

這裡寫圖片描述

根據給定的畫素值閾值,影象中大於該閾值的畫素點被重新設定為該閾值,而小於該閾值的畫素值保持不變。其閾值化後示意圖如下:

這裡寫圖片描述
4.閾值化為0
該閾值型別數學模型如下:

這裡寫圖片描述

與截斷閾值化不同,閾值化為0型別畫素點的灰度值如果大於該閾值則畫素值不變,如果畫素點的灰度值小於該閾值,則畫素值設定為0.其示意圖如下:

這裡寫圖片描述
5.反閾值化為0
其數學模型如下所示:

這裡寫圖片描述

其原理類似於閾值化為0型別只不過在對影象進行操作時相反,畫素值大於該閾值的畫素重新賦值為0,而小於該閾值的畫素值則保持不變,其示意圖如下所示:

這裡寫圖片描述

threshold()函式原型如下:

double cv::threshold  ( InputArray  src,  
  OutputArray  dst,  
  double  thresh,  
  double  maxval,  
  int  type  
 ) 

引數解釋:
. InputArray src: 輸入影象,可以是Mat型別,影象必須為單通道8位或32位浮點型影象
. OutputArray dst: 輸出影象,與輸入影象尺寸和型別相同
. double thresh: 設定的閾值
. double maxval: 使用THRESH_BINARY和THRESH_BINARY_INV型別的最大值
. int type: 閾值化型別,可以通過ThresholdTypes檢視,下面給出opencv中五種閾值化型別及其對應公式:

這裡寫圖片描述

示例程式如下:

/*
 *程式通過建立trackbar來控制閾值化型別
 *通過調節trackbar來調節
 *其具體閾值化型別如下:
 *0: THRESH_BINARY 二進位制閾值化
 *1: THRESH_BINARY_INV 反二進位制閾值化
 *2: THRESH_TRUNC 截斷閾值化
 *3: THRESH_TOZERO 閾值化為0
 *4: THRESH_TOZERO_INV 反閾值化為0
*/

#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>

using namespace std;
using namespace cv;

//定義全域性變數
Mat g_srcImage, g_srcGrayImage, g_dstImage;

const int typeMaxValue = 4;
int typeValue = 0;
const int binaryMaxValue = 255;

const int thresholdMaxValue = 255;      //閾值的最大值
int thresholdValue = 0;     //閾值的初始值

//定義回撥函式
void thresholdFun(int, void*);

int main()
{
    g_srcImage = imread("lena.jpg");

    //判斷影象是否載入成功
    if(g_srcImage.empty())
    {
        cout << "影象記載失敗!" << endl;
        return -1;
    }
    else
        cout << "影象載入成功!" << endl << endl;

    cvtColor(g_srcImage, g_srcGrayImage, COLOR_RGB2GRAY);   //將影象轉化為灰度圖

    //建立軌跡條及其依附視窗
    namedWindow("影象閾值化處理", WINDOW_AUTOSIZE);

    char threasholdTypeName[20];
    sprintf(threasholdTypeName, "閾值化型別 %d", typeMaxValue);
    createTrackbar(threasholdTypeName, "影象閾值化處理", &typeValue, typeMaxValue, thresholdFun);
    thresholdFun(typeValue, 0);

    char thresholdValueName[20];
    sprintf(thresholdValueName, "閾   值 %", thresholdMaxValue);
    createTrackbar(thresholdValueName, "影象閾值化處理", &thresholdValue, thresholdMaxValue, thresholdFun);
    thresholdFun(thresholdValue, 0);

    waitKey(0);

    return 0;
}

//回撥函式
void thresholdFun(int, void*)
{
    int thresholdType;
    switch(typeValue)
    {
    case 0:
        thresholdType = THRESH_BINARY;
        break;
    case 1:
        thresholdType = THRESH_BINARY_INV;
        break;
    case 2:
        thresholdType = THRESH_TRUNC;
        break;
    case 3:
        thresholdType = THRESH_TOZERO;
        break;
    case 4:
        thresholdType = THRESH_TOZERO_INV;
        break;
    default:
        break;
    }

    //影象閾值化處理
    threshold(g_srcGrayImage, g_dstImage, thresholdValue, binaryMaxValue, thresholdType);   

    imshow("影象閾值化處理", g_dstImage);
}

程式執行結果如下:
這裡寫圖片描述