影象處理-灰度變換函式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
版權宣告:本文為博主原創文章,轉載請附上博文連結!