opencv笔记(一)
目录环境搭建
- python3环境
- pip install numpy matplotlib opencv-python
基础用法
常用对象
- 窗口
- 摄像设备
- 视频写入
import cv2
# 创建fourcc对象
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
# 创建VideoWriter对象,参数为1.文件路径、fourcc、帧率、分辨率
vw = cv2.VideoWriter('d.mp4', fourcc, 24, (640, 480))
# 创建窗口对象
cv2.namedWindow('video', cv2.WINDOW_NORMAL)
# 创建摄像设备对象,参数为设备序列号
cap = cv2.VideoCapture(0)
while cap.isOpened():
ok, frame = cap.read()
if ok:
# 屏幕显示
cv2.imshow('video', frame)
# 保存
vw.write(frame)
key = cv2.waitKey(6)
if key & 0xFF == ord('q'):
break
else:
break
# 释放资源
cap.release()
vw.release()
cv2.destroyAllWindows()
- 鼠标回调函数
import cv2
import numpy as np
# 定义回调函数体,参数:1.事件、2.宽、3.高、4.鼠标键或者组合键、5.设置鼠标回调函数时传入的userdata
def mouse_callback(event, x, y, flag, userdata):
print(event, x, y, flag, userdata)
# 创建窗口对象
cv2.namedWindow('video', cv2.WINDOW_NORMAL)
cv2.resizeWindow('video', 1280, 720)
# 设置鼠标回调函数,参数:1.窗口名、2.回调函数、3.userdata值
cv2.setMouseCallback('video', mouse_callback, 'userdata')
img = np.zeros((720, 1280, 3), np.uint8)
while 1:
# 屏幕显示
cv2.imshow('video', img)
key = cv2.waitKey(6)
if key & 0xFF == ord('q'):
break
cv2.destroyAllWindows()
- TrackBar
import cv2
import numpy as np
def callback(userdata):
print(userdata)
cv2.namedWindow('trackbar', cv2.WINDOW_NORMAL)
cv2.resizeWindow('trackbar', 640, 320)
# 创建trackbar
cv2.createTrackbar('R', 'trackbar', 0, 255, callback)
cv2.createTrackbar('G', 'trackbar', 0, 255, callback)
cv2.createTrackbar('B', 'trackbar', 0, 255, callback)
img = np.zeros((320, 640, 3), np.uint8)
while 1:
# 屏幕显示
r = cv2.getTrackbarPos('R', 'trackbar')
g = cv2.getTrackbarPos('G', 'trackbar')
b = cv2.getTrackbarPos('B', 'trackbar')
img[:] = [b, g, r]
cv2.imshow('trackbar', img)
key = cv2.waitKey(6)
if key & 0xFF == ord('q') or cv2.getWindowProperty('trackbar', cv2.WND_PROP_VISIBLE) < 1.0:
break
cv2.destroyAllWindows()
色彩空间
- BGR
- RGB
- HSV:色相+饱和度+明度
- HSL:色相+饱和度+亮度
- YUV
import cv2
def callback(userdata):
print(userdata)
cv2.namedWindow('color', cv2.WINDOW_NORMAL)
img = cv2.imread('1.png')
color_spaces = [cv2.COLOR_BGR2BGRA, cv2.COLOR_BGR2GRAY, cv2.COLOR_BGR2HSV_FULL, cv2.COLOR_BGR2RGBA, cv2.COLOR_BGR2YUV]
cv2.createTrackbar('trans', 'color', 0, len(color_spaces)-1, callback)
while 1:
v = cv2.getTrackbarPos('trans', 'color')
# 色彩空间转换
new_img = cv2.cvtColor(img, color_spaces[v])
cv2.imshow('color', new_img)
key = cv2.waitKey(6)
if key & 0xFF == ord('q') or cv2.getWindowProperty('color', cv2.WND_PROP_VISIBLE) < 1.0:
break
cv2.destroyAllWindows()
Numpy基础
创建矩阵
- 通过array:np.array[[1, 2, 3], [4, 5, 6]]
- 通过zeros:np.zeros((320, 640, 3), np.uint8)
- 通过ones:np.ones((320, 640, 3), np.uint8)
- 通过full:np.full((8, 8, 3), 255, np.uint8)
- 通过identity:np.identity(4)
- 通过eye:np.eye(3, 5, k=2)
矩阵取值与赋值
- img[y, x]:[1, 2, 3]
- img[y, x, channel]:1
ROI
- img[y1:y2, x1:x2]
- img[:, :]
import cv2
import numpy as np
cv2.namedWindow('color', cv2.WINDOW_NORMAL)
img = np.full((320, 640, 3), 0, np.uint8)
img[100:200, 100:200] = [0, 0, 255]
img[:, 300] = [255, 0, 0]
cv2.imshow('color', img)
key = cv2.waitKey(0)
if key & 0xFF == ord('q') or cv2.getWindowProperty('color', cv2.WND_PROP_VISIBLE) < 1.0:
cv2.destroyAllWindows()
Mat
结构
- header:dims维度、rows行数、cols列数、depth像素位深、channels通道数、size矩阵大小、type
- data:矩阵详细数据
拷贝
当显式调用copy()生成新矩阵时会拷贝header和data,否则只拷贝header。
import cv2
import numpy as np
cv2.namedWindow('color', cv2.WINDOW_NORMAL)
img = np.full((320, 640, 3), 0, np.uint8)
img2 = img[:]
img2[:] = [0, 0, 255]
img3 = img.copy()
img3[100:200, 100:200] = [255, 0, 0]
cv2.imshow('color', img)
cv2.imshow('color2', img2)
cv2.imshow('color3', img3)
key = cv2.waitKey(0)
if key & 0xFF == ord('q') or cv2.getWindowProperty('color', cv2.WND_PROP_VISIBLE) < 1.0:
cv2.destroyAllWindows()
属性访问
- img.shape:高、宽、通道数
- img.size:高x宽x通道数
- img.dtype:位深,例如uint8
通道的分离与合并
- split(mat)
- merge((chan1, chan2))
import cv2
import numpy as np
img = np.zeros((320, 640, 3), np.uint8)
b, g, r = cv2.split(img) # split将同时拷贝header与data
b[100:200, 100:200] = 255
g[100:200, 100:200] = 255
r[0:100, 0:100] = 255
img2 = cv2.merge((b, g, r)) # merge将同时拷贝header与data
img2[200:300, 200:300] = [0, 0, 255]
cv2.imshow('color', img)
cv2.imshow('color0', img2)
cv2.imshow('color1', b)
cv2.imshow('color2', g)
cv2.imshow('color3', r)
key = cv2.waitKey(0)
if key & 0xFF == ord('q'):
cv2.destroyAllWindows()
图形绘制
- 线:line
- 矩形:rectangle
- 圆:circle
- 椭圆:ellipse
- 多边形:
- 字体:
import cv2
import numpy as np
# 此处坐标参数为y, x顺序
img = np.zeros((320, 640, 3), np.uint8)
# 此处坐标相关参数全部是(x, y)顺序,参数:图像、起始点、终止点、颜色、线宽、线形
cv2.line(img, (10, 20), (100, 200), (255, 0, 0), 5)
#矩形
cv2.rectangle(img, (80, 80), (200, 200), (0, 255, 0))
# 圆
cv2.circle(img, (140, 140), 60, (0, 0, 255))
# 椭圆 参数:图像、圆心、x和y半径、顺时针旋转角度、绘制起始角度、绘制终止角度、颜色、厚
cv2.ellipse(img, (140, 140), (60, 30), 90, 0, 360, (0, 0, 255), -1)
# 多边形 参数:图像、点、是否闭合、颜色
points = np.array([(300, 5), (132, 109), (480, 109)], np.int32)
cv2.polylines(img, [points], True, (0, 0, 255))
# 填充的多边形 参数:图像、点、颜色
points_fill = np.array([(300, 10), (150, 100), (450, 100)], np.int32)
cv2.fillPoly(img, [points_fill], (255, 0, 0))
# 文本 参数:图像、文本内容、起始点、字体、字号、颜色
cv2.putText(img, 'test', (200, 300), cv2.FONT_HERSHEY_PLAIN, 1, (0, 0, 255))
cv2.imshow('line', img)
key = cv2.waitKey(0)
if key & 0xFF == ord('q'):
cv2.destroyAllWindows()
基本图像运算与处理
加法运算
import cv2
import numpy as np
# 加法运算
# 必须确保两张图像大小通道一致
im1 = cv2.imread('x.png')
# im2 = cv2.imread('y.png')
im2 = np.ones((1080, 1920, 3), np.uint8) * 100
cv2.imshow('add', cv2.add(im1, im2))
cv2.waitKey(0)
减法运算
import cv2
import numpy as np
# 减法运算
# 必须确保两张图像大小通道一致
# 注意受np.uint8类型约束,加法运算逆运算后可能得到与原图有偏差的结果
im1 = cv2.imread('x.png')
im2 = np.ones(im1.shape, np.uint8) * 10
cv2.imshow('ori', im1)
cv2.imshow('subtract', cv2.subtract(cv2.add(im1, im2), im2))
cv2.waitKey(0)
乘除运算
import cv2
import numpy as np
# 减法运算
# 必须确保两张图像大小通道一致
# 注意受np.uint8类型约束,加法运算逆运算后可能得到与原图有偏差的结果
im1 = cv2.imread('x.png')
im2 = np.ones(im1.shape, np.uint8) * 10
cv2.imshow('ori', im1)
cv2.imshow('multiply', cv2.multiply(im1, im2))
cv2.imshow('divide', cv2.divide(im1, im2))
cv2.waitKey(0)
图像溶合
即带权重的图像叠加
import cv2
im1 = cv2.imread('x.png')
im2 = cv2.imread('y.png')
# 参数:图像一、图像一权重、图像二、图像二权重、静态权重
cv2.imshow('addWeighted', cv2.addWeighted(im1, 0.6, im2, 0.4, 0))
cv2.waitKey(0)
图像位运算
-
与
-
或
-
非
-
异或
import cv2
import numpy as np
im1 = np.zeros((200, 200), np.uint8)
im2 = np.zeros((200, 200), np.uint8)
im1[20:120, 20:120] = 255
im2[80:180, 80:180] = 255
cv2.imshow('not', cv2.bitwise_not(im1))
cv2.imshow('and', cv2.bitwise_and(im1, im2))
cv2.imshow('or', cv2.bitwise_or(im1, im2))
cv2.imshow('xor', cv2.bitwise_xor(im1, im2))
cv2.waitKey(0)
图像的变换
图像缩放
import cv2
# 图像缩放
"""
参数:源、缩放后大小、X轴缩放因子、Y轴缩放因子、插值算法,同时指定大小和缩放因子优先取大小
插值算法:INTER_NEAREST(临近插值,速度快,效果差)、INTER_LINEAR(双线性插值,参考周围4点)
INTER_CUBIC(三次插值,参考16点)、INTER_AREA(效果最好)
"""
img = cv2.imread('1.png')
res = cv2.resize(img, (1920, 1080))
res2 = cv2.resize(img, None, fx=0.6, fy=0.6)
cv2.imshow('resize1', res)
cv2.imshow('resize2', res2)
cv2.waitKeyEx(0)
图像翻转
import cv2
# 图像翻转
# 参数:图像、翻转标志(0代表上下翻转, >0代表左右翻转, <0代表上下+左右)
img = cv2.imread('1.png')
cv2.imshow('flip', cv2.flip(img, -1))
cv2.waitKeyEx(0)
图像旋转
import cv2
# 图像旋转
# 参数:图像、旋转标志(ROTATE_90_CLOCKWISE, ROTATE180, ROTATE_90_COUNTERCLOCKWISE)
img = cv2.imread('1.png')
cv2.imshow('rotate', cv2.rotate(img, cv2.ROTATE_90_COUNTERCLOCKWISE))
cv2.waitKeyEx(0)
仿射变换
即图像旋转、缩放、平移的总称
import cv2
import numpy as np
img = cv2.imread('1.png')
# 仿射变换
# 参数:图像、变换矩阵、输出大小、flag插值算法、mode边界外推法标志、value填充边界的值
# X轴平移100
M = np.float32([[1, 0, 100], [0, 1, 0]])
h, w, _ = img.shape
cv2.imshow('warpAffine', cv2.warpAffine(img, M, (w, h)))
# 通过API获取变换矩阵
# 参数:中心点、角度(逆时针)、缩放比例
# 变换不改变图像大小,如果要修改图像大小需要修改dsize
M = cv2.getRotationMatrix2D((100, 100), 30, 1.0)
cv2.imshow('warpAffine2', cv2.warpAffine(img, M, (w, h)))
# 通过API获取变换矩阵-三点定位
# 参数:原三点、目的三点
ori = np.float32([[100, 200], [300, 200], [100, 400]])
new = np.float32([[150, 300], [200, 400], [50, 350]])
M = cv2.getAffineTransform(ori, new)
cv2.imshow('warpAffine3', cv2.warpAffine(img, M, (w, h)))
cv2.waitKeyEx(0)
透视变换
import cv2
import numpy as np
img = cv2.imread('3.jpg')
# 获取变换矩阵
# 参数:原四点、目标四点
src = np.float32([[100, 1100], [2100, 1100], [0, 4000], [2500, 3900]])
des = np.float32([[0, 0], [2300, 0], [0, 3000], [2300, 3000]])
M = cv2.getPerspectiveTransform(src, des)
# 透视变换
# 参数:图像、变换矩阵、输出大小...
warp_perspective = cv2.warpPerspective(img, M, (2300, 3000))
cv2.imshow('warpPerspective', warp_perspective)
cv2.waitKeyEx(0)
图像滤波
一幅图像通过滤波器得到另一幅图像。
卷积
滤波器又称卷积核,滤波的过程称为卷积。
-
卷积核的大小:
一般为奇数(原因包括增加padding和确保锚点居中),例如3x3、5x5等,在深度学习中,卷积核越大,感受野越大,信息越多,提取的特征越好,同时计算量也越大
-
锚点:卷积核中心点
-
边界扩充:
当卷积核大于1且不进行边界扩充,输出尺寸将相应缩小
当卷积核一标准方式进行边界扩充,则输出数据的空间尺寸将与输入相等
N = (W - F + 2P) / S + 1
N即输出图像大小,W源大小,F卷积核大小,P扩充尺寸,S步长大小
-
步长
低通滤波:低于某个阈值的值可以通过,可以去除噪音或者平滑图像
高通滤波:高于某个阈值的值可以通过,可以帮助查找图像边缘
常用滤波器
低通滤波
滤波器名 | 作用或优点 | 缺点 | 备注 |
---|---|---|---|
*方盒滤波(boxFilter) | / | / | normalize=True时为均值滤波,使用较少 |
均值滤波(blur) | 平滑图像,减少锐化 | 失去纹理 | / |
高斯滤波(GaussianBlur) | 涂抹噪点 | 边缘模糊 | 越靠近中心,权重越高,锚点权重约0.148 |
中值滤波(medianBlur) | 消除胡椒噪音 | 对其他噪音效果不佳,边缘模糊 | 取卷积数组的中值作为卷积结果 |
双边滤波(bilateralFilter) | 保留边缘同时对边缘内区域进行平滑处理 | 胡椒噪音效果不佳 |
高通滤波
算子 | 作用或优点 | 缺点 | 备注 |
---|---|---|---|
索贝尔(Sobel) | 抗噪 | 同时求一个以上方向边缘时效果极差 | 卷积核大小为-1时即沙尔 |
*沙尔(Scharr) | 细小边缘检测 | 只能同时求一个方向上的边缘 | 使用较少 |
拉普拉斯(Laplacian) | 同时求多方向边缘 | 噪音敏感 | 使用前需要先做降噪处理 |
边缘检测-Canny
内部实现步骤
- 使用5x5高斯滤波消除噪声
- 从四个方向计算图像梯度:0°/45°/90°/135°
- 取局部极大值
- 阈值计算:高于最大值即是边缘,低于最小值即不是边缘,中间值如与以确定边缘有连续关系则是边缘,否则不是边缘
import cv2
import numpy as np
img = cv2.imread('8.png')
# 图像卷积
# 参数:图像、位深,卷积核,锚点,指定偏差,边界类型
# kernel = np.ones((5, 5), np.float32) / 25
# des = cv2.filter2D(img, -1, kernel)
# 均值滤波,参数:源、卷积核大小...
# blur_des = cv2.blur(img, (5, 5))
# 高斯滤波,参数:源、卷积核(大小)、sigma(值越大越模糊,未指定时参考卷积核大小)
# gauss_des = cv2.GaussianBlur(img, (5, 5), sigmaX=3)
# 中值滤波,参数:源、卷积核大小
# median_des = cv2.medianBlur(img, 5)
# 双边滤波,参数:源、filter大小、颜色sigma、sigma空间
# bil_des = cv2.bilateralFilter(img, 6, 20, 50)
# 索贝尔算子,参数:源、输出位深、对X求导、对Y求导、核大小...
# sobel_des = cv2.add(cv2.Sobel(img, cv2.CV_64F, 1, 0, 5), cv2.Sobel(img, cv2.CV_64F, 0, 1, 5))
# 拉普拉斯算子,参数:源、输出位深、核大小
# lap_des = cv2.Laplacian(img, cv2.CV_64F, ksize=5)
# Canny,参数:源、最小值、最大值
canny_des = cv2.Canny(img, 100, 200)
cv2.imshow('ori', img)
# cv2.imshow('des', des)
# cv2.imshow('blur_des', blur_des)
# cv2.imshow('gauss_des', gauss_des)
# cv2.imshow('median_des', median_des)
# cv2.imshow('bil_des', bil_des)
# cv2.imshow('sobel_des', sobel_des)
# cv2.imshow('lap_des', lap_des)
cv2.imshow('canny_des', canny_des)
cv2.waitKeyEx(0)
形态学
图像二值化
全局二值化
将图像的每个像素变成两种值
import cv2
import numpy as np
ori_img = cv2.imread('8.png')
img = cv2.cvtColor(ori_img, cv2.COLOR_BGR2GRAY)
# 全局二值化,参数:源、阈值、用于替换超过最大值的值、类型
# 类型包含THRESH_BINARY、THRESH_BINARY_INV、THRESH_TRUNC、THRESH_TOZERO、THRESH_TOZERO_INV
_, des = cv2.threshold(img, 140, 255, cv2.THRESH_BINARY)
# 全局二值化(自适应阈值),参数:源、用于替换超过最大值的值、自适应方法、类型、自适应区域、从计算出的平均值或者加权平均值中减去的常量
# 自适应方法:ADAPTIVE_THRESH_MEAN_C(计算邻近区域的平均值)、ADAPTIVE_THRESH_GAUSSIAN_C(高斯窗口加权平均值)
# 类型包含THRESH_BINARY、THRESH_BINARY_INV
auto_des = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 15, 0)
cv2.imshow('ori', ori_img)
cv2.imshow('des', des)
cv2.imshow('auto_des', auto_des)
cv2.waitKeyEx(0)
腐蚀
import cv2
import numpy as np
ori_img = cv2.imread('8.png')
img = cv2.cvtColor(ori_img, cv2.COLOR_BGR2GRAY)
_, des = cv2.threshold(img, 140, 255, cv2.THRESH_BINARY)
# 手动构建卷积核
# kernel = np.ones((3, 3), np.uint8)
# 获取卷积核,参数:卷积核类型、卷积核大小
# 卷积核类型:MORPH_RECT(全1)、MORPH_ELLIPSE(椭圆核,四角为0)、MORPH_CROSS(十字核,横竖为1)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
# 腐蚀,参数:源、卷积核、腐蚀次数
erode_des = cv2.erode(des, kernel)
cv2.imshow('ori', ori_img)
cv2.imshow('erode_des', erode_des)
cv2.waitKeyEx(0)
膨胀
import cv2
import numpy as np
ori_img = cv2.imread('8.png')
img = cv2.cvtColor(ori_img, cv2.COLOR_BGR2GRAY)
_, des = cv2.threshold(img, 140, 255, cv2.THRESH_BINARY)
# 手动构建卷积核
# kernel = np.ones((3, 3), np.uint8)
# 获取卷积核,参数:卷积核类型、卷积核大小
# 卷积核类型:MORPH_RECT(全1)、MORPH_ELLIPSE(椭圆核,四角为0)、MORPH_CROSS(十字核,横竖为1)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
# 腐蚀,参数:源、卷积核、腐蚀次数
erode_des = cv2.erode(des, kernel)
# 膨胀,参数:源、卷积核、腐蚀次数
dilate_des = cv2.dilate(des, kernel)
cv2.imshow('ori', ori_img)
cv2.imshow('erode_des', erode_des)
cv2.imshow('dilate_des', dilate_des)
cv2.waitKeyEx(0)
开运算
先做腐蚀后做膨胀
用于消除背景中的小图形,保留大图形,可以理解为消除主要目标外的背景中的噪点
闭运算
先做膨胀后做腐蚀
用于消除大图形中的小图形,可以理解为消除主要目标中的噪点
梯度运算
梯度=原图-腐蚀后的图,用于得到目标图形的边缘,一定条件下,卷积核越小,得到的边缘越清晰而细小,卷积核越大,得到的边缘越模糊
顶帽运算
顶帽=原图-开运算,用于得到主要目标图形外的小图形,可以理解为获取背景中的噪点
黑帽运算
黑帽=原图-闭运算,用于得到主要图形中的小图形,可以理解为获取目标图形中的噪点
import cv2
ori_img = cv2.imread('8.png')
img = cv2.cvtColor(ori_img, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(img, 140, 255, cv2.THRESH_BINARY)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
# 开运算,参数:源、宏类型(MORPH_OPEN)、卷积核
morph_open = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
# 闭运算,参数:源、宏类型(MORPH_CLOSE)、卷积核
morph_close = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
# 梯度运算,参数:源、宏类型(MORPH_GRADIENT)、卷积核
morph_gr = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)
# 顶帽运算,参数:源、宏类型(MORPH_TOPHAT)、卷积核
morph_top = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
# 黑帽运算,参数:源、宏类型(MORPH_BLACKHAT)、卷积核
morph_black = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)
cv2.imshow('ori', ori_img)
cv2.imshow('morph_open', morph_open)
cv2.imshow('morph_close', morph_close)
cv2.imshow('morph_gr', morph_gr)
cv2.imshow('morph_top', morph_top)
cv2.imshow('morph_black', morph_black)
cv2.waitKeyEx(0)
运算名 | 步骤(方法) | 作用 |
---|---|---|
开运算 | 先做腐蚀后做膨胀,MORPH_OPEN | 消除背景中的噪点 |
闭运算 | 先做膨胀后做腐蚀,MORPH_CLOSE | 消除主要目标中的噪点 |
梯度运算 | 原图-腐蚀后的图,MORPH_GRADIENT | 得到目标图形的边缘 |
顶帽运算 | 原图-开运算,MORPH_TOPHAT | 获取背景中的噪点 |
黑帽运算 | 原图-闭运算,MORPH_BLACKHAT | 获取目标图形中的噪点 |
轮廓查找
图像轮廓即具有相同颜色或强度的连续点的曲线。
图像轮廓的作用
- 图形分析
- 物体的识别与检测
查找轮廓注意
- 需要先对图像进行二值化或Canny操作
- 画轮廓会修改输入图像(需要拷贝)
- 通常会将背景设置为黑色,目标设置为白色
import cv2
ori_img = cv2.imread('9.png')
img = cv2.cvtColor(ori_img, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(img, 140, 255, cv2.THRESH_BINARY)
# 查找轮廓,参数:源、组织已找到轮廓的模式、边框点保存模式,返回值:轮廓结果列表、层级
# 组织已找到轮廓的模式:RETR_EXTERNAL=0(只检测外轮廓)、RETR_LIST=1(检测到的轮廓不建立层级关系)、RETR_CCOMP=2(最多两层)、RETR_TREE=3(树形组织)
# 边框点保存模式:CHAIN_APPROX_NONE(保存所有轮廓上的点)、CHAIN_APPROX_SIMPLE(只保存角点)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 绘制轮廓,参数:源、轮廓(点)、需要绘制的轮廓的索引(-1表示所有)、颜色、线宽(-1表示全部填充)
contours_res = cv2.drawContours(ori_img, contours, -1, (0, 255, 0), 1)
cv2.imshow('binary', binary)
cv2.imshow('contours_res', contours_res)
cv2.waitKeyEx(0)
轮廓的面积和周长
import cv2
ori_img = cv2.imread('9.png')
img = cv2.cvtColor(ori_img, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(img, 140, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contours_res = cv2.drawContours(ori_img, contours, -1, (0, 255, 0), 1)
# 计算轮廓面积,参数:单一轮廓
area = cv2.contourArea(contours[0])
# 计算轮廓周长,参数:单一轮廓、是否闭合
length = cv2.arcLength(contours[0], True)
cv2.imshow('binary', binary)
cv2.imshow('contours_res', contours_res)
cv2.waitKeyEx(0)
多边形逼近与凸包
import cv2
def draw(img, points):
for i in range(len(points)):
if i == len(points) -1:
next_one = points[0][0]
else:
next_one = points[i + 1][0]
cv2.line(img, points[i][0], next_one, (0, 0, 255), 3)
i += 1
ori_img = cv2.imread('10.png')
img = cv2.cvtColor(ori_img, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(img, 140, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contours_res = cv2.drawContours(ori_img, contours, -1, (0, 255, 0), 1)
# 多边形逼近,参数:轮廓(点)、精度(越小越贴合)、是否闭合
approx_res = cv2.approxPolyDP(contours[1], 20, True)
draw(ori_img, approx_res)
# 凸包,参数:轮廓(点)、顺逆时针
convex_res = cv2.convexHull(contours[2])
draw(ori_img, convex_res)
cv2.imshow('ori_img', ori_img)
# cv2.imshow('contours_res', contours_res)
cv2.waitKeyEx(0)
外接矩形
import cv2
import numpy as np
ori_img = cv2.imread('66.png')
img = cv2.cvtColor(ori_img, cv2.COLOR_BGR2GRAY)
_, binary = cv2.threshold(img, 140, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 最小外接矩形,参数:轮廓(点),返回值:RotatedRect(包含起始点(x,y)、宽高(w,h)、角度(angle))
min_r = cv2.minAreaRect(contours[0])
min_box = np.int0(cv2.boxPoints(min_r))
cv2.drawContours(ori_img, [min_box], 0, (0, 255, 0), 3)
# 最大外界矩形,参数:轮廓(点),返回值:Rect(包含起始点(x,y)、宽高(w,h))
x, y, w, h = cv2.boundingRect(contours[0])
cv2.rectangle(ori_img, (x, y), (x + w, y + h), (0, 0, 255), 3)
cv2.imshow('ori_img', ori_img)
cv2.waitKeyEx(0)
标签:des,img,imshow,cv2,笔记,opencv,np,import
From: https://www.cnblogs.com/missfxy/p/16953212.html