OpenCV灰度值线性变换与分段线性变换

1.公式


1.1线性变换

假设原图像 f(x,y)的灰度范围为[a,b],希望变换后图像 g(x,y)的灰度范围扩展至[c,d],则灰度线性变换可表示为


1.2分段线性变换



2.C++代码实现

#include "cv.h"                         
#include "highgui.h"
#include "cvaux.h"
#include "cxcore.h"
#include "opencv2/opencv.hpp"
#include "opencv2/imgproc.hpp"
#include <iostream>
#include <string>

using namespace cv;
using namespace std;


Mat image;//原图像
Mat target1;//输出图像
Mat target2;

//原始图像灰度范围[a,b]
int a = 255;
int b = 0;


//灰度线性变换,前提是传入的图像是灰度图
void toGray(Mat src, float c, float d)
{
    target1 = Mat::zeros(src.size(), src.type());

    for (int i = 0; i < src.rows; i++)
    {
        for (int j = 0; j < src.cols; j++)
        {
            //线性变换,saturate_cast作用是防止数组越界
            target1.at<uchar>(i, j) = saturate_cast<uchar>(( d-c)/(b-a) * (src.at<uchar>(i, j) -a ) + c);

        }
    }
}

//灰度分段线性变换(这里有个小疑惑,可能写错了,我没有按照公式来写)
void piecewiseToGray(Mat src, float c, int d)
{
    target2 = Mat::zeros(src.size(), src.type());

    for (int i = 0; i < src.rows; i++)
    {
        for (int j = 0; j < src.cols; j++)
        {
            if(target2.at<uchar>(i, j) < c)
                target2.at<uchar>(i, j) = saturate_cast<uchar>( (c/a) * src.at<uchar>(i, j) );
            else if(c < target2.at<uchar>(i, j) && target2.at<uchar>(i, j) < d )
                target2.at<uchar>(i, j) = saturate_cast<uchar>((d - c) / (b - a) * (src.at<uchar>(i, j) - a) + c);
            else
                target2.at<uchar>(i, j) = saturate_cast<uchar>((255-d) / (255-b) * (src.at<uchar>(i, j) - b) + d);
        }
    }

}
//获取原图像灰度范围
void getGrayValue(Mat src)
{
    int value = 0;
    for (int i = 0; i < src.rows; i++)
    {
        for (int j = 0; j < src.cols; j++)
        {
            value =  (int)src.at<uchar>(i, j);
            if (value > b)
                b = value;
            if (value < a)
                a = value;

        }
    }
}


int main()
{
    //加上0表示读入灰度图
    image = imread("D:/opencv/testPic/d1.bmp",0);

    if (image.empty())
    {
        printf("could not load pic!\n");
        return -1;
    }

    namedWindow("src");

    imshow("src", image);

    //获得原图像灰度范围
    getGrayValue(image);

    //输入目标图像灰度范围
    int c = 50;
    int d = 150;

    //根据目标图像灰度范围生成目标图像
    toGray(image, c, d);
    piecewiseToGray(image, c, d);

    //Mat target = 255 - src; //相当于a=-1,b=255,OpenCV中有对Mat的运算符重载,可以直接Mat r = 255 - img或者~img来实现

    namedWindow("target1", WINDOW_AUTOSIZE); 
    namedWindow("target2", WINDOW_AUTOSIZE);

    imshow("target1", target1);  
    imshow("target2", target2);

    imwrite("D:/opencv/testPic/d2.bmp",target1);
    imwrite("D:/opencv/testPic/d3.bmp", target2);

    waitKey(0);

    return 0;

}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值