天天看點

OTSU算法 -- 三通道門檻值分割otsu 應用otsu 算法确定圖像前景和背景門檻值分别根據r,g,b三通道的門檻值分離圖像,再merge(r,g,b)Example編譯環境More

otsu 應用

依據像素值的權重,分離圖像前景和背景。

otsu 算法确定圖像前景和背景門檻值

// 關鍵之處是處理像素值的權重占比
// Otsu algorithm
int Otsu(const Mat src)
{
    int height = src.rows;
    int width  = src.cols;
    int size   = height * width;
    unsigned char* data = src.data;

    // histogram    
    long histogram[] = {  };

    // pixel gray value count
    for (int i = ; i < height; i++)
    {
        unsigned char* p = data + i * src.step;
        for (int j = ; j < width; j++)
        {
            histogram[int(*p++)]++;
        }
    }

    /*
     * sum0:前景的灰階總和     sum1:背景灰階總和
     * cnt0:前景像素的總個數   cnt1:背景像素的總個數
     * w0:  前景像素個數占整幅圖像像素的比例
     * w1:  背景像素個數占整幅圖像像素的比例
     * u0:  前景的平均灰階     u1: 背景的平均灰階
     * variance: 類間方差
     */
    long sum0 = , sum1 = ;
    long cnt0 = , cnt1 = ;
    double w0 = , w1 = ;
    double u0 = , u1 = ;
    double variance = ;

    /*
     * u: 整幅圖像的總平均灰階
     * maxVariance: 最大類間方差
     */
    int i, j;
    double u = ;
    double maxVariance = ;

    // 目标門檻值
    int threshold = ;

    // 依次周遊每個像素
    for (i = ; i < ; i++)
    {
        // 初始化
        sum0 = ;  sum1 = ;
        cnt0 = ;  cnt1 = ;
        u0 = ;  u1 = ;
        w0 = ;  w1 = ;

        // 前景
        for (j = ; j < i; j++)
        {
            cnt0 += histogram[j];
            sum0 += (long)(j * histogram[j]);
        }

        // u0:前景平均灰階  w0:前景像素點數量占全部像素點的比例
        u0 = (double)(sum0 *  / cnt0);
        w0 = (double)(cnt0 *   / size);


        // 背景
        for (j = i; j <= ; j++)
        {
            cnt1 += histogram[j];
            sum1 += (long)(j * histogram[j]);
        }

        // u1:背景平均灰階  w1:背景像素點數占全部像素點的比例
        u1 = (double)(sum1 *  / cnt1);
        w1 =  - w0;

        // u:圖像平均灰階   variancn:類間方差
        //u = u0 * w0 + u1 * w1;
        variance = w0 * w1 *  (u0 - u1) * (u0 - u1);

        if (variance > maxVariance)
        {
            maxVariance = variance;
            threshold = i;
        }
    }

    return (threshold);
}
           

分别根據r,g,b三通道的門檻值分離圖像,再merge(r,g,b)

  1. 圖像分離可采用 opencv split()函數,将Mat格式圖像轉換為vector格式的圖像。
  2. 合并r, g, b則采用相反的操作,使用opencv merge()函數,将vector格式的圖像合并成Mat格式的完整圖像。
// splite input image
void ThresholdByOtsu(const Mat src,  Mat & Dst)
{
    // split Mat src to Vector src_v
    vector<Mat>src_v;
    split(src, src_v);

    imshow("r_src", src_v[]);
    imshow("g_src", src_v[]);
    imshow("b_src", src_v[]);

    // save origin image r, g, b
    imwrite((g_kOutputPath + "r_src.tiff"), src_v[]);
    imwrite((g_kOutputPath + "g_src.tiff"), src_v[]);
    imwrite((g_kOutputPath + "b_src.tiff"), src_v[]);

    // get threshold
    int threshold_r, threshold_g, threshold_b = ;
    threshold_r = Otsu(src_v[]);
    threshold_g = Otsu(src_v[]);
    threshold_b = Otsu(src_v[]);

    // output r, g, b threshold after otsu.
    cout << "after otsu:" << endl;
    cout << "------------------" << endl;
    cout << "threshold_r:" << threshold_r << endl;
    cout << "threshold_g:" << threshold_g << endl;
    cout << "threshold_b:" << threshold_b << endl;

    // 二值化
    vector<Mat>out_v;
    threshold(src_v[], src_v[], threshold_r, , CV_THRESH_BINARY);
    threshold(src_v[], src_v[], threshold_g, , CV_THRESH_BINARY);
    threshold(src_v[], src_v[], threshold_b, , CV_THRESH_BINARY);

    // save r, g, b image after otsu
    imwrite((g_kOutputPath + "r_otsu.tiff"), src_v[]);
    imwrite((g_kOutputPath + "g_otsu.tiff"), src_v[]);
    imwrite((g_kOutputPath + "b_otsu.tiff.tiff"), src_v[]);

    // merge three chanels image with r_otsu, g_otsu, b_otsu
    merge(src_v, Dst);

    // clear
    src_v.clear();
}
           

Example

輸入圖像: http://sipi.usc.edu/database/download.php?vol=misc&img=4.2.04

1. 美麗的Lena女士

OTSU算法 -- 三通道門檻值分割otsu 應用otsu 算法确定圖像前景和背景門檻值分别根據r,g,b三通道的門檻值分離圖像,再merge(r,g,b)Example編譯環境More

2. 原圖像 R, G, B 三通道分離,依次輸出r,g,b單通道圖像如下

OTSU算法 -- 三通道門檻值分割otsu 應用otsu 算法确定圖像前景和背景門檻值分别根據r,g,b三通道的門檻值分離圖像,再merge(r,g,b)Example編譯環境More
OTSU算法 -- 三通道門檻值分割otsu 應用otsu 算法确定圖像前景和背景門檻值分别根據r,g,b三通道的門檻值分離圖像,再merge(r,g,b)Example編譯環境More
OTSU算法 -- 三通道門檻值分割otsu 應用otsu 算法确定圖像前景和背景門檻值分别根據r,g,b三通道的門檻值分離圖像,再merge(r,g,b)Example編譯環境More

3. Otsu() 分别計算圖像門檻值得到r, g, b單通道門檻值

channel threshold
r 113
g 102
b 162

3. 原圖像R,G,B三通道,otsu門檻值二值化,依次輸出如下圖像

OTSU算法 -- 三通道門檻值分割otsu 應用otsu 算法确定圖像前景和背景門檻值分别根據r,g,b三通道的門檻值分離圖像,再merge(r,g,b)Example編譯環境More
OTSU算法 -- 三通道門檻值分割otsu 應用otsu 算法确定圖像前景和背景門檻值分别根據r,g,b三通道的門檻值分離圖像,再merge(r,g,b)Example編譯環境More
OTSU算法 -- 三通道門檻值分割otsu 應用otsu 算法确定圖像前景和背景門檻值分别根據r,g,b三通道的門檻值分離圖像,再merge(r,g,b)Example編譯環境More

4. 将二值化的R,G,B三通道進行merge操作,輸出OTSU的最終結果

OTSU算法 -- 三通道門檻值分割otsu 應用otsu 算法确定圖像前景和背景門檻值分别根據r,g,b三通道的門檻值分離圖像,再merge(r,g,b)Example編譯環境More

編譯環境

dev version
os window10
image library opencv3.2.0
compiler Virtual Studio 2015

More

(全文完)