目录
一.图像
1.读取图像
tu_xiang = cv2.imread(文件名,[显示控制参数])
import cv2#导入opencv2
tupian = cv2.imread("E:\jre\eee.jpg")#读取图片
2.显示图像
xianshi_tupian = cv2.imshow(窗口名,图像名)
例子:
import cv2
tupian = cv2.imread("E:\jre\eee.jpg")#读取图像
cv2.imshow("窗口名",tupian)#显示图像
1.因为上面的程序会闪退,所以需要让图像在屏幕上停留一会
- retval = cv2.waitKey( [,delay])
- delay:
delay>0 等待delay毫秒
delay<0 等待键盘敲击
delay = 0 无限等待
范例:
cv2.waitKey(0)
""""
读取一张图片。并显示一秒
延时1000毫秒(1秒)
参数delay(1000)
"""
import cv2
tupian = cv2.imread("E:\jre\eee.jpg")
cv2.imshow("窗口名",tupian)
cv2.waitKey(1000)
""""
读取一张图片。并显示一秒
delay为0,无限延时
"""
import cv2
tupian = cv2.imread("E:\jre\eee.jpg")
cv2.imshow("窗口名",tupian)
cv2.waitKey(0)
""""
读取一张图片。并显示一秒
delay<0等待敲击键盘
"""
import cv2
tupian = cv2.imread("E:\jre\eee.jpg")
cv2.imshow("窗口名",tupian)
cv2.waitKey(-1)
2.cv2.destroyAllWindows()
功能:
删除所有窗口(关掉从内存里删掉所有窗口)
""""
读取一张图片。并显示一秒
delay=1000等待敲击键盘
"""
import cv2
tupian = cv2.imread("E:\jre\eee.jpg")
cv2.imshow("窗口名",tupian)
cv2.waitKey(1000)
cv2.destroyAllWindows() #关闭从内存中删除所有窗口
3.保存图像
bao_cun = cv2.imwrite(文件地址,文件名)
文件地址要存到什么地方,文件名:要保存哪个文件
""""
保存图片
"""
import cv2
img = cv2.imread("E:\jre\eee.jpg")
cv2.imwrite("E:\jre\jrf.png",img)
cv2.imshow("窗口名",img)
cv2.waitKey(1000)
cv2.destroyAllWindows() #关闭从内存中删除所有窗口
二.图像处理基础
1.图像处理入门基础
图像是由像素组成的
二值图像:非黑即白(0和1)一个像素点一个值
灰度图像:黑 白 灰 灰度(256个不同值)(0全黑,255全白)一个像素点一个值
RGB图像: 彩色图像(不同比例三原色混合成各种各样的颜色 ) opencv里面是BGR 一个像素点三个值
因为彩色图像3个值处理起来比较麻烦,灰度图像一个值处理起来比较方便
RGB装灰度图像
2.像素处理
1.读取像素
返回值 = 图像(位置参数)
- 灰度图像
p =img[23,199]#这个时候访问的是23行142列的像素
print(p)#打印像素值
- BGR图像
因为BGR是三通道BGR
第0个通道:blue
第一个通道:green
第三个通道:red
所以要增加一个通道数
blue = img[78,125,0]
print(blue)
green = img[78,125,1]
print(green)
red = img[78,125,2]
print(red)
例如:打印图片像素值
""""
保存图片
"""
import cv2
p = [0,0,0]
img = cv2.imread("E:\jre\eee.jpg")
cv2.imshow("窗口名",img)
p[0] = img[23,56,0]
p[1] = img[23,56,1]
p[2] = img[23,56,2]
print(p[0])
print(p[1])
print(p[2])
cv2.waitKey(1000)
cv2.destroyAllWindows() #关闭从内存中删除所有窗口
如果没有指定是哪个通道:
p = img[78,125]
print(p)
这个时候回出现三个值分别是BGR
2.修改像素
- 灰度图像
img[88,99] = 255#第88行99列像素值等于255
"""
改变一个灰度图像像素
"""
import cv2 as cv
p=cv.imread("E:\jre\eee.jpg")
print(p[25,25])
p[25,25] = 255
print(p[25,25])
- BGR图像可以分通道设置
img = [88,99,0] = 255#第88行99列,第零个通道
img = [88,99,1] = 255
img = [88,99,2] = 255
也可以直接赋值
img[88,99] = [255,255,255]
实例:
"""
改变一个RGB图像像素
"""
import cv2 as cv
p=cv.imread("E:\jre\eee.jpg")
print(p[25,25])
p[25,25] = [255,254,253]
print(p[25,25])
修改一定范围内图片并显示
"""
改变一个RGB图像像素
"""
import cv2 as cv
p=cv.imread("E:\\OPCV_yuanma\\image\\test.png")
cv.imshow("jieguo",p)
p[0:100,0:100,0:100] = [255,255,255]#将一定范围设置修改像素值
cv.imshow("jieguo1",p)
cv.waitKey(0)
cv.destroyAllWindows()
3.使用numpy进行像素处理
- 返回值 = 图像.item(位置参数)
灰度图像:
p = img.item(88,142)
print(p)
BGR图像:
blue = img.item(78,87,0)#对每个通道进行打印
import cv2
import numpy as np
i=cv2.imread("E:\OPCV_yuanma\image\lena512.bmp",cv2.IMREAD_UNCHANGED)#不改变类型,如果不添加参数下面必须添加通道数
print(i.item(88,55))
#print(i.item(100,100))#但因第100行100列
4.获取形状属性(shape)
1.shape可以获取图像的形状,返回包含行数,列数,通道数的元祖
例子:
灰度图像:
import cv2
img = cv2.imread("灰度图像")
print(img.shape)
输出##(512,512)
彩色图像:
import cv2
img = cv2.image("彩色图像")
print("img.shape)
输出##(512,512,3)#512行,512列3通道
2.像素数目
size可以获取图像像素数目
灰度 返回:行数*列数
彩色 返回:行数*列数*通道数
例子:
import cv2
img = cv2.imread(“图像名”)
print(img.size)
3.图像类型(dtype)
返回当前图像数据类型
例子:
import cv2
img = imread("图像名称")
print(img.dtype)
##uint8
例子:
import cv2 as cv
img1 = cv.imread("E:\\OPCV_yuanma\\image\\airfield.bmp",cv.IMREAD_UNCHANGED)
img2 = cv.imread("E:\\OPCV_yuanma\\image\\A.png")
print(img1.shape)
print(img2.shape)
print(img1.size)
print(img2.size)
5.图像ROI
比如当前黄色区域是一个图像,
可以通过下标的方式吧这个区域
import cv2
img = imread("图像名称")
face = img[200:400,200:400]
下面是赋值Roi区域的例程
"""复制roi区域"""
import cv2
import numpy as np
a = cv2.imread("E:\OPCV_yuanma\image\logo.png")#读取一张图片
b = np.ones((101,101,3))#创建了一个图像,这个图像三个通道,每一行都是101行,101列
b = a[220:400,250:350]
a[0:180,0:100]=b
cv2.imshow("original",a)
cv2.waitKey()
cv2.destroyAllWindows()
下面是我自己总结的简单的方法
"""复制roi区域"""
import cv2
import numpy as np
a = cv2.imread("E:\OPCV_yuanma\image\logo.png")#读取一张图片
a[0:180,0:100]=a[220:400,250:350]
cv2.imshow("original",a)
cv2.waitKey()
cv2.destroyAllWindows()
6.通道的拆分与合并
- 拆分通道:把那个通道独立出来:
-
b,g,r = cv2.split(a)
b = cv2.split(a)[0]
- 通道合并
m = cv2.message([b,g,r])
- 用split函数一次性的拆分出b,g,r
"""利用split函数快速拆分BGR通道""" import cv2 import numpy as np a = cv2.imread("E:\OPCV_yuanma\image\logo.png") b,g,r = cv2.split(a) cv2.imshow("B",b) cv2.imshow("G",g) cv2.imshow("R",r) cv2.waitKey() cv2.destroyAllWindows()
如果每次只想得到一个结果,就在split(a)[1]
"""利用split函数快速拆分BGR通道"""
import cv2
import numpy as np
a = cv2.imread("E:\OPCV_yuanma\image\logo.png")
g= cv2.split(a)[1]
cv2.imshow("G",g)
cv2.waitKey()
cv2.destroyAllWindows()
- 彩色通道的合并
与拆分类似
m = cv2.merge([b,g,r])
"""利用split函数快速拆分并且合并BGR通道"""
import cv2
import numpy as np
a = cv2.imread("E:\OPCV_yuanma\image\logo.png")
b,g,r = cv2.split(a)
cv2.imshow("B",b)
cv2.imshow("G",g)
cv2.imshow("R",r)
m = cv2.merge([b,g,r])#合并三通道
cv2.imshow("ref",m)
cv2.waitKey()
cv2.destroyAllWindows()
注意顺序为BGR
三.图像运算
1.图像的加法运算
参与运算图像大小和类型必须保持一致
- numpy加法
取模运算
- 运算方式 结果= 图像1+图像2,如果像素相加没有超过255,则直接相加,
- 如果超过255,则会(255+58)%255 = 58 (取余数)
- 因为比255小的时候和直接取模的结果是一样的,所以
- 直接不管大小都用与255取模的结果就可以了
- Opencv加法
饱和运算
- 运算方式:结果 = cv2.add(图像1,图像2)
- 如果像素值<=255 图像1+图像2
- 如果像素值>255 取值255
接下来是实例:
"""
两个图像相加程序
"""
import cv2
import numpy as np
a = cv2.imread("E:\OPCV_yuanma\image\lena256.bmp")
b = a
add1 = a+b#利用numpy运算
add2 = cv2.add(a,b)#利用opencv进行饱和运算
cv2.imshow("原始图像",a)
cv2.imshow("add1",add1)#
cv2.imshow("add2",add2)
cv2.waitKey()#等待用户输入
cv2.destroyAllWindows()#释放所有窗口
2.图像融合
图像融合虽然也是图像相加,进行图像融合的时候往往融合一些算法进去
- 函数addWeighted
- dst = addWeighted(src1,alpha,src2,beta,gamma)
- det = src1*alpha+src2*beta+gamma
-
参数1:src1,第一个原数组.
参数2:alpha,第一个数组元素权重参数3:src2第二个原数组
参数4:beta,第二个数组元素权重 - 下面是一个图像融合的效果
例如:
import cv2
a = cv2.imread("E:\\OPCV_yuanma\\image\\add\\boat.bmp")
b = cv2.imread("E:\\OPCV_yuanma\\image\\add\\lena.bmp")
c = cv2.addWeighted(a,0.3,b,0.6,0)#系数是调节亮度系数,最后系数是亮度调节值
cv2.imshow("a",a)
cv2.imshow("b",b)
cv2.imshow("c",c)
cv2.waitKey()
cv2.destroyAllWindows()
四.图像类型转换
1.图像类型转换
例如
- 彩色图像转换成灰度图像:cv2.COLOR_BGR2GRAY
b = cv2.cvtColor(a,cv2.COLOR_BGR2GRAY)#参数依次是原图像,转换的图像类型
实例:
彩色图像转灰度图像
- BGR转RGB:cv2.COLOR_BGR2RGB
b = cv2.cvtColor(a,cv2.COLOR_BGR2RGB)
- 灰度转BGR:cv2.COLOR_GRAY2BGR
b = cv2.cvtColor(a,cv2.COLOR_GRAY2BGR)
转换实例:
""
import cv2#导入opencv库
#适用于灰度图像
"""
a= cv2.imread("E:\OPCV_yuanma\image\lena256.bmp",cv2.IMREAD_UNCHANGED)#第二个参数是读入他原始的样子,
b = cv2.cvtColor(a,cv2.COLOR_GRAY2BGR)#将灰度图像转换成彩色图像,本程序不适用
"""
#适用于彩色图像,不用时请屏蔽
a= cv2.imread("E:\OPCV_yuanma\image\lenacolor.png")
b = cv2.cvtColor(a,cv2.COLOR_BGR2GRAY)#彩色图像装换为灰度图像
b = cv2.cvtColor(a,cv2.COLOR_BGR2RGB)#BGR转RGB
cv2.imshow("原始图像",a)#显示读取的图像
cv2.imshow("转换图像",b)#转换后的灰度图像
cv2.waitKey()#等待用户输入
cv2.destroyAllWindows()#释放所有窗口
因为上图灰度图像视觉上没有区别:。所以打印出来,看一下区别:
""
import cv2#导入opencv库
#适用于灰度图像
a= cv2.imread("E:\OPCV_yuanma\image\lena256.bmp",cv2.IMREAD_UNCHANGED)#第二个参数是读入他原始的样子,
b = cv2.cvtColor(a,cv2.COLOR_GRAY2BGR)#将灰度图像转换成彩色图像,本程序不适用
"""
#适用于彩色图像,不用时请屏蔽
a= cv2.imread("E:\OPCV_yuanma\image\lenacolor.png")
b = cv2.cvtColor(a,cv2.COLOR_BGR2GRAY)#彩色图像装换为灰度图像
b = cv2.cvtColor(a,cv2.COLOR_BGR2RGB)#BGR转RGB
"""
print(a.shape)
print(b.shape)
结果为:
E:\untitled5\venv\Scripts\python.exe E:/untitled5/first.py
(256, 256)
(256, 256, 3)
我们看一下三个通道的图片是什么样子
""
import cv2#导入opencv库
a= cv2.imread("E:\OPCV_yuanma\image\lena256.bmp",cv2.IMREAD_UNCHANGED)#第二个参数是读入他原始的样子,
b = cv2.cvtColor(a,cv2.COLOR_GRAY2BGR)#将灰度图像转换成彩色图像,本程序不适用
print(a.shape)
print(b.shape)
bb,bg,br = cv2.split(b)
cv2.imshow("bb",bb)#显示B通道
cv2.imshow("bg",bg)
cv2.imshow("br",br)
cv2.waitKey()
cv2.destroyAllWindows()
得到三个窗口的图像是一样的
五.几何变换
1.图像缩放
- resize
dst = cv2.resize(src,desize[, dst,[,fx[,fy[,interpolation]]]])
这么多参数里有两个参数是必备的,其他参数是可有可无
1.dst = cv2.resize(src,dsize)
src原始图像
desize:缩放大小
l例如:
b = cv2.resize(a,(122,122))行列
import cv2
a = cv2.imread("E:\OPCV_yuanma\chapter6\image\lenacolor.png")
#定义一个元祖,方便下面引用
rows,cols,chn = a.shape
size = (round(cols*0.5),round(rows*1.5))#round是取整
b = cv2.resize(a,size)#对a调整大小为200列100行
cv2.imshow("a",a)
cv2.imshow("b",b)
cv2.waitKey()
cv2.destroyAllWindows()
2.多了两个参数通常是在第二个参数不使用的时候
det = cv2.resize(src,desize,fx,fy)
fx,fy缩放大小,大于1表示放大
小于1表示缩小
等于1表示不变
例如:
b = cv2.resize(a,None,fx = 0.5,fy = 0.7),表示水平方向上,缩小0.5倍,fy缩小为原来的0.7倍
desize和fx,fy只需要设置一个就行了
import cv2
a = cv2.imread("E:\OPCV_yuanma\chapter6\image\lenacolor.png")
#定义一个元祖,方便下面引用
rows,cols,chn = a.shape
b = cv2.resize(a,None,fx=0.5,fy=1.3)#横向0.5倍,纵向103倍
cv2.imshow("a",a)
cv2.imshow("b",b)
cv2.waitKey()
cv2.destroyAllWindows()
2.图像翻转
- 语法
dst = cv2.flip(src,flipCode)#src原始图像,模式参数
范例:
flipCode = 0:现实的是以x轴为对称轴,上下翻转
flipCode > 0:以y轴为对称轴进行 左右翻转
flipCode<0 :在x轴方向和外轴方向同时翻转
dst = cv2.flip(src,1)
实现翻转
import cv2
a = cv2.imread("E:\OPCV_yuanma\chapter6\image\lenacolor.png")
b = cv2.flip(a,0)#0表示上下翻转
#b = cv2.flip(a,1)#0表示上下翻转
#b = cv2.flip(a,2)#0表示上下翻转
cv2.imshow("a",a)
cv2.imshow("b",b)
cv2.waitKey()
cv2.destroyAllWindows()
六.阈值分割
1.阈值分割
- 函数threshold
retval,dst = cv2.threshold(src,thresh,maxval,type)
- retval,阈值 dst,处理结果 src处理的源图像 thresh,阈值(一般情况下设置为128) maxmaxva阈值分割最大值 type阈值分割类型
- 二进制阈值化(和二值化图像不同,不一定是0和1)
二进制阈值化:大于阈值的值处理为255,小于等于 阈值的值处理为0
关键字:cv2.THREST_BINARY
"""
二进制阈值化
用到关键字
cv2.THRESH_BINARY
"""
import cv2
a = cv2.imread("E:\OPCV_yuanma\chapter6\image\lenacolor.png")
r,b = cv2.threshold(a,127,255,cv2.THRESH_BINARY)#a表示原始图像,b表示处理后的图像,r表示阈值127
cv2.imshow("a",a)
cv2.imshow("b",b)
cv2.waitKey()
cv2.destroyAllWindows()
- 反二进制阈值化
小于阈值或等于阈值的像素处理为最大值,大于阈值的像素处理为0
关键字:cv2.THRESH_BINARY_INV
- 截断阈值化
大于阈值的像素都处理为阈值,小于阈值的像素值不变
关键字:cv2.THREST_TRUNC
例如:
"""
二进制阈值化
用到关键字
cv2.THRESH_BINARY
"""
import cv2
a = cv2.imread("E:\OPCV_yuanma\chapter6\image\lenacolor.png")
r,b = cv2.threshold(a,127,255,cv2.THRESH_TRUNC)#a表示原始图像,b表示处理后的图像,r表示阈值127
cv2.imshow("a",a)
cv2.imshow("b",b)
cv2.waitKey()
cv2.destroyAllWindows()
- 反阈值化为0,
把大于阈值的像素处理为0,小于等于等于阈值的像素点不变
关键字:cv2.THRESH_TOZERO_INV
- 阈值化为0
把小于阈值的像素点处理为0.大于阈值的像素点不变
关键字:cv2.THRESH_TOZERO_INV
七.图像平滑处理
1.均值滤波
- opencv均值滤波函数
处理结果 = cv2.blur(原始图像,核大小)
例如:
r = cv2.blur(o,(5,5)#核大小5*5
核大小:以(宽度,高度)表示的一个元祖
import cv2
a = cv2.imread("E:\OPCV_yuanma\chapter8\image\lenaNoise.png")
b = cv2.blur(a,(5,5))#均值滤波
cv2.imshow("a",a)
cv2.imshow("b",b)
cv2.waitKey()
cv2.destroyAllWindows()
- 方框滤波
函数boxFilter
处理结果 = cv2.boxFilter(原始图像,目标图像深度,核大小,normalize属性)
目标图像深度:int类型的目标,图像深度。通常使用“-1”表示与原始图像一致
normalize属性:是否对目标图像进行归一化处理
分两种情况:
1.求均值:与均值滤波相同发
import cv2
o = cv2.imread("E:\OPCV_yuanma\chapter8\image\lenaNoise.png")
r = cv2.boxFilter(o,-1,(5,5,),normalize = 1)#normalize可省略默认为1
cv2.imshow("r",r)
cv2.waitKey()
cv2.destroyAllWindows()
2.求和:很容易发生溢出,25个这样的雨元素相加很容易超过255
例如:
import cv2
o = cv2.imread("E:\OPCV_yuanma\chapter8\image\lenaNoise.png")
r = cv2.boxFilter(o,-1,(5,5,),normalize = 0)#normalize可省略默认为1
cv2.imshow("r",r)
cv2.waitKey()
cv2.destroyAllWindows()
核换成2行2列,效果会好一些
import cv2
o = cv2.imread("E:\OPCV_yuanma\chapter8\image\lenaNoise.png")
r = cv2.boxFilter(o,-1,(2,2,),normalize = 0)#normalize可省略默认为1
cv2.imshow("r",r)
cv2.waitKey()
cv2.destroyAllWindows()
r = cv2.boxFilter(o,-1,(5,5),normalize = 1)#归一化处理与均值滤波相同,normalize省略默认为1
-1:深度和运势图像保持一致
核大小(5,5)
r = cv2.boxFliter(o,-1,(5,5),normalize = 1#不进行归一化处理,几个像素点相加很可能超过255,最后得到一个纯白色的图像
2.高斯滤波
让临近的像素具有更高的重要度,对周围像素计算加权平均值,较近的像素具有较大的权重值。
GaussionBlur函数
dst = cv2.GaussionBlur(src,ksize,sigmaX)#sigmaX,他自己会计算x方向上的方差
Ksize:核大小(N,N)必须是奇数
sigmaX:X方向方差,控制权重
sigmaX = 0时:sigma = 0.3*((ksize-1)*0.5-1)+0.8
y的方差和X保持一致
关键核心代码:
r = cv2.GaussianBlur(o,(3,3),0)
import cv2
o = cv2.imread("E:\OPCV_yuanma\chapter8\image\lenaNoise.png")
r = cv2.GaussianBlur(o,(5,5),0)
cv2.imshow("ee",o)
cv2.imshow("eew",r)
cv2.waitKey()
cv2.destroyAllWindows()
3.中值滤波
滤波效果比前面的都好
让临近像素按照大小排列,取排列像素集中于中间位置的值作为中值滤波后的像素值,可以把那些离群的点,
函数:
medianBlur函数
dst = cv2.medianBlur(src,ksize)
src,源文件
ksize;核大小:必须是比1大的奇数
关键代码:
r = cv2.medianBlur(o,3)#o原始图像,核大小3
历程:
import cv2
o = cv2.imread("E:\OPCV_yuanma\chapter8\image\lenaNoise.png")
r = cv2.medianBlur(o,3)#核大小是3,越大越模糊
cv2.imshow("ooo",o)
cv2.imshow("rrr",r)
cv2.waitKey()
cv2.destroyAllWindows()
八.形态学操作
1.图像腐蚀
形态学转换主要是针对二值图像,腐蚀的是像素点为1的那个点,腐蚀的是白色,
对象1:二值图像
对象2:卷积核:也是一个二值图像
用卷积核遍历每个原始图像的像素点,如果每个在核大小周围的像素点为1(白色),这个白色就保持不变。
如果在核的范围之内存在黑色的点,就将当前的点设为0(黑色)
- 函数erode
dst = cv2.erode(src,kernel,iteration)
det:处理结果
src:源图像 kernel 卷积核,iteration 迭代次数,默认情况下进行1次腐蚀,根据需要可多次腐蚀
生成一个卷积核,
kernel = np.ones((5,5),np.uint8)#ones表示数组里面的元素都是1,5行5列,np.uint8表示数据类型
dst = cv2.erode(src,kernel,iteration)
代码如下:
import cv2
import numpy as np
o = cv2.imread("E:\OPCV_yuanma\chapter8\image\erode.bmp",cv2.IMREAD_UNCHANGED)
k = np.ones((5,5),np.uint8)#定义一个卷积核
r = cv2.erode(o,k,3)#开始腐蚀,不写默认一次
cv2.imshow("o",o)
cv2.imshow("r",r)
cv2.waitKey()
cv2.destroyAllWindows()
2.膨胀
膨胀是腐蚀的逆操作
可通过一次膨胀,一次腐蚀来达到去除噪声(毛刺)的操作
先腐蚀后膨胀,形态学运算中叫做开运算
在卷积核对应大小这篇区域中,有1个像素点为1的点这个点像素就为1,
函数:dilat
dst = cv2.dilat(src,keral,iterations)
dst:处理结果
src:源图像
kernel:卷积核
iterations,迭代次数
import cv2
import numpy as np
o = cv2.imread("E:\OPCV_yuanma\chapter8\image\erode.bmp",cv2.IMREAD_UNCHANGED)
k = np.ones((5,5),np.uint8)#定义一个卷积核
r = cv2.dilate(o,k)#开始腐蚀,不写默认一次
cv2.imshow("o",o)
cv2.imshow("r",r)
cv2.waitKey()
cv2.destroyAllWindows()
3.开运算操作
先腐蚀后膨胀
图像被腐蚀后,去除了噪声,但是图像会压缩,
腐蚀过得图像通过膨胀,可以去除噪声,并曝出,原来的形状
开运算(image) = 膨胀(腐蚀(image)
函数:morphologyEx
opening = cv2.morpholoyEx(img,cv2.MORPH_OPEN,kernel)
opencving :开运算结果
img:源图像
cv2.MORPH_OPEN:开运算
kernel:卷积核
kernel = np.opes((5,5),np.uint8) #生成一个5行5列,用它作为一个卷积核,对原始图像进行开运算
核心代码:
k = np.ones((5,5),np.uint8)
r = cv2.morphologyEx(o,cv2.MORPH_OPEN,K)
import cv2
import numpy as np
a = cv2.imread("E:\OPCV_yuanma\chapter8\image\erode.bmp")
k = np.ones((8,8,),np.uint8)#根据不同要求调解卷积核大小
r = cv2.morphologyEx(a,cv2.MORPH_OPEN,k)
cv2.imshow("a",a)
cv2.imshow("r",r)
cv2.waitKey()
cv2.destroyAllWindows()
4.闭运算
先膨胀后腐蚀,
有助于关闭,前景物体内部小孔,或物体上的小黑点
闭运算(image) = 腐蚀(膨胀(image))
函数:morphologyEx
closing = cv2.morphologyEx(img,cv2.MORPH_CLOSE,kernel)
close ,闭运算结果
img:源图像
cv2.MORPH_CLOSE:闭运算
kernel:卷积核
kernel = np.ones((5,5),np.uint8)
核心代码:
k = np.ones((5,5),np.uint8)
r = cv2.morphologyEx(o,cv2.MORPH_CLOSE,K)
5.图像梯度
在二值图像里白色的像素值是1,黑色的像素值是0
梯度操作 :膨胀图像 - 腐蚀图像 = 轮廓图像
梯度(image) = 膨胀(image)-腐蚀(image)
在opencv中我们不关心细节是怎么实现的,直接调用封装好的函数就行了
函数:morphologyEx
result = cv2.morphpologyEx(img,cv2.MORPH_GRADIENT,kenal)
result梯度结果
img:源图像
cv2.MORPH_GRADIENT,梯度
kernel:卷积核
核心代码
kernel = np.ones((5,5),np.uint8)
r = cv2.morphologyEx(o,cv2.MORPH_GRADIENT,K)
import cv2
import numpy as np
a = cv2.imread("E:\OPCV_yuanma\chapter8\image\gradient.bmp")
k = np.ones((10,10,),np.uint8)#根据不同要求调解卷积核大小
r = cv2.morphologyEx(a,cv2.MORPH_GRADIENT,k)
cv2.imshow("a",a)
cv2.imshow("r",r)
cv2.waitKey()
cv2.destroyAllWindows()
6.礼帽操作(图像顶帽)
礼帽图像 = 原始图像-开运算图像
结果得到噪声图像
函数:morphologyEx
result = cv2.morphologyEx(img,cv2.MORPH_TOPHAT,kernel)
result 礼帽结果
img:源图像
cv2.MORPH_TOPHAT,礼帽
kernel:卷积核
核心代码
k = np.ones((5,5),np.uint8)
r = cv2.morphologyEx(o.cv2.MORPH_TOPHAT,k)
import cv2
import numpy as np
o = cv2.imread("E:\OPCV_yuanma\chapter8\image\opening.bmp")
k = np.ones((5,5),np.uint8)
r = cv2.morphologyEx(o,cv2.MORPH_TOPHAT,k)
cv2.imshow("o",o)
cv2.imshow("r",r)
cv2.waitKey()
cv2.destroyAllWindows()
7.黑帽图像处理
黑帽图像 = 闭运算-原始图像
得到图像内部小点的图像
函数
morphologyEx
result = cv2.morphologyEx(img,cv2.MORPH_BLACKHAT,kernel)
result :黑帽结果
img :源图像
cv2.MORPH_BLACKHAT:黑帽
kernel:卷积核
import cv2
import numpy as np
o = cv2.imread("E:\OPCV_yuanma\chapter8\image\closing2.bmp")
k = np.ones((5,5),np.uint8)
r = cv2.morphologyEx(o,cv2.MORPH_BLACKHAT,k)
cv2.imshow("o",o)
cv2.imshow("r",r)
cv2.waitKey()
cv2.destroyAllWindows()
九.图像梯度
1.sobel使用
dst = cv2.Sobel(src,ddepth,dx,dy,[ksize])#kzize 不写默认是3
dst :计算结果
src:原始图像
ddepth:处理结果图像深度,很多函数里可以直接写成-1,让处理图像和原始图像深度保持一致,
dx:x轴方向
dy:轴方向
ksize:核大小
x轴方向上的梯度,dx = 1,dy = 0
y轴上的梯度,dy = 1,dx = 0
dst = cv2.Sobel(src,ddepth,dx,dy,[ksize])
实例只计算出右边的边界:
"""
只计算出右边边界
"""
import cv2
import numpy as np
o = cv2.imread("E:\OPCV_yuanma\chapter8\image\sobel.bmp",cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(o,-1,1,0)#因为第二个参数为-1,只计算出右边的边界
cv2.imshow("o",o)
cv2.imshow("s",sobelx)
cv2.waitKey()
cv2.destroyAllWindows()
计算出左右边界:
"""
计算出左右边界
把-1改成cv2.CV_64F
"""
import cv2
import numpy as np
o = cv2.imread("E:\OPCV_yuanma\chapter8\image\sobel.bmp",cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(o,cv2.CV_64F,1,0)#计算出左右边的边界
sobelx = cv2.convertScaleAbs(sobelx)#取绝对值,有的图像可能不用调节也可以显示,最好加上
cv2.imshow("o",o)
cv2.imshow("s",sobelx)
cv2.waitKey()
cv2.destroyAllWindows()
计算出上下左右边界:
"""
计算出左右边界
把-1改成cv2.CV_64F
"""
import cv2
import numpy as np
o = cv2.imread("E:\OPCV_yuanma\chapter8\image\man.bmp",cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(o,cv2.CV_64F,1,0)#计算出左右边的边界
sobely = cv2.Sobel(o,cv2.CV_64F,0,1)#计算出上下边界
sobelx = cv2.convertScaleAbs(sobelx)#取绝对值,有的图像可能不用调节也可以显示,最好加上
sobely = cv2.convertScaleAbs(sobely)#取绝对值,有的图像可能不用调节也可以显示,
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)#x和y的系数都输0.5.修正系数设置成0
#sobelxy11 = cv2.Sobel(o,cv2.CV_64F,1,1)#这种方法显示效果不好
sobelxy11 = cv2.convertScaleAbs(sobelxy11)
cv2.imshow("o",o)#显示原始图像
cv2.imshow("x",sobelx)#显示x边界
cv2.imshow("y",sobely)#显示y边界
cv2.imshow("xy",sobelxy)
#cv2.imshow("xy11",sobelxy11)
cv2.waitKey()
cv2.destroyAllWindows()
- 图像梯度中的scharr算子函数及其使用
十,Canny边缘检测
1.canny边缘检测原理
canny边缘检测步骤
.去噪——梯度——非极大值抑制——滞后阈值
- 边缘检测很容易受到噪声的影响。因此在进行边缘处理的时候应该先去噪,通常采用高斯滤波去除噪声
- 对平滑后的值采用sobel算子计算梯度和方向。
梯度的方向一般总是与边界垂直。
梯度的方向分为4类:垂直,水平,和两个对角线
3.非极大值抑制:
逐个遍历像素点,判断当前像素点 是不是所有相同方向中最大的,如果是最大的保留,
4.滞后阈值:
- 滞后阈值1:minVal,极小值
- 滞后阈值2:maxVal,极大值
如果梯度值>边界值,就处理为边界
如果梯度值<边界值,抛弃
中间值,:
如果和边界值相连的保留
与边界不相连抛弃
2.canny边缘检测使用
函数canny
edges = cv2.Canny(image,theshole1,threshold2)
edges 边界图像
image,原始图像
threshold1,阈值1
threshole2阈值2,
如果想让canny边缘检测边界更多,把阈值调小一点
如果想让边界没那么丰富,把这两个阈值调大一点
例如:
"""
cany边缘检测
"""""
import cv2
import numpy as np
o = cv2.imread("E:\OPCV_yuanma\chapter8\image\man.bmp",cv2.IMREAD_GRAYSCALE)
r1 = cv2.Canny(o,100,200)#检测边缘值较大,边缘少
r2 = cv2.Canny(o,64,128)#检测边缘值小,边缘多
cv2.imshow("r1",r1)
cv2.imshow("r2",r2)
cv2.waitKey()
cv2.destroyAllWindows()
十,图像金字塔
1.理论基础
- 向下取样,分辨率越来越小
向上取样分辨率越来越大
1.对图像Gi中进行高斯核卷积
2.删除所有的偶数行和列
向下取样:缩小 图像
原始图像:M*N——>处理结果是M/2*N/2
每次处理后都是原有图像的1/4
上述操作被称为:Octave
- 向上取样
在每个方向上扩大为原来的两倍,新增的 行和列以0填充
使用与“向下采样”同样的卷积核乘以4,获取“新增像素”的新值
如果直接滤波的话,整体来说像素会降低1/4
所以要乘以4,来保证这是一个正常的图像,而不是所有像素值都变为原来1/4这样的一个图像
所有的元素都被规范化为4而不是1
上图告诉我们图像向下以后再向上取样,这个过程不是互逆的无法恢复原有图像,
2.图像金字塔向下取样函数及应用
opencv中提供了cv2.pyrDown(src)
dst = cv2.pyrDown(src)
dst ,向下取样结果
src, 原始图像
"""
向下取样
"""""
import cv2
import numpy as np
o = cv2.imread("E:\jre\\32945694.jpg",cv2.IMREAD_GRAYSCALE)
r = cv2.pyrDown(o)#向下取样
cv2.imshow("o",o)
cv2.imshow("r",r)
cv2.waitKey()
cv2.destroyAllWindows()
进行多次取样的变化,每个图像都是原来的1/4
"""
向下取样
"""""
import cv2
import numpy as np
o = cv2.imread("E:\jre\\32945694.jpg",cv2.IMREAD_GRAYSCALE)
r = cv2.pyrDown(o)#向下取样
s = cv2.pyrDown(r)
t = cv2.pyrDown(s)
cv2.imshow("o",o)#原始图像
cv2.imshow("r",r)#第一次取样
cv2.imshow("s",s)#第二次取样
cv2.imshow("t",t)#第三次取样
cv2.waitKey()
cv2.destroyAllWindows()
3向上取样.
都是以4倍为单位进行变化的
如果向下取样图像的大小变为原来的1/4
opencv中向上取样函数
dst = cv2.pyrUp9(src)
dst :原始图像
src ,原始图像
"""
向上取样
"""""
import cv2
import numpy as np
o = cv2.imread("E:\OPCV_yuanma\chapter8\image\lena256.bmp",cv2.IMREAD_GRAYSCALE)
r = cv2.pyrUp(o)#向下取样
cv2.imshow("o",o)#原始图像
cv2.imshow("r",r)#第一次取样
cv2.waitKey()
cv2.destroyAllWindows()
多次向上取样
"""
向上取样
"""""
import cv2
import numpy as np
o = cv2.imread("E:\OPCV_yuanma\chapter8\image\lena256.bmp",cv2.IMREAD_GRAYSCALE)
r = cv2.pyrUp(o)#向下取样
s = cv2.pyrUp(r)
t = cv2.pyrUp(s)
cv2.imshow("o",o)#原始图像
cv2.imshow("r",r)#第一次取样
cv2.imshow("s",s)#第二次取样
cv2.imshow("t",t)#第三次取样
cv2.waitKey()
cv2.destroyAllWindows()
4.图像金字塔向上取样与向下取样的可逆性研究
先进性向下取样在进行向上取样
"""
向上取样
"""""
import cv2
import numpy as np
o = cv2.imread("E:\OPCV_yuanma\chapter8\image\lena256.bmp",cv2.IMREAD_GRAYSCALE)
r = cv2.pyrDown(o)#向下取样
s = cv2.pyrUp(r)#向上取样
cv2.imshow("o",o)#原始图像
cv2.imshow("r",s)#
cv2.waitKey()
cv2.destroyAllWindows()
4.拉普拉斯金字塔
Li = Gi - PyrUp(PyDown(Gi))
Gi ,原始图像
Li ,拉普拉斯金字塔图像
“”“”“
中间这段笔记没有保存
”“”
14.直方图
1.使用opencv统计直方图
横坐标:[0:255]
纵坐标:各个灰度级的像素个数
绘图的时候仅仅一个纵坐标就能绘制一个图像了
现在计算一个图像的直方图由绘图变成了求数据
opencv第一步就是求出这样一个数据(每一个灰度值对应的个数)
函数calcHist(用来计算这个数组)
hist = cv2.calcHist(images,channels,mask,histSize,range,accumulate)
hist,直方图
images:原始图像 histSizeBINS的数量例如:[256]
channels:指定通道 range: 像素值范围:RANGE例如[0,255]
mask :掩码图像 accumlate:累计标识 可选参数,一般默认省略掉
import cv2
import numpy as np
img = cv2.imread("E:\OPCV_yuanma\chapter8\image\lena.bmp")
hist = cv2.calcHist([img],[0],None,[256],[0,255])
print(type(hist))#返回的类型
print(hist.size)#大小是256个元素
print(hist.shape)#形状256行1列
print(hist)#输出每个灰度级在图像有多少个
2.使用掩模的直方图
掩模:黑色不透明,白色为透明
把掩模放到原始图像上
黑色部分就被覆盖了,白色部分因为是透明的,所以他会映衬过来一个图像,
关键代码:
mask = np.zeros(image.shape,np.uint8)#一般是对灰度图像进行操作
mask = [200:400,200:400] = 255#第200行到400行,200列到400列为白色
生成直方图的时候要先获取统计直方图,
一般形式:
hist = cv2.calc.Hist(image,channels,mask,histSize,ranges)