1. 程式人生 > >影象處理-灰度變換函式imadjust和stretchlim

影象處理-灰度變換函式imadjust和stretchlim

imadjust
在matlab中imadjust原型如下:

g = imadjust(f,[low_in high_in], [low_out high_out], gamma)
1
f表示一張灰度圖片,此函式將f的灰度值映象到g中的新值,也就是將low_in與high_in之間的值對映到low_out和high_out之間的值。 
其中low_in以下與high_in以上的值可以被截去,也就是說小於low_in的值都被對映為low_out,大於high_in的值都被對映為high_out。 
對於imadjust來說,處理影象f和gamma之外,其他所有引數值都限定為0到1之間。 
對於gamma引數,下圖可以進行說明,其中中間部分曲線就是由gamma函式生成的。 

gamma函式很簡單,其形式: 
s=crγ
s=crγ

根據γγ值的不同,其函式曲線不同,下圖是不同γγ值的情況 

stretchlim
stretchlim在matlab原型如下:

Low_High = stretchlim(f, tol)
1
其中f是一張灰度圖片,tol如果是一個兩元素向量[low_frac high_frac],指定了影象低和高畫素的飽和度百分比,tol如果是一個標量,那麼low_frac = tol, high_frac = 1 - low_frac。tol預設值是[0.01 0.99]。簡單的說,就是計算兩個閾值,(預設情況)其中low代表小於這個值的畫素佔整張圖片的1%,其中high代表大於這個值的畫素佔整張圖片的1-0.99=1%。 
通常利用stretchlim配合imadjust來自動地提高圖片的對比度,而不關心引數高低的處理。 
因為在利用c++實現stretchlim時用到了imhist,因此這裡再說說imhist,matlab原型

h = imhist(f, b)
1
imhist用於處理影象直方圖,其中f為輸入影象,h為直方圖h(rk)h(rk),b是用來形成直方圖的“統計堆疊”的數目,預設值是256。“統計堆疊”僅僅是灰度的一部分,例如我們在處理一個uint8型別的影象時,設定b=2,那麼灰度範圍就被分為兩個部分:0~127和128~255。因此直方圖就有兩個值h(1)等於[0,127]間隔內的畫素個數,h(2)等於[128,255]內的畫素個數。

C++ Code
接來下給出上述函式的c++的實現方法,具體內容請參看這裡,有關圖片讀寫問題參看上一篇博文。

imhist
imhist.h

#pragma once
#include "UnsignedImage.h"
#include <vector>
namespace HW
{
    std::vector<int> imhist(const UnsignedImage& image, unsigned int n=256);
}
1
2
3
4
5
6
7
imhist.cpp

#include "imhist.h"
#include "HWImageProcess.h"
#include <iostream>
std::vector<int> HW::imhist(const UnsignedImage& image, unsigned int n /*= 256*/)
{
    std::vector<int> ans(n, 0);
    uint8_t maxGrayValue = 255;
    double a = 1.0*(n - 1) / maxGrayValue;
    int index = 0;
    LOOP_EACH_PIXEL_IMAGE(image)
    {
        index = image.At(i, j, k) * a;
        ++ans[index];
    }
    return ans;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
stretchlim
stretchlim.h

#pragma once

#include "UnsignedImage.h"
#include <vector>
namespace HW
{
    std::vector<double> strechlim(const UnsignedImage& image, double tol_low = 0.01, double tol_high = 0.99);
}
1
2
3
4
5
6
7
8
stretchlim.cpp

#include "stretchlim.h"
#include "imhist.h"
#include "HWImageProcess.h"
#include <numeric>

std::vector<double> HW::strechlim(const UnsignedImage& image, double tol_low/*=0.01*/, double tol_high/*=0.99*/)
{
    double maxGrayValue = 255.0;

    auto hist = imhist(image);
    auto toltalSize = std::accumulate(hist.begin(), hist.end(), 0);
    std::vector<double> lowHigh(2);
    lowHigh[0] = 0;
    lowHigh[1] = 1;
    // find the first position which \sum_{i=0}^p >= tol_low
    for (int i = 0; i < hist.size(); ++i)
    {
        auto sum = std::accumulate(hist.begin(), hist.begin() + i, 0.0);
        if (GE(sum / toltalSize, tol_low))  // > tol_low
        {
            lowHigh[0] = i / maxGrayValue;
            break;
        }
    }
    // find the first position which \sum_{i=0}^p >= tol_high
    for (int i = 0; i < hist.size(); ++i)
    {
        auto sum = std::accumulate(hist.rbegin(), hist.rbegin() + i, 0.0);
        if (GE(sum / toltalSize, 1 - tol_high)) // > tol_high
        {
            lowHigh[1] = 1.0 - i / maxGrayValue;
            break;
        }
    }
    return lowHigh;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
imadjust
imadjust.h

#pragma once
#include "UnsignedImage.h"
#include <vector>
namespace HW
{
    /*
        s=cr^g
        c normal is 1
    */  
     double gamma(double r, double g,double c=1.0);
     UnsignedImage imadjust(const UnsignedImage& f, double low_in, double high_in,
        double low_out, double high_out, double gammaScale=1.0);
     UnsignedImage imadjust(const UnsignedImage& f, const std::vector<double> low_high,
         double low_out, double high_out, double gammaScale = 1.0);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
imadjust.cpp 從程式碼中可以看到,對畫素值進行三種情況的不同處理。

#include "imadjust.h"
#include "HWImageProcess.h"
#include <cmath>
#include <assert.h>

double HW::gamma(double r, double g, double c )
{
    return c*std::pow(r, g);
}
UnsignedImage HW::imadjust(const UnsignedImage& f, double low_in, double high_in,
    double low_out, double high_out, double gammaScale)
{
    assert(low_in < high_in);
    double maxGrayValue = 255.0;    // unsigned char is 255 only
    double slope =  (high_out - low_out)/ (high_in - low_in);
    double p = 0.0;
    double result = 0.0;
    UnsignedImage g(f);
    LOOP_EACH_PIXEL(f.GetHeight(), f.GetWidth(), f.GetComponents())
    {
        p = f.At(i, j, k) / maxGrayValue;

        if (LT(p,low_in))   //[p,low_in, high_in]
        {
            result = low_out;
        }
        else if (GE(p,low_in) && LE(p,high_in)) //[low_in,p,high_in]
        {
            result = (p - low_in) * slope + low_out;
            result = gamma(result, gammaScale);
        }
        else if (GT(p,high_in)) //[low_in, high_in, p]
        {
            result = high_out;
        }
        g.At(i, j, k) = unsigned char(round(result * maxGrayValue));
    }
    return g;
}
UnsignedImage HW::imadjust(const UnsignedImage& f, const std::vector<double> low_high,
    double low_out, double high_out, double gammaScale /* = 1.0 */)
{
    assert(low_high.size() == 2);

    return HW::imadjust(f, low_high[0], low_high[1], low_out, high_out, gammaScale);
}
--------------------- 
作者:芥末的無奈 
來源:CSDN 
原文:https://blog.csdn.net/weiwei9363/article/details/51691826 
版權宣告:本文為博主原創文章,轉載請附上博文連結!