python实现直方图均衡化,理想高通滤波与高斯低通滤波

写在前面

HIT大三上学期视听觉信号处理课程中视觉部分的实验二,经过和学长们实验的对比发现每一级实验要求都不一样,因此这里标明了是2019年秋季学期的视觉实验二。

由于时间紧张,代码没有进行任何优化,实验算法仅供参考。

实验要求

  1. 实现图像直方图均衡化,要求显示均衡化前、后直方图以及均衡化后图像。
  2. 对单通道图像进行DFT变换,要求显示幅度图和相位图,并设计理想高通滤波器和高斯低通滤波器对图像进行频域滤波,并显示滤波之后的图像。 注:除DFT和IDFT外,不允许调库

实验代码

代码首先贴在这里,仅供参考

源代码

首先是实现图像直方图均衡化的代码

from ReadBmp import ReadBmp
import matplotlib.pyplot as plt
import  numpy as np

filename1 = "1.bmp"
bmp = ReadBmp(filename1)
bmp.gray()

# 统计各像素点数
h = np.array([0 for i in range(256)])
h1 = []
for pixel in bmp.data:
    h[pixel[0]] = h[pixel[0]] + 1
    h1.append(pixel[0])
# 画出原先的直方图
plt.subplot(1,2,1)
plt.hist(h1, bins = 256)

# 归一化
hs = h / len(bmp.data)
# 计算累计分布
hp = np.array([0.0 for i in range(256)])
for i in range(256):
    hp[i] = np.round(np.sum(hs[0:i+1]) * 255)
T = hp.astype('uint8')

# 创建新图像,并统计新图像的各个像素点的个数
hn = np.array([0 for i in range(256)])
h2 = []
for pixel in bmp.data:
    s = T[pixel[0]]
    pixel[0] = s
    pixel[1] = s
    pixel[2] = s
    hn[pixel[0]] = hn[pixel[0]] + 1
    h2.append(s)
bmp.creataBmp("2.bmp")
# 画出新图像的直方图
plt.subplot(1,2,2)
plt.hist(h2, bins = 256)
plt.show()

其中读取bmp图像的程序是我自己写的,这里不再赘述(直接调用了实验一写好的bmp文件读取程序,具体代码见github)

然后是理想高通滤波和高斯低通滤波的程序

import numpy as np
import cv2
import matplotlib.pyplot as plt

def IdealHighPassFiltering(f_shift):
    # 设置滤波半径
    D0 = 8
    # 初始化
    m = f_shift.shape[0]
    n = f_shift.shape[1]
    h1 = np.zeros((m, n))
    x0 = np.floor(m/2)
    y0 = np.floor(n/2)
    for i in range(m):
        for j in range(n):
            D = np.sqrt((i - x0)**2 + (j - y0)**2)
            if D >= D0:
                h1[i][j] = 1
    result = np.multiply(f_shift, h1)
    return result

def GaussLowPassFiltering(f_shift):
    # 设置滤波半径
    D0 = 8
    # 初始化
    m = f_shift.shape[0]
    n = f_shift.shape[1]
    h1 = np.zeros((m, n))
    x0 = np.floor(m/2)
    y0 = np.floor(n/2)
    for i in range(m):
        for j in range(n):
            D = np.sqrt((i - x0)**2 + (j - y0)**2)
            h1[i][j] = np.exp((-1)*D**2/2/(D0**2))
    result = np.multiply(f_shift, h1)
    return result

img =cv2.imread('1.bmp',0)
f=np.fft.fft2(img)
f_shift=np.fft.fftshift(f)
# 幅度图
s= np.log(abs(f_shift))
# 相位图
p= abs(np.angle(f_shift))
plt.subplot(2,2,1)
plt.imshow(s, 'gray')
plt.subplot(2,2,2)
plt.imshow(p, 'gray')

# 理想高通滤波
IHPF = IdealHighPassFiltering(f_shift)
new_f1 = np.fft.ifftshift(IHPF)
new_image1 = np.uint8(np.abs(np.fft.ifft2(new_f1)))
plt.subplot(2,2,3)
plt.imshow(new_image1, 'gray')
# 高斯低通滤波
GLPF = GaussLowPassFiltering(f_shift)
new_f2 = np.fft.ifftshift(GLPF)
new_image2 = np.uint8(np.abs(np.fft.ifft2(new_f2)))
plt.subplot(2,2,4)
plt.imshow(new_image2, 'gray')
plt.show()

实验结果

实验结果的图像如下图所示

这是直方图均衡化的运行结果,其中左图是做直方图均衡化前对像素统计的直方图,右图是做直方图均衡化后对像素统计的直方图

这是画出图像的幅度图和相位图,对图像做理想高通滤波和高斯低通滤波的结果,其中1是幅度图,2是相位图,3是理想高通滤波的结果,4是高斯低通滤波的结果

要点讲解

关于实验算法的大致流程,已在程序中用注释标明,这里只记录需要注意的地方

  1. 在直方图均衡化中,要注意直方图函数的用法,该函数可以对输入的矩阵中的数值进行自动的分类,而不用手动分好之后再用直方图函数去画,之前没有仔细看该函数的用法,导致找了好长时间没找到问题。
  2. 关于直方图均衡化的原理,需要一定的数学公式的推导,然而其结论十分简单,只有一个公式,对理解公式推导无需求的直接拿公式来用就可以了。(即程序中的归一化加计算累积分布部分)
  3. 关于理想高通滤波和高斯低通滤波,可以看到其代码大体框架是一致的,只有中间if语句中的判断条件不一样,理解原理之后直接替换if语句即可。
  4. 最终画出理想高通滤波的图像时,网上给出的一些运行结果可能和我们运行的不一致,类似于下图中图一的图像,原因在于这一句话中:new_image1 = np.uint8(np.abs(np.fft.ifft2(new_f1))),注意到中间调用了np.abs()函数,由于经过DFT变换之后所得的数值是复数,而不是实数,若将np.abs()替换为np.real(),即只取其实部,则得到的是图一,而使用np.abs(),得到的则是图二。个人感觉图二才是相对正确一些的结果,图一相当于将虚部舍弃掉了,这是不太好的。

以下是图一

以下是图二

知识总结

关于直方图均衡化的数学原理,我参考的是这篇博客。直方图均衡化的公式推导较为复杂,然而其结果却十分简单,因此在python中一个循环就实现了。
直方图均衡化的数学原理

关于如何画直方图,参考的是这两篇博客
python之matplotlib.pyplot直方图

关于相位图和振幅图的画法,参考的是下面这两篇博客
python opencv dft
进行傅里叶变换,画出幅值谱图、相位谱图以及实现位移后的幅值谱图和相位谱图
案例解释图像傅里叶变换的幅度谱和相位谱的以及反变换

关于理想高通和高斯低通滤波器的实现,参考的是以下这几篇博客
理想高通滤波器
理想低通滤波器、Butterworth滤波器和高斯滤波器(matlab)

其中在理想高通和高斯低通滤波器中,需要用到矩阵乘法,关于几种不同的矩阵乘法参考的是这篇博客
numpy 三种矩阵乘法

实验总结

很简单的一个实验,总时间加起来大致4个小时左右,做这么快的主要原因是,本来同学来哈尔滨找我玩,正玩得开心,结果突然告诉我这个实验要今天晚上交(之前以为这个实验还有一周的ddl),所以潜能爆发,从三点写到六点差不多就写完了

原文地址:https://www.cnblogs.com/fyunaru/p/12103287.html

时间: 2024-08-03 13:42:47

python实现直方图均衡化,理想高通滤波与高斯低通滤波的相关文章

图像处理之基础---高斯低通滤波在指定区域画放大圆形图

像淘宝中的物品图片进行放大扫描效果: 上图中图一为原图,现给定素材,需要将图像画城图二然后输出.现在问题是,给定的图像都是矩形,怎么将矩形的图片画到中间的那两个圆里面呢? http://download.csdn.net/detail/raistlic/5054386 代码 http://bbs.csdn.net/topics/390363649

数学之路-python计算实战(14)-机器视觉-图像增强(直方图均衡化)

我们来看一个灰度图像,让表示灰度出现的次数,这样图像中灰度为 的像素的出现概率是  是图像中全部的灰度数, 是图像中全部的像素数,  实际上是图像的直方图,归一化到 . 把  作为相应于  的累计概率函数, 定义为:  是图像的累计归一化直方图. 我们创建一个形式为  的变化,对于原始图像中的每一个值它就产生一个 ,这样  的累计概率函数就能够在全部值范围内进行线性化,转换公式定义为: 注意 T 将不同的等级映射到  域.为了将这些值映射回它们最初的域,须要在结果上应用以下的简单变换: 上面描写

Python实现图像直方图均衡化算法

title: "Python实现图像直方图均衡化算法" date: 2018-06-12T17:10:48+08:00 tags: [""] categories: ["python"] 效果图 代码 #!/usr/bin/env python3 # coding=utf-8 import matplotlib.image as mpimg from matplotlib import pyplot as plt import sys impor

《OpenCV:直方图应用:直方图均衡化,直方图匹配,对比直方图》

直方图均衡化 直方图均衡化(Histogram Equalization)是直方图最典型的应用,是图像点运算的一种.对于一幅输入图像,通过运算产生一幅输出图像,点运算是指输出图像的每个像素点的灰度值由输入像素点决定,即: 直方图均衡化是通过灰度变换将一幅图像转换为另一幅具有均衡直方图,即在每个灰度级上都具有相同的象素点数过程.从分布图上的理解就是希望原始图像中y轴的值在新的分布中尽可能的展开.变换过程是利用累积分布函数对原始分布进行映射,生成新的均匀拉伸的分布.因此对应每个点的操作是寻找原始分布

直方图均衡化会造成灰度级的合并【伪轮廓】

均衡化处理后的图象只能是近似均匀分布.均衡化图象的动态范围扩大了,但其本质是扩大了量化间隔,而量化级别反而减少了, 因此,原来灰度不同的象素经处理后可能变的相同,形成了一片的相同灰度的区域,各区域之间有明显的边界,从而出现了伪轮廓. 如果原始图像对比度本来就很高,如果再均衡化则灰度调和,对比度降低.在泛白缓和的图像中,均衡化会合并一些象素灰度,从而增大对比度.均衡化后的图片如果再对其均衡化,则图像不会有任何变化. 灰度直方图均衡化的算法,简单地说,就是把直方图的每个灰度级进行归一化处理,求每种灰

图像直方图与直方图均衡化

图像直方图与直方图均衡化 图像直方图以及灰度与彩色图像的直方图均衡化 图像直方图: 概述: 图像的直方图用来表征该图像像素值的分布情况.用一定数目的小区间(bin)来指定表征像素值的范围,每个小区间会得到落入该小区间表示范围的像素数目. 图像直方图图形化显示不同的像素值在不同的强度值上的出现频率,对于灰度图像来说强度范围为[0~255]之间,对于RGB的彩色图像可以独立显示三种颜色的图像直方图. 同时直方图是用来寻找灰度图像二值化阈值常用而且是有效的手段之一,如果一幅灰度图像的直方图显示为两个波

学习笔记(二)——直方图均衡化和匹配

? 本文为原创作品,转载请注明出处 欢迎关注我的博客:http://blog.csdn.net/hit2015spring 和 http://www.cnblogs.com/xujianqing/ 作者:许剑清???? (叶舞清风) ? ? 本文的学习是基于冈萨雷斯<数字图像处理第二版>这本专著的对应于书中章节3.3 这一篇文章如题,主要是讲直方图均衡化和匹配的一些基本概念.不涉及很多的技术问题专业数学推导,只是为入门图像处理做一个感性的认识,具体应用请朋友们自己发挥创造,欢迎大家一起来交流.

灰度直方图均衡化的算数推导

首先考虑连续函数并且让变量r表示待增强图像的灰度级.假设r被归一化到[0,1],且r=0表示黑色,r=0表示白色. 对于连续函数,假设其变换函数为 (公式一) 在原始图像中,对于每一个r对应着一个灰度值s.其中变换函数要满足以下条件: T(r)在[0,1]中为单值,且单调递增. 当0<=r<=1时,0<=T(r)<=1.这样保证输出的灰度级与输入的灰度级有同样的范围. 把公式一的逆函数表示为 (公式二) 令Pr(r)和Ps(s)分别表示随机变量r和s的概率密度函数.由基本概率理论得

opencv直方图均衡化

#include <iostream> #include "highgui.h" #include "cv.h" #include "cxcore.h" #include "math.h" using namespace std; using namespace cv; //绘制1维直方图 Mat draw1DHistogram(Mat histogramMat) { double maxVal = 0, minV