这门课是通过数字图像处理-Digital Image Processing (DIP)进行学习的,由于课中代码实现的部分是Matlab,对我以后的用处不是很大,所以学习的重心是在于理论的部分,至于代码实现部分先暂时搁置,与此同时会查看下 openCV中python接口相关操作的使用。
主要讲的是图像的存储格式和图像的显示
使用cv.imread()
函数读取图像
第二个参数是一个标志,它指定了读取图像的方式。
• cv.IMREAD_COLOR
: 加载彩色图像。任何图像的透明度都会被忽视。它是默认标志。
• cv.IMREAD_GRAYSCALE
:以灰度模式加载图像
• cv.IMREAD_UNCHANGED
:加载图像,包括alpha通道
注意 除了这三个标志,你可以分别简单地传递整数1、0或-1。
import numpy as py
import cv2 as cv
#加载彩色灰度图像
img = cv.imread('messi5.jpg',0)
使用cv.imshow()
函数显示图像,窗口自动适合图像尺寸
cv.imshow('image', img)
cv.waitKey(0)
cv.destroyAllWindows()
cv.waitKey(0)
:键盘绑定函数,输入0等待下一次敲击
cv.destroyAllWindows()
:破坏我们创建的所有窗口
使用函数cv.imwrite()
保存图像。
第一个参数是文件名,第二个参数是要保存的图像。
cv.imwrite('messigray.png',img)
这会将图像以PNG格式保存在工作目录中。
齐次坐标:就是给原来的坐标增加一个维度
几何变换一般过程:
缩放变换
import numpy as np
import cv2 as cv
img = cv.imread('messi5.jpg')
res = cv.resize(img, None, fx=2, fy=2, interpolation=cv.INTER_CUBIC)
# 或者
height, width = img.shape[:2]
res = cv.resize(img, (2*width, 2*height), interpolation= cv.INTER_CUBIC)
平移变换
M = [ 1 0 t x 0 1 t y ] M = \begin{bmatrix} 1 & 0 & t_x \\ 0 & 1 & t_y \end{bmatrix} M=[1001txty]
import numpy as np
import cv2 as cv
img = cv.imread('messi5.jpg',0)
rows, cols = img.shape
M = np.float32([[1,0,100],[0,1,50]])
dst = cv.warpAffine(img, M, (cols,rows)) # 第三个参数为输出图像的大小
cv.imshow('img', dst)
cv.waitKey(0)
cv.destroyAllWindows()
旋转变换
M = [ c o s θ − s i n θ s i n θ c o s θ ] M = \begin{bmatrix} cos\theta & -sin\theta \\ sin\theta & cos\theta \end{bmatrix} M=[cosθsinθ−sinθcosθ]
img = cv.imread('messi5.jpg',0)
rows,cols = img.shape
# cols-1 和 rows-1 是坐标限制
M = cv.getRotationMatrix2D(((cols-1)/2.0,(rows-1)/2.0),90,1)
dst = cv.warpAffine(img,M,(cols,rows))
其中还有仿射变换和透视变换
截止日期 : 2021/4/22
图像增强:不考虑降质原因,关心有用的信息,抑制次要信息,去干扰,增强对比度。不一定要逼近原图像
复原技术:针对降质原因,设法补偿降质因素,尽可能逼近原始图像,恢复原图。
二者有重复的部分:增强带有恢复性质,突出有用信息上,且是局部性恢复
图像灰度变化技术:按一定的变化关系,逐个像素改变原图像中每个像素灰度值的方法。是图像增强处理技术中一种非常基础、直接的空间域图像处理方法。目的是为了改善画质,使图像的显示效果更加清晰。
点运算为:(有线性变换和非线性变换)
g ( x , y ) = T [ f ( x , y ) ] g(x,y)=T[f(x,y)] g(x,y)=T[f(x,y)]
输入图像为 f ( x , y ) f(x,y) f(x,y),输出图像为 g ( x , y ) g(x,y) g(x,y)
点运算又称 对比度增强,对比度拉伸, 灰度变换,不改变其位置。
经过阈值处理后的图像变成了一幅黑白的二值图像
f ( x ) = { 0 , if x < T 255 , if x > T f(x) = \begin{cases} 0, & \text{if }x
有两个函数cv.threshold
和cv.adaptiveThreshold
函数cv.threshold用于应用阈值。
第一个参数是源图像,它应该 是灰度图像。
第二个参数是阈值,用于对像素值进行分类。
第三个参数是分配给超过阈值的像素 值的最大值。
第四个参数是 不同类型的阈值
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
img = cv.imread('gradient.png',0)
ret,thresh1 = cv.threshold(img,127,255,cv.THRESH_BINARY)
ret,thresh2 = cv.threshold(img,127,255,cv.THRESH_BINARY_INV)
ret,thresh3 = cv.threshold(img,127,255,cv.THRESH_TRUNC)
ret,thresh4 = cv.threshold(img,127,255,cv.THRESH_TOZERO)
ret,thresh5 = cv.threshold(img,127,255,cv.THRESH_TOZERO_INV)
titles = ['Original Image','BINARY','BINARY_INV','TRUNC','TOZERO','TOZERO_INV'] images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]
for i in xrange(6):
plt.subplot(2,3,i+1),plt.imshow(images[i],'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([]) plt.show()
函数cv.adaptiveThreshold
用于自适应阈值,算法基于像素周围的小区域确定像素的阈值。因此对于同一图像的不同区域,我们获得了不同的阈值,这为光照度变化的图像提供了更好的结果
参数1:要处理的原图
参数2:最大阈值,一般为255
参数3:小区域阈值的计算方式
ADAPTIVE_THRESH_MEAN_C:小区域内取均值
ADAPTIVE_THRESH_GAUSSIAN_C:小区域内加权求和,权重是个高斯核
参数4:阈值方法,只能使用THRESH_BINARY、THRESH_BINARY_INV,具体见前面所讲的阈值方法
参数5:小区域的面积,如11就是11*11的小块
参数6:最终阈值等于小区域计算出的阈值再减去此值
# 自适应阈值对比固定阈值
img = cv2.imread('sudoku.jpg', 0)
# 固定阈值
ret, th1 = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
# 自适应阈值
th2 = cv2.adaptiveThreshold(
img, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 4)
th3 = cv2.adaptiveThreshold(
img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 17, 6)
titles = ['Original', 'Global(v = 127)', 'Adaptive Mean', 'Adaptive Gaussian']
images = [img, th1, th2, th3]
for i in range(4):
plt.subplot(2, 2, i + 1), plt.imshow(images[i], 'gray')
plt.title(titles[i], fontsize=8)
plt.xticks([]), plt.yticks([])
plt.show()
灰度直方图: 表示图像中具有某种灰度级的像素的个数,反映了图像中每种灰度出现的频率。它是图像最基本的特征
横坐标: 灰度级
纵坐标: 该灰度级出现的个数
从图像灰度级的分布可以看出一幅图像的灰度分布特性。直方图里没有位置信息,图像和直方图之间是多对一的关系。一幅图像各子区的直方图之和是整个直方图。
直方图的计算:在离散形式下,用 r k r_k rk代表离散灰度级, n k n_k nk为图像中出现 r k r_k rk级灰度的像素数,n是图像像素总数,而 n k / n n_k/n nk/n即为频数
p r ( r k ) = n k n 0 ≤ r k ≤ 1 , k = 0 , 1 , 2 , . . . , l − 1 p_r(r_k) = \frac{n_k}{n} \qquad \qquad 0\le r_k\le1,k=0,1,2,...,l-1 pr(rk)=nnk0≤rk≤1,k=0,1,2,...,l−1
经变换后得到的新直方图不很平坦,但比原始图像的直方图平坦的多,扩展了动态范围。对于对比度较弱的图像进行处理很有效。变换后的灰度级减少,这种现象叫做==“简并”==现象。由于简并现象的存在,处理后的灰度级总是要减少。
直方图均衡化计算:
一些直方图有关的术语:
BINS:直方图显示每个像素值的像素数,即从0到255.
DIMS:为其收集数据的参数的数量。我们仅收集强度值数据,所以这里是1
RANGE:要测量的强度值的范围。通常是[0,256]
,即所有强度值
cv.calcHist(images,channels, mask, histSize, ranges[,hist[, accumulate]])
images:它是uint8或float32类型的原图像。他应该放在方括号中,即[img]
channels:也以方括号给出。它是我们计算直方图的通道的索引。例如,如果输入为灰度图 像,则其值为[0]
。对于彩色图像,您可以传递[0],[1]或[2]分别计算蓝色,绿色或红色通道的 直方图
mask:图像掩码。为了找到完整图像的直方图,将其指定为“无”。但是,如果要查找图像特 定区域的直方图,则必须为此创建一个掩码图像并将其作为掩码。(我将在后面显示一个示 例。)
histSize:这表示我们的BIN计数。需要放在方括号中。对于全尺寸,我们通过[256]。
ranges:这是我们的RANGE。通常为[0,256]
。
img = cv.imread('home.jpg',0)
hist = cv.calcHist([img],[0],None,[256],[0,256])
hist,bins = np.histogram(img.ravel(),256,[0,256])
使用Matplotlib,
import numpy as np import cv2 as cv
from matplotlib import pyplot as plt img = cv.imread('home.jpg',0)
plt.hist(img.ravel(),256,[0,256]); plt.show()
使用OpenCV
img = cv.imread('home.jpg',0) # create a mask
mask = np.zeros(img.shape[:2], np.uint8)
mask[100:300, 100:400] = 255
masked_img = cv.bitwise_and(img,img,mask = mask)
# 计算掩码区域和非掩码区域的直方图 # 检查作为掩码的第三个参数
hist_full = cv.calcHist([img],[0],None,[256],[0,256]) hist_mask = cv.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 = cv.imread('wiki.jpg',0) equ = cv.equalizeHist(img)
res = np.hstack((img,equ)) #stacking images side-by-side cv.imwrite('res.png',res)
图像在获取、传输过程中,受干扰的影响,会产生噪声,噪声是一种错误的信号,干扰正常信号。造成图像毛糙,需对图像进行平滑处理。图像去噪是一种信号滤波的方法,目的是保留有用信号,去掉噪音信号。
噪声干扰一般是随机产生的,分布不规则,大小也不规则。噪声像素的灰度是空间不相关,与邻近像素显著不同。
平滑滤波对图像的低频分量增强,同时消弱高频分量,用于消除图像中的随机噪声,起到平滑作用
空间域法:在原图像上直接对像素的灰度值进行处理。分为两类,点运算和局部运算(邻域有关的空间域运算)。
频域法:在图像的变换域上进行处理,增强感兴趣的频率分量,然后进行反变换,得到增强了的图像。
邻域处理方法: 用某一模板对每个像元于其周围邻域的所有像元进行某种数学运算,得到该像元新的灰度值。 新的灰度值不仅与该像元的灰度值有关,还与其邻域内的像元的灰度值有关
模板又称滤波器,掩模,核或窗
2021/5/11 10:03(wc 写完了没保存,关了浏览器没了,我人傻了)
属于低通滤波的处理方法
一幅图像往往受到各种噪声的干扰,噪声常为一些孤立的像素点,往往是叠加在图像上的随机噪声,像雪花使图像被污染,而图像灰度应该相对连续变化的,一般不会突然变大或变小,这种噪声可以用邻域平均法使它得到抑制。
邻域平均法:邻域平均法:通过一点和邻域内像素点求平均来去除突变的像素点,优点是算法简单,计算速度快,代价是会造成图像一定程度上的模糊。
选择式掩模平滑法制作9种形状的屏蔽窗口,取5×5窗口。在窗口内以中心像素f(i,j)为基准点,分别计算每个窗口内的平均值及方差,采用方差最小屏蔽窗口进行平均化
自适应平滑方法:由于含有尖锐边沿的区域,方差比平缓区域大,采用多种形状的屏蔽窗口,分别计算各窗口内的灰度值方差,并采用方差最小的屏蔽窗口进行平均化方法。这种方法在完成滤波操作的同时,又不破坏区域边界的细节。
OpenCV提供了一个函数cv.filter2D来将内核与图像进行卷积。例如,我们将尝试对图像进行平 均滤波。5x5平均滤波器内核如下所示:
K = 1 25 [ 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 ] K = \frac{1}{25} \begin{bmatrix} 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \end{bmatrix} K=251⎣⎢⎢⎢⎢⎡1111111111111111111111111⎦⎥⎥⎥⎥⎤
操作如下:保持这个内核在一个像素上,将所有低于这个内核的25个像素相加,取其平均值,然后 用新的平均值替换中心像素。它将对图像中的所有像素继续此操作。试试这个代码,并检查结果:
import numpy as np import cv2 as cv
from matplotlib import pyplot as plt img = cv.imread('opencv_logo.png') kernel = np.ones((5,5),np.float32)/25 dst = cv.filter2D(img,-1,kernel)
plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(dst),plt.title('Averaging')
plt.xticks([]), plt.yticks([])
plt.show(
通过将图像与低通滤波器内核进行卷积来实现图像模糊。这对于消除噪音很有用。它实际上从图 像中消除了高频部分(例如噪声,边缘)。因此,在此操作中边缘有些模糊。(有一些模糊技术 也可以不模糊边缘)。OpenCV主要提供四种类型的模糊技术。
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
img = cv.imread('opencv-logo.jpg')
blur = cv.blur(img,(5,5))
plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(blur),plt.title('Blurred')
plt.xticks([]), plt.yticks([])
plt.show()
blur = cv.GaussianBlur(img,(5,5),0)
在这里,函数cv.medianBlur() 提取内核区域下所有像素的中值,并将中心元素替换为该中值。 这对于消除图像中的椒盐噪声非常有效。有趣的是,在上述过滤器中,中心元素是新计算的值, 该值可以是图像中的像素值或新值。但是在中值模糊中,中心元素总是被图像中的某些像素值代 替。有效降低噪音。其内核大小应为正奇数整数。
在此演示中,我向原始图像添加了50%的噪声并应用了中值模糊。检查结果:
median = cv.medianBlur(img,11)
邻域平均法:属于低通滤波的处理方法。他在抑制噪声的同时使图像变得模糊,即图像的细节(例如边缘信息)被消弱,
中值滤波: 抑制噪声又要保持细节。将窗口中奇数个数据按大小顺序排列,处于中心位置的那个数作为处理结果
是一种非线性信号处理方法,克服线性滤波器(如邻域平滑滤波)的模糊,对滤除脉冲干扰及图像扫描噪声最为有效。但是对一些细节多,特别是点,线,尖顶细节多的图像不易采用中值滤波
2021/5/14
目的: 突出图像中细节,或者增强被模糊了的细节,增强图像边缘,便于提取目标物体的边界、对图像进行分割、目标区域识别、区域形成提取等,为图像理解和分析打下基础
增强边界信息
提取物体的边界
基本方法:
通常,边缘上的灰度变化平滑,而边缘两侧的灰度变化较快。图像的边缘一般是指在局部不连续的图像特征。一般是局部亮度变化最显著的部分,灰度值的变化,颜色分量的突变,纹理结构的突变都可构成边缘信息。
我们最感兴趣的是恒定灰度区域(平坦段)、突变的开头与结尾(阶梯与斜坡突变)以及沿着灰度级斜坡处的特性。微分运算能够增强边缘和其他突变(如噪声),消弱灰度缓慢变化的区域,微分算子的响应强度与图像在该点的突变程度有关。
双向一次微分 a方加b方再开方
微分运算的作用:
梯度是一个矢量,由分别沿x和y方向计算微分的结果构成
Sobel算子
作用: 强调突变,弱化慢变。
将原始图像和拉普拉斯图像叠加在一起,保持锐化处理的效果,又能复原背景信息
采用多个边缘检测算子
2021/5/16