Opencv3笔记7——图像对比度和FFT

图像对比度,亮度值调整

理论公式

g(x)=a×f(x)+b g ( x ) = a × f ( x ) + b

  • f(x)表示源图像像素
  • g(x)表示输出图像像素
  • a a 表示增益
  • b表示偏置,用来控制图像的亮度
#include 
#include 
#include 
using namespace std;
using namespace cv;
static void on_ConstrasAndBright(int, void *);
//---------------------------【全局变量声明部分】--------
//     描述:全局变量声明
//---------------------------------------------------
int g_nContrastValue;      //对比度值
int g_nBrightValue;        //亮度值
Mat g_srcImage, g_dstImage;
int main()
{
       //读取输入图像
       g_srcImage = imread("1.jpg");
       if (!g_srcImage.data)
       {
              printf("读取图片错误,请确定目录下是否有imread函数指定图片存在~!");
              return false;
       }
       g_dstImage = Mat::zeros(g_srcImage.size(), g_srcImage.type());
       //设定对比度和亮度的初值
       g_nContrastValue = 80;
       g_nBrightValue = 80;
       //创建效果窗口
       namedWindow("【效果图窗口】", 1);

       //创建轨迹条
       createTrackbar("对比度:", "【效果图窗口】", &g_nContrastValue, 300, on_ConstrasAndBright);
       createTrackbar("亮  度:", "【效果图窗口】", &g_nBrightValue, 200, on_ConstrasAndBright);
       // 进行回调函数初始化
       on_ConstrasAndBright(g_nContrastValue, 0);
       on_ConstrasAndBright(g_nBrightValue, 0);
       //按下q,程序退出
       while (char(waitKey(1)) != 'q') {}
       return 0;
}
static void on_ConstrasAndBright(int, void *)
{
       //创建窗口
       namedWindow("【原始图窗口】", 1);
       for (int y = 0; y < g_srcImage.rows; y++)
       {
              for (int x = 0; x < g_srcImage.cols; x++)
              {
                     for (int c = 0; c < 3; c++)
                     {
                           g_dstImage.at(y, x)[c] = saturate_cast((g_nContrastValue*0.01)*(g_srcImage.at(y, x)[c]) + g_nBrightValue);
                     }
              }
       }
       imshow("【原始图窗口】", g_srcImage);
       imshow("【效果图窗口】", g_dstImage);
}

离散傅里叶变换

离散傅里叶变换(Discrete Fourier Transform ,DFT)是指傅里叶变换在时域和频域上都呈现出离散的形式,将时域信息的采样变换为离散时间傅里叶变换频域采样

离散傅里叶变换的原理

将图像从空间域转换到频域
理论基础:任一函数都可以表示为无数个正弦和余弦函数的和的形式

F(k,l)=i=0N1j=0N1f(i,j)ei2π(kiN+ljN)eix=cosx+isinx F ( k , l ) = ∑ i = 0 N − 1 ∑ j = 0 N − 1 f ( i , j ) e − i 2 π ( k i N + l j N ) e i x = c o s x + i s i n x

  • f是空间域的值
  • F是频域值
  • 变换完以后的结果是需要使用实数图像(real image)加虚数图像(complex image)或幅度图像(magitude image)加相位图像(phase image)

高频部分代表了图像的细节,纹理信息.低频部分代表图像的轮廓信息.
用途:图像的增强与图像去噪,图像分割之边缘检测,图像特征提取,图像压缩

dft()函数

void dft(InputArray src, OutputArray dst,int flags = 0,int nonzeroRows = 0)
  • InputArray 类型的src,输入的矩阵,可以为实数或者虚数
  • OutputArray 类型dst,函数调用后的运算结果存在这里,其尺寸和类型却决于标识符,也就是flags
  • int类型的flags,默认值为0
    Opencv3笔记7——图像对比度和FFT_第1张图片

返回DFT最优尺寸大小:getOptimalDFTSIze()函数

返回给定向量尺寸的傅里叶最优尺寸大小

int getOptimalDFTSize(int vecsize)

扩充图像边界:copyMakeBorder()函数

void copyMakeBorder(InputArray src, OutputArray dst,int top,int bottom,int left,int right,int borderType,const Scalar & value = Scalar())
  • InputArray 类型的src,输入图像
  • OutputArray类型的dst,用于存放函数调用后的输出结果
  • top,bottom,left,right分表表示在原图像四个方向上扩充多少像素
  • borderType 边界类型
  • const Scalar 类型的value

计算二维矢量的幅值:magnitude()函数

void magnitude(InputArray x,InputArray y,OutputArray magnitude)
  • InputArray 类型的x,表示矢量的浮点型x坐标值
  • InputArray类型的y,表示矢量浮点型y坐标值
  • OutputArray类型的magnitude输出的幅值,与x同样的尺寸和类型

dst(I)=x(I)2+y(I)2 d s t ( I ) = x ( I ) 2 + y ( I ) 2

计算自然对数:log()函数

void log(InputArray src,OutputArray dst)

这里写图片描述

矩阵归一化:normalize()函数

void normalize(InputArray src, OutputArray dst,double alpha = 1, double beta = 0, int norm_type NORM_L2, int dtype = -1,InputArray mask = noArray())
  • InputArray 类型的src,输入图像
  • OutputArray 类型的dst,调用函授后的结果存在这里
  • double 类型的alpha,归一化为最大值,默认值为1
  • double 类型的beta ,归一化后的最大值,默认值为0
  • int类型的norm_type
  • int类型的dtype默认值为-1,
  • InputArray类型的mask,可选的操作掩码,默认值为noArray()
//--------------------------【头文件、命名空间包含部分】-----------------
//     描述:包含程序所使用的头文件和命名空间
//------------------------------------------------------------------
#include 
#include 
#include 
#include 
using namespace cv;
using namespace std;
//----------------------------【main函数】----------------------------
//     描述:程序入口
//------------------------------------------------------------------
int main()
{
       Mat srcImage = imread("1.jpg", 0);
       if (!srcImage.data)
       {
              printf("读取图片错误,请确定目录下是否有imread函数指定的图片存在~!\n");
              return false;
       }
       imshow("【原始图像】", srcImage);
       // 将输入图像延扩到最佳的尺寸,边界用0补充
       int m = getOptimalDFTSize(srcImage.rows);
       int n = getOptimalDFTSize(srcImage.cols);
       //将添加的像素初始化为0
       Mat padded;
       copyMakeBorder(srcImage, padded, 0, m - srcImage.rows, 0, n - srcImage.cols, BORDER_CONSTANT, Scalar::all(0));
       // 为傅里叶变换的结果分配存储空间
       // 将planes数组组合成一个多通道的数组complexI
       Mat planes[] = { Mat_<float>(padded),Mat::zeros(padded.size(),CV_32F) };
       Mat complexI;
       merge(planes, 2, complexI);
       //进行就地离散傅里叶变换
       dft(complexI, complexI);

       //将复数转化为幅值
       split(complexI, planes);
       magnitude(planes[0], planes[1], planes[0]);
       Mat magnitudeImage = planes[0];
       // 进行对数尺度(logarithmic scale)缩放
       magnitudeImage += Scalar::all(1);
       log(magnitudeImage, magnitudeImage);     //求自然对数
       // 剪切和重分布幅度图像象限
       // 若有奇数行奇数列,进行频谱剪切
       magnitudeImage = magnitudeImage(Rect(0, 0, magnitudeImage.cols&-1, magnitudeImage.rows&-2));
       //重新排列傅里叶图像中的象限,使得原点位于图像的中心
       int cx = magnitudeImage.cols / 2;
       int cy = magnitudeImage.rows / 2;
       Mat q0(magnitudeImage, Rect(0, 0, cx, cy));            //ROI区域的左上
       Mat q1(magnitudeImage, Rect(cx, 0, cx, cy));    //ROI区域的右上
       Mat q2(magnitudeImage, Rect(0, cy, cx, cy));    //ROI区域的左下
       Mat q3(magnitudeImage, Rect(cx, cy, cx, cy));   //ROI区域的右下

       //交换象限 左上右下
       Mat temp;
       q0.copyTo(temp);
       q3.copyTo(q0);
       temp.copyTo(q3);
       //交换象限 右上左下
       q1.copyTo(temp);
       q2.copyTo(q1);
       temp.copyTo(q2);
       //归一化,用0到1之间的浮点数将矩阵变换为可视的图像格式
       normalize(magnitudeImage, magnitudeImage, 0, 1, NORM_MINMAX);
       //显示效果图
       imshow("频谱幅值", magnitudeImage);
       waitKey();
       return 0;
}

Opencv3笔记7——图像对比度和FFT_第2张图片
Opencv3笔记7——图像对比度和FFT_第3张图片

你可能感兴趣的:(Opencv,机器视觉)