c++ opencv数字图像处理:频率域滤波--拉普拉斯滤波(锐化)

本文详细介绍了如何利用OpenCV库在C++环境中对图像进行傅里叶变换和拉普拉斯滤波操作。首先,通过调用OpenCV的dft函数进行傅里叶变换,并展示频谱图。接着,应用拉普拉斯算子对频谱图进行滤波,然后进行逆傅里叶变换。最后,将滤波后的图像与原始图像相加得到最终结果。代码示例包括了完整的拉普拉斯滤波流程,适合对图像处理感兴趣的读者参考学习。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


前言

数字图像处理c++ opencv(VS2019 opencv4.53)持续更新


一、拉普拉斯

频率域中的拉普拉斯:
在这里插入图片描述


二、代码

主代码:

#include<iostream>
#include<opencv2/opencv.hpp>
#include "MY_DFT.h"
#include <math.h>

#define M_PI 3.14159265358979323846

using namespace cv;
using namespace std;

int main()
{
	Mat image, image_gray, image_output, image_transform;   //定义输入图像,灰度图像,输出图像
	image = imread("lena.png");  //读取图像;
	if (image.empty())
	{
		cout << "读取错误" << endl;
		return -1;
	}
	imshow("image", image);

	cvtColor(image, image_gray, COLOR_BGR2GRAY); //转换为灰度图
	imshow("image_gray", image_gray); //显示灰度图

	//1、傅里叶变换,image_output为可显示的频谱图,image_transform为傅里叶变换的复数结果
	My_DFT(image_gray, image_output, image_transform);
	imshow("image_output", image_output);

	//2、拉普拉斯滤波
	Mat planes[] = { Mat_<float>(image_output), Mat::zeros(image_output.size(),CV_32F) };
	split(image_transform, planes);//分离通道,获取实部虚部
	Mat image_transform_real = planes[0];
	Mat image_transform_imag = planes[1];

	int core_x = image_transform_real.rows / 2;//频谱图中心坐标
	int core_y = image_transform_real.cols / 2;
	float h;
	float D;  //距离中心距离
	for (int i = 0; i < image_transform_real.rows; i++)
	{
		for (int j = 0; j < image_transform_real.cols; j++)
		{
			D = (i - core_x) * (i - core_x) + (j - core_y) * (j - core_y);
			h = -4 * M_PI * M_PI * D;
			image_transform_real.at<float>(i, j) = image_transform_real.at<float>(i, j) * h;
			image_transform_imag.at<float>(i, j) = image_transform_imag.at<float>(i, j) * h;

		}
	}
	planes[0] = image_transform_real;
	planes[1] = image_transform_imag;
	Mat image_transform_ilpf;//定义拉普拉斯滤波结果
	merge(planes, 2, image_transform_ilpf);

	//3、傅里叶逆变换
	Mat iDft[] = { Mat_<float>(image_output), Mat::zeros(image_output.size(),CV_32F) };
	idft(image_transform_ilpf, image_transform_ilpf);//傅立叶逆变换
	split(image_transform_ilpf, iDft);//分离通道,主要获取0通道
	magnitude(iDft[0], iDft[1], iDft[0]); //计算复数的幅值,保存在iDft[0]
	normalize(iDft[0], iDft[0], 0, 1, NORM_MINMAX);//归一化处理
	imshow("idft", iDft[0]);//显示逆变换图像

	//4、标定
	iDft[0].convertTo(iDft[0], CV_8U, 255/1.0 ,0);
	Mat image_result(iDft[0].size() , CV_8U);
	for (int i = 0; i < iDft[0].rows; i++)
	{
		for (int j = 0; j < iDft[0].cols; j++)
		{
			image_result.at<uchar>(i, j) = saturate_cast<uchar>(image_gray.at<uchar>(i, j) + iDft[0].at<uchar>(i, j));
		}
	}
	imshow("image_result", image_result);//标定结果


	waitKey(0);  //暂停,保持图像显示,等待按键结束
	return 0;
}

傅里叶变换代码(.h文件):

#pragma once
#include<iostream>
#include<opencv2/opencv.hpp>
#include<cmath>

using namespace cv;
using namespace std;

void My_DFT(Mat input_image, Mat& output_image, Mat& transform_array);

傅里叶变换代码(.cpp文件):

#include "MY_DFT.h"

//傅里叶变换得到频谱图和复数域结果
void My_DFT(Mat input_image, Mat& output_image, Mat& transform_image)
{
	//1.扩展图像矩阵,为2,3,5的倍数时运算速度快
	int m = getOptimalDFTSize(input_image.rows);
	int n = getOptimalDFTSize(input_image.cols);
	copyMakeBorder(input_image, input_image, 0, m - input_image.rows, 0, n - input_image.cols, BORDER_CONSTANT, Scalar::all(0));

	//2.创建一个双通道矩阵planes,用来储存复数的实部与虚部
	Mat planes[] = { Mat_<float>(input_image), Mat::zeros(input_image.size(), CV_32F) };

	//3.从多个单通道数组中创建一个多通道数组:transform_image。函数Merge将几个数组合并为一个多通道阵列,即输出数组的每个元素将是输入数组元素的级联
	merge(planes, 2, transform_image);

	//4.进行傅立叶变换
	dft(transform_image, transform_image);

	//5.计算复数的幅值,保存在output_image(频谱图)
	split(transform_image, planes); // 将双通道分为两个单通道,一个表示实部,一个表示虚部
	Mat transform_image_real = planes[0];
	Mat transform_image_imag = planes[1];

	magnitude(planes[0], planes[1], output_image); //计算复数的幅值,保存在output_image(频谱图)

	//6.前面得到的频谱图数级过大,不好显示,因此转换
	output_image += Scalar(1);   // 取对数前将所有的像素都加1,防止log0
	log(output_image, output_image);   // 取对数
	normalize(output_image, output_image, 0, 1, NORM_MINMAX); //归一化

	//7.剪切和重分布幅度图像限
	output_image = output_image(Rect(0, 0, output_image.cols & -2, output_image.rows & -2));

	// 重新排列傅里叶图像中的象限,使原点位于图像中心
	int cx = output_image.cols / 2;
	int cy = output_image.rows / 2;
	Mat q0(output_image, Rect(0, 0, cx, cy));   // 左上区域
	Mat q1(output_image, Rect(cx, 0, cx, cy));  // 右上区域
	Mat q2(output_image, Rect(0, cy, cx, cy));  // 左下区域
	Mat q3(output_image, Rect(cx, cy, cx, cy)); // 右下区域

	  //交换象限中心化
	Mat tmp;
	q0.copyTo(tmp); q3.copyTo(q0); tmp.copyTo(q3);//左上与右下进行交换
	q1.copyTo(tmp); q2.copyTo(q1); tmp.copyTo(q2);//右上与左下进行交换


	Mat q00(transform_image_real, Rect(0, 0, cx, cy));   // 左上区域
	Mat q01(transform_image_real, Rect(cx, 0, cx, cy));  // 右上区域
	Mat q02(transform_image_real, Rect(0, cy, cx, cy));  // 左下区域
	Mat q03(transform_image_real, Rect(cx, cy, cx, cy)); // 右下区域
	q00.copyTo(tmp); q03.copyTo(q00); tmp.copyTo(q03);//左上与右下进行交换
	q01.copyTo(tmp); q02.copyTo(q01); tmp.copyTo(q02);//右上与左下进行交换

	Mat q10(transform_image_imag, Rect(0, 0, cx, cy));   // 左上区域
	Mat q11(transform_image_imag, Rect(cx, 0, cx, cy));  // 右上区域
	Mat q12(transform_image_imag, Rect(0, cy, cx, cy));  // 左下区域
	Mat q13(transform_image_imag, Rect(cx, cy, cx, cy)); // 右下区域
	q10.copyTo(tmp); q13.copyTo(q10); tmp.copyTo(q13);//左上与右下进行交换
	q11.copyTo(tmp); q12.copyTo(q11); tmp.copyTo(q12);//右上与左下进行交换

	planes[0] = transform_image_real;
	planes[1] = transform_image_imag;
	merge(planes, 2, transform_image);//将傅里叶变换结果中心化
}

结果:
在这里插入图片描述

### 使用 OpenCV 进行拉普拉斯锐化处理 拉普拉斯算子是一种用于检测图像边缘的二阶导数滤波器,在图像锐化方面也有广泛应用。通过突出显示图像中的高频成分(如边界),可以显著提高图像的视觉清晰度。 #### 拉普拉斯锐化的原理 拉普拉斯锐化基于拉普拉斯算子,该算子能够强调图像中的局部变化区域。具体来说,先利用拉普拉斯卷积核对输入图像执行卷积操作得到一个表示梯度强度的地图;再将此地图加回到原图上实现锐化效果[^1]。 对于彩色图片而言,通常会分别对三个颜色通道(RGB)做同样的变换后再合成最终的结果。下面给出完整的Python代码示例: ```python import cv2 import numpy as np def laplacian_sharpen(image): # 转换成浮点型以便于后续运算 float_image = image.astype(float) # 定义拉普拉斯模板 kernel = np.array([[0, 1, 0], [1,-4, 1], [0, 1, 0]]) # 对各通道单独应用拉普拉斯滤波 channels = [] for ch in range(3): channel = cv2.filter2D(float_image[:, :, ch], -1, kernel) channels.append(channel) # 合并多通道数据 result = cv2.merge(channels) # 将结果叠加到原始图像之上完成锐化 sharpened = float_image + result # 确保像素值位于有效范围内 return np.clip(sharpened, 0, 255).astype(np.uint8) if __name__ == "__main__": # 加载测试图像 original = cv2.imread('example.jpg') # 执行拉普拉斯锐化 processed = laplacian_sharpen(original) # 展示对比效果图 combined = np.hstack((original, processed)) cv2.imshow("Before and After", combined) cv2.waitKey(0) cv2.destroyAllWindows() ``` 上述程序实现了基本的拉普拉斯锐化功能,并提供了可视化界面让用户直观感受前后差异。需要注意的是,实际应用场景下可能还需要考虑更多因素,比如噪声抑制等问题[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

‭刘燚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值