opencv笔记(7)——直方图与傅里叶变换

直方图与傅里叶变换

一、直方图

import cv2
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline  #专有魔法指令,即时显示

def cv_show(name,img):
	cv2.imshow(name,img)
	cv2.waitKey(0)
	cv2.destoryAllWindows()
img = cv2.imread('cat.jpg', 0) # 表示灰度图
hist = cv2.calcHist([img], [0], None, [256], [0, 256]) # 注意中括号[]
hist.shape
# 结果是(256,1):一共有0-255的256个取值,1表示是个二维的

plt.hist(img.ravel(), 256) # img.ravel()是多维矩阵变一维矩阵
plt.show

plt.hist(src,pixels)
src:数据源,注意这里只能传入一维数组,使用src.ravel()可以将二维图像拉平为一维数组。
pixels:像素级,一般输入256。

\

img = cv2.imread('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])

mask操作

img = cv2.imread('cat.jpg', 0) # 表示灰度图
 # 创建mask
 mask = np.zeros(img.shape[:2], np.uint8) # 8位无符号整型
 mask[100:300, 100:400] = 255 # 把要保存的部分置为255
 cv_show(mask, 'mask')
 masked_img = cv2.bitwise_and(img, img, mask=mask) # 与操作
 cv_show(masked_img , 'masked_img ')
 hist_full = cv2.calcHist([img], [0], None, [256], [0, 256]) # 不带掩码
 hist_mask = cv2.calcHist([img], [0], mask, [256], [0, 256]) # 带掩码
 
plt.subplot(221), plt.imshow(img, 'gray')
plt.subplot(222), plt.imshow(mask, 'gray')
plt.subplot(223), plt.imshow(masked_img, 'gray')
plt.subplot(224), plt.plot(hist_full), plt.plot(hist_mask)
plt.xlim([0, 256])
plt.show()

img.shape[:2] 取彩色图片的长、宽。
如果img.shape[:3] 则取彩色图片的长、宽、通道。

关于img.shape[0]、[1]、[2]
img.shape[0]:图像的垂直尺寸(高度)
img.shape[1]:图像的水平尺寸(宽度)
img.shape[2]:图像的通道数

在矩阵中,[0]就表示行数,[1]则表示列数。

直方图均衡化
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
可以提高 对比度
\

# 不做均衡化
img = cv2.imread('cat.jpg', 0) # 0表示灰度图 #clahe
plt.hist(img.ravel(), 256); # ravel返回的是视图,用ravel()方法将数组a拉成一维数组
plt.show()

# 做均衡化
equ = cv2.equalizeHist(img)
plt.hist(equ.ravel(), 256)
plt.show()
res = np.hstack((img, equ))
cv.show(res, 'res')

自适应直方图均衡化
将整个图像分隔成一个个小的

clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
res_clahe = clahe.apply(img) # apply(func,*args,**kwargs)的返回值就是func()的返回值,apply()的元素参数是有序的,元素的顺序必须和func()形式参数的顺序一致
res = np.hstack((img, equ, res_clahe))
cv_show(res, 'res')

二、傅里叶变换

傅里叶变换
傅里叶变换的作用
(1)高频:变化剧烈的灰度变量,例如边界
(2)低频:变化缓慢的灰度变量,例如一片大海

滤波
(1)低通滤波器:只保留低频,会使得图像模糊
(2)高通滤波器:只保留高频,会使得图像细节增强

(3)opencv中主要就是cv2.dft()和cv2.idft(),输入图像需要先转换成np.float32格式
(4)得到的结果中频率为0的部分会在左上角,通常要转换到中心位置,可以通过shift变换来实现
(5)cv2.dft()返回的结果是双通道的(实部, 虚部),通常还需要转换成图像格式才能展示(0, 255)

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

img = cv2.imread('lena.jpg', 0)

img_float32 = np.float32(img)

dft = cv2.dft(img_float32, flags = cv2.DFT_COMPLEX_OUTPUT)
dft_shift = np.fft.fftshift(dft) # shift操作,低频值转换到中间
# 得到灰度图能表示的形式
magnitude_spectrum = 20*np.log(cv2.magnitude(dft_shift[:,:,0], dft_shift[:,:,1])) # 转换两个通道,结果非常小,映射出来*20

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 Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()
# 低频
import numpy as np
import cv2
from matplotlib import pyplot as plt

img = cv2.imread('lena.jpg', 0)

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) # 中心位置

# 低通滤波
mask = np.zeros((rows, cols, 2), np.uint8)
mask[crow-30:crow+30, ccol-30:ccol+30] = 1

# 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()
# 高频
img = cv2.imread('lena.jpg', 0)

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) # 中心位置

# 高通滤波
mask = np.ones((rows, cols, 2), np.uint8)
mask[crow-30:crow+30, ccol-30:ccol+30] = 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()

三、常用函数

  • cv2.calcHist(img, channels, mask, histSize, ranges)

     像素直方图统计:
     img:原图像格式为uint8或floart32。当传入函数时应用中括号[]来,例如[img],通常是灰度图
     channels:同样用中括号,他会告诉我们统幅图像的直方图。如果入图像是灰度图它的值就是[0],如果是彩色图像
     		的传入的参数可以是[0][1][2],他们分别对应着BGR。
     mask:掩码图像。统整幅图像的直方图就把它为None。但是如果你想统图像某一分的直方图的,就制作一个掩码图
     		像并使用它。
     histSize:BIN的数目。也应用中括号括来,可以自己指定直方图的size大小
     ranges:像素值范围常为[0256]
    
  • cv2.bitwise_and(img, img, mask=mask)

     与操作
    
  • cv2.equalizeHist(img)

     直方图均衡化
    
  • cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))

     自适应直方图均衡化
     clipLimit:颜色对比度的阈值
      titleGridSize:进行像素均衡化的网格大小,即在多少网格下进行直方图的均衡化操作
    
  • cv2.dft()

     执行傅里叶变换
    
  • cv2.idft()

     傅里叶逆变换
    
  • cv2.magnitude(a1, a2)

     用于求取传入数据的平方根
    

Numpy中的傅里叶变换

主要使用np.fft.fft2()、np.fft.fftshift()以及20*np.log(np.abs(fshift))函数来实现。

np.fft.fft2()

numpy.fft.fft2(img, s=None, axes=(-2, -1), norm=None)
1
参数如下:

img:输入图像(二维数组),即灰度图像
s:可选参数,它决定输出数组的大小。如果它大于输入图像的大小,则在计算FFT之前用零填充输入图像。如果小于输入图像,将裁切输入图像。如果未传递任何参数,则输出数组的大小将与输入的大小相同
axes:计算FFT的轴。如果未给出,则使用最后两个轴。轴上重复的索引表示该轴上的变换执行了多次
norm:可选参数
返回值是一个复数数组
对于np.fft.fft()以及np.fft.fftn()函数,第一个参数分别是一维数组和n维数组,返回值均为复数数组,第二个参数同上。

np.fft.fftshift()

函数参数主要是np.fft.fft2()函数的输出,即复数数组。此函数可以将零频率分量移到频谱中心。变换之后的频谱显示范围从[0, N]变为:[-N/2,N/2-1](N为偶数)或[-(N-1)/2,(N-1)/2](N为奇数)。

20*np.log(np.abs(fshift))

函数参数主要是np.fft.fftshift()函数的输出,傅里叶变换得到的结果是一个复数数组,不能直接用于显示图像,要想得到频谱灰度图像,需要一个映射,把复数映射[0, 255]之间。

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
img = cv.imread('./opencv.png',0)

f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
magnitude_spectrum = 20*np.log(np.abs(fshift))

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 Spectrum'), plt.xticks([]), plt.yticks([])
plt.show()
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清园暖歌

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值