3.1 直方图

概念:计算图像单个通道像素的分布。
步骤:把图像灰度级分为n个区间,计算每个区间像素的频数,把频数转化为频率,得到图像的直方图。如果图像有多个通道,分别计算每个通道的直方图。


Mat calcGrayHist02(const Mat &image,int bins)
{   // histogram矩阵
    Mat histogram = Mat::zeros(Size(1, bins), CV_32SC1);
    int step = int(256/bins);
    //图像的高和宽
    int rows = image.rows;
    int cols = image.cols;
    for (int r = 0; r < rows; r++)
    {
        for (int c = 0; c < cols; c++)
        {
            int index = int(image.at<uchar>(r, c));
            index /= step;
            if index>bins-1{index-=index}
            histogram.at<int>(0, index) += 1;
        }
    }
    return histogram;
}

3.2 线性变换

/*

Mat::convertTo(OutputArray m, int rtype, double alpha=1, double beta=0)
m 代表输出矩阵;
参数 rtype 是输出矩阵 m 的数据类型;
参数 alpha 和 beta 分别可以理解为线性变换中的 ? 和 ?。
*/
Mat I = (Mat_<uchar>(2, 2) << 10, 30, 31, 25);
Mat O;
I.convertTo(O, CV_8UC1, 1.5, 3);
//第二种方法
Mat O=1.5*I+20;
//线性变换的第三种方式
//convertScaleAbs(InputArray src, OutputArray dst, double alpha=1, double beta=0)
Mat I = (Mat_<uchar>(2, 2) << 0, 200, 23, 4);
Mat O;
convertScaleAbs(I,O,1.23,10);

3.3 直方图归一化

把图像直方图缩放到指定区间

/*
o(i,j) = o_min+ (img(i,j)-img_min)*((o_max-o_min)/(img_max-img_min))+

void minMaxLoc(InputArray src, double* minVal, double* maxVal=0, Point* minLoc
=0, Point* maxLoc=0, InputArray mask=noArray())

src 输入矩阵
minVal 最小值,double 类型指针
maxVal 最大值,double 类型指针
minLoc 最小值的位置索引,Point 类型指针
maxLoc 最大值的位置索引,Point 类型指针
*/

Mat I = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE);
//找到 I 的最大值和最小值
double Imax, Imin;
minMaxLoc(I, &Imin, &Imax, NULL, NULL);
//设置 Omin和Omax
double Omin = 0, Omax = 255;
//计算 a 和 b
double a = (Omax - Omin) / (Imax - Imin);
double b = Omin - a*Imin;
//线性变换
Mat O;
convertScaleAbs(I, O, a, b);
//显示原图和直方图正规化的效果
imshow("I", I);
imshow("O", O);

归一化函数 normalize

/*
void normalize(InputArray src, OutputArray dst, double alpha=1, double beta=0,
int norm_type=NORM_L2, int dtype=-1, InputArray mask=noArray())
src 输入矩阵
dst 输出矩阵
alpha 系数
beta 系数
norm_type 归一化类型:一范数、二范、无穷大范数、NORM_MINMAX(先把像素值缩放到0~1之间,再乘以目标区间范围(最大减最小),最后加上目标区间的最小值。
dtype 数据类型
*/
#include<opencv2/core.hpp>
#include<opencv2/imgproc.hpp>
#include<opencv2/highgui.hpp>
using namespace cv;
int main(int argc, char*argv[])
{
    //输入图像
    Mat src = imread(argv[1], CV_LOAD_IMAGE_ANYCOLOR);
    if (!src.data)
        return -1;
    //直方图正规化
    Mat dst;
    normalize(src, dst, 255-20, 20, NORM_MINMAX, CV_8U);
}

3.4 Gamma变换

Gamma变换用来调节图像的亮度,先把图像I除以255得到I1,使得像素值归一化到0~1之间,再求I1的r次方。当r<1时,图像整体变亮;当r>1时,图像整体变暗。

/*
Gamma变换公式
img = (img/255.0)**y 
对矩阵中的每一个值进行幂运算:
void pow(InputArray src, double power, OutputArray dst)

*/
//输入图像矩阵
Mat I = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE);
//灰度值归一化
Mat fI;
I.convertTo(fI, CV_64F, 1.0 / 255, 0);
//伽马变换
double gamma = 0.5;
Mat O;
pow(fI, gamma, O);//注意 O 和 fI 有相同的数据类型
//显示伽马变换后的效果
imshow("O",O);
O.convertTo(O, CV_8U, 255,0);

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部