Python下opencv使用笔记(十)(图像频域滤波与傅里叶变换)

前面曾经介绍过空间域滤波,空间域滤波就是用各种模板直接与图像进行卷积运算,实现对图像的处理,这种方法直接对图像空间操作,操作简单,所以也是空间域滤波。

频域滤波说到底最终可能是和空间域滤波实现相同的功能,比如实现图像的轮廓提取,在空间域滤波中我们使用一个拉普拉斯模板就可以提取,而在频域内,我们使用一个高通滤波模板(因为轮廓在频域内属于高频信号),可以实现轮廓的提取,后面也会把拉普拉斯模板频域化,会发现拉普拉斯其实在频域来讲就是一个高通滤波器。

既然是频域滤波就涉及到把图像首先变到频域内,那么把图像变到频域内的方法就是傅里叶变换。关于傅里叶变换,感觉真是个伟大的发明,尤其是其在信号领域的应用,对于傅里叶变换的理解,要是刚接触这个东西,想要理解还真是非常的困难,除非你的数学功底特别好。这里推荐一个非常好的通俗易懂的博客(待会再去o-_-)

傅里叶分析之掐死教程(完整版)

傅里叶的原理表明,任何连续测量的时序或信号,都可以表示为不同频率的正弦波信号的无限叠加。利用傅立叶变换算法直接测量原始信号,以累加方式来计算该信号中不同正弦波信号的频率、振幅和相位就可以表示原始信号。这里借用上述博客的一个图:

这个图就是把时域图像(大概是方波)变成了一系列的正弦波的线性叠加,其等价关系可以表示为:

f(原始信号)=A1sin(w1x+?1)+A2sin(w2x+?2)+...

那么w1,w2,...可以看成是频率的变化(一般认为就是从1,2,…n定死了),所有的A就是对应频率下的振幅,所有的?就是对应频率下的相位,那么对于任一个信号,如果都认为频率w是从1,2,3…一直增加的话,那么每个信号就只由一组振幅与一组?来决定,他们的不同决定了最终信号的不同。

再来理解下什么是振幅,振幅就是各个频率下的信号的决定程度有多大,如果某个频率的振幅越大,那么它对原始信号的的重要性越大,像上图,当然是w=1的时候振幅最大,说明它对总的信号影响最多(去掉w=1的信号,原始信号讲严重变形)。越往后面,也就是越高频,振幅逐渐减小,那么他们的作用就越小,而他们对于整体信号又有什么影响呢?既然越小,那就是影响小,所以其实去掉,原始信号也基本上不变,他们影响就在于对原始信号的细节上的表现,比如原始信号上的边边角角,偶尔有个小凸起凹槽什么的,这些小细节部分都是靠这些个影响不大的高频信号来表现出来的。深入推广一下,这就很好理解为什么图像的高频信号其实表现出来的就是图像的边缘轮廓、噪声等等这些细节的东西了,而低频信号,表现的却是图像上整块整块灰度大概一样的区域了(这些个区域又称为直流分量区域)。

再来理解下什么是相位,相位表示其实表面对应频率下的正弦分量偏离原点的程度,再借用下上述博客中的一个图,把分量示意图放大了:

上图看到,如果各个频率的分量相位都是0的话,那么每个正弦分量的最大值(在频率轴附近的那个最大值)都会落在频率轴为0上,然而上述图并不是这样。在说简单一点,比如原始信号上有个凹槽,正好是由某一频率的分量叠加出来的,那么如果这个频率的相位变大一点或者变小一点的话,带来的影响就会使得这个凹槽向左或者向右移动一下,也就是说,相位的作用就是精确定位到信号上一点的位置的。

好了,有了上述的概念,再来看看图像的傅里叶变换,上述举得例子是一维信号的傅里叶变换,并且信号是连续的,我们知道图像是二维离散的,连续与离散都可以用傅里叶进行变换,那么二维信号无非就是在x方向与y方向都进行一次一维的傅里叶变换得到,这么看来,可以想象,它的频率构成就是一个网格矩阵了,横轴从w=1到n,纵轴也是这样。所有图像的频率构成都认为是这样的,那么不同的就是一幅图的振幅与相位了(振幅与相位此时同样是一个网格矩阵),也就是说你在opencv或者matlab下对图像进行傅里叶变换后其实是可以得到图像的振幅图与相位图的,而想把图像从频域空间恢复到时域空间,必须要同时有图像的振幅图与相位图才可以,缺少一个就恢复的不完整(后面会实验看看)。

下面看看二维傅里叶变换,一个图像为M*N的图像f(x,y)进过离散傅里叶变换得到F(u,v),那么一般的公式为:

F(u,v)=∑x=0M?1∑y=0N?1f(x,y)e?j2π(ux/M+vy/N)

它的反变换就是

f(x,y)=1MN∑x=0M?1∑y=0N?1F(u,v)ej2π(ux/M+vy/N)

反变换就可以实现将频域图像恢复到时域图像。对正变换分析,当u=v=0时,那么:

F(0,0)=∑x=0M?1∑y=0N?1f(x,y)=fˉ(x,y)

看看这个式子发现它是什么?f(x,y)可是时域里面图像的灰度。很明显,这个东西其实是整个图像的灰度求平均了(这里说的都是灰度图像),当图像进行傅里叶变换以后,你去把F(0,0)与原始图像平均灰度去比较看看是不是一样的。那么F(0,0)在频域内称为直流分量,其他的所有F称为交流分量,直流分量可以看到是在0处获得的,所以很明显是存在于低频分量下的。

说了这么多,来上个实验看看到底什么是傅里叶变换吧。在python+opencv下想实现图像傅里叶变换有两种途径,一种采用numpy包可以实现,还有opencv自带的可以实现,其中numpy带的使用方便,直观易懂。

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

img = cv2.imread(‘flower.jpg‘,0) #直接读为灰度图像
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
#取绝对值:将复数变化成实数
#取对数的目的为了将数据变化到较小的范围(比如0-255)
s1 = np.log(np.abs(f))
s2 = np.log(np.abs(fshift))
plt.subplot(121),plt.imshow(s1,‘gray‘),plt.title(‘original‘)
plt.subplot(122),plt.imshow(s2,‘gray‘),plt.title(‘center‘)

注意的是,上图其实并没有什么含义,显示出来的可以看成是频域后图像的振幅信息,并没有相位信息,图像的相位?=atan(实部虚部),numpy包中自带一个angle函数可以直接根据复数的实部与虚部求出角度(默认出来的角度是弧度)。像上述程序出来的f与fshift都是复数,就可以直接angle函数一下,比如试试并把对应的相位图像显示出来:

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

img = cv2.imread(‘flower.jpg‘,0) #直接读为灰度图像
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
#取绝对值:将复数变化成实数
#取对数的目的为了将数据变化到较小的范围(比如0-255)
ph_f = np.angle(f)
ph_fshift = np.angle(fshift)

plt.subplot(121),plt.imshow(ph_f,‘gray‘),plt.title(‘original‘)
plt.subplot(122),plt.imshow(ph_fshift,‘gray‘),plt.title(‘center‘)

这就是图像上每个像素点对应的相位图,其实是毫无规律的,理解就是偏移的角度。

Ok再来说说程序中为什么要有一个np.fft.fftshift(f)中心化操作,整个图像是在傅里叶变换的一个周期内完成的,将其看成横纵两个方向的一维傅里叶变换,在每个方向上都会有高频信号和低频信号,那么傅里叶变换将低频信号放在了边缘,高频信号放在了中间,然而一副图像,很明显的低频信号多而明显,所以将低频信号采用一种方法移到中间,在时域上就是对f乘以(-1)^(M+N),换到频域里面就是位置的移到了。

图像变换到频域后就可以进行操作了,目前接触到的频域操作似乎也就是一些滤波操作,如同空域里面的滤波操作一样,不过原理不一样了,后面再说说一些频域滤波方法。好了一旦操作完,得到的数据还是频域数据,那么如何将其变换到时域呢?这里就是傅里叶反变换了,公式表示就如同前面那样。这个频域变换到时域的操作就是逆向傅里叶变换再走一遍(比如先反中心化,在逆变换)。一个实例如下:

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

img = cv2.imread(‘flower.jpg‘,0) #直接读为灰度图像
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
#取绝对值:将复数变化成实数
#取对数的目的为了将数据变化到0-255
s1 = np.log(np.abs(fshift))
plt.subplot(131),plt.imshow(img,‘gray‘),plt.title(‘original‘)
plt.subplot(132),plt.imshow(s1,‘gray‘),plt.title(‘center‘)
# 逆变换
f1shift = np.fft.ifftshift(fshift)
img_back = np.fft.ifft2(f1shift)
#出来的是复数,无法显示
img_back = np.abs(img_back)
plt.subplot(133),plt.imshow(img_back,‘gray‘),plt.title(‘img back‘)

可以看到恢复的一模一样。

我们说,恢复一个频域图像需要图像的振幅以及相位,而一个复数也正好包含这些,振幅就是实部虚部的平方和开方,相位就是atan(实部虚部),前面说过。那么现在假设我们只用一副图像的振幅或者相位来将频域内图像恢复到时域会怎么样呢?下面给出只用振幅、只用相位以及两者在联合起来来恢复的程序:

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

img = cv2.imread(‘flower.jpg‘,0) #直接读为灰度图像
f = np.fft.fft2(img)
fshift = np.fft.fftshift(f)
#取绝对值:将复数变化成实数
#取对数的目的为了将数据变化到0-255
s1 = np.log(np.abs(fshift))
plt.subplot(221),plt.imshow(img,‘gray‘),plt.title(‘original‘)
plt.xticks([]),plt.yticks([])
#---------------------------------------------
# 逆变换--取绝对值就是振幅
f1shift = np.fft.ifftshift(np.abs(fshift))
img_back = np.fft.ifft2(f1shift)
#出来的是复数,无法显示
img_back = np.abs(img_back)
#调整大小范围便于显示
img_back = (img_back-np.amin(img_back))/(np.amax(img_back)-np.amin(img_back))
plt.subplot(222),plt.imshow(img_back,‘gray‘),plt.title(‘only Amplitude‘)
plt.xticks([]),plt.yticks([])
#---------------------------------------------
# 逆变换--取相位
f2shift = np.fft.ifftshift(np.angle(fshift))
img_back = np.fft.ifft2(f2shift)
#出来的是复数,无法显示
img_back = np.abs(img_back)
#调整大小范围便于显示
img_back = (img_back-np.amin(img_back))/(np.amax(img_back)-np.amin(img_back))
plt.subplot(223),plt.imshow(img_back,‘gray‘),plt.title(‘only phase‘)
plt.xticks([]),plt.yticks([])
#---------------------------------------------
# 逆变换--将两者合成看看
s1 = np.abs(fshift) #取振幅
s1_angle = np.angle(fshift) #取相位
s1_real = s1*np.cos(s1_angle) #取实部
s1_imag = s1*np.sin(s1_angle) #取虚部
s2 = np.zeros(img.shape,dtype=complex)
s2.real = np.array(s1_real) #重新赋值给s2
s2.imag = np.array(s1_imag)

f2shift = np.fft.ifftshift(s2) #对新的进行逆变换
img_back = np.fft.ifft2(f2shift)
#出来的是复数,无法显示
img_back = np.abs(img_back)
#调整大小范围便于显示
img_back = (img_back-np.amin(img_back))/(np.amax(img_back)-np.amin(img_back))
plt.subplot(224),plt.imshow(img_back,‘gray‘),plt.title(‘another way‘)
plt.xticks([]),plt.yticks([])

可以看到,仅仅振幅的恢复图啥也不是,仅仅的相位图还有那么点意思,当然也是啥也不是。最后是把振幅与相位分别作为频域内复数的实部和虚部,得到的恢复图才与原来的一样。

基于此,我们来做一个有趣的实验,假设有两幅图像,将这两幅图像进行傅里叶变换到频域,然后把用一个图像的振幅做为振幅,用另一幅图像的相位作为相位生成一副新的图像,那么,这个图像会怎么样呢?你觉得生成的图像会更像取振幅的那副还是取相位的那副呢?来看看吧:

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

img_flower = cv2.imread(‘flower.jpg‘,0) #直接读为灰度图像
img_man = cv2.imread(‘woman.jpg‘,0) #直接读为灰度图像
plt.subplot(221),plt.imshow(img_flower,‘gray‘),plt.title(‘origial1‘)
plt.xticks([]),plt.yticks([])
plt.subplot(222),plt.imshow(img_man,‘gray‘),plt.title(‘origial_2‘)
plt.xticks([]),plt.yticks([])
#--------------------------------
f1 = np.fft.fft2(img_flower)
f1shift = np.fft.fftshift(f1)
f1_A = np.abs(f1shift) #取振幅
f1_P = np.angle(f1shift) #取相位
#--------------------------------
f2 = np.fft.fft2(img_man)
f2shift = np.fft.fftshift(f2)
f2_A = np.abs(f2shift) #取振幅
f2_P = np.angle(f2shift) #取相位
#---图1的振幅--图2的相位--------------------
img_new1_f = np.zeros(img_flower.shape,dtype=complex)
img1_real = f1_A*np.cos(f2_P) #取实部
img1_imag = f1_A*np.sin(f2_P) #取虚部
img_new1_f.real = np.array(img1_real)
img_new1_f.imag = np.array(img1_imag)
f3shift = np.fft.ifftshift(img_new1_f) #对新的进行逆变换
img_new1 = np.fft.ifft2(f3shift)
#出来的是复数,无法显示
img_new1 = np.abs(img_new1)
#调整大小范围便于显示
img_new1 = (img_new1-np.amin(img_new1))/(np.amax(img_new1)-np.amin(img_new1))
plt.subplot(223),plt.imshow(img_new1,‘gray‘),plt.title(‘another way‘)
plt.xticks([]),plt.yticks([])
#---图2的振幅--图1的相位--------------------
img_new2_f = np.zeros(img_flower.shape,dtype=complex)
img2_real = f2_A*np.cos(f1_P) #取实部
img2_imag = f2_A*np.sin(f1_P) #取虚部
img_new2_f.real = np.array(img2_real)
img_new2_f.imag = np.array(img2_imag)
f4shift = np.fft.ifftshift(img_new2_f) #对新的进行逆变换
img_new2 = np.fft.ifft2(f4shift)
#出来的是复数,无法显示
img_new2 = np.abs(img_new2)
#调整大小范围便于显示
img_new2 = (img_new2-np.amin(img_new2))/(np.amax(img_new2)-np.amin(img_new2))
plt.subplot(224),plt.imshow(img_new2,‘gray‘),plt.title(‘another way‘)
plt.xticks([]),plt.yticks([])

这就是合成的图像,是不是很有趣,图像3是图1的振幅加图2的相位,图像4是图1的相位加上图2的振幅。很明显的可以看到,新图像占用谁的相位就越像谁,为什么会这样?很简单,可以理解振幅不过描述图像灰度的亮度,占用谁的振幅不过使得结果哪些部分偏亮或者暗而已,而图像是个什么样子是由它的相位决定的。相位描述的是一个方向,方向正确了,那么最终的结果离你的目的就不远了。可想而知,方向对于一件事物是多么的重要,大自然的规律尚且如此,更别说做人做事了,找准并相信一个方向,慢慢的走下去吧,总有一天会看到成果的,哪怕你的振幅不对,走的慢一点,但是最终也能走的像模像样的,不会说到了人生的最后,回头一看,再来感叹哎呀这是什么玩意,那就很悲哀了。

好了,扯回来我们的问题,关于傅里叶变换下的图像恢复基本上就是这了。但是我们发现,似乎我们只说了开头(怎么变换)和结尾(怎么变回去),那么中间我们要做的东西才是傅里叶变换的目的—频域下的各种变化操作。

这里主要介绍频域下的滤波–低通滤波器,高通滤波器,带通带阻滤波器。

我们知道,图像在变换加移动中心后,从中间到外面,频率上依次是从低频到高频的,那么我们如果把中间规定一小部分去掉,是不是相对于把低频信号去掉了呢?这也就是相当于进行了高通滤波。这个滤波模板画出来可能就是这样的:

黑色为0,白色为1,把这个模板去和图像进过傅里叶变换的频域矩阵去与(相乘)一下就实现了高通滤波。比如下面:

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

img_man = cv2.imread(‘woman.jpg‘,0) #直接读为灰度图像
plt.subplot(121),plt.imshow(img_man,‘gray‘),plt.title(‘origial‘)
plt.xticks([]),plt.yticks([])
#--------------------------------
rows,cols = img_man.shape
mask = np.ones(img_man.shape,np.uint8)
mask[rows/2-30:rows/2+30,cols/2-30:cols/2+30] = 0
#--------------------------------
f1 = np.fft.fft2(img_man)
f1shift = np.fft.fftshift(f1)
f1shift = f1shift*mask
f2shift = np.fft.ifftshift(f1shift) #对新的进行逆变换
img_new = np.fft.ifft2(f2shift)
#出来的是复数,无法显示
img_new = np.abs(img_new)
#调整大小范围便于显示
img_new = (img_new-np.amin(img_new))/(np.amax(img_new)-np.amin(img_new))
plt.subplot(122),plt.imshow(img_new,‘gray‘),plt.title(‘Highpass‘)
plt.xticks([]),plt.yticks([])

可以看到,高通滤波器有利于提取图像的轮廓,这里我们从原理上分析一下为什么,图像的轮廓或者边缘或者一些噪声处,灰度变化剧烈,那么在把它们经过傅里叶变换后,就会变成高频信号(我们知道高频时捕捉细节的),所以在把图像低频信号滤掉以后剩下的自然就是轮廓了。

反过来我们来看看空间域滤波中的拉普拉斯模板,我们知道这个模板是这样的

M=???0?10?14?10?10???

现在我们把这个模板进行傅里叶变换到频域看看:

import numpy as np
import matplotlib.pyplot as plt

laplacian = np.array([[0,1,0],[1,-4,1],[0,1,0]])
f = np.fft.fft2(laplacian)
f1shift = np.fft.fftshift(f)
img = np.log(np.abs(f1shift))
plt.imshow(img,‘gray‘)

可以看到,这个模板的频域变换下四周特别亮,也就是是个高通滤波器。其它空间域下的模板都可以转到频域下来看看。

下面再来试试低通滤波器什么效果,构造个低通滤波器也很简单,把上述模板中的1变成0,0变成1,其实就是低通了:

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

img_man = cv2.imread(‘woman.jpg‘,0) #直接读为灰度图像
plt.subplot(121),plt.imshow(img_man,‘gray‘),plt.title(‘origial‘)
plt.xticks([]),plt.yticks([])
#--------------------------------
rows,cols = img_man.shape
mask = np.zeros(img_man.shape,np.uint8)
mask[rows/2-20:rows/2+20,cols/2-20:cols/2+20] = 1
#--------------------------------
f1 = np.fft.fft2(img_man)
f1shift = np.fft.fftshift(f1)
f1shift = f1shift*mask
f2shift = np.fft.ifftshift(f1shift) #对新的进行逆变换
img_new = np.fft.ifft2(f2shift)
#出来的是复数,无法显示
img_new = np.abs(img_new)
#调整大小范围便于显示
img_new = (img_new-np.amin(img_new))/(np.amax(img_new)-np.amin(img_new))
plt.subplot(122),plt.imshow(img_new,‘gray‘),plt.title(‘Highpass‘)
plt.xticks([]),plt.yticks([])

可以看到低通滤波后图像除了轮廓模糊了外,基本上没什么变化,图像的大部分信息基本上都保持了。从原理上来看,图像的主要信息都集中在低频上,所以低通滤波器的效果是这样也是可以理解的。上述的高通、低通滤波器的构造有0,1构成的理想滤波器,也是最简单的滤波器,还有一些其他的滤波器,比如说高斯滤波器,butterworth滤波器等等,下面是参考冈萨雷斯书上的图:

还有就是把高通低通都结合一部分到一个模板上形成的带通滤波器,这在一些场合会很有用,还是以理想的带通滤波器实验下:

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

img_man = cv2.imread(‘woman.jpg‘,0) #直接读为灰度图像
plt.subplot(121),plt.imshow(img_man,‘gray‘),plt.title(‘origial‘)
plt.xticks([]),plt.yticks([])
#--------------------------------
rows,cols = img_man.shape
mask1 = np.ones(img_man.shape,np.uint8)
mask1[rows/2-8:rows/2+8,cols/2-8:cols/2+8] = 0
mask2 = np.zeros(img_man.shape,np.uint8)
mask2[rows/2-80:rows/2+80,cols/2-80:cols/2+80] = 1
mask = mask1*mask2
#--------------------------------
f1 = np.fft.fft2(img_man)
f1shift = np.fft.fftshift(f1)
f1shift = f1shift*mask
f2shift = np.fft.ifftshift(f1shift) #对新的进行逆变换
img_new = np.fft.ifft2(f2shift)
#出来的是复数,无法显示
img_new = np.abs(img_new)
#调整大小范围便于显示
img_new = (img_new-np.amin(img_new))/(np.amax(img_new)-np.amin(img_new))
plt.subplot(122),plt.imshow(img_new,‘gray‘)
plt.xticks([]),plt.yticks([])

这就是带通的效果,既可以保留一部分低频,也可以保留一部分高频,至于保留多少,怎么保留就视问题的不同而不同了。

当然频域滤波的应用绝不仅限于此,更多的应用还有待探索学习。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-09-29 00:10:45

Python下opencv使用笔记(十)(图像频域滤波与傅里叶变换)的相关文章

Python下opencv使用笔记(一)(图像简单读取、显示与储存)

写在之前 从去年開始关注python这个软件,途中间间断断看与学过一些关于python的东西.感觉python确实是一个简单优美.easy上手的脚本编程语言,众多的第三方库使得python异常的强大.能够处理很多不同的问题,同一时候它的很多开源免费的库使得python的使用也是十分的广泛. 在科学计算.数据处理与图像领域,自己以前一直在使用matlab.感觉matlab也是一个语言优美.简单方便的编程语言,都说matlab与python在某些领域是非常类似的,确实是这样,就科学计算.数据处理上真

Python下opencv使用笔记(五)(图像的平滑与滤波)

对于图形的平滑与滤波,但从滤波角度来讲,一般主要的目的都是为了实现对图像噪声的消除,增强图像的效果. 首先介绍二维卷积运算,图像的滤波可以看成是滤波模板与原始图像对应部分的的卷积运算.关于卷积运算,找到几篇相关的博客: 图像处理:基础(模板.卷积运算) 图像处理-模板.卷积的整理 对于2D图像可以进行低通或者高通滤波操作,低通滤波(LPF)有利于去噪,模糊图像,高通滤波(HPF)有利于找到图像边界. (一)统一的2D滤波器cv2.filter2D Opencv提供的一个通用的2D滤波函数为cv2

Python下opencv使用笔记(十二)(k均值算法之图像分割)

k均值(kmeans)聚类是一种最为简单的聚类方法,直接根据数据点之间的距离(欧氏距离,几何距离等等)来划分数据是属于哪一类的,当所有数据点所属的类别不在变化的时候,聚类也就完成了.详细原理可索引下面一个博客: 聚类分析笔记-K均值matlab算法(一) 关于kmeans再谈几点认识: 重要的一点:聚类数目的问题.有的聚类.分类问题已经限制好了要聚类成几类,也就是聚类数目一定,那么这种聚类通常简单些,直接规定聚类数就好了.而有的聚类问题不知道分成几类才好,这个时候怎么办?那么就需要找到一种评价指

Python下opencv使用笔记(四)(图像的阈值处理)

图像的阈值处理一般使得图像的像素值更单一.图像更简单.阈值可以分为全局性质的阈值,也可以分为局部性质的阈值,可以是单阈值的也可以是多阈值的.当然阈值越多是越复杂的.下面将介绍opencv下的三种阈值方法. (一)简单阈值 简单阈值当然是最简单,选取一个全局阈值,然后就把整幅图像分成了非黑即白的二值图像了.函数为cv2.threshold() 这个函数有四个参数,第一个原图像,第二个进行分类的阈值,第三个是高于(低于)阈值时赋予的新值,第四个是一个方法选择参数,常用的有: ? cv2.THRESH

Python下opencv使用笔记(七)(图像梯度与边缘检测)

梯度简单来说就是求导,在图像上表现出来的就是提取图像的边缘(不管是横向的.纵向的.斜方向的等等),所需要的无非也是一个核模板,模板的不同结果也不同.所以可以看到,所有的这些个算子函数,归结到底都可以用函数cv2.filter2D()来表示,不同的方法给予不同的核模板,然后演化为不同的算子而已.并且这只是这类滤波函数的一个用途,曾经写过一个关于matlab下滤波函数imfilter()的扩展应用(等同于opencv的cv2.filter2D函数): 图像滤波函数imfilter函数的应用及其扩展

Python下opencv使用笔记(三)(图像的几何变换)

写在之前 二维与三维图像的几何变换在计算机图形学上有重要的应用,包括现在的许多图像界面的切换.二维与三维游戏画面控制等等都涉及到图像几何变换,就比如说在三维游戏中,控制角色三维移动的时候,画面是要跟着移动的,那么怎么移动,怎么让上一时刻的画面移动到这一时刻,这都是根据了你的移动量,然后找到三维坐标之间的对应关系,用这一时刻的坐标替换到上一时刻的坐标像素值实现图像的切换. 图像的几何变换主要包括:平移.扩大与缩小.旋转.仿射.透视等等.图像变换是建立在矩阵运算基础上的,通过矩阵运算可以很快的找到对

Python下opencv使用笔记(二)(简单几何图像绘制)

简单几何图像一般包括点.直线.矩阵.圆.椭圆.多边形等等.首先认识一下opencv对像素点的定义.图像的一个像素点有1或者3个值,对灰度图像有一个灰度值,对彩色图像有3个值组成一个像素值,他们表现出不同的颜色. 那么有了点才能组成各种多边形. (一)首先绘制直线 函数为:cv2.line(img,Point pt1,Point pt2,color,thickness=1,line_type=8 shift=0) 有值的代表有默认值,不用给也行.可以看到这个函数主要接受参数为两个点的坐标,线的颜色

Python下opencv使用笔记(六)(图像的形态学转换)

形态学一般是使用二值图像,进行边界提取,骨架提取,孔洞填充,角点提取,图像重建等等.常用的形态学操作时腐蚀与膨胀,在他们的基础上演变出一些变体,包括开运算.闭运算.梯度等等.形态学一般是对二值图像进行的操作. 下面贴几个比较好的介绍图像形态学方面的博客 图像处理基本算法-形态学 图像的形态学处理 (一)腐蚀 关于腐蚀就是将图像的边界腐蚀掉,或者说使得图像整体上看起来变瘦了.它的操作原理就是卷积核沿着图像滑动,如果与卷积核对应的原图像的所有像素值都是1,那么中心元素保持原来的值,否则就变为0.这对

Python下opencv使用笔记(十一)(详解hough变换检测直线与圆)

在数字图像中,往往存在着一些特殊形状的几何图形,像检测马路边一条直线,检测人眼的圆形等等,有时我们需要把这些特定图形检测出来,hough变换就是这样一种检测的工具. Hough变换的原理是将特定图形上的点变换到一组参数空间上,根据参数空间点的累计结果找到一个极大值对应的解,那么这个解就对应着要寻找的几何形状的参数(比如说直线,那么就会得到直线的斜率k与常熟b,圆就会得到圆心与半径等等). 关于hough变换,核心以及难点就是关于就是有原始空间到参数空间的变换上.以直线检测为例,假设有一条直线L,