图像处理-灰度变换函数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 
版权声明:本文为博主原创文章,转载请附上博文链接!

猜你喜欢

转载自blog.csdn.net/cys119/article/details/83754299