opencv-python 小白笔记(2)

(一)灰度图(cv2.cvtColor)

这里我们需要用到cv2.cvtColor(a1,a2)函数,这是颜色空间转换函数。
a1是需要转换的图片,a2是转换成何种格式。
cv2.COLOR_BGR2RGB 将BGR格式转换成RGB格式
cv2.COLOR_BGR2GRAY 将BGR格式转换成灰度图片

import cv2
import numpy as np

img = cv2.imread("lena.png")
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv2.imshow("img_gray", img_gray)
cv2.waitKey(0)    
cv2.destroyAllWindows() 

在这里插入图片描述
需要特别注意的是图片读出来的格式是BGR,不是我们最常见的RGB格式,颜色肯定有区别。

(二)高斯滤波,均值滤波,中值滤波,方框滤波( cv2.GaussianBlur,cv2.blur,cv2.medianBlur,cv2.boxFilter)

img = cv2.imread('lena.png')

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

这里我们先读取一张有噪音的图片,等一会分别使用高斯滤波,均值滤波,中值滤波,方框滤波,对其进行处理

高斯滤波

# 高斯滤波
# 高斯模糊的卷积核里的数值是满足高斯分布,相当于更重视中间的
import cv2
import numpy as np
img = cv2.imread('lena.png')
cv2.imshow('img', img)
aussian = cv2.GaussianBlur(img, (5, 5), 1)  #(5, 5)表示高斯矩阵的长与宽都是5,标准差取1

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

在这里插入图片描述
均值滤波

# 均值滤波
# 简单的平均卷积操作
import cv2
import numpy as np
img = cv2.imread('lena.png')
cv2.imshow('img', img)
blur = cv2.blur(img, (3, 3))

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

在这里插入图片描述
中值滤波

# 中值滤波
# 相当于用中值代替
import cv2
import numpy as np
img = cv2.imread('lena.png')
cv2.imshow('img', img)
median = cv2.medianBlur(img, 5)  # 中值滤波

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

在这里插入图片描述

方框滤波

import cv2
import numpy as np
img = cv2.imread('lena.png')
cv2.imshow('img', img)
box = cv2.boxFilter(img,-1,(3,3), normalize=True) #这里的 normalize为归一化,如果为normalize=False,则表示不使用归一化

cv2.imshow('box', box)
cv2.waitKey(0)
cv2.destroyAllWindows()
#######################
import cv2
import numpy as np
img = cv2.imread('lena.png')
cv2.imshow('img', img)
box = cv2.boxFilter(img,-1,(3,3), normalize=False) #这里的 normalize为归一化,如果为normalize=False,则表示不使用归一化

cv2.imshow('box', box)
cv2.waitKey(0)
cv2.destroyAllWindows()
#######################

在这里插入图片描述
其中 ,均值滤波,中值滤波,方框滤波这几个函数均有归一化选项,这里就不多举例解释了,读者可自行百度(应为别人写的更好)
如果你处理一张带有噪音点的图片,分别使用这几个函数处理后,你会发现处理效果最好的可能是中值滤波,但这并不意味着其他几种方法不重要,尤其是高斯滤波在图像处理中尤为重要

(三)边缘检测(cv2.Canny)

这里我们使用cv2.Canny()函数。在使用该函数前,由于边缘检测很容易受到噪音影响,所以第一步是使用5x5的高斯滤波器去除噪音。
edge = cv2.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient ]]])
cv2.Canny()第一个参数是输入图像,第二和第三个分别是minVal和maxVal。第三个参数设置用来计算图像梯度的Sobel卷积核的大小,默认值为3。最后一个参数是L2gradient,它可以用来设定求梯度大小的方程。
其中minVal和maxVal。当图像的灰度梯度高于maxVal时被认为是真的边界,那些低于minVal的边界会被抛弃。如果介于两者之间的话,就要看这个点是否与某个被确定为真正边界点相连,如果是,就认为它也是边界点,如果不是就抛弃。
上代码:

import cv2
import numpy as np
img=cv2.imread("lena.png",cv2.IMREAD_GRAYSCALE)

img1=cv2.Canny(img,80,150)
img2=cv2.Canny(img,50,100)
#根据你的需要,你可以修改上下阈值的大小来得到你想要的效果
out_put = np.hstack((img1,img2))
cv_show(out_put,'out_put')

在这里插入图片描述
这其中,我引入了一个新的函数np.hstack,因为图像的本质就是矩阵,所以这里我使用这个函数将这两个矩阵的信息水平堆叠在一起了。这里的cv_show()是我自己定义的一个函数

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

如果你不想使用它,那你就使用常规的的图像显示方法也是可以的

(四)腐蚀(cv2.erode)

把前景物体的边界腐蚀掉,但是前景仍然是白色的。卷积核沿着图像滑动,如果与卷积核对应的原图像的所有像素值都是1,那么中心元素就保持原来的像素值,否则就变为零。根据卷积核的大小靠近前景的所有像素都会被腐蚀掉(变为0),所以前景物体会变小,整幅图像的白色区域会减少。这对于去除白噪音很有用,也可以用来断开两个连在一块的物体。在图像的预处理中,我们会经常用到它。
erosion = cv2.erode(img,kernel,iterations=1)
kernel:是我们定义的卷积核(kernel = np.ones((3,3),np.uint8) )一般我们3*3的
iterations=1:表示我们的迭代次数为一,也就是执行该操作1次,你可以改变它的次数
上代码:

import cv2
import numpy as np
img=cv2.imread("lena.png",cv2.IMREAD_GRAYSCALE)

img1=cv2.Canny(img,80,150)
kernel = np.ones((3,3),np.uint8) 
erosion = cv2.erode(img1,kernel,iterations = 1)
#这里我们为了突出处理效果,我们使用经过cv2.Canny()函数处理后的img1,kernel为(3*3),迭代次数为1次
cv2.imshow('img1', img1)
cv2.imshow('erosion', erosion)
cv2.waitKey(0)
cv2.destroyAllWindows()

这里之所以将两张图片单独放置,是为了方便通过窗口信息对比图片,所以没有使用np.hstack((p1,p2))
这个函数,当然你也可以使用matplotlib,当然我们后面会使用
在这里插入图片描述
你也可以修改kernel的大小,和迭代的次数
PS:我这里测试发现,运行结果是一张全黑的图片(应该不是程序问题)可能是图像中的边缘线条过细,导致图片直接被腐蚀完,所以我建议先对边缘检测的图片进行膨胀操作,这样能得到更明显的现象,或则你使用其他的图片。

(五)膨胀(cv2.dilation)

与腐蚀相反,与卷积核对应的原图像的像素值中只要有一个是1,中心元素的像素值就是1。所以这个操作会增加图像中白色区域(前景)。一般在去噪音时先腐蚀再膨胀,因为腐蚀再去掉白噪音的同时,也会使前景对象变小,所以我们再膨胀。这时噪音已经被去除,不会再回来了,但是前景还在并会增加,膨胀也可以用来连接两个分开的物体。
dilation = cv2.dilation(img,kernel,iterations=1)
参数的解读与腐蚀相同
上代码:

import cv2
import numpy as np
img=cv2.imread("lena.png",cv2.IMREAD_GRAYSCALE)

img1=cv2.Canny(img,80,150)
kernel = np.ones((3,3),np.uint8)
dilation = cv2.dilate(img1,kernel,iterations = 1)
cv2.imshow('img1', img1)
cv2.imshow('dilation', dilation)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

(六)开运算与闭运算(cv2.morphotogyEx)

开运算是先进行腐蚀再进行膨胀就叫做开运算。被用来去除噪音,用来消除小黑点,在纤细点处分离物体、平滑较大物体的边界的 同时并不明显改变其面积。函数可以使用cv2.morphotogyEx()
参数有3个,分别是传入图像,cv2.MORPH_OPEN,然后是卷积核kernel

import cv2
import numpy as np

img=cv2.imread("lena.png",cv2.IMREAD_GRAYSCALE)

img1=cv2.Canny(img,80,150)
kernel = np.ones((3,3),np.uint8)
dilation = cv2.dilate(img1,kernel,iterations = 1)
opening = cv2.morphologyEx(dilation, cv2.MORPH_OPEN, kernel)
#这里我们为了突出处理效果,先对图片膨胀一下,如果直接开运算会直接得到纯黑的图片,毕竟开运算要先进行一次腐蚀操作
cv2.imshow('img1', img1)
cv2.imshow('dilation', dilation)
cv2.imshow('opening',opening)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述
这里最右边的图片要给比中间的图片要略细(这里效果不明显,个人感觉是主要是图片选的不好)

闭运算是先膨胀后腐蚀的过程。闭运算可以用来排除小黑洞。
closing = cv2.morphotogyEx(img,cv2.MORPH_CLOSE,kernel)
参数有3个,分别是传入图像,cv2.MORPH_CLOSRE,然后是卷积核kernel

import cv2
import numpy as np

img=cv2.imread("lena.png",cv2.IMREAD_GRAYSCALE)

img1=cv2.Canny(img,80,150)
kernel = np.ones((3,3),np.uint8)

closing = cv2.morphologyEx(img1, cv2.MORPH_CLOSE, kernel)

cv2.imshow('img1', img1)
cv2.imshow('closing',closing)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述
这里明显能看出,右边图片的线条要粗,因为你对一个线条进行膨胀后,虽然以后也对其进行了腐蚀,但是线条要比整个闭运算之前粗(打个比喻就是,一颗小树苗,你轻轻用力就能将它连根拔起,但等它长大后,你使用相同的力,可能就拔不动了),总而言之,就是翅膀变硬了。

(七)礼帽与黑帽(cv2.morphotogyEx)

礼帽 = 原始输入-开运算结果,该操作可以突出比原轮廓亮的部分。
cv2.morphotogyEx(img,cv2.MORPH_TOPHAT,kernel)
参数有3个,分别是传入图像,cv2.MORPH_TOPHAT,然后是卷积核kernel

import cv2
import numpy as np

img=cv2.imread("lena.png",cv2.IMREAD_GRAYSCALE)

img1=cv2.Canny(img,80,150)
kernel = np.ones((3,3),np.uint8)

tophat = cv2.morphologyEx(img1, cv2.MORPH_TOPHAT, kernel)

cv2.imshow('img1', img1)
cv2.imshow('tophat',tophat)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述
好吧,看不出啥效果

黑帽 = 闭运算-原始输入,该操作将突出比原轮廓暗的部分
cv2.morphotogyEx(img,cv2.MORPH_BLACKHAT,kernel)
参数有3个,分别是传入图像,cv2.MORPH_BLACKHAT,然后是卷积核kernel

import cv2
import numpy as np

img=cv2.imread("lena.png",cv2.IMREAD_GRAYSCALE)

img1=cv2.Canny(img,80,150)
kernel = np.ones((3,3),np.uint8)

blackha = cv2.morphologyEx(img1, cv2.MORPH_BLACKHAT, kernel)

cv2.imshow('img1', img1)
cv2.imshow('blackha',blackha)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述
这个效果明显,反正重量个操作,我都很少用

(八)阈值操作(cv2.threshold)

ret, dst = cv2.threshold(src, thresh, maxval, type)
src: 输入图,只能输入单通道图像,通常来说为灰度图
dst: 输出图
thresh: 阈值
maxval: 当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值
type:二值化操作的类型,包含以下5种类型: cv2.THRESH_BINARY;cv2.THRESH_BINARY_INV; cv2.THRESH_TRUNC; cv2.THRESH_TOZERO;cv2.THRESH_TOZERO_INV

cv2.THRESH_BINARY 超过阈值部分取maxval(最大值),否则取0
cv2.THRESH_BINARY_INV THRESH_BINARY的反转
cv2.THRESH_TRUNC 大于阈值部分设为阈值,否则不变
cv2.THRESH_TOZERO 大于阈值部分不改变,否则设为0
cv2.THRESH_TOZERO_INV THRESH_TOZERO的反转

import cv2
import numpy as np
import matplotlib.pyplot as plt#这里引入matplotlib,它的使用方法,可自行百度,方法都有
img=cv2.imread('lena.png')
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, thresh1 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
ret, thresh2 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY_INV)
ret, thresh3 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TRUNC)
ret, thresh4 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO)
ret, thresh5 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO_INV)

titles = ['Original Image', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]

#img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
#这里将img转为rgb,这样用matplotlib显示原图是就会是原来的颜色了

for i in range(6):
    plt.subplot(2, 3, i + 1), plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()

在这里插入图片描述
dst = cv2.adaptiveThreshold(src, maxval, Method, type, Block Size, C)
src: 输入图,只能输入单通道图像,通常来说为灰度图
dst: 输出图
maxval: 当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值
Method: 阈值的计算方法,包含以下2种类型:cv2.ADAPTIVE_THRESH_MEAN_C; cv2.ADAPTIVE_THRESH_GAUSSIAN_C.
type:二值化操作的类型,与固定阈值函数相同,包含以下5种类型: cv2.THRESH_BINARY; cv2.THRESH_BINARY_INV; cv2.THRESH_TRUNC; cv2.THRESH_TOZERO;cv2.THRESH_TOZERO_INV.
Block Size: 图片中分块的大小
C :阈值计算方法中的常数项

# 自适应阈值对比固定阈值
import cv2
import numpy as np
import matplotlib.pyplot as plt #这里引入matplotlib,它的使用方法,可自行百度,方法都有
img = cv2.imread('lena.png',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();

在这里插入图片描述

(九)结语

哇,终于写完了

学习opencv有很多的方法,我的建议是你可以加一些群,可以充分利用B站,CSDN,和百度。

在我的博客中,我不会讲解opencv的算法实现(当然我也不太会),我只会讲解一些函数的调用,不理解就多改一些参数,多尝试尝试,慢慢你就理解来。相信你总有一天可以说opencv不过“Ctrl+C,Crtl+V”

如果有什么错误的地方,还请大家批评指正,最后,希望小伙伴们都能有所收获。

在这里插入图片描述

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值