OpenCV——分离颜色通道,图像对比度,亮度调整,离散傅里叶变换(10)

离散傅里叶变换
离散傅里叶变换(DFT): 是指傅里叶变换在时域和频域上是离散的,将时域信号的采用变换为在离散傅里叶变换频域上的采用。 形式上,变换两端是有限的,但实际上这两组序列是主值序列。需要对其进行周期延拓成为周期信号再进行变换。
3.1 离散傅里叶变换原理
对图像使用傅里叶变换,就是将其分解成 正弦余弦两部分,也就是将图像从时域(空域)转换到频域。
任意函数都可以表示成无数个正弦和余弦的和的形式,分解工具就是:傅里叶变换。

F ( k , l ) = ∑ i = 0 N − 1 ∑ j = 0 N − 1 f ( i , j ) e − i 2 π ( k i N + l j N ) F(k,l) = \sum\limits_{i=0}^{N-1} \sum\limits_{j=0}^{N-1}f(i,j)e^{-i2\pi(\frac{ki}{N} + \frac{lj}{N})}F (k ,l )=i =0 ∑N −1 ​j =0 ∑N −1 ​f (i ,j )e −i 2 π(N k i ​+N l j ​)
e i x = c o s x + i s i n x e^{ix} = cosx + isinx e i x =c o s x +i s i n x
式中f f f是空间域,而F是频域值,转换之后的频域值是复数,显示转换后的图像需要使用实数图像(real image)+虚数图像(comples image),或者幅度图像+相位图像的形式.在实际的图像处理中,只要有幅度图像就可以了,它几乎包含了我们需要的图像的几何信息。如果需要修改幅度或相位图像来修改原图,需要使用逆傅里叶变换,得到修改后的时域图像了,需要幅度和相位图。
在频域里,对于一幅图像,高频部分代表了图像的细节,纹理信息,低频代表了图像的轮廓信息。。如果对一幅图像使用低通滤波,那么就只剩轮廓信息了。如果图像受到的噪声恰好位于某个特定的频率范围,则可以通过滤波器来恢复原来的图像。
傅里叶变换在图像处理中可以做到图像增强与图像去噪,图像分割之边缘检测,图像特征提取,图像压缩.

3.2 dft()函数
dft函数的作用是 :对一个二维或二维幅点数组进行正向或方向离散傅里叶变换
函数原型: void dft(InputArray src, OutputArray dst, int flags=0, int nonzeroRows=0)

  • 参数一:输入矩阵,可以是实数也可以是虚数;
  • 参数二:输出结果存放处,尺度取决于第三个标志符;
  • 参数三:转换标志符,默认0,取值列表如下:
    OpenCV——分离颜色通道,图像对比度,亮度调整,离散傅里叶变换(10)
  • 参数四:当此参数设置为非0时(最好取想要处理的那一行),函数会假设只有输入矩阵的第一个非零行包含非零元素,或只有输出矩阵的第一个非零行 包含非零元素。这样的处理高效。

下面是一个用dft函数计算两个二维实矩阵卷积的片段

void convolveDFT(InputArray A, InputArray B, OutputArray C)
{

    C.create(abs(A.ROWS - B.rows) + 1, abs(A.cols - B.cols) + 1, A.type());
    Size dftSize;

    dftSize.width = getOptimalDFTSize(A.cols + B.cols - 1);
    dftSize.height = getOptimalDFTSize(A.rows + B.rows -1);

    Mat tempA(dftSize, A.type(), Scalar::all(0));
    Mat tempB(dftSize, B.type(), Scalar::all(0));

    Mat roiA(tempA, Rect(0, 0, A.cols, A.rows));
    A.copyTo(roiA);
    Mat roiB(tempB, Rect(0, 0, B.cols, B.rows));
    B.copyTo(roiB);

    dft(tempA, tempA, 0, A.rows);
    dft(tempB, tempB, 0, B.rows);

    mulSpectrums(tempA, tempB, tempA);

    dft(tempA, tempA, DFT_INVERSE + DFT_SCALE, C.rows);

    tempA(Rect(0, 0, C.cols, C.rows)).copyTo(C);

}

MulSpectrums():计算两个傅里叶频谱的每个元素的乘法,前俩个参数为输入的参数乘法运算,第三个参数是乘法得到的输出结果。
3.3 返回DFT最优尺寸大小:getOptimalDFTSize()函数
getOptimalDFTSize函数返回给定向量尺寸的傅里叶最优尺寸大小。为了提高离散傅里叶变换的速度,需要扩充图像,具体扩充多少由这个函数来决定
原型: int getOptimalDFTSize(int vecsize)
参数是向量的尺寸即图片的rows和cols

3.4 扩充图像边界:copyMakeBorder()函数
void copyMakeBorder(InputArray src, OutputArray dst, int top, int hottom, int left, int right, int borderType, const Scalar& value=Scalar())

  • 参数一:原图像;
  • 参数二:调用此函数后的输出结果,需和原图像尺寸,类型一样,且size应为Size(src.cols + left + right, src.rows + top + bottom).

  • 参数三,四,五,六接下来的四个参数分别是原图像四个方向上的扩充多少个像素,扩充多少像素的边界。

  • 参数七:边界类型,常见取值BORDER_CONSTANT
  • 参数八:默认是Scalar()就是0, 当borderType取BORDER_CONSTANT时,这个参数表示边界值。

3.5 计算二维矢量的幅度:magnitude()函数
void magnitude(InputArray x, InputArray y, OutputArray magnitude)

  • 参数一:表示矢量的浮点型坐标值,也就是实部;
  • 参数二:表示矢量的浮点型坐标值,也就是虚部;
  • 参数三:输出的幅值,它和 第一个参数x有一样的尺寸和类型。
    magnitude()函数的原理:d s t ( I ) = x ( I ) 2 + y ( I ) 2 dst(I) = \sqrt{x(I)^2 + y(I)^2}d s t (I )=x (I )2 +y (I )2 ​

3.6 计算自然对数:log()函数
作用:计算每个数组元素绝对值的自然对数;

  • 参数一:输入图像;
  • 参数二:得到的对数值;
    原理:d s t ( I ) = { l o g ∣ s r c ( I ) ∣ , i f s r c ( I ) ≠ 0 C , o t h e r w i s e dst(I) = \begin{cases}log|src(I)| , if src(I)\ne0 \ C , otherwise\end{cases}d s t (I )={l o g ∣s r c (I )∣,i f s r c (I )​=0 C ,o t h e r w i s e ​

3.7归一化函数:normalize()函数
作用:对矩阵进行归一化
void normalize(InputArray src, OutputArray dst, double alpha=1, double beta=0, int norm_type = NORM_L2, int dtype=01, InputArray mask=noArray())

  • 参数一:原图像;
  • 参数二:调用后的输出结果存放位置;
  • 参数三:归一化后的最大值,默认1;
  • 参数四:同上,默认0;
  • 参数五:归一化类型。有NORM_INF, NORM_L1, NORM_L2, NORM_MINMAX等;
  • 参数六:当此参数为负值时,输出矩阵和原图像有相同的类型。否则,和src有相同的通道数,且此时的图像深度为CV_MAT_DEPTH(dtype);
  • 参数七:可选的操作掩膜,默认noArray();

Original: https://blog.csdn.net/weixin_46417419/article/details/124288761
Author: 思考之路
Title: OpenCV——分离颜色通道,图像对比度,亮度调整,离散傅里叶变换(10)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/703454/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球