(二)OpenCV入门,代码练习,详细注释【二值化,滤波,边缘检测】【300行】【原创】

文章目录


文字

#图像阈值
#新的学习方法
#图像二值化/反转/几种二值化模式/图像平滑滤波

“”"
均值滤波就是构造33数组,求出里面九个像素点数值之和再除以9求均值
5
5也行,均值滤波就是去除噪声,定义一个卷积核大小,里面全是1,要除以9,归一化操作
“”"
“”"
方框滤波,和均值滤波一样,当采取归一化处理,它等于均值滤波,如果不采取则会出现数值越界
图像会出现大面积发白,所有越界的值全变为255,就是设置True还是False
“”"
“”"
高斯滤波,就是高斯函数,就是正态分布,就是根据权重进行选择滤波,离得越近效果越强,越远滤波效果越不强
“”"
“”"
中值滤波,就是取九个值中的中间值替换成所有的值,是最易理解,也是最简单的,唐宇迪视频里看到
此方法滤波效果最好
“”"

代码

#图像阈值
#新的学习方法
#图像二值化/反转/几种二值化模式/图像平滑滤波

"""
均值滤波就是构造3*3数组,求出里面九个像素点数值之和再除以9求均值
5*5也行,均值滤波就是去除噪声,定义一个卷积核大小,里面全是1,要除以9,归一化操作
"""
"""
方框滤波,和均值滤波一样,当采取归一化处理,它等于均值滤波,如果不采取则会出现数值越界
图像会出现大面积发白,所有越界的值全变为255,就是设置True还是False
"""
"""
高斯滤波,就是高斯函数,就是正态分布,就是根据权重进行选择滤波,离得越近效果越强,越远滤波效果越不强
"""
"""
中值滤波,就是取九个值中的中间值替换成所有的值,是最易理解,也是最简单的,唐宇迪视频里看到
此方法滤波效果最好
"""
"""
# 展示所有的图像/所有拼接在一起容易比较各图像效果
res = np.hstack((blur,aussian,median))#blur,aussian,median 是三个图片拼接在一起/hstack是横着拼接/vstack是竖着拼接
#print (res)
cv2.imshow('median vs average', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
"""

"""
# 形态学腐蚀操作
# 就是去掉“迪哥”中的毛刺胡须,就是侵犯它腐蚀它,让它缩一缩,执行后字体毛刺消失,且线条变细
# 就是建立3*3卷积核,就是当卷积核框住了毛刺部分,就会将它腐蚀掉,例程中腐蚀黑色背景白色圆
# 腐蚀就是将它变为黑色,迭代次数iterations,就是再腐蚀一圈,比如迪哥腐蚀三次就看不到字体了,全部为黑色了
# 还有卷积核3*3内核小,如果是5*5就大了,那么腐蚀效果会好一些,因为框住了范围变大
# 例程中腐蚀三次,白色圆会越来越小
img = cv2.imread('dige.png')

cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
kernel = np.ones((3,3),np.uint8) 
erosion = cv2.erode(img,kernel,iterations = 1) #1是迭代次数

cv2.imshow('erosion', erosion)
cv2.waitKey(0)
cv2.destroyAllWindows()
pie = cv2.imread('pie.png')

cv2.imshow('pie', pie)
cv2.waitKey(0)
cv2.destroyAllWindows()

kernel = np.ones((30,30),np.uint8) 
erosion_1 = cv2.erode(pie,kernel,iterations = 1)
erosion_2 = cv2.erode(pie,kernel,iterations = 2)
erosion_3 = cv2.erode(pie,kernel,iterations = 3)
res = np.hstack((erosion_1,erosion_2,erosion_3))
cv2.imshow('res', res)
cv2.waitKey(0)
cv2.destroyAllWindows()
"""

"""
膨胀操作
就是字体意思,就是膨胀,就是将腐蚀后细线条迪哥变为粗一点的迪哥

框到黑色变白色,白色还是白色,与腐蚀操作完全对偶操作
"""

"""
开运算与闭运算
开就是先腐蚀再膨胀
闭就是先膨胀再腐蚀,闭操作不能处理迪哥
"""

"""
梯度运算
膨胀>腐蚀>膨胀-腐蚀(白大-黑小)>得到一个轮廓
"""

"""
礼貌与黑帽//这两个就是梯度运算
礼帽得到迪哥两字的毛刺
黑帽得到迪哥两字的轮廓
"""

"""
scharr算子敏感
-3 0 3
-10 0 10
-3 0 3
lapaclan算子拉普拉斯算子/对噪声敏感
0 1 0
1 -4 1
0 1 0
图像梯度-Sobel算子
Gx与Gy//计算图像梯度//用于边缘检测//思路也是利用卷积核进行对图像提取
Gx表示水平,
-1 0 1
-2 0 2
-1 0 1    
Gy表示竖直,
-1 -2 -1
0  0  0
1  2  1
第一个实验,还是那个白球
img = cv2.imread('pie.png',cv2.IMREAD_GRAYSCALE)
cv2.imshow("img",img)
cv2.waitKey()
cv2.destroyAllWindows()
dst = cv2.Sobel(src, ddepth, dx, dy, ksize)#这一步是梯度运算

ddepth:图像的深度
dx和dy分别表示水平和竖直方向
ksize是Sobel算子的大小

ksize一般为3*3

def cv_show(img,name):
    cv2.imshow(name,img)
    cv2.waitKey()
    cv2.destroyAllWindows()
# 表示算水平的/每一个位置右边-左边(此种方法白圆轮廓右边消失因为负数截断) 
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3) #
sobelx = cv2.convertScaleAbs(sobelx) # 这一步是取绝对值,必须要这句,这时出现右侧边框  
cv_show(sobelx,'sobelx')


sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
sobely = cv2.convertScaleAbs(sobely) #绝对值 
cv_show(sobely,'sobely')
# 这是采取Gy方式寻出轮廓/上下轮廓

# 分别计算x和y,再求和
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0) #按权重进行Gx+Gy
cv_show(sobelxy,'sobelxy')# 显示Gx+Gy显示的轮廓
x上下有虚断线/y左右有断点/上面是x+y方式效果不好,不建议
"""

"""
sobelxy=cv2.Sobel(img,cv2.CV_64F,1,1,ksize=3)
sobelxy = cv2.convertScaleAbs(sobelxy)
cv_show(sobelxy,'sobelxy')
# 上面是两个直接进行运算,效果很差

# 下面是单独求再相加,效果很好,求出轮廓
img = cv2.imread('lena.jpg',cv2.IMREAD_GRAYSCALE)
cv_show(img,'img')

img = cv2.imread('lena.jpg',cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
sobely = cv2.convertScaleAbs(sobely)
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)
cv_show(sobelxy,'sobelxy')

"""

"""
拉普拉斯算子
对噪声敏感1
"""
#"""
# 三种算子算法拼接图/图像梯度-Sobel算子/图像梯度-Scharr算子/图像梯度-laplacian算子
import cv2
import matplotlib.pyplot as plt
import numpy as np #numpy是数组

def cv_show(img,name):
    cv2.imshow(name,img)
    cv2.waitKey()
    cv2.destroyAllWindows()

img = cv2.imread('E:/jupyter-notebook/notebook1/lena.jpg',cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)   
sobely = cv2.convertScaleAbs(sobely)  
sobelxy =  cv2.addWeighted(sobelx,0.5,sobely,0.5,0)  

scharrx = cv2.Scharr(img,cv2.CV_64F,1,0)# 这个效果最好
scharry = cv2.Scharr(img,cv2.CV_64F,0,1)
scharrx = cv2.convertScaleAbs(scharrx)   
scharry = cv2.convertScaleAbs(scharry)  
scharrxy =  cv2.addWeighted(scharrx,0.5,scharry,0.5,0) 

laplacian = cv2.Laplacian(img,cv2.CV_64F)
laplacian = cv2.convertScaleAbs(laplacian)   

res = np.hstack((sobelxy,scharrxy,laplacian))
cv_show(res,'res')

img = cv2.imread('E:/jupyter-notebook/notebook1/lena.jpg',cv2.IMREAD_GRAYSCALE)
cv_show(img,'img')
#"""

"""
Canny边缘检测
1) 使用高斯滤波器,以平滑图像,滤除噪声。
2) 计算图像中每个像素点的梯度强度和方向。
3) 应用非极大值(Non-Maximum Suppression)抑制,以消除边缘检测带来的杂散响应。
4) 应用双阈值(Double-Threshold)检测来确定真实的和潜在的边缘。
5) 通过抑制孤立的弱边缘最终完成边缘检测。
"""
img=cv2.imread("E:/jupyter-notebook/notebook1/lena.jpg",cv2.IMREAD_GRAYSCALE)# 灰度图

v1=cv2.Canny(img,100,200) # 左边是双阈值检测
v2=cv2.Canny(img,50,100) # 阈值越小检测宽泛,阈值越大检测越精确要求更高

res = np.hstack((v1,v2))
cv_show(res,'res')

# 图像金字塔
# 高斯金字塔
# 拉普拉斯金字塔
img = cv2.imread("E:/jupyter-notebook/notebook1/lena.jpg",0)# 0表示灰度图
hist = cv2.calcHist([img],[0],None,[256],[0,256])
print(hist.shape)# (256, 1) 256是表示0到255共256种取值,1是表示一维
plt.hist(img.ravel(),256);#好坑啊,这个符号是;而不是:
plt.show()

img = cv2.imread("E:/jupyter-notebook/notebook1/lena.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])
    plt.show()# 会打印三张直方图,分别是三个通道

# 去除偶数行偶数列,可以向上或者向下,记住向下是添加0,向上是去除点是缩小
# 可以上采样或者下采样就是向上或者向下
# 向下采样添加0会模糊
# 拉普拉斯金字塔,就是结合高斯金字塔计算,先这样理解,后面项目再讲
#

# 轮廓检测默认使用   RETR_TREE:检索所有的轮廓,并重构嵌套轮廓的整个层次;
#

"""
高斯滤波就是根据算子中的九个值(根据3*3)权重进行计算总和
非极大值抑制,看视频可以理解,挺复杂的
双阈值检测,分三种情况进行处理,
"""

"""
up=cv2.pyrUp(img)
up_down=cv2.pyrDown(up)
cv_show(up_down,'up_down')

cv_show(np.hstack((img,up_down)),'up_down')

up=cv2.pyrUp(img)
up_down=cv2.pyrDown(up)
cv_show(img-up_down,'img-up_down')

down=cv2.pyrDown(img)
down_up=cv2.pyrUp(down)
l_1=img-down_up
cv_show(l_1,'l_1')

cv2.findContours(img,mode,method)
mode:轮廓检索模式
RETR_EXTERNAL :只检索最外面的轮廓;
RETR_LIST:检索所有的轮廓,并将其保存到一条链表当中;
RETR_CCOMP:检索所有的轮廓,并将他们组织为两层:顶层是各部分的外部边界,第二层是空洞的边界;
RETR_TREE:检索所有的轮廓,并重构嵌套轮廓的整个层次;
method:轮廓逼近方法
CHAIN_APPROX_NONE:以Freeman链码的方式输出轮廓,所有其他方法输出多边形(顶点的序列)。
CHAIN_APPROX_SIMPLE:压缩水平的、垂直的和斜的部分,也就是,函数只保留他们的终点部分。

cnt = contours[0]# 表示第一个轮廓,contours其实是每个轮廓所有的点集
#面积
cv2.contourArea(cnt)
8500.5
#周长,True表示闭合的
cv2.arcLength(cnt,True)# 第一个轮廓
437.9482651948929

轮廓近似(就是轮廓尽量变为直线)#就是让检测图片的轮廓变为矩形,即使被检图片边缘毛刺也是直线
img = cv2.imread('contours2.png')

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
binary, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
cnt = contours[0]# 左下角第一个图形内轮廓点集合

draw_img = img.copy()
res = cv2.drawContours(draw_img, [cnt], -1, (0, 0, 255), 2)
cv_show(res,'res')

# cnt = contours[0]# 左下角第一个图形内轮廓点集合   0.15越小越没变化,越大变化越夸张
epsilon = 0.15*cv2.arcLength(cnt,True) # 按周长的百分比来设置,数值大小需要自己调试
approx = cv2.approxPolyDP(cnt,epsilon,True)# cnt是第一个轮廓点

draw_img = img.copy()
res = cv2.drawContours(draw_img, [approx], -1, (0, 0, 255), 2)#表示在draw_img上画第一个轮廓,但是不会改变img原图
cv_show(res,'res')

边界矩形
img = cv2.imread('contours.png')

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
binary, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
cnt = contours[0]#第一个轮廓外圈点信息给cnt,contours是列表,contours[1]是第一个轮廓内圈点信息,以此类推


x,y,w,h = cv2.boundingRect(cnt)#boundingRect就是将一个轮廓外圈xywh换算成外接矩形四个值赋xywh,然后下面draw出矩形
img = cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)#2代表是线粗细
cv_show(img,'img')
# 根据上面计算下面的比例
area = cv2.contourArea(cnt)
x, y, w, h = cv2.boundingRect(cnt)
rect_area = w * h
extent = float(area) / rect_area
print ('轮廓面积与边界矩形比',extent)
# 外接圆
(x,y),radius = cv2.minEnclosingCircle(cnt) 
center = (int(x),int(y)) 
radius = int(radius) 
img = cv2.circle(img,center,radius,(0,255,0),2)
cv_show(img,'img')


# 模板匹配

"""
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
如果你想对二图像进滤波操作,可以尝试使用形态学滤波或者均滤波。 形态学滤波可以帮助去除图像中的小的噪点,同时保持物体的整体形状。常用的形态学滤波方法包括腐蚀和膨胀操作,可以结合使用来实现滤波效果。 以下是一个使用OpenCV库进形态学滤波的示例代码: ```python import cv2 import numpy as np # 读取二图像 image = cv2.imread('binary_image.png', 0) # 定义结构元素 kernel = np.ones((3,3), np.uint8) # 开运算 result = cv2.morphologyEx(image, cv2.MORPH_OPEN, kernel) # 显示结果图像 cv2.imshow('Result', result) cv2.waitKey(0) cv2.destroyAllWindows() ``` 在这个代码中,我们首先读取了二图像,然后定义了一个3x3的正方形结构元素。接下来,我们使用`cv2.morphologyEx()`函数进开运算操作,其中`cv2.MORPH_OPEN`参数表示开运算。最后,我们显示了处理后的图像结果。 另外一种常用的滤波方法是均滤波,它可以用于去除图像中的噪声。以下是一个使用OpenCV库进滤波的示例代码: ```python import cv2 # 读取二图像 image = cv2.imread('binary_image.png', 0) # 均滤波 result = cv2.blur(image, (3, 3)) # 显示结果图像 cv2.imshow('Result', result) cv2.waitKey(0) cv2.destroyAllWindows() ``` 在这个代码中,我们使用`cv2.blur()`函数对二图像进滤波,其中`(3, 3)`表示滤波器的大小。最后,我们显示了处理后的图像结果。 你可以根据具体需求选择合适的滤波方法和参数,以达到滤波效果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值