通信系统仿真

崔春雷

目录

  • 1 第一单元: MATLAB基础
    • 1.1 课程说明与资料
      • 1.1.1 作业参考答案
      • 1.1.2 移动22级作业答案
    • 1.2 MATLAB安装与运行环境
      • 1.2.1 MATLAB介绍
    • 1.3 基本数据类型:数值类型
    • 1.4 基本数据类型:字符类型
    • 1.5 数据类型转换与输出
    • 1.6 数组与矩阵基础
      • 1.6.1 矩阵运算进阶
    • 1.7 数组与矩阵常用函数
    • 1.8 matlab中的逻辑运算
    • 1.9 实验: MATLAB常用数学函数
      • 1.9.1 实验 作业答案
    • 1.10 元胞数组
    • 1.11 结构体数组
      • 1.11.1 结构体进阶
      • 1.11.2 元胞数组与结构体数组对比
      • 1.11.3 map 容器
    • 1.12 附录:MATLAB常用基础命令
    • 1.13 拓展内容:实时脚本
      • 1.13.1 实时脚本示例
    • 1.14 课程作业与答案
      • 1.14.1 《通信系统仿真》期末考试
  • 2 第二单元:Matlab 程序设计
    • 2.1 顺序结构程序
    • 2.2 分支结构—— if语句
    • 2.3 分支结构—— switch语句
    • 2.4 循环结构—— while语句
    • 2.5 循环结构—— for语句
    • 2.6 图像处理基础
    • 2.7 Matlab的函数
      • 2.7.1 函数内容的课外扩展
    • 2.8 本章实验:for循环的应用
      • 2.8.1 素数问题
        • 2.8.1.1 素数的螺旋线排列
      • 2.8.2 3X+1猜想
      • 2.8.3 7 行代码计算 π
    • 2.9 排序算法
      • 2.9.1 冒泡排序
      • 2.9.2 选择排序
      • 2.9.3 插入排序
      • 2.9.4 快速排序
      • 2.9.5 基数排序
      • 2.9.6 计数排序
      • 2.9.7 堆排序
    • 2.10 动态规划算法
      • 2.10.1 动态规划编程实例
      • 2.10.2 动态规划:01背包问题
      • 2.10.3 动态规划常见题目分析
      • 2.10.4 动态规划题目分析2
    • 2.11 常用算法简介
      • 2.11.1 剪枝算法
      • 2.11.2 二分查找
      • 2.11.3 递归算法
      • 2.11.4 回溯算法
        • 2.11.4.1 Leetcode回溯题目合集
        • 2.11.4.2 回溯算法总结
        • 2.11.4.3 回溯法解数独问题
        • 2.11.4.4 DFS与BFS
          • 2.11.4.4.1 DFS/BFS原理
          • 2.11.4.4.2 BFS的应用:Dijkstra算法
      • 2.11.5 n 皇后问题专题
      • 2.11.6 双指针算法
      • 2.11.7 数组模拟链表(约瑟夫环)
      • 2.11.8 Hash(哈希表)
      • 2.11.9 图论与路径规划
        • 2.11.9.1 迪杰斯特拉算法
        • 2.11.9.2 A*算法
          • 2.11.9.2.1 A*算法的MATLAB实现
        • 2.11.9.3 RRT路径规划算法
          • 2.11.9.3.1 RRT算法 MATLAB代码
          • 2.11.9.3.2 参考资料
      • 2.11.10 数据结构
        • 2.11.10.1 数据结构例题
      • 2.11.11 前缀和 差分 双指针
      • 2.11.12 位运算
      • 2.11.13 常用算法代码模板
    • 2.12 练习题库
    • 2.13 code
      • 2.13.1 简易计算器gui代码
      • 2.13.2 五子棋
      • 2.13.3 连连看小游戏
      • 2.13.4 递归算法与汉诺塔
      • 2.13.5 有理数的小数循环节
    • 2.14 MATLAB编程风格
      • 2.14.1 向量化编程专题
  • 3 第三单元:Matlab 图形图像处理
    • 3.1 二维图形绘图基础
    • 3.2 二维图形绘图进阶
    • 3.3 三维图形绘图
      • 3.3.1 MATLAB绘图小结
        • 3.3.1.1 用matlab绘制好看图像
    • 3.4 MATLAB高级绘图
    • 3.5 文件操作
    • 3.6 Matlab图像处理进阶
      • 3.6.1 补充:Matlab图像处理常用函数
      • 3.6.2 RGB/HSV/HSI颜色模型
      • 3.6.3 图片切换动画效果
      • 3.6.4 图像连通域标记
      • 3.6.5 图像旋转与插值
      • 3.6.6 图像的形态学
      • 3.6.7 空间滤波
        • 3.6.7.1 图像中常见的噪声类型与滤波方法
        • 3.6.7.2 matlab中的滤波函数
        • 3.6.7.3 BM3D 去噪算法
        • 3.6.7.4 双边滤波
      • 3.6.8 图像的频域处理
    • 3.7 本章总结
    • 3.8 实验 : matlab 绘图练习1
    • 3.9 实验: matlab 绘图练习2
    • 3.10 实验 :数学函数图像绘制
    • 3.11 实验:绘图综合练习
    • 3.12 实验:曲线拟合
    • 3.13 实验:牛顿法求解方程的根
    • 3.14 实验:信号的傅里叶变换
      • 3.14.1 傅里叶变换、小波变换、希尔伯特变换
      • 3.14.2 新建目录
    • 3.15 课外补充:图像处理基础1
    • 3.16 课外补充:图像处理基础2
    • 3.17 课外补充:图像处理基础3
    • 3.18 课外补充:PYTHON基础
  • 4 第五单元:MATLAB通信仿真
    • 4.1 现代通信系统的介绍
    • 4.2 模拟通信系统的仿真原理
    • 4.3 HDB3编解码的仿真实现
    • 4.4 SIMULINK和其模块简介
    • 4.5 数字通信系统的仿真原理
    • 4.6 模拟通信系统Simulink仿真
    • 4.7 数字通信系统Simulink仿真
    • 4.8 音频信号测处理与仿真
    • 4.9 图像数字水印技术
      • 4.9.1 三角函数到傅里叶变换再到语音识别与数字水印
    • 4.10 信息系统与算法
      • 4.10.1 递归算法
        • 4.10.1.1 递归与堆栈的关系
      • 4.10.2 哈希表
      • 4.10.3 双指针算法
        • 4.10.3.1 双指针算法实战
        • 4.10.3.2 双指针进阶:滑动窗口算法
      • 4.10.4 字符串匹配 KMP算法
        • 4.10.4.1 字符串匹配B-M算法
      • 4.10.5 快速傅里叶变换
      • 4.10.6 回溯算法
      • 4.10.7 动态规划
      • 4.10.8 分治算法
      • 4.10.9 Dijkstra算法
  • 5 第六单元: systemview通信仿真
    • 5.1 SystemView概述
    • 5.2 模拟通信系统 数字系统的仿真分析
    • 5.3 SystemView通信系统仿真进阶
    • 5.4 新建课程目录
  • 6 第四单元:MATLAB高级应用
    • 6.1 符号运算基础
      • 6.1.1 利用Matlab自动推导公式
    • 6.2 Matlab中的数值计算
      • 6.2.1 积分的计算
      • 6.2.2 龙格库塔:常微分方程的数值解法
      • 6.2.3 fmincon函数与非线性方程最小值
    • 6.3 统计、拟合、插值
      • 6.3.1 协方差与相关系数
    • 6.4 GUI设计初步
    • 6.5 matlab GUI界面编程
      • 6.5.1 gui实例
      • 6.5.2 gui编程中常用函数
      • 6.5.3 App Designer入门
    • 6.6 实验:GUI设计图像空间变换系统
    • 6.7 作业:利用GUI设计 计算器、信号发生器等
    • 6.8 MTALB数据导入方法
    • 6.9 课外补充:MATLAB的App会取代GUI吗?
    • 6.10 模拟退火算法matlab实现
    • 6.11 遗传算法的Matlab实现
      • 6.11.1 进化算法(Evolutionary Algorithm)及相关函数介绍
    • 6.12 粒子群算法 matlab实现
      • 6.12.1 粒子群算法及MATLAB实例仿真
    • 6.13 BP网络的应用
    • 6.14 matlab 结构体
    • 6.15 群智能算法合集
  • 7 拓展知识
    • 7.1 什么是算法的时间复杂度?
    • 7.2 Notepad++使用教程
    • 7.3 MATLAB常用函数总结
    • 7.4 MATLAB常用知识点总结
    • 7.5 MATLAB命令大全
    • 7.6 视频:MATLAB官方基础教程
    • 7.7 经典书籍:Matlab2012经典超强教程
    • 7.8 经典书籍:MATLAB揭秘(自学宝典)
    • 7.9 经典资料:MATLAB N个实用技巧
    • 7.10 Matlab编程小技巧
    • 7.11 寻优算法
      • 7.11.1 Dijkstra算法python实现
    • 7.12 PYTHON基础教程
      • 7.12.1 Python进阶
      • 7.12.2 Python小技巧
      • 7.12.3 Python总结
        • 7.12.3.1 Python循环语句总结
        • 7.12.3.2 24个顶级Python库
        • 7.12.3.3 魔法函数
      • 7.12.4 廖雪峰python
      • 7.12.5 正则表达式基础
      • 7.12.6 numpy
        • 7.12.6.1 101道Numpy习题
        • 7.12.6.2 Numpy简要语法教程
        • 7.12.6.3 Numpy实现全连接神经网络 (手写数字识别)
        • 7.12.6.4 图解NumPy
      • 7.12.7 matplotlib
        • 7.12.7.1 matplotlib练习50题
        • 7.12.7.2 Matplotlib速查表
        • 7.12.7.3 Matplotlib 实操指南
      • 7.12.8 Python3 模块 import
      • 7.12.9 Python 小项目
    • 7.13 参考资源:数据结构与算法
      • 7.13.1 十大经典排序算法总结
    • 7.14 机器学习概述
      • 7.14.1 反向传播算法
        • 7.14.1.1 反向传播的数学原理
      • 7.14.2 极大似然估计
        • 7.14.2.1 极大似然估计与最小二乘法
      • 7.14.3 Batch Normalization
        • 7.14.3.1 Batch Normalization&Dropout浅析
        • 7.14.3.2 ​BN层的梯度反向传播计算
        • 7.14.3.3 Batch Size的大小与神经网络的性能
        • 7.14.3.4 标准化和归一化
      • 7.14.4 主成分分析PCA与SVD奇异值分解
        • 7.14.4.1 岭回归 与 PCA
        • 7.14.4.2 PCA原理推导
        • 7.14.4.3 PCA原理新解
        • 7.14.4.4 svd
        • 7.14.4.5 PCA数学原理
      • 7.14.5 正则化
        • 7.14.5.1 L1、L2正则化和过拟合 总结
        • 7.14.5.2 L1 和 L2 正则化的直观解释
      • 7.14.6 SVM
        • 7.14.6.1 从零推导支持向量机(SVM)
        • 7.14.6.2 支持向量机(SVM)介绍
        • 7.14.6.3 SVM推导与实战
        • 7.14.6.4 支持向量机的直观理解
        • 7.14.6.5 浅显易懂的支持向量机SVM
      • 7.14.7 线性回归
      • 7.14.8 逻辑回归
      • 7.14.9 BP算法
        • 7.14.9.1 万能逼近——神经网络拟合任意函数原理
      • 7.14.10 激活与池化
        • 7.14.10.1 激活函数与损失函数 小结
      • 7.14.11 深度学习简述
        • 7.14.11.1 MATLAB2020深度学习实例
      • 7.14.12 损失函数与误差反向传播
        • 7.14.12.1 梯度下降与损失函数
      • 7.14.13 深度学习优化问题
      • 7.14.14 梯度下降法
        • 7.14.14.1 各类梯度下降算法的Python实现
        • 7.14.14.2 梯度下降的直观理解
        • 7.14.14.3 动量、RMSProp、Adam
      • 7.14.15 卷积的概念
        • 7.14.15.1 卷积的矩阵化算法
      • 7.14.16 局部连接
      • 7.14.17 RNN
      • 7.14.18 LSTM
      • 7.14.19 CNN-四大经典CNN技术浅析
      • 7.14.20 熵(Entropy)与交叉熵
      • 7.14.21 softmax函数详解
      • 7.14.22 自编码算法详细理解与代码实现
      • 7.14.23 pytorch
        • 7.14.23.1 ​PyTorch简介
          • 7.14.23.1.1 Pytorch快速入门资料
        • 7.14.23.2 CNN的PyTorch实现
        • 7.14.23.3 pytorch总结
        • 7.14.23.4 PyTorch trick 集锦
        • 7.14.23.5 在PyTorch上加载自定义数据集
        • 7.14.23.6 实战:Pytorch识别验证码
        • 7.14.23.7 实战:Transformer的最简洁pytorch实现
        • 7.14.23.8 使用PyTorch实现神经网络分类
      • 7.14.24 卷积神经网络CNN概述
        • 7.14.24.1 CNN 简易原理
        • 7.14.24.2 卷积神经网络CNN原理详解
        • 7.14.24.3 自己手写一个卷积神经网络
        • 7.14.24.4 CNN反向传播算法
        • 7.14.24.5 卷积计算、作用与思想
        • 7.14.24.6 用卷积神经网络CNN识别手写数字集
        • 7.14.24.7 卷积 池化 参数的计算
        • 7.14.24.8 im2col方法实现卷积算法
        • 7.14.24.9 卷积核的梯度计算
        • 7.14.24.10 卷积层反向传播推导及实现
        • 7.14.24.11 反向传输算法
          • 7.14.24.11.1 resnet残差网络
        • 7.14.24.12 CNN反向传播的MATLAB实现
      • 7.14.25 神经网络的调参技巧
      • 7.14.26 BP神经网络
        • 7.14.26.1 零开始搭建bp神经网络
        • 7.14.26.2 MATLAB自带的bp工具箱
        • 7.14.26.3 神经网络中偏置(bias)的作用
      • 7.14.27 聚类分析 k-means
        • 7.14.27.1 matlab做聚类分析(k-means)
        • 7.14.27.2 聚类模型探讨综述
        • 7.14.27.3 5种经典聚类算法
      • 7.14.28 深度学习的一些概念
      • 7.14.29 人工智能简述:AI的过去和现在
      • 7.14.30 k-NN(k近邻算法)
      • 7.14.31 神经网络中的优化器:BGD、SGD、MBGD、Momentum
      • 7.14.32 卷积神经网络的经典网络总结
        • 7.14.32.1 卷积神经网络中十大拍案叫绝的操作
      • 7.14.33 GAN 对抗样本攻击
      • 7.14.34 蒙特卡洛模拟
      • 7.14.35 dropout与随机部分连接
      • 7.14.36 Jupyter 等 IDE概览
      • 7.14.37 分类算法常用评价指标
      • 7.14.38 Inception 网络与不变性
      • 7.14.39 卷积神经网络的可视化
      • 7.14.40 隐马尔可夫模型HMM
        • 7.14.40.1 马尔科夫链
    • 7.15 MATLAB音频处理
      • 7.15.1 python处理音频信号
    • 7.16 图像处理
      • 7.16.1 图像处理中的指标
    • 7.17 代码集
    • 7.18 论文写作与阅读方法
      • 7.18.1 期刊投稿攻略
      • 7.18.2 论文排版教程
      • 7.18.3 SCI-HUB论文下载技巧
      • 7.18.4 几种论文写作神器,提高写作效率
      • 7.18.5 latex入门
      • 7.18.6 LaTeX教程
    • 7.19 机器学习常用的网站以及资源
      • 7.19.1 很详细的ML&DL学习博客
    • 7.20 SymPy 符号计算基本教程
  • 8 程序设计数学基础
    • 8.1 编程数学基础
      • 8.1.1 概率的历史
      • 8.1.2 概率
        • 8.1.2.1 常见概率分布
          • 8.1.2.1.1 二维正态分布
        • 8.1.2.2 蒙特卡罗方法
        • 8.1.2.3 置信区间
        • 8.1.2.4 协方差与相关系数
      • 8.1.3 矩阵 向量求导法则
      • 8.1.4 雅可比矩阵 海森矩阵
      • 8.1.5 矩阵的几种分解方式
      • 8.1.6 行列式和代数余子式
      • 8.1.7 向量
      • 8.1.8 矩阵的基本运算
      • 8.1.9 矩阵分析
      • 8.1.10 矩阵的LU分解
      • 8.1.11 矩阵奇异值分解(SVD)
        • 8.1.11.1 SVD分解2
        • 8.1.11.2 SVD分解逐步推导
        • 8.1.11.3 奇异值与特征值的意义
      • 8.1.12 随机向量
        • 8.1.12.1 随机过程简述
      • 8.1.13 投影矩阵和最小二乘
      • 8.1.14 知乎数学精选集
        • 8.1.14.1 高数问题集
      • 8.1.15 小波变换
      • 8.1.16 程序设计数学基础1:高等数学
      • 8.1.17 程序设计数学基础2:线性代数
      • 8.1.18 程序设计数学基础3:概率论和数理统计
      • 8.1.19 向量的距离与相似度计算
      • 8.1.20 复数
      • 8.1.21 高等数学——幂级数
      • 8.1.22 无穷小的本质
      • 8.1.23 数列极限和收敛性
      • 8.1.24 不定积分技巧总结
    • 8.2 有趣的数学题目
    • 8.3 高等数学
      • 8.3.1 泰勒级数
  • 9 路径规划与智能算法
    • 9.1 常见路径规划算法简介
    • 9.2 Dijkstra算法详细
  • 10 教学文档
    • 10.1 授课计划
    • 10.2 课程标准
Matlab图像处理进阶

                                     Matlab图像处理


参考:    https://www.cnblogs.com/tiandsp/p/14337176.html

1、图像处理基本函数

MATLAB图像处理函数:读取、写入、显示和修改图像

https://ww2.mathworks.cn/help/matlab/images_btfntr_-1.html

显示图像

imshow显示图像
image从数组显示图像
imagesc使用缩放颜色显示图像

读取、写入和修改图像

imread从图形文件读取图像
imresize调整图像大小
imtile将多个图像帧合并为一个矩形分块图
imwrite将图像写入图形文件
imfinfo有关图形文件的信息
imformats管理图像文件格式注册表

转换图像类型

frame2im返回与影片帧关联的图像数据
im2frame将图像转换为影片帧
im2java将图像转换 Java 图像
im2double将图像转换为双精度值
ind2rgb将索引图像转换为 RGB 图像
rgb2gray将 RGB 图像或颜色图转换为灰度图
rgb2ind将 RGB 图像转换为索引图像
getrangefromclass基于所属类的图像的默认显示范围

修改图像颜色

imapprox通过减少颜色数量来近似处理索引图像
dither转换图像,通过抖动提高表观颜色分辨率
cmpermute重新排列颜色图中的颜色
cmunique消除颜色图中的重复颜色;将灰度或真彩色图像转换为索引图像

属性

Image 属性图像的外观和行为


Image Processing Toolbox 本工具箱可执行图像处理、可视化和分析

https://ww2.mathworks.cn/help/images/index.html

Image Processing Toolbox™ 为图像处理、分析、可视化和算法开发提供了一套全面的参考标准算法和工作流 App。您可以使用深度学习和传统图像处理技术执行图像分割、图像增强、去噪、几何变换和图像配准。工具箱支持处理二维、三维和任意大的图像。

Image Processing Toolbox App 可让您自动完成常见的图像处理工作流。您可以交互方式分割图像数据、比较图像配准技术,以及对大型数据集进行批量处理。利用可视化函数和 App,您可以探查图像、三维体和视频;调整对比度;创建直方图;以及对关注区域 (ROI) 执行操作。


                                matlab影像处理

一、Introduction to digital image(介绍数字影像)


(一)Digital Image and Its Acquisition(数字图像及其采集)

1、An image is an artifact that depicts or records visual perception(图像是描述或记录视觉感知的人工制品)

2、Typically acquired by using charge-coupled device(CCD)or complementary metal-oxide-semiconductor(CMOS)device(通常通过电荷耦合器件(CCD)或互补金属氧化物半导体(CMOS)器件获得)




(二)Where Does the Color Come from?

1、Three kinds of light-sensitive photoreceptor cells in the human eye(i.e.,cone cells)respond most to red,green and blue(人眼中三种感光细胞(即视锥细胞)对红、绿、蓝的反应最为强烈)



(三)Typical RGB Image



(四)图像在MATLAB中的存储格式

Type of Digital Image

1、Binary(黑白图):Each pixel is just black or white(每个像素都是黑白的)

2、Grayscale(灰度图):Each pixel is a shade of gray,normal from 0(black)to 255(white)(每个像素都是灰色,数值一般在0到255之间)

3、True color or RGB(彩图):Each pixel has a particular color described by the amount of red,green and blue in it(每个像素都有一种特定的颜色,用其中的红、绿和蓝的数量来描述)


(五)Elements of Images(图像元素)

1、Binary(黑白图):



2、Grayscale(灰度图):



3、True color or RGB(彩图):




二、Read and show write image(图片的读取、显示、写入)

(一)读取与写入图像指令

1、读取图片:imread()

2、显示图片:imshow()

示例代码:

clc;
close all;
I = imread('Pout.tif');%read
imshow(I);%show

输出结果:



3、写入图片:imwrite() 将图像写入图形文件


语法

imwrite(A,filename)

说明

imwrite(A,filename) 将图像数据 A 写入 filename 指定的文件,并从扩展名推断出文件格式。imwrite 在当前文件夹中创建新文件。输出图像的位深取决于 A 的数据类型和文件格式。对于大多数格式来说:

如果 A 属于数据类型 uint8,则 imwrite 输出 8 位值。


如果 A 属于数据类型 uint16 且输出文件格式支持 16 位数据(JPEG、PNG 和 TIFF),则 imwrite 将输出 16 位的值。如果输出文件格式不支持 16 位数据,则 imwrite 返回错误。


如果 A 是灰度图像或者属于数据类型 double 或 single 的 RGB 彩色图像,则imwrite 假设动态范围是 [0,1],并在将其作为 8 位值写入文件之前自动按 255 缩放数据。如果 A 中的数据是 single,则在将其写入 GIF 或 TIFF 文件之前将 A 转换为 double。


如果 A 属于 logical 数据类型,则 imwrite 会假定数据为二值图像并将数据写入位深为 1 的文件(如果格式允许)。BMP、PNG 或 TIFF 格式以输入数组形式接受二值图像。


如果 A 包含索引图像数据,则应另外指定 map 输入参数。


如:将一个 50×50 的灰度值数组写入当前文件夹中的 PNG 文件。

A = rand(50);
imwrite(A,'myGray.png')


(二)Image Variable in Workspace(工作区中的图像变量)



1、示例代码:

whos

输出结果:



2、示例代码:

clc;
close all;
I0 = imread('Pout.tif');%read
imshow(I0);%show
I=I0 ;
for i = 1:size(I,1)
    for j = 1:size(I,2)
          if   (rem(i,2) == 0 && rem(j,2)==0)
                I(i,j) = 0;
          end
    end
end
imshow(I)

输出结果:

左边为原图,右边为偶数位置置0后的图片(这些位置为黑色)

                         

(三)Image Info:显示影像信息

示例代码:

imageinfo('pout.tif')

输出结果:


(四)Image Viewer(图像查看器)

Get pixel information in image viewer(在图像查看器中获取像素信息)

示例代码:

imtool('pout.tif')

输出结果:


(五)Image Processing(图像处理)

1、Any form of signal processing for which the input is an image(输入为图像的任何形式的信号处理)



注意:

noisy lena(透镜噪声)

Gaussian filter(高斯滤波)

median filter(中值滤波器)

Wiener filter(维纳滤波器)

三、Image arithmetic(影像四则运算)

(一)影像四则运算函数



(二)Image Multiplication:图像乘法 immultiply()

示例代码:

I = imread('rice.png');
subplot(1,2,1);
imshow(I);
J = immultiply(I,1.5);          %每个灰度都乘以1.5倍
subplot(1,2,2);
imshow(J);

输出结果:



Excise:How to reduce the brightness of the image?

答案代码:

I = imread('rice.png');
subplot(1,2,1);
imshow(I);
J = I ./ 3;%每个灰度都除以3
subplot(1,2,2);
imshow(J);

输出结果:



(三)Image Addition:图像加法 imadd()

示例代码:

I = imread('rice.png');
J = imread('cameraman.tif')
K = imadd(I,J);                %两个图像的矩阵大小要相同
subplot(1,3,1);imshow(I);
subplot(1,3,2);imshow(K);
subplot(1,3,3);imshow(J);

输出结果:



Practice

1、Adjust the “brightness”and“contrast”of rice.png and display it on the screen(调整rice.png 的“亮度”和“对比度”,并将其显示在屏幕上)

答案代码:

I=imread('rice.png');
subplot(1,3,1);imshow(I)  %显示原图
for i = 1:size(I,1)
    for j = 1:size(I,2)
        I1(i,j)=I(i,j) + 50;       %增加亮度
        I2(i,j)=I(i,j) .* 1.5;       %增加对比度
    end
end
subplot(1,3,2);imshow(I1)  %增加亮度
subplot(1,3,3);imshow(I2)  %增加对比度

输出结果:



(四)Image Histogram:图像直方图  imhist()

示例代码:

I = imread('Pout.tif');%read
subplot(1,2,1);
imshow(I);%show
subplot(1,2,2);
imhist(I)

输出结果:



======================================

                                直方图


直方图就是用来统计一幅图像各个亮度的像素的个数,并在一个2维图像上显示。横向(x轴方向)是灰度值,最左边像素值为0(黑),最右边像素值为255(白),纵向(y轴方向)是各像素值在图像中出现的个数。一张照片的明暗可以通过直方图看出来,也就是说我们可以通过直方图知道图像的欠曝和过曝。对于欠曝,形象的可以理解图像太暗了,过曝可理解为图像太亮了。

需要了解的是,相机在记录信息的时候会同时产生噪点。在较亮区域,因为记录下的光线多,所以噪点并不明显。而在较暗区域,相机记录的光线信号很少,噪点就会一下子突显出来。至于为什么在较暗的区域噪点会更明显的原因主要是,因为信噪比(芯片收到的光线信号与芯片本身噪点数量的比值)太低。所以在这种情况下,如果后期再对暗部提亮,噪点就会更加明显。

直方图如下:


那具体如何从直方图中得到这些信息?就需要简单地聊一聊。
直方图的x轴方向还可以被进一步地划分为5个区域,分别是:黑色,阴影,中间调,高光和白色。这只是一种感性的认识,至于说多大值称为阴影,完全在主观。


一张理想的图像应该是直方图堆积在中部,最左侧和最右侧都没有被切断。切断或者溢出,是指在直方图左右两个边缘,有很高的柱子堆积,也就是存在很多像素点在左(过暗)右(过亮)两边。
       一幅正常的图像的直方图:

一幅欠曝图像的直方图:在视觉上看整体偏暗。而在直方图中看,会看到最左边的像素很多。



        一幅过曝图像的直方图:在视觉上看整体很亮。而在直方图中看,最右边的像素(255附近)很多,使得那一块的柱形很高。


灰度直方图的作用

任何一幅图像都有灰度直方图,但相同的灰度直方图可能对应不同的图像,因为在形成灰度直方图的时候丢失了空间信息,即你并不能知道该灰度对应于图像中的位置





直方图应用:利用直方图进行图像中边界阈值的选择

这里写图片描述
我们可以看到(a)图对应的直方图有2个波峰,前一个波峰对应图像中比较暗的地方,这是由于它处于灰度级的低值部分决定的,实际也就是对应图像中的水体河流部分,我们将阈值选在2个波峰之间的波谷上,使得大于阈值的等于1,小于阈值的等于0,这样我们就可以提取出水体。



======================================


Practice

1、Plot the histograms of the images before and after the “brightness”and“contrast”adjustment for rice.png (在rice.png 的“亮度”和“对比度”调整前后绘制图像的直方图)

答案代码:

I=imread('rice.png');
subplot(2,3,1);imshow(I)%显示原图
for i = 1:size(I,1)
   for j = 1:size(I,2)
       I1(i,j)=I(i,j) + 50;%增加亮度
       I2(i,j)=I(i,j) .* 1.5;%增加对比度
   end
end
subplot(2,3,2);imshow(I1)%增加亮度
subplot(2,3,3);imshow(I2)%增加对比度
subplot(2,3,4);imhist(I);%原图的直方图
subplot(2,3,5);imhist(I1);%增亮的直方图
subplot(2,3,6);imhist(I2);%增对比度的直方图

输出结果:



(五)Histogram Equalization直方图均衡):histeq()

如果图像的对比度太差,常用的方法就是灰度直方图均衡化。在matlab中,能达到这个目的的函数就是histeq.那么直方图均衡化的原理是什么呢?下面就主要讲解一下: 

histeq的原理:



Matlab中的histeq函数——图像灰度直方图均衡化

首先来看一下没有进行灰度直方图均衡化的图片和经过灰度直方图均衡化后的图片的对比:



左为原图,右为经过灰度直方图均衡化处理后的图片,很显然,经过处理之后的图片在对比度方面有了显著的提升,下面附上两张图片的灰度直方图:



左图为原图像的灰度直方图,右图为处理后的图片的灰度直方图。从灰度直方图上来看,二者有很大的不同,特别是在灰度值处于100-255范围内的直方图,但细细观察我们会发现,右图相较于左图,其实可以看做是左图直方图的扩展,即原图像的直方图范围可能是0-80,经过均衡化后,将其范围扩展到0-255,因此,图像灰度直方图均衡化处理的关键点就在于扩充,即找到原图中某个灰度级的点在处理后图片中的位置并映射过去,从而达到扩充的目的。下面附上matlab源码:


function dst = my_histeq(src)

%histeq函数实现图片灰度直方图均衡化的原理


[m, n] = size(src);

dst = ones(m, n);

% 创建一个和原图像同等大小的矩阵

h = imhist(src);

I = length(h);


PDF = h/numel(src);

%概率密度PDF和概率分布函数CDF

CDF = cumsum(PDF);

j = CDF.*256;

% 取整扩展,结果是均衡化之后的灰度直方图

J = round(j);


for y = 1:m

    for x = 1:n

        src_y_x = src(y, x);

        % 原图中该点的灰度值

        dst(y, x) = J(src_y_x + 1);

        % 找到原图中该点的灰度值在概率分布函数中的值

    end

end




1、Enhances the contrast of the image(增强图像的对比度)

示例代码:

I=imread('pout.tif');
I2 = histeq(I);
subplot(1,4,1);imhist(I);
subplot(1,4,2);imshow(I);
subplot(1,4,3);imshow(I2);
subplot(1,4,4);imhist(I2);

输出结果:



2、Practice:Write your own equalization function,try it on pout.tif,and display it on the screen(编写自己的均衡功能,在pout.tif上尝试,并显示在屏幕上)

(1)Find the new gray level for each pixel(找到每个像素的新灰度)

(2)Write a loop to update the gray level of all the pixels(写一个循环来更新所有像素的灰度)

答案代码:(经典!)

f = imread('pout.tif');
[m,n]=size(f);
f1 = im2uint8(ones(m,n));     %将图像转换为 8 位无符号整数,创建一个纯1矩阵
h = imhist(f);      %h为I的直方图
I = length(h);      %将直方图的长度赋予f
%概率密度,表示对应的某一灰度级数在图片中出现的概率
fx = h / numel(f);    %计算数组元素的数目
%分布函数,某一灰度级数的分布函数值则表示小于等于该灰度级数的所有灰度值在图片中所占概率。
%(概率论课本上的)
FX=cumsum(fx);    %累积和
j = FX .* 256;
J = round(j);          %由于灰度级为1-256之间的整数,圆整

for i = 1:I                      %I = 256
   old = find(J == i);     %找出扩展后的级数对应的扩展前的级数
   L = length(old);
   for k=1:L                   %m每一个n*n的
         oldlocation = find(f == (old(k)-1));    %找到拓展前的灰度级数对应的像素点
         f1(oldlocation) = i;
   end

end
subplot(1,2,1),imhist(f1);
subplot(1,2,2),imshow(f1);


%chunchunlei_code20210422


clear
f0 = imread('pout.tif');
f=double(f0);
[m,n]=size(f);
f1 = uint8(ones(m,n));  
P_MAX=max(f(:));
P_MIN=min(f(:));
f1=uint8(round(255*(f-P_MIN)/(P_MAX-P_MIN)));
subplot(2,2,1),imhist(f0);
subplot(2,2,2),imshow(f0);
subplot(2,2,3),imhist(f1);
subplot(2,2,4),imshow(f1);


输出结果:



注意:这个不使用histeq()重在原理的理解,本人参考以下内容

MATLAB中histeq的原理以及自写的具体实现函数_matlab_yutong5818的博客-CSDN博客blog.csdn.net图标




                              直方图匹配

        https://blog.csdn.net/cjsh_123456/article/details/79218179

在上一篇中,我们使用matlab完成了直方图的均衡化,在这一篇中,我们要实现图像的直方图匹配。与直方图均衡不同的一点是,直方图匹配要得到的是具有特定形状的直方图的图像。

当图像中接近0的像素过多,进行直方图均衡的时候,会导致统计概率变大,直接映射到高灰度,直接导致图像整体变亮,达不到原来想要的结果,此时就需要使用直方图匹配,让变化后的图像具有特定的直方图。有时候,我们为了使两幅图像的色调保持一致,也可以采用该方法。

 直方图匹配的计算过程:


matlab代码如下:

1. 直方图匹配函数如下:

该匹配函数为histmatching, 输入需要进行直方图匹配的图像,模板直方图,输出为直方图匹配之后的图像,变换向量。

当给出模板图像时,需要在调用该函数之前使用imhist(I)作为函数的模板直方图。该函数使用灰度级别为256的灰度图像。

function [image_out, T3] = histmatching(image_in, hist)

% 直方图匹配(规定化)函数

% 输入为需要进行直方图匹配的灰度图像,模板直方图

% 输出为直方图匹配后的灰度图像,进行变换的向量。


% Level为灰度级别

% T1, T2分别为输入图像,模板直方图的均衡化用到的变换向量

% T3为输入图像匹配模板直方图用到的变换向量

Level = 256;

[m, n] = size(image_in);

image_hist = imhist(image_in);

image_out = image_in;


% 求解T1

ac1 = zeros(Level, 1);

T1 = zeros(Level, 1, 'uint8');

ac1(1) = image_hist(1);

for i = 2 : Level

    ac1(i) = ac1(i - 1) + image_hist(i);

end

ac1 = ac1 * (Level - 1);

for i = 1 : 256

    T1(i) = uint8(round((ac1(i)) / (m * n)));

end


% 求解T2

ac2 = zeros(Level, 1);

T2 = zeros(Level, 1, 'uint8');

ac2(1) = hist(1);

for i = 2 : Level

    ac2(i) = ac2(i - 1) + hist(i);

end

ac2 = ac2 * (Level - 1);

hist_sum = sum(hist);

for i = 1 : 256

    T2(i) = uint8(round((ac2(i)) / hist_sum));

end


% 求解T3

% T1映射到T2^(-1)时,若有多个值,选取最小的那个值。

% 产生0 到 255 之间的256个点,即产生0,1,2,...,255的大小为256的数组

temp = zeros(Level, 1, 'uint8');

T3 = T1;

for i = 1 : 256

    for j = 1 : 256

        temp(j) = abs(T1(i) - T2(j));

    end

    [~, B] = min(temp);

    T3(i) = B - 1;

end


% 根据T3转换输入图像的值

for i = 1 : m

    for j = 1 : n

        image_out(i, j) = T3(uint32(image_in(i, j)) + 1);

    end

end


end

 测试代码如下:

clear all;

clc;


image2 = imread('2.png');

image3 = imread('3.png');

hist3 = imhist(image3);

match1 = histeq(image2, hist3);

[match2, T] = histmatching(image2, hist3);

figure;

subplot(2, 4, 1), imshow(image2), title('原图像');

subplot(2, 4, 2), imshow(image3), title('模板图像');

subplot(2, 4, 3), imshow(match2), title('匹配后得到的图像');

subplot(2, 4, 4), imshow(match1), title('调用histeq的结果');

subplot(2, 4, 5), imhist(image2), title('原图像的直方图');

subplot(2, 4, 6), imhist(image3), title('模板图像的直方图');

subplot(2, 4, 7), imhist(match2), title('匹配后的直方图');

subplot(2, 4, 8), imhist(match1), title('调用histeq得到图像对应的直方图');



关于用到的matlab函数的一些说明:

1. [A, B] = min(V);  V为一个向量,函数返回值A表示V中最小的值,B表示该最小值的位置,当有多个最小值时,返回第一个出现的位置。

2. matlab的函数调用中,对于有多个返回值的函数,例如有2个返回值[A, B],若在之后的过程中不需要使用到所有的值,可以在接受时将相应位置的参数用~代替。例如代码中对于min(V)函数,我们不需要用到其最小值,只需要用到最小值所在的位置,可以用[~,B] = min(V)。若只需要用到前几个返回值,可以省略后面的。例如:[A] = min(V); 返回的是V的最小值(A = min(V) 与 [A] = min(V)等价)。

3. histeq函数(可以在matlab 通过 help histeq 查看该函数的相关说明)

J = histeq(I, hist);  I为输入图像,hist为匹配直方图,可以是用不同方式表示的灰度图像的直方图,例如doule/single类型(横坐标范围0~1),uint8类型(横坐标范围0~255),uint16和int16

J = histeq(I, n); 直方图均衡函数,I为输入图像,n为均衡后的灰度级别,缺省值为64。

[J, T] = histeq(I); T为将灰度图像I中灰度级映射到J中灰度级的灰度变换,值范围为[0, 1]。

另外,还有3个针对索引图像调色板的函数如下:

newmap = histeq(X,map,hgram)

newmap = histeq(X,map)

[newmap,T] = histeq(X,...)





(六)Geometric Transformation(几何变换):






1、Moving the coordinate(Not the gray-levels)of the pixels in an image(移动图像中像素的坐标(不是灰度))



2、Geometic Transformation Matrices(2D)


https://www.mathworks.com/help/images/performing-general-2-d-spatial-transformations.htmlwww.mathworks.com


(七)Image Rotation:图像旋转 imrotate()

示例代码:

I = imread('rice.png');
subplot(1,2,1);imshow(I);
J = imrotate(I,35,'bilinear');   %旋转35°
subplot(1,2,2);imshow(J);
size(I)
size(J)                                    %旋转后的影像会变大

输出结果:



Practice:In two dimensions,rotation of a point(x,y)for an angle θ“counter-clockwise”can be written as:(在二维中,一个点(x,y)的旋转角度θ“逆时针”可以写成:)



答案代码:

jiaodu=45;                           %要旋转的角度,旋转方向为顺时针
img=imread('rice.png');       %这里v为原图像的高度,u为原图像的宽度
subplot(121)
imshow(img);                       %这里y为变换后图像的高度,x为变换后图像的宽度
[h w]=size(img);

theta=jiaodu/180*pi;%转换为弧度
rot=[cos(theta) -sin(theta) 0;
   sin(theta) cos(theta) 0;
   0 0 1];
pix1=[1 1 1]*rot;               %变换后图像左上点的坐标
pix2=[1 w 1]*rot;               %变换后图像右上点的坐标
pix3=[h 1 1]*rot;               %变换后图像左下点的坐标
pix4=[h w 1]*rot;               %变换后图像右下点的坐标

height=round(max([abs(pix1(1)-pix4(1))+0.5 abs(pix2(1)-pix3(1))+0.5]));     %变换后图像的高度
width=round(max([abs(pix1(2)-pix4(2))+0.5 abs(pix2(2)-pix3(2))+0.5]));      %变换后图像的宽度
imgn=zeros(height,width);

delta_y=abs(min([pix1(1) pix2(1) pix3(1) pix4(1)]));            %取得y方向的负轴超出的偏移量
delta_x=abs(min([pix1(2) pix2(2) pix3(2) pix4(2)]));            %取得x方向的负轴超出的偏移量

for i=1-delta_y:height-delta_y
   for j=1-delta_x:width-delta_x
       pix=[i j 1]/rot;                                %用变换后图像的点的坐标去寻找原图像点的坐标,
       %否则有些变换后的图像的像素点无法完全填充
       float_Y=pix(1)-floor(pix(1));
       float_X=pix(2)-floor(pix(2));
       
       if pix(1)>=1 && pix(2)>=1 && pix(1) <= h && pix(2) <= w
           
           pix_up_left=[floor(pix(1)) floor(pix(2))];          %四个相邻的点
           pix_up_right=[floor(pix(1)) ceil(pix(2))];
           pix_down_left=[ceil(pix(1)) floor(pix(2))];
           pix_down_right=[ceil(pix(1)) ceil(pix(2))];
           
           value_up_left=(1-float_X)*(1-float_Y);              %计算临近四个点的权重
           value_up_right=float_X*(1-float_Y);
           value_down_left=(1-float_X)*float_Y;
           value_down_right=float_X*float_Y;
           
           imgn(i+delta_y,j+delta_x)=value_up_left*img(pix_up_left(1),pix_up_left(2))+ ...
               value_up_right*img(pix_up_right(1),pix_up_right(2))+ ...
               value_down_left*img(pix_down_left(1),pix_down_left(2))+ ...
               value_down_right*img(pix_down_right(1),pix_down_right(2));
       end
       
   end
end
subplot(122)
imshow(uint8(imgn))

输出结果:



注意:一般有 最邻近差值 与 双线性差值 两种方法

最邻近差值:

matlab练习程序(图像旋转,最邻近插值) - Dsp Tian - 博客园www.cnblogs.com

双线性差值:

matlab练习程序(图像旋转,双线性插值) - Dsp Tian - 博客园www.cnblogs.com图标

(八)Write Image:imwrite()

1、Format support:

'bmp'
'gif'
'hdf'
'jpg'
'jpeg'
'jp2'
'jpx'
'pcx'
'pnm'
'ppm'
'ras'
'tif'
'tiff'
'xwd'

示例代码:

imwrite(I,'pout2.png');  %上面示例的格式均可,不一定png


=============================================================


图像类和类型间的转换


im2uint8  将输入中所有小于0的设置为0,而将输入中所有大于1的设置为255 其他的所有乘以255

im2uint16  将输入中所有小于0的设置为0,而将输入中所有大于1的设置为65535

mat2gray   把一个double类的任意数组转换成值范围在[0,1]的归一化double类数组

im2double 将输入转换为double类.若输入是uint8类 uint16 类 logical类则函数将其转换为范围[0,1]之间的类.若输入是double类,则函数im2double将返回一个与输入相等的数组.

g=im2bw(f,T)将一副亮度图像f转换成一副二值图像g ,输出二值图像g中值为0的像素,对应于输入亮度图像f中值小于T的的像素点,输出二值图像g中的1对应于输入亮度图像中大于T的像素点..不管输入是何种数据类图像,T的取值必须在[0,1]内.

亮度变换函数
函数
imadjust是对灰度图像进行亮度转换的基本IPT工具
g=imadjust(f,[low-in   high-in],[low_out  high_out],gmma)

此函数将图像f中的亮度值映像到g中的新值,即将low_in至high_in之间的值的映射到low_out和high_out之间的值.low_in以下high_in以上的值被剪切了.   参数gamma给出曲线的形状.该曲线用来映射f的亮度值,以便生成图像g.若gamma小于1,则映射被加权至更高的输出值.



****************假设某图像数据A(uint8格式)**********************

>>A = uint8([235 200 89 20])
A =
  235  200  89  20
>> double(A)                 %返回与原矩阵数值相同但类型为double的矩阵;
ans =
   235   200 89   20
>> im2double(A)              
%返回矩阵类型:double;数值范围[0 1] ,0对应uint8中的0;1对应uint8中的255;
ans =
    0.9216    0.7843   0.3490    0.0784
>> mat2gray(A)                %对原矩阵归一化
ans =
    1.0000    0.8372   0.3209      0
****************假设矩阵A为一般二维数组,非图像数据(double格式)**********************
A =
   235   200    89    20 
>> double(A)
ans =
   235   200   89    20
>> im2double(A)
ans =
   235   200   89    20
>> mat2gray(A)
ans =
    1.0000    0.8372    0.3209      0 
**********************小结***************************
im2double:如果输入类型是uint8、unit16 、logical,则按照0-->>0,255-->>1,将其值按比例处理成0~1之间的double数值;如果输入类型是double,输出没有处理;
double:返回数值与输入相同的double类型矩阵;
mat2gray:对输入进行归一化处理,最小值-->>0;最大值-->>1,输出类型为double。
在实际的对图像处理过程中,由于我们读入图像是unit8型,而在MATLAB的矩阵运算中要求所有的运算变量为double型(双精度型)。因此通常使用im2double函数将图像数据转换成双精度型数据。


mat2gray

功能:将矩阵转化为灰度图像。
用法:I = mat2gray(A,[amin amax])        把一个double类的任意数组转换成取值范围为[0 1]的亮度图像。其中图像I的取值范围也在0(黑色)到1(白色)之间。参数amin和amax表示将A中小于amin的值转换为0,将A中大于amax的值转换为1。I = mat2gray(A)      将矩阵A中实际最小值和最大值分别赋给amin和amax。


>> A = randint(5, 5, [0 255])
A =
   208    24    40    36   167
   231    71   248   107     9
    32   140   245   234   217
   233   245   124   202   239
   161   247   204   245   173
>> mat2gray(A)
ans =
    0.8326    0.0628    0.1297    0.1130    0.6611
    0.9289    0.2594    1.0000    0.4100         0
    0.0962    0.5481    0.9874    0.9414    0.8703
    0.9372    0.9874    0.4812    0.8075    0.9623
    0.6360    0.9958    0.8159    0.9874    0.6862
>> im2double(A)
ans =
   208    24    40    36   167
   231    71   248   107     9
    32   140   245   234   217
   233   245   124   202   239
   161   247   204   245   173

mat2gray函数原理分析:

matlab里面很多函数都非常好用,但是当我们需要转化成C的时候就必须理解它的原理,mat2gray这个函数的原理经过单步调式发现其中有个函数imlincombc并没有提供源代码,这里我通过测试几组有意义的数据,基本弄明白了它的原理,具体算法步骤如下:
    
1、mat2gray是将输入数据F归一化为0-1之间的double型数据



==============================================================


影像处理二

graythresh()

T=graythresh() ,从灰度图像 I 计算一个全局阈值T,使用 Otsu的方法。这个方法是选择一个相对于黑像素和白像素最小的一个方差。全局阈值T可以用来将灰度图像转换为二值图像,使用 imbinarize. 阈值T肯定是属于 [0 1] 区间。


BW= imbinarize( I )

从2D 或 3D灰度图像 I 创建一个二值化图像,通过将所有数值用全局阈值转换为0 或者是1。


im2bw()

BW=im2bw(I ,level) , 将灰度图转换为二值化图像。通过将所有的像素用亮于 level 的变为1, 低于 level 的变为0。

I =imread('rice.png');

level=graythresh(I);    %计算最佳阈值

bw=im2bw(I,level);      %将灰度图转换为二值化图

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

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


一、Image thresholding(图像阈值化/二值化)

(一)Problem Setup

1、Count the rice grains and identify their sizes in this image(数一数米粒并确定它们的大小)

2、What are your strategies?



(二)Image Thresholding(图像阈值化/二值化)

1、A gray-level image can be turned into a binary image by using a threshold(使用阈值可以将灰度图像转换为二值图像)



示例代码:

I = imread('rice.png');
subplot(121);imshow(I);
subplot(122);imhist(I);

输出结果:



(三)graythresh()and im2bw()

1、graythresh() computes an optimal threshold level(计算最佳阈值级别)

2、im2bw() converts an images into binary image(将图像转换为二进制图像)



示例代码:

I = imread('rice.png');
level = graythresh(I);%找到最佳的二值化级
bw = im2bw(I,level);%将图像根据找到的I进行二值化
subplot(121);imshow(I);
subplot(122);imshow(bw);

输出结果:



(四)Practice:

1、Write a program to convert the image rice.png into a binary image using a threshold(编写程序,使用阈值将图像rice.png 转换为二进制图像)

2、Do NOT use im2bw()(不要用函数im2bw

3、Try different threshold values to see if you program works(尝试不同的阈值以查看程序的执行情况)

答案代码:

I = imread('rice.png');
[gaodu,kuangdu] = size(I);%将图片的高度(heigh)和宽度(width)存为变量
level = 100;                 %输入你所希望的阈值
for i = 1:gaodu
    for j = 1:kuangdu
        if I(i,j) > level    %若大于阈值,则为白色
            I(i,j) = 1;
        else                  %否则为黑色
            I(i,j) = 0;
        end
    end
end
I = uint8(I * 255);          %转为位图,1*255白色,0*255黑色
imshow(I)

输出结果:


level = 100时的效果


(五)Issue of the Binary Image(二值图像问题)

1、The binary image is not “perfect”(二值化不完美)

(1)Existing sparkles in the background(背景中现有的噪点)

(2)Some grains are missing(一些米粒消失了)

2、What is the cause of this issue?(什么原因导致这个问题)

3、How do we solve it?(如何解决)

二、Background estimation((在二值化过程中)背景估算)

(一)Background Estimation(预测背景)

1、Estimation for the gray level of the background:



示例代码:

I = imread('rice.png');
BG = imopen(I,strel('disk',15));%strel()与imopen()见注意事项
imshow(BG);

输出结果:



注意:

·strel('disk',15)。创建一个半径为15的圆盘形结构元素

如:



Morphological structuring element(形态学上的结构元素)


https://ww2.mathworks.cn/help/images/ref/strel.htmlww2.mathworks.cn



·imopen(I,strel('disk',15)),

以形态学的方式打开图片


Morphologically open image - MATLAB imopen - MathWorks 中国ww2.mathworks.cn图标


(二)Background Subtraction(背景相减)



示例代码:

I = imread('rice.png');
subplot(131);imshow(I);
BG = imopen(I,strel('disk',15));
subplot(132);imshow(BG);
I2 = imsubtract(I,BG);
subplot(133);imshow(I2);

输出结果:



(三)Thresholding on Background Removed Image(将背景移除图像)

示例代码:

I = imread('rice.png');
%% 直接使用graythresh给出的预估值进行二值化
level = graythresh(I);
bw = im2bw(I,level);
subplot(121);imshow(bw);
%% 先对图像进行除背景操作,并将背景与原图进行相减
BG = imopen(I,strel('disk',15));
I2 = imsubtract(I,BG);
%% 使用相减后的图像,然后通过graythresh函数进行二值化
level = graythresh(I2);
bw2 = im2bw(I2,level);
subplot(122);imshow(bw2);

输出结果:



(四)Now What?

1、Want to identify how many grains are there in the image(想知道图像中有多少谷粒)

How?



三、Connected-component labeling((图像处理过程中)连接点标签)

(一)A procedure for assigning a unique label to each object(为每个对象指定唯一标签的过程)



(二)Connected-component Labeling(Cont'd)

1、Finish labeling of a component(完成组件的标记)



2、Iterative process until all the pixel are checked(迭代过程,直到检查所有像素)



(三)Connected-component Labeling :bwlabel()

1、Built-in connected-component labeling algorithm(连通分量标注算法插件)

示例代码:

I = imread('rice.png');
BG = imopen(I,strel('disk',15));
I2 = imsubtract(I,BG);
level = graythresh(I2);
BW = im2bw(I2,level);
[labeled,numObjects] = bwlabel(BW,8);%8联通区域

输出结果:



注意:

·bwlabel(BW,8)函数,用于找联通区域



2、练习1:What is the size of the largest grain?

练习2:What is mean size of the grains?

答案代码:


I = imread('rice.png');
BG = imopen(I,strel('disk',15));
I2 = imsubtract(I,BG);
level = graythresh(I2);
BW = im2bw(I2,level);
[labeled,numObjects] = bwlabel(BW,8);
[heigh,width] = size(labeled);

largest = 0;%用于存储最大米粒的像素个数
sum = 0;%用于计算平均数前的总数
for num = 1:1:numObjects %用于迭代米粒的个数标号
    calc = 0;  %初始化每粒米个数
    for i = 1:1:heigh
        for j = 1:1:width
            if labeled(i,j) == num
                calc = calc + 1;
            end
        end
    end
    if calc > largest
        largest = calc;
    end
    sum = calc + sum;
end
largest
average = sum/numObjects

输出结果:



(四)Color-coding Objects:label2rgb()

1、Converts a label matrix into an RGB color image

2、Visualize the labeled regions

示例代码:


I = imread('rice.png');
BG = imopen(I,strel('disk',15));%得到背景
I2 = imsubtract(I,BG);%去除背景
level = graythresh(I2);%自动选取二值化的阈值
BW = im2bw(I2,level);%以level为阈值进行二值化
[labeled,numObjects] = bwlabel(BW,8);%以8联通计算米粒的个数
RGB_label = label2rgb(labeled);%将标签矩阵转换为RGB图像
imshow(RGB_label);

输出结果:



注意:

·label2rgb(labeled)将标签矩阵转换为RGB图像

(五)Practice

1、Plot the histogram of grain size(绘制米粒大小直方图)

2、Identify all the grains in the image by painting them in red(将图像中的所有颗粒涂成红色,以识别它们)



答案1:

I=imread('rice.png');

BG=imopen(I, strel('disk', 15));

I2=imsubtract(I, BG); level=graythresh(I2);

BW=im2bw(I2, level);

[labeled, numObjects]=bwlabel(BW, 8);


%% 直方图

num_of_lab = zeros(1,numObjects); %预为哈希表先分配空间

for i=1:size(labeled, 1)

    for j=1:size(labeled, 2)

        index = labeled(i,j);

        if index ~= 0 %如果该点不为0,即被标记了,对应该标记的米粒大小加一

           num_of_lab(index)=num_of_lab(index)+1; %思想类似哈希表

        end

    end

end

histogram(num_of_lab)


%% 上色

r = BW * 255; %把白色部分的red分量置为全红

g = zeros(size(BW)); %green分量和blue分量为全0

b = zeros(size(BW));

red_rice = cat(3,r,g,b); %将RGB三个分量拼接为一个三维的彩图矩阵

figure; imshow(red_rice)




答案2:

I=imread('rice.png');
BG=imopen(I, strel('disk', 15));
I2=imsubtract(I, BG); level=graythresh(I2);
BW=im2bw(I2, level);
[labeled, numObjects]=bwlabel(BW, 8);
No=zeros(1,99);
for i=1:256;
    for j=1:256;
        for n=1:numObjects;
            if labeled(i,j)==n;
                No(n)=1+No(n);
            else
            end
        end
    end
end
max(No)
mean(No)
perfectnum=0;
for k=1:99;
    if No(k)<80;
        perfectnum=perfectnum+0;
    else if No(k)>350;
            perfectnum=perfectnum+2;
        else perfectnum=perfectnum+1;
        end
    end
end
disp(perfectnum);
%以上为显示优化计算后的米的数量,下面显示柱状图与红米;
subplot(121);histogram(No);
RGB_label = label2rgb(BW,'flag','k');
subplot(122);imshow(RGB_label);

输出结果:



(六)Object Properties:regionprops()

1、Provides a set of properties for each connected component(为每个连接的组件提供一组属性)

示例代码:

I=imread('rice.png');
BG=imopen(I, strel('disk', 15));
I2=imsubtract(I, BG); 
level=graythresh(I2);
BW=im2bw(I2, level);
[labeled, numObjects]=bwlabel(BW, 8);
graindata = regionprops(labeled,'basic');        %'basic'基本属性
graindata(51)

输出结果:



注意:

·Centroid 中心点

·BoundingBox 边界框

(七)Interactive Selection:bwselect()

1、Lets you select object using the mouse

示例代码:

I=imread('rice.png'); level=graythresh(I);
BG=imopen(I, strel('disk', 15));
I2=imsubtract(I, BG); 
BW=im2bw(I2, graythresh(I2));
ObjI = bwselect(BW);
%显示图像后要需要点击图上的米,然后点击右键(或回车)后显示选中的图像
imshow(ObjI);

输出结果:






======================================================

======================================================


4.使用MATLAB分析图像:目标计数

我们想要通过MATLAB分析rice.png图片中米粒的个数.

在这里插入图片描述

图像预处理

要分析图像中的米粒个数,我们需要对图像进行两步预处理:

  1. 去除图像的背景:

    I = imread('rice.png');
    subplot(1,3,1); imshow(I);
    BG = imopen(I, strel('disk', 15));
    subplot(1,3,2); imshow(BG);
    I2 = imsubtract(I, BG);
    subplot(1,3,3); imshow(I2);

    在这里插入图片描述

  2. 对图像进行二值化:

    I2 = imsubtract(I, BG); level=graythresh(I2);
    bw2 = im2bw(I2, level);

下面代码展示了是否去除背景对图像二值化结果的影响:

% 直接对图像进行二值化
I = imread('rice.png'); 
level=graythresh(I); bw = im2bw(I, level);
subplot (1,2,1); imshow(bw); title('直接进行二值化');

% 去除背景后对图像进行二值化
BG = imopen(I, strel('disk', 15)); I2 = imsubtract(I, BG); 
level=graythresh(I2); bw2 = im2bw(I2, level);
subplot(1,2,2); imshow(bw2); title('去除背景后进行二值化');

在这里插入图片描述

目标计数:标记连通区域

识别米粒个数的关键在于识别连通区域.

在这里插入图片描述

在这里,我们使用MATLAB自带的bwlabel()函数计算连通区域,该函数使用了连通区域标记算法,将每个连通区域内的像素点赋值为同一个值.

在这里插入图片描述

I=imread('rice.png');
BG=imopen(I, strel('disk', 15));
I2=imsubtract(I, BG); level=graythresh(I2);
BW=im2bw(I2, level);
[labeled, numObjects]=bwlabel(BW, 8);

得到labeled为标记好的矩阵,其尺寸与原图片相同,每个连通区域都被赋值为一个相同的整数,其他区域被赋值为0.numObjects为计算出的连通区域个数,为99.

使用label2rgb()函数可以将标记结果以彩色图片的形式展示

RGB_label=label2rgb(labeled); 
imshow(RGB_label);

在这里插入图片描述

分析检测结果

使用regionprops()函数可以将检测结果封装成结构体数组.

graindata = regionprops(labeled, 'basic');
graindata(51)
       Area: 155
   Centroid: [112.4258 245.8645]
BoundingBox: [108.5000 234.5000 8 22]

使用bwselect()函数可以交互式选择连通区域

ObjI = bwselect(BW); 
imshow(ObjI);

在这里插入图片描述





==================================

==================================


Matlab中image、imagesc和imshow函数用法解析


1、显示RGB图像

相同点:这三个函数都是把m*n*3的矩阵中的数值当做RGB值来显示的。

区别:imshow将图像以原始尺寸显示,image和imagesc则会对图像进行适当的缩放(显示出来的尺寸大小)。

2、显示灰度图像

说明:先搞明白什么是索引图像?(灰度图像也是索引图像的一种)

  当用Matlab中的imread函数将图像读入并存入矩阵时,我们知道如果是RGB图像,得到是m*n*3的矩阵,但如果是索引图像,得到就是m*n的矩阵,这个矩阵的每个元素只是1个数值,那么怎么确定它的RGB值来显示图像呢?这就需要colormap了,colormap是一个m*3的矩阵,每一行有3列元素构成RGB组,也就是一种颜色,一个m*3的colormap中有m中颜色,而索引图像存储的数值和colormap中的行号对应起来就可以像RGB那样显示图片了,至于对应方法,可以直接对应(比如1对应1,2对应2)也可以是线性映射对应(比如[-128,128]映射到[1,256])。还有一点要说明的是,默认情况下每一个figure都有且仅有一个colormap,而且默认的是 jet(64),可在figure窗口通过,edit->colormap...查看,另外在弹出的窗口colormap editor中,可通过Tools->Standard colormap来修改当前figure的colormap,这里是Matlab已经做好的一些colormap。

(1)当灰度图像转化成矩阵后,矩阵中的元素都介于[0,255],下面我们结合具体实例来看看这三个函数的调用效果,并解释原因。代码:


  1. clear all;clc;close all;  

  2. img = imread('lenna.bmp');  

  3. % my picture is named lenna.bmp while yours may be not  

  4. I = rgb2gray(img);  

  5. % Attention: we use the axis off to get rid of the axis.  

  6. figure(1),image(I); %equals to imagesc(I,[1 64]);you can try it.  

  7. colorbar,title('show by image in figure1');axis off;  

  8. figure(2),imagesc(I);  

  9. %equals to imagesc(I,[min(I(:)) max(I(:))]);you can try it.  

  10. colorbar,title('show by imagesc in figure2');axis off;  

  11. %colormap(gray) %use this statement you can get a gray image.  

  12. figure(3),imshow(I),colorbar,title('show by imshow in figure3');  



显示效果:




     我们看到现象是image 和imagesc 显示出来是彩色的,只有imshow显示出来是灰度图像,为什么会出现这种情况呢?还记得前面所说的吗,索引图像是矩阵和colormap配合起来显示的,而每个figure默认使用的colormap jet(64),而不是gray(graygray(64)是一样的),这个jet(64)就使得figure1figure2中显示出来时是彩色的,当然你也可以修改当前figurecolormap使用colormap(gray)(使用64个等级的灰度色图),或者colormap(gray(256))(使用256个等级的灰度色图,这就是调用imshow函数时使用的colormap,后面有讲解)。而figure3为什么会是灰度图像呢,这是因为当调用imshow来显示索引图像时,这个函数就会把当前的figurecolormap设置成gray(256),这下明白为什么会出现这种情况了吧。我们再仔细观察一下figure1figure2会发现,figure2中人物的轮廓显示的还算可以,而figure1中则出现了大面积的红色的区域,人物的轮廓被抹掉了很多。

为什么会出现这样的情况呢?这就要说说索引图像矩阵中的数(以下简称矩阵中的数)和colormap中的索引(index)的对应关系了。


image这个函数,直接把矩阵中的数当做索引值(我称为直接映射),例如colormap中索引为1的是颜色RGB1,索引为2的是颜色RGB2,……,索引为64的是颜色RGB64。那么矩阵中为1的数就显示成颜色RGB1,矩阵中为2的数就显示成颜色RGB2,……,矩阵中为64的数就显示成颜色RGB64,值得注意的是当矩阵中的数小于1时,此时该数也将被显示成颜色RGB1,同样,而矩阵中大于64的数将被显示成颜色RGB64(类似于信号处理里面的限幅,也可以认为是削顶或者削底了),这下我们就能明白为什么figure1中会出现大面积的红色区域,这说明这些地方的数值都大于等于64

 

imagesc: figure2中我们用imagesc来显示图像与figure1相比能较好的显示出来,同样我们也得搞明白调用imagesc时矩阵的数和colormap中索引的对应关系,与image不同的是imagesc采用的不是直接映射而是线性映射,至于什么是线性映射,我粗略的说一下,比如把区间A = [0,a]映射到区间B = [0,b]我们对A中的元素做A/a*b就可以了,矩阵的数到colormap索引的线性映射大概就是这样,Matlab会自动获取矩阵中数的最小值和最大值,并把区间[Cmin,Cmax]映射到colormap[最小索引,最大索引]比如[1,64],然后再根据这个对应关系把图像显示出来,具体的算法细节是Matlab确定的,当然也可以自己指定显示范围,比如一副索引图像I范围为[27,218],而我只想显示[1 64 ],使用命令imagesc(I,[1 64])就可以了,如果你把上面程序中的imagesc(I)换成imagesc(I,[1,64]),那么figure2中的效果就和figure1中一样了,因为只是把[1,64]这个范围映射到色图,超过的都被认为是64。关于映射,我截图Matlabimageschelp页给大家看看,这里要自己慢慢体会哦,使用imagesc(I)这种线性映射就可以用到整个色图从而将图像较好的显示出来,这就是figure2中的显示效果比figure1中好的原因。




imshow调用这个函数会把当前figurecolormap设置成gray256,这个前面也有提到,我们先讨论矩阵元素是uint8型(范围:0~255,整数,一般使用imread和 rgb2gray返回的都是uint8型的),同样我们也要搞明白矩阵中的数和colormap中颜色索引的对应关系,imshow的功能是比较全的,它即可使用像image那样的直接映射,也可使用像imagesc那样的线性映射,当我们使用imshow(I),即只有一个矩阵作为参数,这时采用的是直接映射,比如矩阵中元素0就显示成colormap中索引为1的颜色也就是黑色,矩阵中元素255就显示成colormap中索引为256的颜色也就是白色,(注意:uint8范围是0~255,而gray256)的索引是1:256,当然这些我们只要了解就可以了,编程并不会用到,因为这些对应的细节Matlab已经帮我们做好了)如果这样调用imshow(I,[ ])此时矩阵中的数和颜色表就是线性映射,为什么会这样,我解释一下,我们看这种调用方式和imagesc(I,[1 64])很相似,其实原理是一样的,第二个参数是一个向量,这个向量指定了矩阵中映射到颜色表的数的范围,也就是显示范围(Matlab里叫做display range前面已经介绍了,Matlabimshowhelp中说如果采用imshow(I,[low high])调用imshow的话而且你用[ ]代替[low high]那么imshow会使用[min(I(:)) max(I(:))]作为显示范围,也就说I中的最小值会显示成黑色,最大值会显示成白色,这其实就是整个范围的线性映射(没有削顶也没有削底),此时的imshow(I,[ ])函数就相当于imagesc(I);


为了说明imshow不仅具有image的功能也具有imagesc的功能,同时体会一下直接映射和线性映射的区别,我们来写一段小程序来测试一下,程序如下:


clear all;clc;close all;  

  1. img = imread('lenna.bmp');  

  2.    

  3. I = rgb2gray(img);  

  4.    

  5. figure(1),image(I); colormap(gray(256));  

  6. colorbar,title('show by image in figure1');axis off;  

  7. figure(2),imagesc(I);colormap(gray(256));  

  8. % We can see that the image showed in figure(2) is a little bright  

  9. % than in figure(1).  

  10. colorbar,title('show by imagesc in figure2');axis off;  

  11. % When we use the imshow, we do not need to set the colormap,  

  12. % because the imshow set the colormap to gray(256) automatically.  

  13. figure(3),imshow(I),colorbar,title('show by imshow(I) in figure3');  

  14. % The effectiveness in figure(3) is the same as in figure(1).  

  15. figure(4),imshow(I,[]),colorbar,title('show by imshow(I,[]) in figure3');  

  16. % The effectiveness in figure(4) is the same as in figure(2).  


显示效果:





我们可以看出figure2中的图像比figure1中的图像要亮一些,而且,figure3中的显示效果和figure1中是一样的,figure4中的显示效果和figure2中是一样的,为什么会这样呢?这是因为image(I)imshow(I)是将I中的值直接作为colormap(gray(256))中的索引,也就是我所说的直接映射,我这里读到的索引图像矩阵也就是I中的数值的范围是[27,218],也就是说直接映射显示I,只用到的色图(colormap)[27,218]范围的颜色,(比如表示白色的索引255就没有用到),从右边的colorbar也可以看出来。但线性映射就不一样了,imagesc(I),imshow(I,[ ])采用的就是线性映射,线性映射把[27,218]按照线性算法(Matlab写的)映射到色图索引[1,256]然后再显示出来,这样整个色图的颜色都被用到了,这里也可以认为把[27,218]放大到[1,256],这就是figure2中显示效果比figure1中亮的原因。


小结:直接映射和线性映射的区别在于映射到色图的数值范围,如果是[min(I(:)) max(I(:))]就是线性映射,如果是0-255或者1-64或者0-1就是直接映射。这个数值范围就叫做显示范围(display range)。


3、最后再说说imageimagesc,imshow 在显示double型数据时的用法,

我们做图像处理就会对图像进行运算,使用uint8型数据精度不高,因为当运算结果超过255时会被认为是255,而负数就会被认为是0注意在Matlab中数据默认采用double型(64位)进行存储和运算)所以,我们读到灰度图像后一般都会将图像转换成double型(I = double(I))然后再参与运算,运算的结果有正有负,也有小数,正的还可能超过255,比如我经过运算后的得到图像矩阵I,假如I的范围是[-187,152],当然你也可以用max(I(:))min(I(:))去获取,这时怎么显示图像呢?image,imagesc,imshow 都可以用来显示double型数据的图像矩阵,主要区别如下:

imagedouble型数据取整(正数取整就是把小数部分舍掉)然后使用直接映射的方法按照颜色表显示。

imagesc这个函数很好,会对数据进行缩放再显示,也就是把显示范围自动设置成[min(I(:)) max(I(:))],也就是线性  映射。

imshow:这个函数调用方式不同,显示效果也不同,如下:

imshow(I)直接调用,因为当图像为double型时imshow函数会把显示范围设置成[0 , 1],这样小于0的就变成黑色了,大于1的就变成白色了,所以处理不当就会出现全白的情况。

imshow( I/(max(I(:)))针对直接调用imshow函数出现的问题,用max(I(:) ) 对图像矩阵进行归一化再显示,这样负数部分会变黑,正数部分还可以正常显示,但有一部分信息丢失了。

imshow(uint8(I))这种方式把I转化成uint8,负数会被归零,超过255的被置为255,而且小数也会被round(四舍五),当参数为uint8型时,imshow函数把显示范围设置成[0,255],这样图像虽然也能显示出来,但与原始数据相比来说,丢掉很多信息,但有时可能却是想要的结果,这个要看具体情况。

imshow(I,[ ])这种方式就是把imshow的显示范围设置成[min(I(:)) max(I(:))],也就是线性映射,相当于imagesc(I),colormap(gray(256))可以将整幅图像的信息显示出来。




imshow与image的用法小节:

相同点:

imshow与image都会产生一个image对象。

区别:

1. imshow的用法:

    1)imshow(路径与文件名字符串)

    2)imshow(图像矩阵)

    3)若当前figure存在坐标轴,imshow会将产生的image对象(即图像对象)显示在当前坐标轴内;

    若当前figure不存在坐标轴,imshow会产生一个隐藏的坐标轴,并将产生的 image 对象显示于其中;

    4)imshow不会扩展填充图像数据即不会拉伸图像使其铺满坐标轴而是改变坐标轴宽高比使其适应图像数据;

2. image的用法

   image不会改变坐标轴的大小尺寸而是扩展填充图像矩阵,使其铺满坐标轴区域

   image是用来显示附标图像,即显示的图像上有x,y坐标轴的显示,可以看到图像的像素大小。

3. imagesc的用法

   imagese函数具有image的功能,所不同的是imagesc函数还自动将输入数据比例化,以全色图的方式显示。

示例

close all; clear; clc
a=imread('andrew.jpg'); 
   
size(a)                               
class(a)
figure(1)
image(a) 
            % displays array a as image
axis image 
         % makes the pixels square
colormap(gray(256)) 
  % set standard 8-bit grayscale colormap



MATLAB中image和imshow都可以用来图像显示,image函数的语法调用常有以下几种格式:image(A);image(x,y,A);


其中,image(A)是将矩阵A 作为一个图像显示,A中的每一个元素都被指定一种颜色;image(x,y,A)其中的x,y分别表示显示图像左上角的坐标,其它与image(A)含义相同。当然image还有别的调用格式,这里先不一一介绍了。
对于imshow函数,它的调用格式常见的有:imshow(A,n);imshow(A,[low high]);imshow(BW)等。
其中,imshow(A,n)表示利用n个灰度等级来显示一幅灰度图像A,当忽略n时,对于24位显示系统来说n的默认值是256,对于其他系统n默认值是64.
imshow(A,[low high])表示显示灰度图像A,并且指定A的数据范围。A中的数据小于或者等于low的数值被显示为黑的,大于或者等于high的数值被显示为白的,属于区间[low high]的数值自动按照灰度等级进行显示。如果使用空矩阵‘[]’来代替[low high]的话,imshow函数此时自动设置为[min(A) max(A)]就是说,A中最小的值显示为黑色,最大值显示为白色。
imshow(BW)用于显示二进制图像BW,BW中数值为0的像素显示为黑色,数值为1的像素显示为白色。
所以,你说的这三种格式的函数处理图像的时候效果是不一样的,而且要注意处理的图像格式也有区别。


MATLAB图像处理——傅里叶变换

pic=imread(' F:\hua01.jpg ');    %读取自己的图片。

pic2=rgb2gray(pic);             %RGB彩图转灰度

F=fft2(pic2);                          %二维fft变换

F=fftshift(F);

F=abs(F);

F=mapminmax(F,0,1);

T=log(F+1);

T=mapminmax(T,0,1);

subplot(2,2,1); imshow(pic);   %彩图

subplot(2,2,2); imshow(pic2); %灰度图

subplot(2,2,3); imshow(F);    %fft之后图像的频谱分布

subplot(2,2,4); imshow(T);    %fft之后,数据经过log处理之后,图像的频谱分布




mapminmax介绍:

在利用matlab构建神经网络时,通常需要对数据预处理,一种方式就是将待处理数据归一化到[-1 +1],如没有指定YMIN和YMAX,默认情形下,将输入矩阵按行进行归一化映射,将输入矩阵中行元素的最小值映射为-1,行元素的最大值映射为+1。

默认:

(1)将矩阵的每行分别进行归一化;

(2)每行的最大值最小值作为每行归一化的xmin和xmax;

(3)将数据归一化到[-1,1].

若要将数据归一化到0到1之间,即y∈[0,1],使用

b = mapminmax(a,0,1);

————————————————



fftshift介绍:

在matlab中,经过fft变换后,数据的频率范围是从[0,fs]排列的。而一般,我们在画图或者讨论的时候,是从[-fs/2,fs/2]的范围进行分析。因此,需要将经过fft变换后的图像的[fs/2,fs]部分移动到[-fs/2,0]这个范围内。

而fftshift就是完成这个功能。通常,如果想得到所见的中间是0频的图像,经过fft变换后,都要再经过fftshift这个过程。



Matlab fftshift 详解

一.实信号情况

因为实信号以fs为采样速率的信号在 fs/2处混叠,所以实信号fft的结果中前半部分对应[0, fs/2],后半部分对应[ -fs/2, 0]

1)实信号fft的结果前半部分对应[0, fs/2]是正频率的结果,后半部分对应[ -fs/2, 0]是负频率的结果。大于fs/2的部分的频谱实际上是实信号的负频率加fs的结果。故要得到正确的结果,只需将视在频率减去fs即可得到频谱对应的真实负频率

2)如果要让实信号fft的结果与[-fs/2, fs/2]对应,则要fft后fftshift一下即可,fftshift的操作是将fft结果以fs/2为中心左右互换

3)如果实信号fft的绘图频率f从[-fs/2, fs/2],并且没有fftshift,则fft正频谱对应f在[0, fs/2]的结果将混叠到(f - fs/2)的位置;

fft负频谱对应f在[-fs/2, 0]的结果混叠到 f + fs - fs/2 的位置,注意这里f为负值,也就是说此种情况下fft负频谱对应的视在频率减去fs/2即可得到频谱对应的真实负频率

 

二.复信号情况

1)复信号没有负频率,以fs为采样速率的信号,fft的频谱结果是从[0,fs]的。

2)在 f> fs/2时,对复信号的fft结果进行fftshift会产生频率混叠(将下面的示例2中的频率从f=15改为f=85可以验证f=85的谱线在fftshift后跑到 f= -15 = 85 - fs = 85 - 100的位置了),所以复信号也一般要求 f <= fs/2

3)在对雷达的慢时间维(复信号)进行fft后,由于要用doppler= ((0:LFFT-1)/LFFT  - 0.5)*PRF; 计算多普勒频率,所以对该慢时间信号fft后要fftshift下,以便和正确的频率单元相对应。注意多普勒频率fd < = PRF/2 时才测的准!

fftshift

作用:将零频点移到频谱的中间

用法:

Y=fftshift(X)
Y=fftshift(X,dim)

描述:fftshift移动零频点到频谱中间,重新排列fft,fft2和fftn的输出结果。将零频点放到频谱的中间对于观察傅立叶变换是有用的。

示例1 -实信号的情况:

clf;

fs=100;N=256;   %采样频率和数据点数
n=0:N-1;t=n/fs;   %时间序列
x=0.5*sin(2*pi*15*t)+2*sin(2*pi*40*t); %信号

y1=fft(x,N);    %对信号进行快速Fourier变换
y2=fftshift(y1);

mag1=abs(y1);     %求得Fourier变换后的振幅
mag2=abs(y2);    

f1=n*fs/N;    %频率序列
f2=n*fs/N-fs/2;

subplot(3,1,1),plot(f1,mag1,'r');  %绘出随频率变化的振幅
xlabel('频率/Hz');
ylabel('振幅');title('图1:usual FFT','color','r');grid on;

subplot(3,1,2),plot(f2,mag1,'b');  %绘出随频率变化的振幅
xlabel('频率/Hz');
ylabel('振幅');title('图2:FFT without fftshift','color','b'); grid on;

subplot(3,1,3),plot(f2, mag2,'c');  %绘出随频率变化的振幅
xlabel('频率/Hz');
ylabel('振幅');title('图3:FFT after fftshift','color','c'); grid on;



结论:

1)如果期望绘制的幅频图的频率范围为0~fs,则无需运行fftshift变换,正频率对应在[0, fs/2],

大于fs/2的频谱的频率值为对应[-fs/2  , 0 ]负频率f + fs,注意f是负频率,是个负数。如图1。

2)如果期望绘制的幅频图的频率范围为-fs/2~fs/2,则需要运行fftshift变换,如图3;

如果不变换,图示的响应频点会发生变换,如图2,分析见顶端。

示例2 -复信号的情况:

close all; 

clear; 

clf;

fs=100;N=256;   %采样频率和数据点数
n=0:N-1;t=n/fs;   %时间序列
x=0.5*exp(j*2*pi*15*t)+2*exp(j*2*pi*40*t); %信号

y1=fft(x,N);    %对信号进行快速Fourier变换
y2=fftshift(y1);

mag1=abs(y1);     %求得Fourier变换后的振幅
mag2=abs(y2);    

f1=n*fs/N;    %频率序列
f2=n*fs/N-fs/2;

subplot(3,1,1),plot(f1,mag1,'r');  %绘出随频率变化的振幅
xlabel('频率/Hz');
ylabel('振幅');title('图1:usual FFT','color','r');grid on;

subplot(3,1,2),plot(f2,mag1,'b');  %绘出随频率变化的振幅
xlabel('频率/Hz');
ylabel('振幅');title('图2:FFT without fftshift','color','b') ; grid on;

subplot(3,1,3),plot(f2,mag2,'c');   %绘出随频率变化的振幅
xlabel('频率/Hz');
ylabel('振幅');title('图3:FFT after fftshift','color','c'); grid on;





我们知道Fourier分析是信号处理里很重要的技术,matlab提供了强大的信号处理能力,但是有一些细节部分需要我们注意。

记信号f(t)的起始时间为t_start, 终止时间为t_end, 采样周期为t_s, 可以计算信号的持续时间Duration为 t_end – t_start, 信号离散化造成的采样点数 N = Duration/t_s + 1;

根据Fourier分析的相关结论,我们知道时域的采样将会造成频域的周期化,该周期为采样频率f_s(著名的香农采样定理基于此).

于是, 经过matlab的fft函数处理后,得到数据的横坐标为0:f_s/(N-1):f_s。相关代码如下所示:

%matlab fft 测试代码


t_s = 0.01;        %把t_s 改更小试试?t_s就是采样时间间隔

t_start = 0.5; t_end = 5;
t = t_start:t_s:t_end;
y = 0.5*sin(2*pi*15*t)+2*sin(2*pi*40*t);
y_f = fft(y);

subplot(3,1,1);
plot(t,y); title('original signal');

Duration = t_end - t_start;
Sampling_points = Duration/t_s + 1;

f_s = 1/t_s;
f_x = 0:f_s/(Sampling_points-1):f_s;

subplot(3,1,2);
plot(f_x,abs(y_f)); title('fft transform');

subplot(3,1,3);
plot(f_x-f_s/2,abs(fftshift(y_f))); title('shift fft transform');



也就是说,如果我们不使用fftshift,其变换后的横坐标为0:f_s/(N-1):f_s, 如果使用fftshift命令,0频率分量将会移到坐标中心,这也正是matlab中帮助中心给出的意思:对fft的坐标进行了处理。实际上由于频谱的周期性,我们这样做是合理的,可以接受的。

请读者特别要注意横坐标的差别。另外,根据函数的特性,频谱应当只有在15Hz,40Hz出现峰值,但是fft变换后在60Hz,及85Hz处同样出现了峰值,应当可以从fft的计算过程中得到相应的解释(采样率不够高引起的)。

事实上,如果我们用15Hz,60Hz来测试fft变换,也即是 y = 0.5*sin(2*pi*15*t)+2*sin(2*pi*60*t);图像如下所示,没有任何变化。



t_s=0.001时的结果:





这种现象提醒我们,频率在f_s以内,即 0<f<f_s,f 以及 f_s – f 都有可能是测试信号的频率谱,这就给我们带来了歧义。并且从第三个子图也可以看出,这时候的fftshift会给我们带来错误的引导,也就是说,如果我们试图采样fft或者fftshift来分析信号的频率谱显得不那么靠谱了,matlab的fft谱线与信号的实际频率并不是一一对应的映射关系。这当然不是我们所期望看到的结果,所以实际分析信号时,有关这个问题需要额外的注意。

实际上,这也就间接地证明了Nyquist采样定理的合理性:采样频率要高于截止频率的两倍,上面的处理中我们所使用的采样频率为100Hz,于是当截止频率超过50Hz时,就会出现混叠效应,特殊情况就如上图所示:完全一样。于是,这也就告诉我们若要正确的显示频谱,需要仔细地考量采样频率与截止频率的关系,若太小,则有可能出现混叠,若太大,则计算代价过高。