在matlab中imadjust原型如下:
g = imadjust(f,[low_in high_in], [low_out high_out], gamma)
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函数很简单,其形式:
stretchlim在matlab原型如下:
Low_High = stretchlim(f, tol)
其中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)
imhist用于处理图像直方图,其中f为输入图像,h为直方图 h(rk) ,b是用来形成直方图的“统计堆栈”的数目,默认值是256。“统计堆栈”仅仅是灰度的一部分,例如我们在处理一个uint8类型的图像时,设置b=2,那么灰度范围就被分为两个部分:0~127和128~255。因此直方图就有两个值h(1)等于[0,127]间隔内的像素个数,h(2)等于[128,255]内的像素个数。
接来下给出上述函数的c++的实现方法,具体内容请参看这里,有关图片读写问题参看上一篇博文。
imhist.h
#pragma once
#include "UnsignedImage.h"
#include
namespace HW
{
std::vector<int> imhist(const UnsignedImage& image, unsigned int n=256);
}
imhist.cpp
#include "imhist.h"
#include "HWImageProcess.h"
#include
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;
}
stretchlim.h
#pragma once
#include "UnsignedImage.h"
#include
namespace HW
{
std::vector<double> strechlim(const UnsignedImage& image, double tol_low = 0.01, double tol_high = 0.99);
}
stretchlim.cpp
#include "stretchlim.h"
#include "imhist.h"
#include "HWImageProcess.h"
#include
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;
}
imadjust.h
#pragma once
#include "UnsignedImage.h"
#include
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);
}
imadjust.cpp 从代码中可以看到,对像素值进行三种情况的不同处理。
#include "imadjust.h"
#include "HWImageProcess.h"
#include
#include
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);
}