(数字图像处理MATLAB+Python)第五章图像增强-第一节:图像增强概述和基于灰度级变换的图像增强

news2025/1/23 17:32:12

文章目录

  • 一:图像增强概述
  • 二:基于灰度级变换的图像增强
    • (1)线性灰度级变换
      • A:基本线性灰度级变换
      • B:分段线性灰度级变换
        • ①:定义
        • ②:截取式灰度变换
        • ③:窗切片
    • (2)非线性灰度级变换
      • A:对数变换
      • B:指数变换
      • C:幂次变换
      • D:程序

一:图像增强概述

图像增强(Image Enhancement):指不考虑图像降质原因,利用各种数学方法和变换手段,增强图像中人们感兴趣部分或提高有用的图像特征的清晰度。从图像质量来看,图像增强提高了图像的可懂度,改善了图像的视觉效果

例如在现实场景中,针对那些对比度较差、视觉效果不好的图像,我们就可以利用图像增强改善视觉质量

在这里插入图片描述

图像增强可分为如下几种

  • 基于灰度级变换的图像增强
  • 基于直方图修正的图像增强
  • 基于照度反射模型的图像增强
  • 基于模糊技术的图像增强
  • 基于伪彩色处理的图像增强
  • 其他图像增强方法

二:基于灰度级变换的图像增强

基于灰度级变换的图像增强:设原始图像为 f ( x , y ) f(x,y) f(x,y),增强后的图像为 g ( x , y ) g(x,y) g(x,y) T ( r ) T(r) T(r)表示灰度级变换函数,其中 r r r表示像素的灰度值。则增强后的图像可以表示为

g ( x , y ) = T ( f ( x , y ) ) g(x,y)=T(f(x,y)) g(x,y)=T(f(x,y))

其中, T ( r ) T(r) T(r)是一个非线性灰度级变换函数,它将原始图像的灰度级值映射到一个新的灰度级值。常见的灰度级变换函数包括线性变换、对数变换、幂次变换、伽马变换等。由于一般都是将过暗的图像灰度值进行重新映射,扩展灰度级范围,使其分布在整个灰度值区间,因此通常称为扩展

(1)线性灰度级变换

A:基本线性灰度级变换

基本线性灰度级变换 :设基本线性变换函数为 tan ⁡ α \tan \alpha tanα,有

  • α = 45 ° \alpha=45° α=45°:灰度范围不变
  • α > 45 ° \alpha>45° α>45°:拉伸灰度范围
  • α < 45 ° \alpha<45° α<45°:压缩灰度范围

g ( x , y ) = f ( x , y ) ⋅ tan ⁡ α g(x,y)=f(x,y)\cdot \tan \alpha g(x,y)=f(x,y)tanα

在这里插入图片描述

下图是一个变换示例
在这里插入图片描述

下图为实际效果

在这里插入图片描述

B:分段线性灰度级变换

①:定义

分段线性灰度级变换:设原始图像为 f ( x , y ) f(x,y) f(x,y),增强后的图像为 g ( x , y ) g(x,y) g(x,y),则有

g ( x , y ) = { c a f ( x , y ) 0 ≤ f ( x , y ) < a d − c b − a [ f ( x , y ) − a ] + c a ≤ f ( x , y ) < b L − 1 − d L − 1 − b [ f ( x , y ) − b ] + d b ≤ f ( x , y ) < L − 1 g(x, y)=\left\{\begin{array}{cc}\frac{c}{a} f(x, y) & 0 \leq f(x, y)<a \\\frac{d-c}{b-a}[f(x, y)-a]+c & a \leq f(x, y)<b \\\frac{L-1-d}{L-1-b}[f(x, y)-b]+d & b \leq f(x, y)<L-1\end{array}\right. g(x,y)= acf(x,y)badc[f(x,y)a]+cL1bL1d[f(x,y)b]+d0f(x,y)<aaf(x,y)<bbf(x,y)<L1

其中,参数a、b、c、d为确定三段线段斜率的常数

在这里插入图片描述

下图为具体实例

在这里插入图片描述

②:截取式灰度变换

若用户仅对感兴趣范围 [a, b) 线性拉伸,则:

在这里插入图片描述

实现如下效果

在这里插入图片描述


MATLAB实现:相关函数如下,具体解释可看MATLAB帮助手册

  • J= imadjust(I,[LOW_IN;HIGH_IN ], [LOW_OUT; HIGH_OUT], GAMMA )
  • NEWMAP= imadjust(MAP, [LOW_IN;HIGH_IN], [LOW_OUT;HIGH_OUT],GAMMA )
  • RGB2 = imadjust (RGB1,...)

imadjust是MATLAB中用于图像灰度级调整的函数,用于将图像的灰度级范围调整到指定范围。其函数原型如下

J = imadjust(I,[low_in high_in],[low_out high_out],gamma)

其中,I是输入的灰度图像,[low_in high_in]是输入灰度级范围,[low_out high_out]是输出灰度级范围,gamma是伽马变换参数。

imadjust函数的具体功能包括:

  • 将图像的灰度级范围调整到指定范围。
  • 增强图像的对比度。
  • 进行非线性的灰度级变换。

imadjust函数的参数[low_in high_in][low_out high_out]用于指定输入和输出的灰度级范围,可以控制输出图像的灰度级分布。参数gamma可以用于进行伽马变换,增强图像的暗部细节,同时保留图像的亮度信息

代码如下

Image=im2double(rgb2gray(imread('lotus.bmp')));%读取图像,灰度化并转换为double型
[h,w]=size(Image);   %获取图像尺寸
NewImage1=zeros(h,w);NewImage2=zeros(h,w); %新图像初始化  
NewImage3=Image;
a=30/256; b=100/256; c=75/256; d=200/256;  %参数设置         
for x=1:w
    for y=1:h
        if Image(y,x)<a 
            NewImage1(y,x)=Image(y,x)*c/a;
        elseif Image(y,x)<b
            NewImage1(y,x)=(Image(y,x)-a)*(d-c)/(b-a)+c;%分段线性变换
        else
            NewImage1(y,x)=(Image(y,x)-b)*(1-d)/(1-b)+d;
        end  
        if Image(y,x)>a && Image(y,x)<b
            NewImage3(y,x)=(Image(y,x)-a)*(d-c)/(b-a)+c; %高低端灰度保持
        end        
    end
end
NewImage2=imadjust(Image,[a;b],[c;d]);  %截取式灰度变换
imwrite(Image,'gray_lotus.bmp');
imwrite(NewImage1,'lotus1.bmp');
imwrite(NewImage2,'lotus2.bmp');
imwrite(NewImage3,'lotus3.bmp');
imshow(Image);title('原始lotus图像');
figure;imshow(NewImage1);title('分段线性灰度级变换图像');
figure;imshow(NewImage2);title('截取式灰度级变换图像');
figure;imshow(NewImage3);title('高低端灰度级保持不变图像');

Python实现:使用Python实现上述同样的功能

import cv2
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']

# Read the image and convert it to grayscale
image = cv2.imread('lotus.bmp')
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
image = image.astype('float64')/255.0

# Get the image size
h, w = image.shape

# Initialize new images
new_image1 = np.zeros((h, w))
new_image2 = np.zeros((h, w))
new_image3 = image.copy()

# Set the parameters
a = 30/256
b = 100/256
c = 75/256
d = 200/256

# Apply the gray level transformations
for x in range(w):
    for y in range(h):
        if image[y,x] < a:
            new_image1[y,x] = image[y,x]*c/a
        elif image[y,x] < b:
            new_image1[y,x] = (image[y,x]-a)*(d-c)/(b-a)+c
        else:
            new_image1[y,x] = (image[y,x]-b)*(1-d)/(1-b)+d
        if image[y,x] > a and image[y,x] < b:
            new_image3[y,x] = (image[y,x]-a)*(d-c)/(b-a)+c

new_image2 = cv2.convertScaleAbs(image, alpha=(d-c)/(b-a), beta=c-a*(d-c)/(b-a))

# Save the images
cv2.imwrite('gray_lotus.bmp', image*255.0)
cv2.imwrite('lotus1.bmp', new_image1*255.0)
cv2.imwrite('lotus2.bmp', new_image2)
cv2.imwrite('lotus3.bmp', new_image3*255.0)

# Display the images
plt.figure(figsize=(12, 10))
plt.subplot(2, 2, 1)
plt.imshow(image, cmap='gray')
plt.title('原始lotus图像')
plt.axis('off')

plt.subplot(2, 2, 2)
plt.imshow(new_image1, cmap='gray')
plt.title('分段线性灰度级变换图像')
plt.axis('off')

plt.subplot(2, 2, 3)
plt.imshow(new_image2, cmap='gray')
plt.title('截取式灰度级变换图像')
plt.axis('off')

plt.subplot(2, 2, 4)
plt.imshow(new_image3, cmap='gray')
plt.title('高低端灰度级保持不变图像')
plt.axis('off')

plt.show()

③:窗切片

窗切片(window slicing):是一种用于图像增强的特殊分段线性变换技术。在窗口切片中,输入图像的灰度级被分成多个区间,每个区间被映射到一个特定的输出灰度级范围内,使用户能够增强图像中特定灰度级范围内的细节

在这里插入图片描述

例如,假设我们有一张灰度级范围从0到255的输入图像,我们想增强中等灰度级范围内(即100-150)的细节。我们可以将灰度级分成三个区间:0-99、100-150和151-255。然后,我们可以分别对每个区间应用线性变换,将中间区间内的灰度级映射到更高的输出灰度级范围,同时保持其他区间内的灰度级不变。如果输入灰度级位于特定范围(即窗口)内,则输出灰度级将使用以下公式映射到新的范围内

  • x x x是输入灰度级
  • a a a b b b是窗口的下限和上限
  • c c c d d d是输出范围的下限和上限

f ( x ) = ( x − a ) ∗ ( ( d − c ) / ( b − a ) ) + c f(x) = (x - a) * ((d-c)/(b-a)) + c f(x)=(xa)((dc)/(ba))+c
实现如下效果

在这里插入图片描述

MATLAB实现

Image=im2double(imread('AG.jpg'));%读取图像并转换为double型
[h,w]=size(Image);   %获取图像尺寸
NewImage1=zeros(h,w);
NewImage2=Image;
a=170/256; b=200/256; c=90/256; d=250/256;  %参数设置         
for x=1:w
    for y=1:h
        if Image(y,x)<a 
            NewImage1(y,x)=c;
        else 
            NewImage1(y,x)=d;      %图5-6(a)窗切片方法  
        end  
        if Image(y,x)>c && Image(y,x)<a 
            NewImage2(y,x)=0;        %图5-6(b)窗切片方法
        end  
    end
end
imwrite(NewImage1,'AG1.bmp');
imwrite(NewImage2,'AG2.bmp');
imshow(Image);title('ACG图像');
figure;imshow(NewImage1);title('图5-6(a)窗切片图像');
figure;imshow(NewImage2);title('图5-6(b)窗切片图像');

Python实现

import cv2
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']

Image = cv2.imread('AG.jpg', cv2.IMREAD_GRAYSCALE).astype(np.float64) / 255.0
h, w = Image.shape[:2]

NewImage1 = np.zeros((h, w), dtype=np.float64)
NewImage2 = Image.copy()

a, b, c, d = 170/256, 200/256, 90/256, 250/256
for x in range(w):
    for y in range(h):
        if Image[y, x] < a:
            NewImage1[y, x] = c
        else:
            NewImage1[y, x] = d
        
        if Image[y, x] > c and Image[y, x] < a:
            NewImage2[y, x] = 0

cv2.imwrite('AG1.bmp', NewImage1*255.0)
cv2.imwrite('AG2.bmp', NewImage2*255.0)

plt.subplot(1, 3, 1), plt.imshow(Image, cmap='gray'), plt.title('ACG图像')
plt.subplot(1, 3, 2), plt.imshow(NewImage1, cmap='gray'), plt.title('图5-6(a)窗切片图像')
plt.subplot(1, 3, 3), plt.imshow(NewImage2, cmap='gray'), plt.title('图5-6(b)窗切片图像')
plt.show()

(2)非线性灰度级变换

A:对数变换

对数变换:设原始图像为 f ( x , y ) f(x,y) f(x,y),增强后的图像为 g ( x , y ) g(x,y) g(x,y),则有

g ( x , y ) = c ⋅ log ⁡ ( f ( x , y ) + 1 ) g(x,y)=c \cdot \log(f(x,y)+1) g(x,y)=clog(f(x,y)+1)

对数变换压缩图像高灰度区,扩展图像低灰度区,一般适用于处理过暗图像

在这里插入图片描述

B:指数变换

指数变换:设原始图像为 f ( x , y ) f(x,y) f(x,y),增强后的图像为 g ( x , y ) g(x,y) g(x,y),则有

g ( x , y ) = b c ⋅ [ f ( x , y ) − a ] = − 1 g(x,y)=b^{c \cdot [f(x,y)-a]}=-1 g(x,y)=bc[f(x,y)a]=1

指数变换扩展图像高灰度区,压缩图像低灰度区,一般适用于处理过亮图像

在这里插入图片描述

C:幂次变换

指数变换:设原始图像为 f ( x , y ) f(x,y) f(x,y),增强后的图像为 g ( x , y ) g(x,y) g(x,y),则有

g ( x , y ) = c ⋅ [ f ( x , y ) ] γ g(x,y)=c \cdot [f(x,y)]^{\gamma} g(x,y)=c[f(x,y)]γ

幂次变换常用于图像获取、打印和显示的各种装置设备的伽马校正,因此幂次变换也称为伽马变换

在这里插入图片描述

D:程序

实现如下效果
在这里插入图片描述


MATLAB实现

Image=(rgb2gray(imread('Goldilocks.bmp')));  
imwrite(Image,'GGoldilocks.bmp');
Image=double(Image);
NewImage1=46*log(Image+1);     %对数函数非线性灰度级变换
NewImage2=185*exp(0.325*(Image-225)/30)+1;%指数函数非线性灰度级变换
a=0.5; c=1.1;
NewImage3=[(Image/255).^a]*255*c;
imwrite(uint8(NewImage1),'Goldilocks1.bmp');
imwrite(uint8(NewImage2),'Goldilocks2.bmp');
imwrite(uint8(NewImage2),'Goldilocks3.bmp');
imshow(Image,[]);title('Goldilocks灰度图像');
figure;imshow(NewImage1,[]);title('对数函数非线性灰度级变换');
figure;imshow(NewImage2,[]);title('指数函数非线性灰度级变换');
figure;imshow(NewImage3,[]);title('幂次函数非线性灰度级变换');

Python实现

import cv2
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']

# 读取图像并转为灰度图
img = cv2.imread('Goldilocks.bmp')
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 保存灰度图
cv2.imwrite('GGoldilocks.bmp', img_gray)

# 将图像转为浮点型
img_gray = np.float32(img_gray)

# 对数函数非线性灰度级变换
new_img1 = 46 * np.log(img_gray + 1)

# 指数函数非线性灰度级变换
new_img2 = 185 * np.exp(0.325 * (img_gray - 225) / 30) + 1

# 幂次函数非线性灰度级变换
a = 0.5
c = 1.1
new_img3 = ((img_gray / 255) ** a) * 255 * c

# 保存变换后的图像
cv2.imwrite('Goldilocks1.bmp', new_img1)
cv2.imwrite('Goldilocks2.bmp', new_img2)
cv2.imwrite('Goldilocks3.bmp', new_img3)

# 显示原始灰度图像及变换后的图像
plt.figure()
plt.imshow(img_gray, cmap='gray')
plt.title('Goldilocks灰度图像')
plt.show()

plt.figure()
plt.imshow(new_img1, cmap='gray')
plt.title('对数函数非线性灰度级变换')
plt.show()

plt.figure()
plt.imshow(new_img2, cmap='gray')
plt.title('指数函数非线性灰度级变换')
plt.show()

plt.figure()
plt.imshow(new_img3, cmap='gray')
plt.title('幂次函数非线性灰度级变换')
plt.show()

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/433969.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【权限维持】LinuxOpenSSHPAM后门SSH软链接公私钥登录

文章目录 权限维持-Linux-替换版本-OpenSSH后门拓展玩法&#xff1a;OpenSSH后门的防范方法 权限维持-Linux-更改验证-SSH-PAM后门配置环境 权限维持-Linux-登录方式-软链接&公私钥&新帐号SSH软链接公私钥后门帐号 参考 权限维持-Linux-替换版本-OpenSSH后门 这里复现…

java 获取时间的方法

Java的时间是通过字节码指令来控制的&#xff0c;所以 java程序的运行时间是通过字节码指令来控制的。但是由于 Java程序在运行时&#xff0c; JVM会产生一些状态&#xff0c;所以在执行 JVM指令时&#xff0c; JVM也会产生一些状态。 我们在执行 java程序时&#xff0c;主要是…

JVM(面试问题简析)学习笔记

文章目录 1. JVM中有哪几块内存区域&#xff1f;Java 8 之后对内存分代做了什么改进&#xff1f;2. 你知道JVM是如何运行起来的吗&#xff1f;堆内存中对象的分配的基本策略&#xff1f;3. 说说 JVM 在哪些情况下会触发垃圾回收&#xff1f;JVM 的年轻代垃圾回收算法&#xff1…

【杂凑算法篇】密码杂凑算法的安全强度

【杂凑算法篇】密码杂凑算法的安全强度 杂凑&#xff08;哈希&#xff09;算法安全强度—【蘇小沐】 文章目录 【杂凑算法篇】密码杂凑算法的安全强度&#xff08;一&#xff09;安全强度&#xff08;Security Strength)&#xff08;二&#xff09;杂凑算法的安全强度与对比总…

x86汇编

寄存器 常规 AX累加&#xff0c;算术运算或函数返回值存储 基址寄存器(BX)&#xff0c;指向数据的指针 计数寄存器CX&#xff0c;移位&#xff0c;循环&#xff0c;一些量 数据寄存器DX&#xff0c;运算超过16位&#xff0c;高16位放在DX 堆栈指针寄存器SP&#xff0c;用于指向…

系统设计访谈-业内人事指南 《System Design Interview-An insider‘s guide》中文版

前言&#xff1a; We are delighted that you have decided to join us in learning the system design interviews. System design interview questions are the most difficult to tackle among all the technical interviews. The questions require the interviewees to de…

(Qt) 重定向内置日志

文章目录 前言代码.pri 独立的包log.priLOG_Config.hppLOG.hLOG.cpp examplelog_test.promain.cpp 使用效果debug模式release模式 分析Qt内部结构核心函数核心配置 END 前言 在软件开发过程中&#xff0c;避免不了日志的使用。 在Qt中&#xff0c;我们平常用的#include <Q…

Django | 解决admin增加新用户只有用户名密码和确认密码的问题

文章目录 如图所示&#xff0c;下面给出解决方案&#xff1a; 如果您使用 使用 Django 默认的后台管理界面添加用户时&#xff0c;只看到了三个字段&#xff08;通常是 username、password和 repassword&#xff09;&#xff0c;那么可以通过定义 add_fieldsets 属性来增加更多…

Jenkins关联GitLab

1、Jenkins、GitLab服务器上面生成公钥、私钥 ssh-keygen -t ecdsa # 回车 指到没有交互式2、GitLab WEB端添加 刚刚生成的公钥 cat ~/.ssh/id_ecdsa.pub # 查看密钥登入gitlab > 右上角头像 > 偏好设置 > SSH秘钥 使用相同方法 添加Jenkins秘钥 3、Jenkins创建一…

Graph push pull

图数据的存储结构 键值对存储因具有可扩展强、结构简单、查找迅速等特点被广泛应用于图查询系统中&#xff0c;如Wukong、Trinity.RDF。在Wukong系统中&#xff0c;图上的边会转换成键值对进行存储&#xff0c;将顶点编号、边的类型、边的方向、值的地址和大小等信息组合成键&…

Bitmap 实现当前在线用户数量

Bitmap是什么&#xff1f; Bitmap是Redis中的一种数据结构&#xff0c;它是一个类似于位数组的数据结构&#xff0c;用于处理位数据。在Redis中&#xff0c;Bitmap是使用字符串来存储的&#xff0c;一个Byte可以存储8个二进制位&#xff0c;一个字符串可以存储232个二进制位&a…

成功解决:NLTK包的安装错误

成功解决NLTK包的安装错误 创建环境NLP_Pre_train l环境 conda create -n NLP_Pre_train python3.8激活 conda activate NLP_Pre_train安装NLTK&#xff0c;套用以下命令 pip install NLTK之后是验证NLTK是否安装成功&#xff0c;采用的步骤如下所示&#xff1a; import n…

认识Java文件操作和IO流

文件操作&#xff08;一&#xff09; 文章目录 文件操作&#xff08;一&#xff09;文件的特性路径文件分类File类的使用文件的创建文件的删除文件创建加目录创建列出当前文件夹包含的文件文件重命名函数 文件的特性 我们所说的文件一般指的是硬盘文件&#xff0c;其实文件不止…

Minio对象存储服务介绍、单机和集群部署及其使用

Minio对象存储服务介绍、单机和集群部署及其使用 前言Minio简介Minio版本选择AGPL协议说明Minio优缺点优点缺点 Minio分server 和clientminio-client下载二进制文件查看 mc 版本 Minio分布式集群详细搭建基础环境操作系统Minio下载 准备工作1、机器资源2、创建相关目录3、创建启…

IOC容器与DI依赖注入示例

IOC容器与DI依赖注入示例 IOC深入理解IOC示例&#xff1a; DI深入理解DI示例 IOC深入理解 我们先通过几个问题来加深一下对IOC的理解 (1)Spring是使用IOC容器来管理bean对象的&#xff0c;我们主要管理什么? 主要管理项目中所使用到的类对象&#xff0c;比如(Service层对像和…

哈希表|STL使用

哈希表 时间复杂度为O(1) 拉链法 把X代表的数字映射到N所在区间&#xff0c;有可能会发生冲突俩个或多个数字映射到1个数 拉链法&#xff1a;把冲突的数字挂起来&#xff0c;用单链表挂起来 一般取模的数要取成质数&#xff0c;而且这个质数离二的n次幂要比较远&#xff0c;这样…

什么是深度学习?

目录 简介 深度学习的由来 深度学习未来的趋势 总结 简介 深度学习是在20世纪80年代被提出来的&#xff0c;主要是由加拿大的计算机科学家Geoffrey Hinton、Yoshua Bengio、Yann LeCun等人发起的。Geoffrey Hinton等人在经过多年的研究和实践之后&#xff0c;…

C语言的指针(进阶)

目录 数组指针 数组指针的使用 函数指针 函数指针数组 指向函数指针数组的指针 回调函数 数组指针 数组指针是指针&#xff1f;还是数组&#xff1f; 答案是&#xff1a;指针 数组指针也就是指向一个数组的指针 看下面两条代码&#xff1a; int *p1[10]; int (*p2)[10]; …

Manjaro安装clash-for-windows-bin

安装 安装Clash for Windows yay -S clash-for-windows-bin 配置 命令行进入~/.config/clash/ &#xff0c;配置文件 config.yaml 和 Country.mmdb wget -O config.yaml [订阅链接]wget -O Country.mmdb https://gitee.com/mirrors/Pingtunnel/raw/master/GeoLite2-Country.…

领导给了一千多个需求,这个排序法救了我的命……

什么是MoSCoW排序法&#xff1f; 莫斯科排序法是一种优先级排序法&#xff0c;用于管理需求、任务或功能列表。该方法可以帮助团队确定哪些需求、任务或功能是最重要的&#xff0c;并决定在特定时间段内是否需要完成它们。 所以在对需求进行排序时&#xff0c;可以从以下维度…