实验环境
Anaconda3 + OpenCV3 + Spyder
图像处理基础
图像读入、显示与保存
1.读入图像
retval = cv2.imread(文件名[,显示控制参数])
参数:
-文件名:完整文件名
-显示控制参数:cv.IMREAD_UNCHANGED、cv.IMREAD_GRAYSCALE、cv.IMREAD_COLOR
范例:1
img=cv2.imread("d:\\image.jpg")
2.显示图像
None=cv2.imshow(窗口名,图像名)
范例:1
cv2.imshow("demo",image)
retval=cv2.waitKey([,delay])
delay:
-delay>0 等待delay毫秒
-delay<0 等待键盘单击
-delay=0 无限等待
范例:1
cv2.waitKey(0)
cv2.destroyAllWindows()
功能:删除所有窗口
3.保存图像
retval=cv2.imwrite(文件地址,文件名)
范例:1
cv2.imwrite("D:\\test.jpg",img)
图像处理入门基础
- 图像是由像素构成的
- 图像分类:二值图像、灰度图像、RGB图像
OpenCV中通道顺序是BGR
常见操作:RGB转灰度、灰度转二值
像素处理
读取像素
返回值=图像(位置参数)
-灰度图像,返回灰度值。
范例:1
2p=img[88,142]
print(p)
-BGR图像,返回值为B,G,R的值。
范例:1
2
3
4
5blue=img[78,125,0], green=img[78,125,1], red=img[78,125,2]
print(blue), print(green), print(red)
p=img[78,125]
print(p)
修改像素值
像素=新值
-灰度图像
范例:1
img[88,99]=255
-BGR图像
范例:1
2
3img[88,99,0]=255, img[88,99,1]=255, img[88,99,2]=255
img[88,99]=[255,255,255]
使用numpy进行像素处理
读取像素
返回值=图像.item(位置参数)
-灰度图像,返回灰度值。
范例:1
2p=img.item(88,142)
print(p)
-BGR图像,返回值为B,G,R的值。
范例:1
blue=img.item(78,125,0), green=img.item(78,125,1), red=img.item(78,125,2)
修改像素值
图像名.itemset(位置,新值)
-灰度图像
范例:1
img.itemset((88,99), 255)
-BGR图像
范例:1
2
3img.itemset((88,99,0), 255)
img.itemset((88,99,1), 255)
img.itemset((88,99,2), 255)
获取图像属性
1.形状:行、列、通道数
shape可以获取图像的形状,返回包含行数,列数,通道数的元组。
-灰度 返回行数,列数
-彩色 返回行数,列数,通道数
范例:1
img.shape
2.像素数目
size可以获取图像的像素数目。
-灰度 返回:行数*列数
-彩色 返回:行数*列数*通道数
范例:1
img.size
3.图像的数据类型
dtype返回的是图像的数据类型。
范例:1
img.dtype
感兴趣区域ROI
ROI(region of interest),感兴趣区域。
从被处理的图像以方框、圆、椭圆、不规则多边形等方式勾勒出需要处理的区域。
可以通过各种算子(Operator)和函数来求得感兴趣区域ROI,并进行图像的下一步处理。
范例:1
2face=img[200:400,200:400]
img[200:400,600:800]=face
通道的拆分与合并
1.拆分通道

范例:1
2
3
4
5
6
7
8
9
10
11import cv2
img = cv2.imread('图像名')
b = img[:,:,0]
g = img[:,:,1]
r = img[:,:,2]
b,g,r = cv2.split(img)
b = cv2.split(img)[0]
g = cv2.split(img)[1]
r = cv2.split(img)[2]
2.合并通道

范例:1
2
3
4
5rows, cols, chn = a.shape
b = cv2.split(img)[0]
g = np.zeros((rows,cols), dtype=a.dtype)
r = np.zeros((rows,cols), dtype=a.dtype)
m = cv2.merge([b,g,r])
图像运算
图像加法
1.Numpy加法
取模加法
运算方式:结果=图像1+图像2


2.OpenCV加法
饱和运算
运算方式:结果=cv2.add(图像1, 图像2)

范例:1
2result1 = a + b
result2 = cv2.add(a,b)

注意的问题:
参与运算的图像大小、类型必须一致。
图像融合
将2张或2张以上的图像信息的融合到1张图像上
融合的图像含有更多的信息、能够更方便人来观察或者计算机处理

图像加法:结果图像=图像1+图像2
img=img1+img2
图像融合:结果图像=图像1*系数1+图像2*系数2+亮度调节量
img=img1*0.3+img2*0.7+18
函数addWeighted
dst = cv2.addWeighted(src1, aplha, scr2, beta, gamma)
dst = scr1*alpha + src2*beta + gamma
-参数gamma不能省略

范例:1
result = cv2.addWeighted(a,1,b,1,0)
图像类型转换
将图像由一种类型转换为另外一种类型
OpenCV提供了200多种不同类型之间的转换。
cv2.COLOR_BGR2GRAY 彩色转灰度
cv2.COLOR_BGR2RGB BGR转RGB
cv2.COLOR_GRAY2BGR 灰度转BGR
范例:1
2
3b = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
bb,bg,br = cv2.split(img)
几何变换
图像缩放
resize函数
语法格式
dst = cv2.resize(src,dsize[,dst[,fx[,fy[,interpolation]]]])
dst = cv2.resize(src,dsize,fx,fy)
-scr 原始图像
-dsize 缩放大小
-fx,fy 缩放大小
①dsize, ②fx,fy 设置一个即可
范例:1
2
3
4rows,clos = a.shape[:2]
b = cv2.resize(a,(round(cols*5),round(rows*1.2))) #列,行
b = cv2.resize(a,None,fx=1.2,fy=0.5)
图像翻转
flip函数
语法:
dst = cv2.flip(src, flipCode)
-flipCode=0 以X轴为对称轴翻转
-flipCode>0 以Y轴为对称轴翻转
-flipCode<0 在X轴、Y轴方向同时翻转
范例:1
dst = cv2.flip(src, 1)
阈值分割
基础知识

原始图像像素值分布

二进制阈值化
先要选定一个特定的阈值量,比如:127
新的阈值产生规则为:
- 大于等于127的像素点的灰度值设定为最大值(如8位灰度值最大为255)
- 灰度值小于127的像素点的灰度值设定为0

反二进制阈值化
该阈值化与二进制阈值化相似,先选定一个特定的灰度值作为阈值。以8位灰度图为例:
- 大于阈值的设定为0
- 小于该阈值的设定为255

截断阈值化
首先需要选定一个阈值,图像中大于该阈值的像素点被设定为该阈值,小于该阈值的保持不变。例如:阈值选取为127
- 小于127的阈值不改变
- 大于等于127的像素点设定为该阈值127

反阈值化为0
先选定一个阈值,然后对图像做如下处理:
- 大于等于阈值的像素点,值变为0
- 小于该阈值的像素点,值保持不变

阈值化为0
先选定一个阈值,然后对图像做如下处理:
- 大于等于阈值的像素点,值保持不变
- 小于该阈值的像素点,值变为0

threshold函数
函数threshold
retval, dst = cv2.threshold(src, thresh, maxval, type)
-retval,阈值
-dst,处理结果
-src,源图像
-threshold,阈值
-maxval,最大值
-type,类型
二进制阈值化:cv2.THRESH_BINARY
反二进制阈值化:cv2.THRESH_BINARY_INV
截断阈值化:cv2.THRESH_TRUNC
反阈值化为0:cv2.THRESH_TOZERO_INV
阈值化为0:cv2.THRESH_TOZERO
范例:1
r,b = cv2.threshold(a,127,255,cv2.THRESH_BINARY)

图像平滑处理
均值滤波
任意一点的像素值,都是周围N*N个像素值的均值
针对原始图像内的像素点,逐个采用核进行处理,得到结果图像。



函数blur
处理结果 = cv2.blur(原始图像, 核大小)

范例:1
r = cv2.blur(o,(5,5))


方框滤波
函数boxFilter
处理结果 = cv2.boxFilter(原始图像, 目标图像深度, 核大小, normalize属性)
目标图像深度:int类型的目标图像深度。通常使用“-1”表示与原始图像一致。
核大小:(5,5)、(3,3)
normalize属性:是否对目标图像进行归一化处理。

范例:1
2
3r = cv2.boxFilter(o,-1,(5,5),normalize=1) #归一化处理,与均值滤波相同
r = cv2.boxFilter(o,-1,(2,2)) #省略normalize参数,进行归一化处理



高斯滤波
让临近的像素具有更高的重要度。对周围像素计算加权平均值,较近的像素具有较大的权重值。

GaussianBlur函数
dst = cv2.GaussianBlur(src, ksize, sigmaX)
src:原始图像,要处理的源图像
ksize:核大小(N,N)必须是奇数

sigmaX:X方向方差,控制权重
sigmaX=0时:sigma = 0.3((ksize-1)0.5 - 1) + 0.8
范例:1
r = cv2.GaussianBlur(o,(3,3),0)

中值滤波
让临近的像素按照大小排列,取排序像素集中位于中间位置的值作为中值滤波后的像素值。

medianBlur函数
dst = cv2.medianBlur(src, ksize)
src:源图像
ksize:核大小,必须是比1大的奇数,如3,5,7等
范例:1
r = cv2.medianBlur(o,3)

形态学操作
基础
1.形态学转换主要针对的是二值图像。
2.两个输入对象。
对象1:二值图像
对象2:卷积核
图像腐蚀
卷积核的中心点逐个像素扫描原始图像。
被扫描到的原始图像中的像素点,只有当卷积核对应的元素值均为1时,其值才为1,否则值为0。
函数erode
dst = cv2.erode(src, kernel, iterations)
-dst,处理结果
-src,源图像
-kernel,卷积核 kernel=np.ones((5,5),np.uint8)
-iterations,迭代次数 默认情况下,迭代次数是1,根据需要可以进行多次腐蚀操作
范例:1
2
3
4kernel = np.ones((5,5),np.uint8)
erosion = cv2.erode(img, kernel)
erosion = cv2.erode(img, kernel, iterations=9)
图像膨胀
膨胀是腐蚀操作的逆操作

被扫描到的原始图像中的像素点,当卷积核对应的元素值只要有一个为1时,其值就为1,否则值为0。
函数dilate
dst=cv2.dilate(src, kernel, iterations)
-dst,处理结果
-src,源图像
-kernel,卷积核 kernel=np.ones((5,5),np.uint8)
-iterations,迭代次数
范例:1
2kernel = np.ones((5,5),np.uint8)
dilation = cv2.dilate(img, kernel)
开运算
开运算(image)=膨胀(腐蚀(image))

- 图像被腐蚀后,去除了噪声,但是会压缩图像。
- 对腐蚀过的图像,进行膨胀处理,可以去除噪声,并保持原有形状。
函数morphologyEx
result = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
-result,结果
-img,源图像
-cv2.MORPH_OPEN,开运算
-cv2.MORPH_CLOSE,闭运算
-cv2.MORPH_GRADIENT,梯度
-cv2.MORPH_TOPHAT,礼帽
-cv2.MORPH_BLACKHAT,黑帽
-kernel,卷积核 kernel=np.ones((5,5),np.uint8)
范例:1
2kernel = np.ones((5,5),np.uint8)
r = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
闭运算
闭运算(image)=腐蚀(膨胀(image))

- 先膨胀,后腐蚀
- 它有助于关闭前景物体内部的小孔,或物体上的小黑点
梯度运算
梯度(image)=膨胀(image)-腐蚀(image)

像素值:白色(1)、黑色(0)
- 梯度图像=膨胀图像-腐蚀图像
- 得到轮廓图像
礼帽(顶帽)操作
礼帽(image)=image-开运算(image)

- 礼帽图像=原始图像-开运算图像
- 得到噪声图像
黑帽操作
黑帽(image)=闭运算(image)-image

- 黑帽图像=闭运算图像-原始图像
- 得到图像内部的小孔,或前景色中的小黑点
腐蚀:去除边缘(变细)
可逆性研究:尺度一样、清晰度不一样、不可逆
图像梯度
sobel算子的理论基础
sobel算子及其函数使用
scharr算子函数及其使用
sobel算子和scharr算子的比较
laplacian算子及使用
canny边缘检测
canny边缘检测原理
canny函数及使用
图像金字塔
理论基础
pyrDown函数及使用
pyrUp函数及使用
取样可逆性研究
拉普拉斯金字塔
图像轮廓
图像轮廓(极简版)
1.轮廓是什么?
边缘检测能够测出边缘,但是边缘是不连续的。
将边缘连接为一个整理,构成轮廓。

2.注意问题:
对象是二值图像。所以需要预先进行阈值分割或者边缘检测处理。
查找轮廓需要更改原始图像。因此,通常使用原始图像的一份拷贝操作。
在OpenCV中,是从黑色背景中查找白色对象。因此,对象必须是白色的,背景必须是黑色的。

3.使用函数:
cv2.findContours()
cv2.drawContours()
查找图像轮廓的函数是cv2.findContours(),通过cv2.drawContours()将查找到的轮廓绘制到图像上。
image, contours, hierarchy = cv2.findContours(image, mode, method)
-image,修改后的原始图像(即二值化处理后的图像)
-contours,轮廓
-hierarchy,图像的拓扑信息(轮廓层次)
-image,原始图像
-mode,轮廓检索模型
- cv2.RETR_EXTERNAL:表示只检测外轮廓
- cv2.RETR_LIST:检测的轮廓不建立等级关系
- cv2.RETR_CCOMP:建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。如果内孔内还有一个连通物体,这个物体的边界也在顶层。
- cv2.RETR_TREE:(常用)建立一个等级树结构的轮廓。
-method,轮廓的近似方法
- cv2.CHAIN_APPROX_NONE:(常用)存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2), abs(y2-y1))==1
- cv2.CHAIN_APPROX_SIMPLE:(常用)压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息
- cv2.CHAIN_APPROX_TC89_L1:使用teh_Chinl chain近似算法
- cv2.CHAIN_APPROX_TC89_KCOS:使用teh_Chinl chain近似算法
r = cv2.drawContours(o, contours, contourIdx, color[, thickness])
-r:目标图像,直接修改目标的像素点,实现绘制
-o:原始图像
-contours:需要绘制的边缘数组
-contourIdx:需要绘制的边缘索引,如果全部绘制则为-1
-color:绘制的颜色,为BGR格式的Scalar。
-thickness:可选,绘制的密度,即描绘轮廓时所用的画笔粗细
4.范例1
2
3
4
5
6
7
8
9
10
11
12import cv2
o = cv2.imread('image\\contours.png')
gray = cv2.cvtColor(o, cv2.COLOR_BGR2GRAY) #色彩空间的转换(BGR转为灰度)
ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY) #灰度图像调整为二值图像
image, contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) #查找边界
co = o.copy() #不想改变原始图像
r = cv2.drawContours(co, contours, -1, (0,0,255), 1) #绘制所有边界,红色
# r = cv2.drawContours(co, contours, 0, (0,0,255), 6) #绘制第1个边界,粗细调粗
cv2.imshow("original",o)
cv2.imshow("contours",r)
cv2.waitKey()
cv2.destroyAllWindows()
直方图
直方图的概念
绘制直方图
使用OpenCV统计直方图
绘制OpenCV统计直方图
使用掩膜的直方图
掩膜原理及演示
直方图均衡化原理
直方图均衡化函数equalizeHist
subplot函数的使用
matplotlib.pyplot.imshow函数的使用
直方图均衡化对比
参考
书名 | 出版日期 | 简要评价 |
---|---|---|
Python+OpenCV图穷匕见 | py3.6 | 网易云课堂 |
OpenCV-Python-Toturial-中文版 | py3.5 | 官方文档翻译 |
OpenCV-Python-Tutorial | py3.6 | 官方文档翻译+博主自己的demo |
【视觉与图像】OpenCV篇:Python+OpenCV实用教程 | py3.6 | 优质博客 |
1 |