OpenCV计算机视觉实战(Python)_08-直方图与傅里叶变换
2021/8/7 11:06:01
本文主要是介绍OpenCV计算机视觉实战(Python)_08-直方图与傅里叶变换,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
什么是histogram?
- 它可以给出图像的密度分布的总体概念,它的x轴是像素值(0到255)y轴是对应的像素在图像里的数量。
- 看histogram你可以得到对比度,亮度,密度分布等直观信息。今天的所有图像处理工具都提供了histogram属性,
1. 直方图
直方图
OpenCV代码: cv2.calcHist(image, channels, mask, histSize, ranges)
- images: 原图像图像格式为uint8或float32,当传入函数时,应用中括号[]来表示,例如[img]
- channels: 同样用[]来表示,如果图像时灰度图,那么它的值就是[0],如果是彩色图像,那么传入的参数可以是0,1,2,它们分别对应着RGB
- [0],[1]和[2]来分别计算蓝色,绿色和红色通道的histogram。
- mask: 掩模图像,如果想统计整幅图中的直方图就把它写为None,如果想统计某一部分的直方图,就制作一个掩模图像并使用它。
- histSize:BIN的数目,也应该用中括号表示 (需要用户方括号传入),对于全刻度,我们传入[256].
- ranges:像素值范围常为[0,256] (RANGE,一般来说是[0,256])
In [3]:
import cv2
img = cv2.imread("D:/WeChat.picture/cat.jpg",0) # 0 表示转为 灰度图
hist = cv2.calcHist([img] , [0] , None ,[256] ,[0,256]) #None 表示 没掩盖 对整个图进行处理
hist.shape # 结果显示出可能有256 个 取值 , 1 表示 2维 统计出现个数
Out[3]:
(256, 1)
In [8]:
# opencv 是 (B G R)的形式 , matplotlib 是 (R B G) 的形式 可用 ravel 转化
import matplotlib.pyplot as plt
plt.hist(img.ravel() , 256) # plt.hist(img.ravel() , 16) 将其 别分为 16 区间
plt.show()
In [5]:
cv2.imshow("img" , img)
cv2.waitKey(0)
cv2.destroyAllWindows()
In [9]:
img = cv2.imread("D:/WeChat.picture/cat.jpg")
color = ('b', 'g' ,'r')
for i, col in enumerate (color):
histr = cv2 .calcHist([img] , [i] , None , [256] , [0,256])
plt.plot(histr , color = col) # 画线
plt.xlim([0,256]) #表示 [ 0 ,x] 表示 x的区间 , 并 建立一个坐标 (第一象限)
# 三个颜色通道在直方图的统计结果
直方图均衡化
mask创建 (掩码) mask = np.zeros(img , shape[:2] , np.uint8)
In [22]:
def cv_show(img , name):
cv2.imshow(name , img)
cv2.waitKey(0)
cv2.destroyAllWindows()
import numpy as np
import cv2
img = cv2.imread("D:/WeChat.picture/cat.jpg",0)
mask = np.zeros(img.shape[:2],np.uint8)
print(img.shape)
mask [100:300 ,100:400] = 255
cv_show(mask , "mask")
mask_img = cv2.bitwise_and(img , img , mask =mask) #与操作
cv_show(mask_img ,"mask_img")
(414, 500)
In [23]:
hist_full = cv2.calcHist([img] , [0] , None , [256] , [0 ,256])
hist_mask = cv2.calcHist([img] , [0] , mask , [256] , [0 ,256])
plt.plot(hist_full), plt.plot(hist_mask)
plt.xlim([0,256])
plt.show()
plt.imshow()函数负责对图像进行处理,并显示其格式,而plt.show()则是将plt.imshow()处理后的函数显示出来。
In [20]:
# 使用plt.subplot来创建小图. plt.subplot(221)表示将整个图像窗口分为2行2列, 当前位置为1.
plt.subplot(221) , plt.imshow(img ,"gray")
plt.subplot(222) , plt.imshow(mask ,"gray" )
plt.subplot(223) , plt.imshow(mask_img ,"gray")
plt.subplot(224) , plt.plot(hist_full) , plt.plot(hist_mask) #直接输出
plt.show()
自适应直方图均衡化
In [24]:
import cv2
import matplotlib.pyplot as plt
img = cv2.imread("D:/WeChat.picture/clahe.jpg",0)
hist = cv2.calcHist([img] , [0] ,None , [256] ,[0 ,256])
plt.hist(img.ravel() ,256) # number 表示分为 多少部分, ravel bgr 转为 rgb
plt.show()
In [135]:
equ = cv2.equalizeHist(img)
plt.hist(equ.ravel(),256)
plt.show()
分小块进行直方图均衡化处理:
In [136]:
import numpy as np
res = np.hstack((img ,equ)) # 要求维度 一致 灰度为2维 彩色图为 3 维度
cv_show(res , "res")
自适直方图均衡化
In [137]:
clahe = cv2.createCLAHE(clipLimit = 2.0 , tileGridSize = (8, 8))
res_clahe = clahe.apply(img)
res = np.hstack((img , equ ,res_clahe))
cv_show(res , "res")
2. 傅里叶变换
介绍
傅里叶变换:
将时域(以时间为主轴,在某个时间发生了什么事情) 转换为频域(只要知道发生了什么事就好,不管在哪个时间发生的,只考虑发生的事情和频率)
应用
傅里叶变换的作用:
- 高频:变化剧烈的灰度分量,例如边界
- 低频:变化缓慢的灰度分量,例如一片大海
滤波:
- 低通滤波器:只保留低频,会使得图像模糊
- 高通滤波器:只保留高频,会使得图像细节增强
OpenCV程序
步骤:
- OpenCV中主要是cv2.dft() 和 cv2.idft(),输入图像需要先转换为np.float32格式
- 得到的结果中频率为0的部分会再左上角,通常要转换到中心位置,可以通过shift变换来实现
- cv2.dft()返回的结果是双通道的(实部,虚部),通常还需要转换为图像格式才能显示(0,255)
In [41]:
import numpy as np
import cv2
import matplotlib.pyplot as plt
img = cv2.imread("D:/WeChat.picture/lena.png", 0) # 需转化为灰度图 处理
# 转换为:float32
img_float32 = np.float32(img)
# 转换到频域
dft = cv2.dft(img_float32 , flags = cv2.DFT_COMPLEX_OUTPUT)
# 平移到原点
dft_shift = np.fft.fftshift(dft)
# 得到灰度图能表示的形式 将实部和虚部转换为0-255之间的数值
magnitude_spectrum = 20 * np.log(cv2.magnitude(dft_shift[:,:,0] , dft_shift[:,:,1]))
# 画图
plt.subplot(121), plt.imshow(img , cmap = "gray")
plt.title('Input Image') ,plt.xticks([]) , plt.yticks([])
plt.subplot(122) , plt.imshow(magnitude_spectrum , cmap = "gray" )
plt.title("Magnitude Sepctrum") , plt.xticks([]) , plt.yticks([])
plt.show()
In [61]:
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread("D:/WeChat.picture/lena.png" , 0)
# 转换为:float32
img_float32 = np.float32(img)
# 转换到频域
dft = cv2.dft(img_float32 , flags = cv2.DFT_COMPLEX_OUTPUT) # 不可省去 flags
# 平移到原点
dft_shift = np.fft.fftshift(dft)
# 计算中心位置
rows , cols = img.shape # 灰度图
crow , ccol = int (rows/2) ,int (cols/2)
# 低通滤波:创建掩码,掩码大小与图像大小一致,保留的位置的边界扩大30,保证能包括所有要保留的区域
mask = np.zeros((rows ,cols ,2) , np.uint8)
mask[crow-30 :crow+30 , ccol-30 :ccol +30] = 1
# IDFT
fshift = dft_shift * mask # 低通
#fshift = dft_shift*mask
f_ishift = np.fft.ifftshift(fshift)
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:,:,0], img_back[:,:,1])
plt.subplot(121) , plt.imshow(img , cmap = "gray")
plt.title("Input Image") ,plt.xticks([]) , plt.yticks([])
plt.subplot(122) , plt.imshow(img_back , cmap = "gray")
plt.title("Result") , plt.xticks([]) , plt.yticks([])
plt.show() # 不可省去
In [ ]:
In [63]:
import numpy as np
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('D:/Wechat.picture/lena.png',0)
# 转换为:float32
img_float32 = np.float32(img)
# 转换到频域
dft = cv2.dft(img_float32, flags=cv2.DFT_COMPLEX_OUTPUT)
# 平移到原点
dft_shift = np.fft.fftshift(dft)
# 计算中心位置
rows, cols = img.shape
crow, ccol = int(rows/2), int(cols/2)
# 高通滤波:创建掩码,掩码大小与图像大小一致,保留的位置的边界扩大30,保证能包括所有要保留的区域
mask = np.ones((rows,cols,2),np.uint8) # mask = np.zeros((rows,cols,2),np.uint8) 修改 zeros
mask[crow-30:crow+30, ccol-30:ccol+30] = 0 # mask[crow-30:crow+30, ccol-30:ccol+30] = 1 1 改为 0
# IDFT
fshift = dft_shift * mask # 高通
f_ishift = np.fft.ifftshift(fshift) # 逆变换
img_back = cv2.idft(f_ishift)
img_back = cv2.magnitude(img_back[:,:,0], img_back[:,:,1])
# 画图
plt.subplot(121), plt.imshow(img, cmap='gray')
plt.title('Input Image'), plt.xticks([]),plt.yticks([])
plt.subplot(122),plt.imshow(img_back, cmap='gray')
plt.title('Result'), plt.xticks([]),plt.yticks([])
plt.show()
这篇关于OpenCV计算机视觉实战(Python)_08-直方图与傅里叶变换的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-14获取参数学习:Python编程入门教程
- 2024-11-14Python编程基础入门
- 2024-11-14Python编程入门指南
- 2024-11-13Python基础教程
- 2024-11-12Python编程基础指南
- 2024-11-12Python基础编程教程
- 2024-11-08Python编程基础与实践示例
- 2024-11-07Python编程基础指南
- 2024-11-06Python编程基础入门指南
- 2024-11-06怎么使用python 计算两个GPS的距离功能-icode9专业技术文章分享