OpenCV4.5.5学习笔记(九):图像的亮度、对比度调节,离散傅里叶变换dft()

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

笔者本科时候有幸接触了OpenCV3.2.0版本的学习,后因考研压力不得不暂时停下学习的脚步,现在考研任务结束了,未来的导师也是从事的该方向,笔者又开始了新一轮的学习。回来发现OpenCV已经出到了4.5.5版本,遂重新下载新版本并决定记录这一学习历程。由于笔者水平有限,可能有错误之处还请诸位大佬多多包涵并烦请指出,让我们一起学习,共同进步。
首先需要说明的是:我是按着毛星云前辈编写的OpenCV3编程入门进行学习的,我会尽力把星云前辈的程序转成符合OpenCV4.5.5版本的。毛星云前辈于2021年12月11日不幸过世,他是我非常敬仰的一位业内大佬,我也是看他的书才开始接触OpenCV。

一、图像的亮度、对比度调节

1.算子

通用图像处理算子是一种获取一个或多个输入图像并产生输出图像的函数。图像变换可以看作:点算子(像素变换),邻域(基于区域)。
在这种图像处理变换中,每个输出像素的值仅取决于相应的输入像素值(可能还有一些全局收集的信息或参数)。此类运算符的示例包括亮度和对比度调整以及颜色校正和转换。
两个常用的点过程是带常数的乘法和加法:
在这里插入图片描述
参数α和β通常称为增益和偏置参数;参数分别控制对比度和亮度。
可以想到F(x)作为源图像像素和G(x)作为输出图像像素。然后我们可以更方便地把表达式写成:
在这里插入图片描述

2.实现过程

来源于OpenCV官方代码(另:星云前辈那个也可以,他加入了滑动条更易控制)

//-----------------------------------【头文件包含部分】---------------------------------------
//	描述:包含程序所依赖的头文件
//---------------------------------------------------------------------------------------------- 
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>

//-----------------------------------【命名空间声明部分】---------------------------------------
//	描述:包含程序所使用的命名空间
//-----------------------------------------------------------------------------------------------   
using namespace std;
using namespace cv;

int main()
{
    
    
    //我们使用cv::imread加载图像并将其保存在 Mat 对象中:
    Mat image = imread("1.jpg");
    //现在,由于我们将对这个图像进行一些转换,我们需要一个新的 Mat 对象来存储它。此外,我们希望它具有以下功能:初始像素值为零;与原始图像相同的大小和类型
    Mat new_image = Mat::zeros(image.size(), image.type());
    //我们观察到cv::Mat::zeros基于image.size()和image.type()返回一个 Matlab 风格的零初始化器
    double alpha = 1.0; /*< Simple contrast control */
    int beta = 0;       /*< Simple brightness control */
    cout << " Basic Linear Transforms " << endl;
    cout << "-------------------------" << endl;
    cout << "* Enter the alpha value [1.0-3.0]: "; cin >> alpha;
    cout << "* Enter the beta value [0-100]: ";    cin >> beta;
    //使用三重循环访问像素
    for (int y = 0; y < image.rows; y++) {
    
    
        for (int x = 0; x < image.cols; x++) {
    
    
            for (int c = 0; c < image.channels(); c++) {
    
    
                new_image.at<Vec3b>(y, x)[c] =
                    saturate_cast<uchar>(alpha * image.at<Vec3b>(y, x)[c] + beta);
            }
        }
    }
    //最后,我们以通常的方式创建窗口并显示图像。
    imshow("Original Image", image);
    imshow("New Image", new_image);
    waitKey();
}

执行结果(参数α和β分别为2与50):
在这里插入图片描述


二、离散傅里叶变换

1.什么是傅里叶变换

傅立叶变换将图像分解为其正弦和余弦分量。换句话说,它将图像从其空间域转换到其频域。这个想法是任何函数都可以用无限正弦和余弦函数之和来精确逼近。傅里叶变换是一种方法。数学上二维图像傅里叶变换是:
在这里插入图片描述
这里 f 是其空间域中的图像值, F 是其频域中的图像值。转换的结果是复数。可以通过实数图像和虚数图像或通过幅度和相位图像来显示这一点(或是幅度图像和相位图像的形式)。然而,在整个图像处理算法中,只有幅度图像是有用的,因为它包含了我们需要的关于图像几何结构的所有信息。不过,如果您打算以这些形式对图像进行一些修改,然后需要重新转换它,则需要保留这两种形式。
频域中,高频部分代表了图像的细节、纹理,高频部分代表了图像的轮廓。如果使用低通滤波器(只允许低频信号保留),那么结果就剩下轮廓了。所以傅里叶变换在很多图像处理的方面均有不可小觑的作用。

2.傅里叶函数dft()

执行一维或二维浮点数组的正向或反向离散傅里叶变换。
在OpenCV官方文档中是这么写的:
void cv::dft (
InputArray src,
OutputArray dst,
int flags = 0,
int nonzeroRows = 0
)
第一个参数是可能的实数或复数的输入数组,
第二个参数是输出数组,其大小和类型取决于标志,
第三个参数是转换标志,
第四个参数是当参数不为零时,函数假定只有输入数组的第一个 nonzeroRows 行(未设置DFT_INVERSE)或只有输出数组的第一个 nonzeroRows(设置了DFT_INVERSE)包含非零

单通道CSS输出结果如下:
一维数组:
在这里插入图片描述

二维数组:
在这里插入图片描述
输入阵列必须是浮点型,可以是单/双通道,如果是单通道,那么数组必须是实数组,并且输出将以复数共轭对(CCS)的形式保存(上面那个)。如果是双通道,则两个通道分别代表实部和虚部。

这块我回头再仔细研究研究。。。


总结

今天最要命的就是这个傅里叶变换,这里需要研究的地方很多,在笔记中就写这么多吧。

猜你喜欢

转载自blog.csdn.net/qq_43264167/article/details/124320676