分段线性拉伸

分段线性拉伸

一、目的与原理

(1)目的:图像增强,增加对比度,为了突出感兴趣的目标或灰度区间,相对抑制那些不感兴趣的灰度区间。常用是三段线性变换,即对一个灰度区间进行线性拉伸,其他的区间被压缩。

(2)原理:本文介绍的是三段线性拉伸,通过设置两个点将线段划分为三段,当k=1的时候,图像没变化,当k<1的时候,图像灰度被抑制,灰度值变小,效果是变得更暗;当k>1的是偶,图像灰度变量,可以通过调节两个点的数据增加图像的对比度。

 

 

 

 

三段线段的斜率:

①    k1 = Y1/X1;

②    k2 = (Y2-Y1)/(X2-X1);

③    k3 = (255-Y2)/(255-X2);

 

 

三段线段的函数,代入(x,y)和k可求得b1,b2,b3:

 

二、步骤

1.设置两个临界点,根据这两个点将直线分成三段

2.根据点计算出三条线段的斜率

3.根据斜率和点,计算出三条线段的y方向的偏移值

4.定义一个大小256的数组,作为表存放每个灰度值在不同线段中的频率

5.根据数组(表)填充到目标图像中

6.显示图像

 

 

三、源码

void dividedLinearStrength(cv::Mat& matInput, cv::Mat& matOutput, float x1, float x2,float y1, float y2)

{

    //计算直线参数
    //L1
    float fK1 = y1 / x1;

    //L2
    float fK2 = (y2 - y1) / (x2- x1);
    float fC2 = y2 - fK2 * x2;

    //L3
    float fK3 = (255.0f - y2) / (255.0f - x2);
    float fC3 = 255.0f - fK3 * 255.0f;


    //建立查询表
    std::vector<unsigned char> loolUpTable(256);
    for (size_t m = 0; m < 256; m++)
    {
        if (m < x1)
        {
            loolUpTable[m] = static_cast<unsigned char>(m * fK1);
        }
        else if (m > x2)
        {
            loolUpTable[m] = static_cast<unsigned char>(m * fK3 + fC3);
        }
        else
        {
            loolUpTable[m] = static_cast<unsigned char>(m * fK2 + fC2);
        }
    }

    //构造输出图像
    matOutput = cv::Mat::zeros(matInput.rows, matInput.cols, matInput.type());

    //灰度映射
    for (int i = 0; i < matInput.rows; i++)
    {
        for (int j = 0; j < matInput.cols; j++)
        {
            Vec3b* pInput = matInput.ptr<Vec3b>(i);
            for (int c = 0; c < matInput.channels(); c++) {
                //查表gamma变换
                matOutput.at<Vec3b>(i, j).val[c] = loolUpTable[pInput[j].val[c]];
            }
        }
    }
}

 

 

 

四、结果图

 

 

posted @ 2021-05-07 09:12  will-z  阅读(1400)  评论(0编辑  收藏  举报