opencv图像基础操作


1. 图像读取

读取方式:
cv2.IMREAD_COLOR:彩色图像
cv2.IMREAD_GRAYSCALE:灰度图像

import cv2

img=cv2.imread('myimg.jpg') # opencv读取的格式默认是BGR

2. 图像通道转换

转换方式:
cv2.COLOR_BGR2GRAY:彩->灰
cv2.COLOR_GRAY2BGR:灰->彩

2.1. 彩图转换为灰度图

gray_img = cv2.cvtColor(bgr_img, cv2.COLOR_BGR2GRAY)  

2.2. 灰度图转换为彩图

bgr_img = cv2.cvtColor(gray_img, cv2.COLOR_GRAY2BGR)

2.3. 灰度图转换为HSV

hsv_img = cv2.cvtColor(bgr_img, cv2.COLOR_BGR2HSV)

3. 截图

image = img[0:100, 0:100]

4. 二值化

ret, dst = cv2.threshold(src, thresh, maxval, type)
函数的返回值是两个值:

  • ret:这是输入图像的深度。
  • dst:这是阈值化后的图像。

函数的参数:

  • src:输入的灰度图像。
  • thresh:阈值,用于决定像素值将被视为前景或背景。
  • maxval:当像素值超过(或小于,取决于阈值类型)阈值时要赋予的值。
  • type:阈值类型,决定如何进行二值化操作。有以下几种类型:
    • cv2.THRESH_BINARY:阈值的二值化操作,大于阈值使用 maxval 表示,小于阈值使用 0 表示。
    • cv2.THRESH_BINARY_INV:阈值的二值化翻转操作,大于阈值的使用 0 表示,小于阈值的使用 maxval 表示。
    • cv2.THRESH_TRUNC:进行截断操作,大于阈值的使用阈值表示,小于阈值的不变。
    • cv2.THRESH_TOZERO:进行化零操作,大于阈值的不变,小于阈值的使用 0 表示。
    • cv2.THRESH_TOZERO_INV:进行化零操作的翻转,大于阈值的使用 0 表示,小于阈值的不变。
# 应用阈值化操作,这里使用 THRESH_BINARY 类型 
ret, thresh = cv2.threshold(gray_image, 127, 255, cv2.THRESH_BINARY)
# 将灰度值大于175的像素设置为255,小于175的像素设置为0

5. 图像滤波

原始图像(来源网络):

在这里插入图片描述

5.1. 平滑

5.1.1. 均值滤波

# 均值滤波  
blur = cv2.blur(img,(5,5)) # (5,5)表示滤波器的大小 

在这里插入图片描述

5.1.2. 高斯滤波

# 高斯滤波:高斯模糊的卷积核里的数值是满足高斯分布,相当于更重视中间的
blur_gaussian = cv2.GaussianBlur(img,(5,5),0) # (5,5)表示滤波器的大小,0表示标准差

image.png

5.1.3. 中值滤波

# 中值滤波  
blur_median = cv2.medianBlur(img,5)

image.png

5.1.4. 方框滤波

# 方框滤波:基本和均值一样,可以选择归一化,容易越界
box = cv2.boxFilter(img,-1,(3,3), normalize=True)
box = cv2.boxFilter(img,-1,(3,3), normalize=False)  

image.pngimage.png

5.2. 锐化

5.2.1. Scharr算子

# 使用Sobel算子计算图像在x方向和y方向的梯度,可以在边缘方向上增强边缘
sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3)
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3)

# 用来对Sobel梯度图像进行绝对值化和缩放的,这个操作也可以使得边缘和角点的特征更加明显
sobelx = cv2.convertScaleAbs(sobelx)
sobely = cv2.convertScaleAbs(sobely)

# 将x方向和y方向的梯度图像进行加权合并
sobelxy = cv2.addWeighted(sobelx, 0.5, sobely, 0.5, 0)

image.png

5.2.2. laplacian算子

# 使用Scharr算子计算图像在x方向和y方向的梯度
scharrx = cv2.Scharr(img,cv2.CV_64F,1,0)
scharry = cv2.Scharr(img,cv2.CV_64F,0,1)

# 用来对Scharr梯度图像进行绝对值化和缩放的,使得边缘和角点的特征更加明显
scharrx = cv2.convertScaleAbs(scharrx)   
scharry = cv2.convertScaleAbs(scharry)

# 是将x方向和y方向的梯度图像进行加权合并,合并后的图像就是Scharr梯度图像
scharrxy =  cv2.addWeighted(scharrx,0.5,scharry,0.5,0)

image.png

5.2.3. 拉普拉斯算子

# 拉普拉斯算子,cv2.CV_64F 指定了输出图像的深度为64位浮点型
laplacian = cv2.Laplacian(img,cv2.CV_64F)

# 是用来对Laplacian梯度图像进行绝对值化和缩放,使得边缘和角点的特征更加明显
laplacian = cv2.convertScaleAbs(laplacian)

# 将拉普拉斯算子的结果加到原始图像上,实现锐化操作  
sharp = cv2.addWeighted(img,1.5,laplacian,-0.5) 

image.png

6. 形态学操作

6.1. 膨胀操作

作用于扩大图像中物体的边界

# 定义结构元素  
kernel = np.ones((30,30),np.uint8)  
  
# 膨胀操作,iterations表示次数
dilation = cv2.dilate(img,kernel,iterations = 1)

原图膨胀图

6.2. 腐蚀操作

腐蚀操作用于消除图像中小于某个阈值的像素点,从而缩小图像中物体的边界。

# 定义结构元素 
kernel = np.ones((30,30),np.uint8) 
# iterations表示次数
erosion = cv2.erode(img,kernel,iterations = 1)

原图腐蚀图

6.3. 开运算

开运算是先进行腐蚀操作,再进行膨胀操作。
这个操作可以消除图像中较小的对象,同时也可以平滑较大对象的边缘。

# 定义结构元素  
kernel = np.ones((30,30),np.uint8)  
  
# 开运算操作  
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel) 

原图开运算

6.4. 闭运算

闭运算是先进行膨胀操作,再进行腐蚀操作。
这个操作可以消除图像中较大的空洞,同时也可以平滑较小对象的边缘。

# 定义结构元素  
kernel = np.ones((30,30),np.uint8)  
  
# 闭运算操作  
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)

原图闭操作

6.5. 梯度运算

梯度=膨胀-腐蚀
形态梯度对于检测对象的轮廓非常有用,是膨胀操作和腐蚀操作之间的差异
计算形态学梯度,可以得到原始图像与结构元素的差分。

# 定义结构元素  
kernel = np.ones((30,30),np.uint8)

grad = cv2.morphologyEx(gray.copy(), cv2.MORPH_GRADIENT, kernel)

原图梯度

6.6. 顶帽/白帽运算

礼帽 = 原始输入-开运算结果
检测图像的亮区域
作用主要是增强图像的亮度,同时保留图像中的较亮的区域。
可以用来消除图像中的暗点噪声,同时也可以增强图像的对比度。
通过对原始图像和结构元素进行卷积来实现,它会使得高于周围像素的孤立点或斑块更加突出,而较低的区域会变暗。

# 定义结构元素  
kernel = np.ones((30,30),np.uint8)

tophat = cv2.morphologyEx(gray.copy(), cv2.MORPH_TOPHAT, kernel)

原图顶帽/白帽

6.7. 黑帽运算

黑帽 = 闭运算-原始输入
检测图像的亮区域
主要用于增强图像的暗部区域,同时保留图像中较暗的区域。
可以用来消除图像中的亮点噪声,同时也可以增强图像的对比度。
黑帽变换也可以通过对原始图像和结构元素进行卷积来实现,但它会使得低于周围像素的孤立点或斑块更加突出,而较亮的区域会变暗。

# 定义结构元素
kernel = np.ones((30,30),np.uint8)

closing = cv2.morphologyEx(gray.copy(), cv2.MORPH_BLACKHAT, kernel)

原图黑帽

7. BGR通道

7.1. 获取三色通道

b, g, r = cv2.split(img)

7.2. 显示三通道图片

7.2.1. 只保留R

# 只保留R
cur_img = img.copy()
cur_img[:,:,0] = 0
cur_img[:,:,1] = 0
cv_show('R',cur_img)

7.2.2. 只保留G

# 只保留G
cur_img = img.copy()
cur_img[:,:,0] = 0
cur_img[:,:,2] = 0
cv_show('G',cur_img)

7.2.3. 只保留B

# 只保留B
cur_img = img.copy()
cur_img[:,:,1] = 0
cur_img[:,:,2] = 0
cv_show('B',cur_img)

image.pngimage.pngimage.png

8. 图像边界填充

填充方式:
BORDER_REPLICATE:复制法,也就是复制最边缘像素。
BORDER_REFLECT:反射法,对感兴趣的图像中的像素在两边进行复制例如:fedcba|abcdefgh|hgfedcb
BORDER_REFLECT_101:反射法,也就是以最边缘像素为轴,对称,gfedcb|abcdefgh|gfedcba
BORDER_WRAP:外包装法cdefgh|abcdefgh|abcdefg
BORDER_CONSTANT:常量法,常数值填充。

# 定义图像边界的尺寸,即顶部、底部、左侧和右侧各100像素
top_size, bottom_size, left_size, right_size = (100, 100, 100, 100)

replicate = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, borderType=cv2.BORDER_REPLICATE)
reflect = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_REFLECT)
reflect101 = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_REFLECT_101)
wrap = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_WRAP)
constant = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_CONSTANT, value=0)

import matplotlib.pyplot as plt

plt.subplot(331), plt.imshow(img, 'gray'), plt.title('ORIGINAL')
plt.subplot(332), plt.imshow(replicate, 'gray'), plt.title('REPLICATE')
plt.subplot(333), plt.imshow(reflect, 'gray'), plt.title('REFLECT')
plt.subplot(334), plt.imshow(reflect101, 'gray'), plt.title('REFLECT_101')
plt.subplot(335), plt.imshow(wrap, 'gray'), plt.title('WRAP')
plt.subplot(336), plt.imshow(constant, 'gray'), plt.title('CONSTANT')

# 显示所有的子图
plt.show()

image.png

9. 边缘检测

# 应用Canny边缘检测算法  
edges = cv2.Canny(gray, 100, 200)

原图边缘

10. 图像轮廓

10.1. 轮廓提取

cv2.findContours说明:
使用模板:cv2.findContours(image, mode, method, offset=(0, 0))
返回值:

  • contours:是一个列表,其中每个元素都是图像中的一个轮廓,用numpy中的ndarray表示。
  • hierarchy:是一个ndarray,其中的元素个数和轮廓个数相同,每个轮廓对应4个hierarchy元素,表示后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号,如果没有对应项,则该值为负数。

参数:

  • image: 二值图像,通常使用cv2.threshold或cv2.adaptiveThreshold进行阈值处理得到。
  • mode: 轮廓查找模式,有以下三种:
    • cv2.RETR_EXTERNAL:只检索最外面的轮廓。
    • cv2.RETR_LIST:检索所有的轮廓,并以列表形式返回。
    • cv2.RETR_CCOMP:检索所有的轮廓,并将它们组织为两个层次:外部的和内部的。
    • cv2.RETR_TREE:检索所有的轮廓,并以树状结构组织它们。
  • method: 轮廓近似方法,有以下两种:
    • cv2.CHAIN_APPROX_NONE:存储所有轮廓点。
    • cv2.CHAIN_APPROX_SIMPLE:存储轮廓的稀疏点集。
  • offset: 偏移量,用于从输入图像的左上角开始偏移,然后绘制轮廓。通常可以设置为(0, 0)。
# 提取轮廓(版本不同,返回值的数量有可能有差异),使用二值图像可以提高精度
_,contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# 绘制轮廓并显示结果
cv2.drawContours(img_copy, contours, -1, (255, 0, 255), 2)

# 显示img_copy

image.png

10.2. 轮廓特征

  1. 面积:cv2.contourArea(cnt) # cnt为轮廓列表中的某一个轮廓
  2. 周长:cv2.arcLength(cnt, True) # True表示闭合的

10.3. 轮廓近似

10.3.1. 边界多边形

# 轮廓提取
binary, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
# 遍历轮廓
for contour in contours:  
    epsilon = 0.1 * cv2.arcLength(contour, True)
    # 使用等距距离方法近似轮廓。这将得到一个多边形,该多边形尽可能地逼近原始轮廓。
    approx = cv2.approxPolyDP(contour, epsilon, True)  
    image = cv2.drawContours(image, [approx], 0, (0, 0, 255), 2)

image.png

10.3.2. 边界矩形

# 轮廓提取
binary, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
# 遍历轮廓
for contour in contours:
    x,y,w,h = cv2.boundingRect(cnt)
    # 绘制外接矩形
    img = cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)
    cv_show(img,'img')

image.png

10.3.3. 边界圆

# 轮廓提取
binary, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
# 遍历轮廓
for contour in contours:
    # 计算最小外接圆,返回两个值:圆心坐标和半径
    (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')

image.png

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

悟解了

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值