一、目的(本次实验所涉及并要求掌握的知识点)

通过本实验加深对数字图像增强操作的理解,熟悉MATLAB中的有关函数;了解直方图均衡化和卷积滤波的原理;熟悉低通和高通滤波模板的构造方法。

二、实验内容与设计思想(设计思路、主要代码结构、主要代码段的文字分析、输出结果截图)

  1. 直方图均衡化

1.1 观察实验结果,写出和原图像有什么不同之处

clear;

I = imread('tire.tif');

J = histeq(I);

imshow(I)

figure, imshow(J)

imhist(I,64)

figure; imhist(J,64)

  • 图像:

原始图像 I 显得对比度较低,颜色层次不够分明,物品边界比较模糊,一些细节可能因为对比度过低而难以辨认

经过直方图均衡化处理的图像 J 由于对比度的增强,暗部和亮部的细节都会更加突出,使得图像看起来更加鲜明和清晰。

  • 直方图分布:

原始图像 I 的直方图可能会集中在左边的灰度值上,表明图像的亮度分布不均匀。

处理后的图像 J 的直方图均匀地分布在所有可能的灰度值上,这表示每个灰度级别的像素数更接近,从而提高了图像的整体对比度。

1.2 输入代码,比较I、J两幅图像的差别,写出其原因

I=imread('pout.tif');

J=histeq(I);

subplot(1,2,1);imshow(I);

subplot(1,2,2);imshow(J);

    

  • 图像对比:

原图 I:看起来可能有些灰蒙蒙的,在某些地方太暗,或者太亮。整体上对比度可能不太强,细节可能不太清楚,特别是在光线较弱的地方。

均衡化后的图像 J:经过均衡化后,图像的整体对比度增强了,细节变得更加清晰。特别是那些暗的部分,或者太亮的部分,都会看得更清楚。整体上看起来比较鲜明,层次感也更强。

  • 原因:

直方图均衡化把图像的亮度(灰度值)分布得更均匀。原图中可能有很多地方的亮度集中在某些范围,导致图像看起来对比度不够强。均衡化后,它将图像的灰度值分布拉伸到更广泛的范围,这样图像中暗的部分不会那么黑,亮的部分也不会那么刺眼,细节会更容易看到。

1.3 将程序中的图像换成其他图像,验证你的说法是否正确。

1.4 画出I、J的直方图,写出两者的差别。

对于原始图像 I,其直方图通常会显示出在特定亮度水平上的集中现象,这暗示着图像的对比度可能存在不足。具体表现为直方图中某些亮度等级的条形异常高耸,而其余部分则相对较低,表明图像中的大多数像素灰度值集中在较窄的区间内。

相比之下,处理后的图像 J 经过直方图均衡化处理后,其直方图呈现出更为均匀的分布特征。这种变化意味着图像内的亮度层次得到了更加广泛的利用,进而提升了图像的整体对比度。直方图均衡化技术通过扩展图像的动态范围,有效改善了原图中过暗或过亮区域的细节呈现,使得图像的视觉效果更加丰富和细腻。

  1. 图像滤波

2.1 观察实验结果,写出和原图像有什么不同之处

clear;

I=imread('blood1.tif');

h=ones(5,5)/25;

J=imfilter(I,h);

figure(1);

imshow(I);

figure(2);

imshow(J);

右边的图片比左边的图片边缘更模糊,噪声显著减少,细微结构和纹理变得不那么明显。

2.2 将h分别修改下列的值,观察实验结果,写出产生此现象的原因

h=ones(3,3)/9;

右图相比左图,图片边缘更模糊一些,噪声减少一些,细微结构和纹理变得有些补明显,但相比上一个变化,图像中的细微结构和纹理仍然较为清晰。

a=[1 1 1

       1 2 1

       1 1 1]

h=a/10;

2.3 构造一个低通滤波模板,并加以实现

  1. 设计思路

目标:使用低通滤波器对图像进行平滑处理,减少噪声并使图像更加柔和。

步骤:

  • 读取图像:从指定路径读取图像文件。
  • 定义滤波器模板:构造一个3x3的低通滤波器模板,该模板对中心像素赋予较大的权重,对周围像素赋予较小的权重。
  • 应用滤波器:使用 imfilter 函数将滤波器应用于图像。
  • 显示结果:在同一个图形窗口中显示原始图像和处理后的图像,以便对比效果。

  1. 主要代码结构
  • 清除工作区:清除所有变量,确保工作区干净。
  • 读取图像:使用 imread 函数读取图像文件。
  • 定义滤波器模板:创建一个3x3的矩阵 a,并将其归一化为滤波器 h。
  • 应用滤波器:使用 imfilter 函数将滤波器 h 应用于图像 I,得到处理后的图像 J。
  • 显示图像:使用 figure 和 subplot 函数在同一图形窗口中显示原始图像和处理后的图像。

  1. 主要代码段的文字分析

J = imfilter(I, h);

功能:使用 imfilter 函数将滤波器 h 应用于图像 I,得到处理后的图像 J。

输入:原始图像 I 和滤波器 h。

输出:处理后的图像 J。

  1. 输出结果截图

2.4 构造2—3个高通滤波模板,并加以实现,和低通滤波的效果加以对比,写出高通滤波和低通滤波的差别,并写出低通滤波模板、高通滤波模板构造的规律。

  1. 设计思路
  • 读取图像:从指定路径读取图像,并将其转换为灰度图像。
  • 定义滤波器模板:构造低通滤波器和高通滤波器模板。
  • 应用滤波器:使用 imfilter 函数将滤波器应用于图像。
  • 归一化滤波结果:确保滤波后的图像值在合理范围内。
  • 显示结果:使用 imshow 函数显示原始图像和滤波后的图像。

  1. 主要代码结构
  • 读取图像并加载到变量 I 中。
  • 定义三种滤波器:低通滤波器、拉普拉斯高通滤波器和差分高通滤波器。
  • 使用 imfilter 函数将滤波器应用于原图像。
  • 使用 subplot 和 imshow 将原图和处理后的图像一起显示,便于比较效果。

  1. 主要代码段的文字分析

low_pass_filter = [1 1 1; 1 1 1; 1 1 1] / 9;

high_pass_filter_1 = [-1 -1 -1; -1 8 -1; -1 -1 -1];

high_pass_filter_2 = [0 -1 0; -1 4 -1; 0 -1 0];

低通滤波器:定义一个3x3的均值滤波器模板 low_pass_filter,每个元素为1/9,用于平滑图像。

高通滤波器1:定义一个3x3的拉普拉斯滤波器模板 high_pass_filter_1,中心权重为8,周围权重为-1,用于检测图像中的边缘。

高通滤波器2:定义一个3x3的差分滤波器模板 high_pass_filter_2,中心权重为4,周围权重为-1,用于检测图像中的边缘。

J_low = imfilter(I, low_pass_filter);

J_high_1 = imfilter(I, high_pass_filter_1);

J_high_2 = imfilter(I, high_pass_filter_2);

使用 imfilter 函数将定义的滤波器应用于图像 I,并将结果分别存储在变量 J_low、J_high_1 和 J_high_2 中。

  1. 输出结果截图

  1. 高通滤波和低通滤波的差别:
  • 低通滤波器:平滑图像,减少高频噪声,模糊图像中的细节和边缘。
  • 高通滤波器:增强图像中的细节和边缘,突出高频信息。

  1. 低通滤波模板、高通滤波模板构造的规律:
  • 低通滤波模板:中心值大,表示对中心像素加权较强;周围值小或接近零,以减少周围像素的影响。
  • 高通滤波模板:中心值大(正值),通常为正值(如1或更大);周围值负,通常为负值(如-1),以突出图像的变化。

  1. 使用C/C++编程实现直方图均衡化函数(histeq)和卷积滤波函数(imfilter)
  1. 设计思路
  • 读取图像并将其显示。
  • 对图像进行直方图均衡化。
  • 对图像应用卷积滤波。
  • 将处理后的图像保存到文件。
  • 显示处理前后图像。

  1. 主要代码结构
  • 函数声明与定义:
  1. readImage(const char* path):读取图像文件并转换为灰度图像。
  2. saveImage(const char* path, const cv::Mat& img):将图像保存为指定路径。
  3. showImage(const char* windowName, const cv::Mat& img):显示图像窗口。
  4. histeq(const cv::Mat& input):进行直方图均衡化处理。
  5. imfilter(const cv::Mat& input, const cv::Mat& kernel):应用卷积滤波。
  • 主函数 (main):
  1. 读取图像。
  2. 进行直方图均衡化和卷积滤波。
  3. 显示和保存处理后的图像。

  1. 主要代码段的文字分析

直方图均衡化函数:

cv::Mat histeq(const cv::Mat& input) {

cv::Mat output;

cv::equalizeHist(input, output);

return output;

}

功能:对图像进行直方图均衡化。

cv::equalizeHist(input, output):OpenCV 内置的函数,输入灰度图像 input,输出增强后的图像 output,增强图像的对比度。

卷积滤波函数:

cv::Mat imfilter(const cv::Mat& input, const cv::Mat& kernel) {

cv::Mat output;

int ddepth = CV_32F;

cv::filter2D(input, output, ddepth, kernel);

output.convertTo(output, CV_8U);

return output;

}

功能:应用卷积滤波对图像进行处理。

cv::filter2D(input, output, ddepth, kernel):使用给定的卷积核 kernel 对输入图像 input 进行滤波,生成输出图像 output。

output.convertTo(output, CV_8U):将输出图像的深度转换为 8 位无符号整型,以便显示和保存。

  1. 输出结果截图

  1. 使用C/C++编程实现灰度映射

目标:使用C语言和OpenCV库实现灰度映射功能,处理指定路径的图像文件,并显示处理结果。

步骤:

  • 读取图像:从指定路径读取图像文件。
  • 定义灰度映射函数:实现线性、指数和对数灰度映射函数。
  • 创建灰度映射函数:编写一个通用的灰度映射函数,可以接受不同的灰度映射函数作为参数。
  • 应用灰度映射:将图像转换为灰度图像,并分别应用线性、指数和对数灰度映射。
  • 显示结果:在同一个图形窗口中显示原始图像和处理后的图像,以便对比效果。

  1. 主要代码结构
  • 包含必要的头文件;
  • 定义灰度映射函数;
  • 创建灰度映射函数;
  • 主函数。

  1. 主要代码段的文字分析

float linearGrayMap(int pixelValue) {

    return pixelValue;

}

float exponentialGrayMap(int pixelValue) {

    return pow(pixelValue / 255.0, 0.5) * 255.0;

}

float logarithmicGrayMap(int pixelValue) {

    return log1p(pixelValue / 255.0) * 255.0 / log(256.0);

}

功能:定义三种不同的灰度映射函数。

线性灰度映射:直接返回像素值,不改变亮度。

指数灰度映射:使用指数函数调整像素值,增强暗部细节。

对数灰度映射:使用对数函数调整像素值,增强亮部细节。

int main() {

    cv::Mat image = cv::imread("D:\\大三上\\数字信号与图像处理\\实验\\实验四\\可爱小狗.jpg");

    if (image.empty()) {

        fprintf(stderr, "无法读取图像文件\n");

        return -1;

    }

    cv::Mat grayImage;

    cv::cvtColor(image, grayImage, cv::COLOR_BGR2GRAY);

    cv::Mat linearGrayImage = grayImage.clone();

    createGrayMap(linearGrayImage, linearGrayMap);

    cv::Mat expGrayImage = grayImage.clone();

    createGrayMap(expGrayImage, exponentialGrayMap);

    cv::Mat logGrayImage = grayImage.clone();

    createGrayMap(logGrayImage, logarithmicGrayMap);

    cv::imshow("原始图像", image);

    cv::imshow("灰度图像", grayImage);

    cv::imshow("线性灰度映射图像", linearGrayImage);

    cv::imshow("指数灰度映射图像", expGrayImage);

    cv::imshow("对数灰度映射图像", logGrayImage);

    cv::waitKey(0);

    return 0;

}

功能:读取图像文件,转换为灰度图像,应用不同的灰度映射函数,并显示结果。

步骤:

读取图像:使用 cv::imread 函数读取图像文件,检查是否成功读取。

转换为灰度图像:使用 cv::cvtColor 函数将图像从BGR格式转换为灰度格式。

创建线性灰度映射图像:克隆灰度图像,调用 createGrayMap 函数应用线性灰度映射。

创建指数灰度映射图像:克隆灰度图像,调用 createGrayMap 函数应用指数灰度映射。

创建对数灰度映射图像:克隆灰度图像,调用 createGrayMap 函数应用对数灰度映射。

显示结果:使用 cv::imshow 函数显示原始图像和处理后的图像。

等待用户按键:使用 cv::waitKey(0) 函数等待用户按键,防止窗口立即关闭。

  1. 输出结果截图

三、实验使用环境(本次实验所使用的平台和相关软件)

  1. MATLAB R2022b
  2. VS 2017

实验小实验中遇到的问题及解决过程、实验中产生的错误及原因分析、实验体会和收获)

  • 通过本次实验,我们不仅加深了对数字图像增强操作的理解,还熟练掌握了MATLAB中常用的图像处理函数。直方图均衡化有效提高了图像的对比度,而卷积滤波则可以根据需要选择不同的滤波器模板,实现图像的平滑或锐化。此外,我们还了解了低通和高通滤波器的构造方法及其应用场景,为进一步的图像处理研究打下了坚实的基础。
  • 一开始灰度映射函数计算结果不正确,导致图像显示异常。后来发现是有可能计算过程中数据类型转换错误或是数学函数使用不当;后来我确保灰度映射函数返回值在 [0, 255] 范围内;使用 std::min 和 std::max 函数限制返回值范围。
  • 一开始在程序运行过程中出现内存泄漏,导致崩溃。后来发现是动态分配的内存未释放与对象未正确销毁。后来我使用智能指针来确保所有动态分配的内存都已释放。

五、参考文献(书籍、网址链接等)

  1. 数字信号与图像处理
  2. CSDN

  • 源代码附件(完整的程序源代码,注意排版紧凑,如果代码较长,字体、字间距选择小一点的
%% 1.4

I = imread('pout.tif');

J = histeq(I);

figure;

subplot(1,2,1);

imshow(I);

title('Original Image (I)');

subplot(1,2,2);

imshow(J);

title('Equalized Image (J)');

figure;

subplot(1,2,1);

imhist(I);

title('Histogram of Original Image (I)');

subplot(1,2,2);

imhist(J);

title('Histogram of Equalized Image (J)');



%% 2.3

clear;

I = imread('D:\大三上\数字信号与图像处理\实验\实验四\可爱小猫.jpg');

a = [1 1 1;

1 2 1;

1 1 1];

h = a / 10;

J = imfilter(I, h);



figure;

subplot(1,2,1);

imshow(I);

title('原始图像');



subplot(1,2,2);

imshow(J);

title('使用低通滤波器过滤的图像');



%% 2.4

clear;

I = imread('D:\大三上\数字信号与图像处理\实验\实验四\可爱小猫.jpg');

low_pass_filter = [1 1 1; 1 1 1; 1 1 1] / 9;

high_pass_filter_1 = [-1 -1 -1; -1 8 -1; -1 -1 -1];

high_pass_filter_2 = [0 -1 0; -1 4 -1; 0 -1 0];



J_low = imfilter(I, low_pass_filter);

J_high_1 = imfilter(I, high_pass_filter_1);

J_high_2 = imfilter(I, high_pass_filter_2);



figure;

subplot(2, 2, 1);

imshow(I);

title('原图');



subplot(2, 2, 2);

imshow(J_low);

title('低通滤波效果');



subplot(2, 2, 3);

imshow(J_high_1);

title('高通滤波效果1(Laplacian)');



subplot(2, 2, 4);

imshow(J_high_2);

title('高通滤波效果2(差分)');



%% 3.

#include <opencv2/opencv.hpp>

#include <stdio.h>



cv::Mat readImage(const char* path) {

cv::Mat img = cv::imread(path, cv::IMREAD_GRAYSCALE);

if (img.empty()) {

printf("Could not open or find the image\n");

exit(1);

}

return img;

}



void saveImage(const char* path, const cv::Mat& img) {

if (!cv::imwrite(path, img)) {

printf("Failed to write the image\n");

exit(1);

}

}



void showImage(const char* windowName, const cv::Mat& img) {

cv::namedWindow(windowName, cv::WINDOW_NORMAL);

cv::imshow(windowName, img);

}



cv::Mat histeq(const cv::Mat& input) {

cv::Mat output;

cv::equalizeHist(input, output);

return output;

}



cv::Mat imfilter(const cv::Mat& input, const cv::Mat& kernel) {

cv::Mat output;

int ddepth = CV_32F;

cv::filter2D(input, output, ddepth, kernel);

output.convertTo(output, CV_8U);

return output;

}



int main() {

const char* imagePath = "D:\\大三上\\数字信号与图像处理\\实验\\实验四\\可爱小狗.jpg";

cv::Mat img = readImage(imagePath);

cv::Mat kernel = (cv::Mat_<float>(3, 3) << 1 / 9.0, 1 / 9.0, 1 / 9.0,

1 / 9.0, 1 / 9.0, 1 / 9.0,

1 / 9.0, 1 / 9.0, 1 / 9.0);



cv::Mat img_histeq = histeq(img);

saveImage("D:\\大三上\\数字信号与图像处理\\实验\\实验四\\可爱小狗_histeq.jpg", img_histeq);

showImage("原始图像", img);

showImage("直方图均衡化图像", img_histeq);



cv::Mat img_filtered = imfilter(img, kernel);

saveImage("D:\\大三上\\数字信号与图像处理\\实验\\实验四\\可爱小狗_filtered.jpg", img_filtered);

showImage("卷积滤波图像", img_filtered);



cv::waitKey(0);

cv::destroyAllWindows();



printf("图像处理完成。\n");

return 0;

}



%% 4.

#include <stdio.h>

#include <stdlib.h>

#include <opencv2/opencv.hpp>



float linearGrayMap(int pixelValue) {

return pixelValue;

}



float exponentialGrayMap(int pixelValue) {

return pow(pixelValue / 255.0, 0.5) * 255.0;

}



float logarithmicGrayMap(int pixelValue) {

return log1p(pixelValue / 255.0) * 255.0 / log(256.0);

}



void createGrayMap(cv::Mat &image, float(*grayMap)(int)) {

for (int y = 0; y < image.rows; ++y) {

for (int x = 0; x < image.cols; ++x) {

int pixelValue = image.at<uchar>(y, x);

image.at<uchar>(y, x) = (unsigned char)grayMap(pixelValue);

}

}

}



int main() {

cv::Mat image = cv::imread("D:\\大三上\\数字信号与图像处理\\实验\\实验四\\可爱小狗.jpg");

if (image.empty()) {

fprintf(stderr, "无法读取图像文件\n");

return -1;

}



cv::Mat grayImage;

cv::cvtColor(image, grayImage, cv::COLOR_BGR2GRAY);



cv::Mat linearGrayImage = grayImage.clone();

createGrayMap(linearGrayImage, linearGrayMap);



cv::Mat expGrayImage = grayImage.clone();

createGrayMap(expGrayImage, exponentialGrayMap);



cv::Mat logGrayImage = grayImage.clone();

createGrayMap(logGrayImage, logarithmicGrayMap);



cv::imshow("原始图像", image);

cv::imshow("灰度图像", grayImage);

cv::imshow("线性灰度映射图像", linearGrayImage);

cv::imshow("指数灰度映射图像", expGrayImage);

cv::imshow("对数灰度映射图像", logGrayImage);



cv::waitKey(0);



return 0;

}

Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐