python进行图像处理rows, cols = Img.shape,copyMakeBorder()、merge()、dft()、log()和normalize()

这篇博客是学习OpenCV的笔记,重点介绍了如何使用Python实现图像处理的几个关键函数,包括:copyMakeBorder用于添加图像边框,merge用于通道合并,dft进行离散傅里叶变换,log计算数组元素的自然对数,以及normalize进行图像数据的归一化操作。
部署运行你感兴趣的模型镜像

这是学习opencv官网上例子的笔记跳转官网示例(用python实现)关于函数的用法,例如:copyMakeBorder(),merge()、dft()、getoptimeditsize()、log()和normalize()。
在这里插入图片描述
1.解释rows, cols = Img.shape
这行代码的意思是把图片像素的行数,列数返回给rows,cols
2。getOptimalDFTSize函数
m = cv.getOptimalDFTSize( rows ) n = cv.getOptimalDFTSize( cols )
getOptimalDFTSize()函数返回给定向量尺寸的傅里叶最优尺寸大小,这里返回的时rows和cols
3.copyMakeBorder()函数
cv.copyMakeBorder(InputArray src, OutputArray dst, int top, int bottom,int left, int right, int borderType, const Scalar& value=Scalar() )
InputArray src:输入图像
OutputArray dst:输出的图像,与输入图像相同类型
int top, int bottom, int left, int right:在原来边界的基础上每个方向添加的像素个数,就是改变边框的粗细
int borderType:表示边界的类型
const Scalar& value=Scalar():表示如果上一个边界的类型值是 BORDER_CONSTANT (opencv中边界的类型之一) ,那么这一个就是边界的颜色值;

4.merge()函数
merge( )进行通道合并
方法:cv.merge(const Mat* mv, size_t count, OutputArray dst) 参数分别是被合并图像的指针,数目,合并后输出的图像
而split()函数与其相反是将多通道图像分离
5.dft()函数
对一维或者二维浮点数数组进行正向或反向离散傅里叶变换
cv.dft(InputArraysrc, OutputArray dst, int flags=0, int nonzeroRows=0)
对应参数输入图像,输出图像,转换标识符(默认值为0),第四个参数默认值为0,当其不为0时,函数会假设只有输入数组的第一行或第一个输出数组有非零值。
6.log()
对数组的每一个元素取自然对数
cv.log(InputArraysrc, OutputArray dst) 参数:输入图像和输出图像
7.normalize()归一化函数
将图像或者数据处理到一定范围
cv2.normalize(src[, dst[, alpha[, beta[, norm_type[, dtype[, mask]]]]]]) → dst
输入图像,输出图像,归一化后的最大值,最小值,归一化的类型

您可能感兴趣的与本文相关的镜像

Python3.11

Python3.11

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

// 扩展图像到最佳DFT尺寸 int optimalRows = getOptimalDFTSize(img.rows); int optimalCols = getOptimalDFTSize(img.cols); Mat padded; copyMakeBorder(img, padded, 0, optimalRows - img.rows, 0, optimalCols - img.cols, BORDER_CONSTANT, Scalar::all(0)); // 准备DFT输入(两个通道:实部虚部) Mat planes[] = {Mat_<float>(padded), Mat::zeros(padded.size(), CV_32F)}; Mat complexImg; merge(planes, 2, complexImg); // 执行傅里叶变换 dft(complexImg, complexImg); // 将低频移到频谱中心 int cx = complexImg.cols / 2; int cy = complexImg.rows / 2; Mat q0(complexImg, Rect(0, 0, cx, cy)); // 左上象限 Mat q1(complexImg, Rect(cx, 0, cx, cy)); // 右上象限 Mat q2(complexImg, Rect(0, cy, cx, cy)); // 左下象限 Mat q3(complexImg, 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 mask = Mat::zeros(complexImg.size(), CV_32F); float D0 = 60; // 截止频率(控制滤波强度) for (int i = 0; i < mask.rows; i++) { for (int j = 0; j < mask.cols; j++) { float d = sqrt(pow(i - cy, 2) + pow(j - cx, 2)); mask.at<float>(i, j) = exp(-(d * d) / (2 * D0 * D0)); } } // 应用频域滤波器 split(complexImg, planes); multiply(planes[0], mask, planes[0]); multiply(planes[1], mask, planes[1]); merge(planes, 2, complexImg); // 逆交换象限(恢复原始排列) Mat q0_new = complexImg(Rect(0, 0, cx, cy)); Mat q3_new = complexImg(Rect(cx, cy, cx, cy)); q0.copyTo(tmp); q3_new.copyTo(q0_new); tmp.copyTo(q3_new); Mat q1_new = complexImg(Rect(cx, 0, cx, cy)); Mat q2_new = complexImg(Rect(0, cy, cx, cy)); q1.copyTo(tmp); q2_new.copyTo(q1_new); tmp.copyTo(q2_new); // 逆傅里叶变换 idft(complexImg, complexImg, DFT_SCALE | DFT_REAL_OUTPUT); // 裁剪归一化处理结果,,,对于不知道傅里叶原理细节的人,如何理解这段代码并一步
03-25
#include <opencv2/opencv.hpp> #include <cmath> #include <complex> #include <vector> #include <iostream> using namespace cv; using namespace std; // 位反转函数(用于蝶形运算准备) int bitReverse(int num, int log2n) { int result = 0; for (int i = 0; i < log2n; ++i) { if (num & (1 << i)) result |= 1 << (log2n - 1 - i); } return result; } // 1D FFT实现(基2-FFT蝶形运算) void fft(vector<complex<float>>& data, bool inverse = false) { const int n = data.size(); const int log2n = static_cast<int>(log2(n)); // 位反转重排 vector<complex<float>> temp(n); for (int i = 0; i < n; ++i) { int rev = bitReverse(i, log2n); temp[i] = data[rev]; } // 蝶形运算 for (int s = 1; s <= log2n; ++s) { int m = 1 << s; // 当前处理块大小 float ang = 2 * CV_PI / m * (inverse ? 1 : -1); complex<float> wm(cos(ang), sin(ang)); for (int k = 0; k < n; k += m) { complex<float> w(1.0f); for (int j = 0; j < m / 2; ++j) { complex<float> t = w * temp[k + j + m / 2]; complex<float> u = temp[k + j]; temp[k + j] = u + t; temp[k + j + m / 2] = u - t; w *= wm; } } } // 逆变换缩放 if (inverse) { for (auto& x : temp) x /= n; } data = temp; } // 2D FFT实现 void fft2d(Mat& complexImage, bool inverse = false) { int rows = complexImage.rows; int cols = complexImage.cols; // 行变换 for (int y = 0; y < rows; ++y) { vector<complex<float>> rowData; for (int x = 0; x < cols; ++x) { rowData.push_back(complexImage.at<Vec2f>(y, x).val[0] + complexImage.at<Vec2f>(y, x).val[1] * 1if); } fft(rowData, inverse); for (int x = 0; x < cols; ++x) { complexImage.at<Vec2f>(y, x) = Vec2f(rowData[x].real(), rowData[x].imag()); } } // 列变换 for (int x = 0; x < cols; ++x) { vector<complex<float>> colData; for (int y = 0; y < rows; ++y) { colData.push_back(complexImage.at<Vec2f>(y, x).val[0] + complexImage.at<Vec2f>(y, x).val[1] * 1if); } fft(colData, inverse); for (int y = 0; y < rows; ++y) { complexImage.at<Vec2f>(y, x) = Vec2f(colData[y].real(), colData[y].imag()); } } } // 频域中心化 (fftshift) void fftShift(Mat& mag) { int cx = mag.cols / 2; int cy = mag.rows / 2; Mat q0(mag, Rect(0, 0, cx, cy)); Mat q1(mag, Rect(cx, 0, cx, cy)); Mat q2(mag, Rect(0, cy, cx, cy)); Mat q3(mag, 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); } // 计算MSE double calculateMSE(const Mat& img1, const Mat& img2) { if (img1.size() != img2.size() || img1.type() != img2.type()) { cerr << "Images must have same size and type" << endl; return -1; } Mat diff; absdiff(img1, img2, diff); diff = diff.mul(diff); Scalar s = sum(diff); return s[0] / (img1.total() * img1.channels()); } // 计算PSNR double calculatePSNR(const Mat& img1, const Mat& img2) { double mse = calculateMSE(img1, img2); if (mse <= 1e-10) return 100; // 避免除以0 return 10.0 * log10((255.0 * 255.0) / mse); } // 创建低通滤波器掩膜 Mat createLowPassFilter(Size size, double D0) { Mat mask = Mat::zeros(size, CV_32F); Point center(size.width / 2, size.height / 2); for (int y = 0; y < size.height; y++) { for (int x = 0; x < size.width; x++) { double d = sqrt(pow(x - center.x, 2) + pow(y - center.y, 2)); if (d <= D0) { mask.at<float>(y, x) = 1.0f; } } } return mask; } int main() { // 读取灰度图像 Mat img = imread("input.jpg", IMREAD_GRAYSCALE); if (img.empty()) { cerr << "Could not read image" << endl; return -1; } // 调整大小为2的幂次(FFT要求) int newRows = pow(2, ceil(log2(img.rows))); int newCols = pow(2, ceil(log2(img.cols))); resize(img, img, Size(newCols, newRows)); // 转换为浮点型并归一化 Mat floatImg; img.convertTo(floatImg, CV_32F, 1.0 / 255.0); // 准备复数矩阵(实部=图像,虚部=0) Mat planes[] = { Mat_<float>(floatImg), Mat::zeros(floatImg.size(), CV_32F) }; Mat complexImg; merge(planes, 2, complexImg); // ===== 执行FFT ===== fft2d(complexImg); // 分离实部虚部 split(complexImg, planes); // 计算幅度谱 (log scale) Mat mag; magnitude(planes[0], planes[1], mag); mag += Scalar::all(1); // 避免log(0) log(mag, mag); normalize(mag, mag, 0, 1, NORM_MINMAX); // 频域中心化 fftShift(mag); // 显示幅度谱 imshow("Frequency Spectrum", mag); imwrite("spectrum.jpg", mag * 255); waitKey(0); // ===== 重建原始图像 (IFFT) ===== fft2d(complexImg, true); // 逆变换 // 获取实部作为重建图像 split(complexImg, planes); Mat reconstructed; normalize(planes[0], reconstructed, 0, 1, NORM_MINMAX); // 显示重建图像 imshow("Reconstructed Image", reconstructed); imwrite("reconstructed.jpg", reconstructed * 255); // 计算重建MSE/PSNR double mseOriginal = calculateMSE(floatImg, reconstructed); double psnrOriginal = calculatePSNR(floatImg, reconstructed * 255); cout << "MSE (Original): " << mseOriginal << endl; cout << "PSNR (Original): " << psnrOriginal << " dB" << endl; // ===== 低通滤波处理 ===== // 创建低通滤波器(截止频率=图像尺寸的15%) double D0 = min(img.rows, img.cols) * 0.45; Mat lpfMask = createLowPassFilter(complexImg.size(), D0); // 应用滤波器(在频域中心化状态) fftShift(mag); // 确保频域在中心 Mat filteredPlanes[] = { planes[0].mul(lpfMask), planes[1].mul(lpfMask) }; Mat filteredComplex; merge(filteredPlanes, 2, filteredComplex); // 逆变换得到滤波后图像 fft2d(filteredComplex, true); split(filteredComplex, filteredPlanes); Mat filteredImg; normalize(filteredPlanes[0], filteredImg, 0, 1, NORM_MINMAX); // 显示滤波后图像 imshow("Low-Pass Filtered", filteredImg); imwrite("filtered.jpg", filteredImg * 255); // 计算滤波后PSNR double mseFiltered = calculateMSE(floatImg, filteredImg); double psnrFiltered = calculatePSNR(floatImg, filteredImg * 255); cout << "MSE (Filtered): " << mseFiltered << endl; cout << "PSNR (Filtered): " << psnrFiltered << " dB" << endl; waitKey(0); return 0; }在这个代码上修改并给出完整代码
06-05
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值