【PyTorch学习笔记_02】--- Opencv笔记(图像预处理使用)

OpenCV 笔记

1. 计算机眼中的图像

  • RGB: 图像的颜色通道
# 数据读取-图像
import cv2
import matplotlib.pyplot as plt
import numpy as np

# %matplotlib inline      # jupyter中使用

img = cv2.imread('cat.jpg')
  • cv2.IMREAD_COLOR : 彩色图像
  • cv2.IMREAD_GRAYSCALE: 灰度图像
  • opencv 读取的格式是BGR
import cv2

img = cv2.imread('cat.jpg')
# 图像的显示,也可以创建多个窗口
cv2.imshow('image', img)
# 等待时间,毫秒级,0表示任意键终止
cv2.waitKey(0)
cv2.destroyAllWindows()

2. 视频的读取与处理

# 显示函数封装
import cv2


def cv_show(name, img):
    cv2.imshow(name, img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
  • img.shape 获取图像(high, wight, 通道数color) — BGR
import cv2

# 读取灰度图
img = cv2.imread('cat.jpg', cv2.IMREAD_GRAYSCALE)

# 保存图片
cv2.imwrite('mycat.jpg', img)

# np.array的格式
type(img)

img.size  # 查看大小
img.dtype  # 查看数值类型 uint8
  • 读取视频
import cv2

vc = cv2.VideoCapture('test.mp4')

# 检测是否打开正确
if vc.isOpened():
    open, frame = vc.read()
else:
    open = False

while open:
    ret, frame = vc.read()
    if frame is None:
        break
    if ret == True:
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        cv2.imshow('result', gray)
        if cv2.waitKey(0) & 0xFF == 27:
            break
vc.release()
cv2.destroyAllWindows()

3. ROI区域

import cv2


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


img = cv2.imread('cat.jpg')
# 截取部分图像数据
cat = img[0:200, 0:200]
cv_show('cat', cat)

# 颜色通道提取
b, g, r = cv2.split(img)

# 图像组合
img = cv2.merge((b, g, r))

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

4. 边界填充

import cv2

img = cv2.imread('cat.jpg')
# 上下左右填充的大小
top_size, bottom_size, left_size, right_size = (50, 50, 50, 50)
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(231), plt.imshow(img, 'gray'), plt.title('ORIGINAL')  # 原始图
plt.subplot(232), plt.imshow(replicate, 'gray'), plt.title('REPLICATE')  # 复制法, 复制最边缘像素
plt.subplot(233), plt.imshow(reflect, 'gray'), plt.title(
    'REFLECT')  # 反射法,  对感兴趣的图像中的像素在两边进行复制,如:fedcba:abcdefgh:hgfedcb
plt.subplot(234), plt.imshow(reflect101, 'gray'), plt.title('REFLECT_101')  # 反射法, 以最边缘像素为轴,对称, gfedcb|abcdefgh|gfed
plt.subplot(235), plt.imshow(wrap, 'gray'), plt.title('WRAP')  # 外包装法,  cdefgh|abcdefgh|abcdefg
plt.subplot(236), plt.imshow(constant, 'gray'), plt.title('CONSTANT')  # 常量法,   常数值填充

plt.show()

5. 数值计算

import matplotlib.pyplot as plt
import cv2

img_cat = cv2.imread('cat.jpg')
img_dog = cv2.imread('dog.jpg')

img_cat2 = img_cat + 10
img_cat[:5, :, 0]  # 打印前五行
img_cat2[:5, :, 0]

# 相当于 %256, 取余数
(img_cat + img_cat2)[:5, :, 0]

cv2.add(img_cat, img_cat2)[:5, :, 0]  # 最大值255,相加超过的像素,会得到255

# 图像融合,大小必须一致
img_cat.shape
img_dog = cv2.resize(img_dog, (500, 414))
img_dog.shape

res = cv2.resize(img_cat, (0, 0), fx=3, fy=1)
plt.imshow(res)

res = cv2.resize(img_cat, (0, 0), fx=1, fy=3)
plt.imshow(res)

res = cv2.addWeighted(img_cat, 0.4, img_dog, 0.6, 0)  # 指定权重后融合
plt.show(res)

6.腐蚀操作----形态学(逐渐变小)

import cv2
import numpy as np

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

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

kernel = np.ones((5, 5), np.uint8)
erosion = cv2.erode(img, kernel, iterations=1)

cv2.imread('erosion', erosion)
cv2.waitKey(0)
cv2.destroyAllWindows()

pie = cv2.imread('pie.png')
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()

7. 膨胀操作----形态学(和腐蚀操作互为逆操作)

import numpy as np
import cv2

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

kernel = np.ones((3, 3), np.uint8)
dige_ersion = cv2.erode(img, kernel, iterations=1)  # 腐蚀

kernel = np.ones((3, 3), np.uint8)
dige_dilate = cv2.dilate(dige_ersion, kernel, iterations=1)  # 膨胀

8. 开运算与闭运算

import cv2
import numpy as np

# 开:先腐蚀,再膨胀
img = cv2.imread('dige.png')

kernel = np.ones((5, 5), np.uint8)
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)  # morphology:形态学

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

# 闭运算:先膨胀,再腐蚀
img = cv2.imread('dige.png')

kernel = np.ones((5, 5), np.uint8)
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)

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

9. 梯度运算

import numpy as np
import cv2

# 梯度=膨胀-腐蚀 (减法运算)   结果会是一个轮廓
pie = cv2.imread('pie.png')
kernel = np.ones((7, 7), np.uint8)
dilate = cv2.dilate(pie, kernel, iterations=5)
erosion = cv2.erode(pie, kernel, iterations=5)

res = np.hstack((dilate, erosion))

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

gradient = cv2.morphologyEx(pie, cv2.MORPH_GRADIENT, kernel)

cv2.imshow('gradient', res)
cv2.waitKey(0)
cv2.destroyAllWindows()

10. 礼帽与黑帽

  • 礼帽 = 原始输入 - 开运算结果
  • 黑帽 = 闭运算 - 原始输入
import cv2
import numpy as np

kernel = np.ones((7, 7), np.uint8)
# 礼帽
img = cv2.imread('dige.png')
tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
cv2.imshow('tophat', tophat)
cv2.waitKey(0)
cv2.destroyAllWindows()

# 黑帽
img = cv2.imread('dige.png')
blackhat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)
cv2.imshow('blackhat', blackhat)
cv2.waitKey(0)
cv2.destroyAllWindows()

11. Sobel 算子

  • 图像梯度-Sobel算子
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JM5452UA-1667466692506)(image/Sobel算子.png)]
import cv2

img = cv2.imread('pie.png', cv2.IMREAD_GRAYSCALE)
cv2.imshow("img", img)
cv2.waitKey(0)
cv2.destroyAllWindows()


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


sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=0)

cv_show('sobelX', sobelx)
  • dst = cv2.Sobel(src, ddepth, dx, dy, ksize)
  • ddepth: 图像的深度
  • dx dy: 分别表示水平和竖直方向
  • ksize是Sobel算子的大小

12. 梯度计算方法

  • 白到黑是整数,黑到白就是负数了,所有的负数会被截断成0,所以要取绝对值
import cv2


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


img = cv2.imread('pie.png', cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=0)
# 取绝对值
sobelx = cv2.convertScaleAbs(sobelx)
cv_show('sobelx', sobelx)
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=0)
sobely = cv2.convertScaleAbs(sobely)
cv_show(sobely, 'sobely')
# 分别计算x, y, 再求和
sobelxy = cv2.addWeighted(sobelx, 0.5, sobely, 0.5, 0)
cv_show('sobelxy', sobelxy)
# 不建议直接计算
sobelxy = cv2.Sobel(img, cv2.CV_64F, 1, 1, ksize=0)
sobelxy = cv2.convertScaleAbs(sobelxy)
cv_show('sobelxy', sobelxy)

13. scharr(夏尔) 与 lapkacian(拉普拉斯)算子

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EC86pmD0-1667466692507)(image/Scharr算子.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yjA54Bgr-1667466692508)(img.png)]

  • 拉普拉斯算子对噪音点敏感
import numpy as np
import cv2


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


# 不同算子的差异
img = cv2.imread('lena.jpg', cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=0)
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=0)
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.stack(sobelxy, scharrxy, laplacian)
cv_show('res', res)

14. 图像平滑处理

  • 均值滤波
# 简单的平均卷积操作
import cv2

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

blur = cv2.blur(img, (3, 3))  # 均值滤波

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

# 方框滤波
# 基本和均值一样,可以选择归一化
box = cv2.boxFilter(img, -1, (3, 3), normalize=True)  # 归一化,主要处理越界问题

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

15. 高斯与中值滤波

  • 高斯滤波:离中心值越近,相关性越大
import numpy as np
import cv2

img = cv2.imread('lenaNoise.png')
# 高斯模糊的卷积核里的数值是满足高斯分布,相当于更重视中间的
aussian = cv2.GaussianBlur(img, (5, 5), 1)

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

# 中值滤波:从小到大排序,找中间的
median = cv2.medianBlur(img, 5)  # 中值滤波

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

# 展示所有
res = np.stack((aussian, median))  # 横着的
res_v = np.vstack((aussian, median))  # 竖着的
print(res)
cv2.imshow('aussian vs median', res)
cv2.waitKey(0)
cv2.destroyAllWindows()

16. 图像阈值

  • 阈值:大于256怎么处理,小于256怎么处理
  • ret, dst = cv2.threshold(src, thresh, maxval, type)
  • src: 输入图, 只能是单通道的图像,通常是灰度图
  • dst: 输出图
  • thresh: 阈值
  • maxval: 当像素值超过了阈值(或者小于阈值,根据type来决定),
  • type: 二值化操作的类型,包含以下五种类型:
    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 matplotlib.pyplot as plt
import cv2

img_gray = cv2.imread('lenaNoise.png', cv2.IMREAD_GRAYSCALE)

ret, thread1 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
ret, thread2 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY_INV)
ret, thread3 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TRUNC)
ret, thread4 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO)
ret, thread5 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO_INV)

titles = ['Original Image', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
images = [img_gray, thread1, thread2, thread3, thread4, thread5]

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()

17. Canny边缘检测流程

  • 使用高斯滤波,以平滑图像,滤除噪声
  • 计算图像中每个像素点的梯度强度和方向
  • 应用非极大值抑制,以消除边缘检测带来的杂散响应
  • 应用双阈值检测来确定真实和潜在的边缘
  • 通过抑制孤立的弱边缘最终完成边缘检测
  • 记住:梯度和方向使用Sobel算子

18. 非极大值抑制

  • 线性插值法:
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5Yprjp00-1667466692508)(image/线性插值法.png)]
  • 固定八个方向,比较梯度幅值大小,保留最大的
    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FJ8CXGI5-1667466692509)(image/插值法优化.png)]

19.边缘检测效果

  • 双阈值检测
  • 梯度值 > maxVal: 处理为边界
  • minVal < 梯度值 < maxVal: 连有边界则保留,否则舍弃
  • 梯度值 < minVal: 则舍弃
import numpy as np
import cv2


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


img = cv2.imread('lena.jpg', cv2.IMREAD_GRAYSCALE)

v1 = cv2.Canny(img, 80, 150)
v2 = cv2.Canny(img, 5, 100)

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

20. 轮廓检测方法

  • cv2.findContours(img, mode, method)

  • mode: 轮廓检索模式

  • RETR_EXTERNAL: 只检索最外面的轮廓

  • RETR_LIST: 检索所有的轮廓,并将其保存到一条链表中

  • RETR_CCOMP: 检索所有的轮廓,并将他们组织为两层:顶层是各部分的外部边界,第二层是空洞的边界

  • RETR_TREE: 检索所有的轮廓,并重构嵌套轮廓的整个层次

  • method: 轮廓逼近的方法

  • CHAIN_APPROX_NONE: 以Freeman链码的方式输出轮廓,所有其他方法输出多边形

  • CHAIN_APPROX_SIMPLE: 压缩水平的,垂直的和斜的部分,也就是,函数只保留他们的终点部分

import cv2


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


img = cv2.imread('contours.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
cv_show('thresh', thresh)

binary, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

21. 模板匹配

  • TM_SQDIFF: 计算平方不同,计算出来的值越小,越相关
  • TM_CCORR: 计算相关性,计算出来的值越大,越相关
  • TM_CCOEFF: 计算相关系数,计算的值越大,越相关
  • TM_SQDIFF_NORMED: 计算归一化平方不同,计算的值越接近0,越相关
  • TM_CCORR_NORMED: 计算归一化相关性, 计算的值越接近1, 越相关
  • TM_CCOEFF_NORMED: 计算归一化相关系数,计算的值越接近1, 越相关
import cv2

# 模板匹配
img = cv2.imread('lena.jpg', 0)
template = cv2.imread('face.jpg', 0)
h, w = template.shape[:2]

methods = ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCORR', 'cv2.TM_CCORR_NORMED', 'cv2.TM_SQDIFF',
           'cv2.TM_SQDIFF_NORMED']

res = cv2.matchTemplate(img, template, 1)

min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)

22. 图像金字塔

  • 高斯金字塔: 向下采样方法(缩小) 将Gi 与高斯内核卷积 将所有偶数行和列去除
  • 拉普拉斯金字塔:向上采样方法(放大) 将图像在每个方向扩大为原来的两倍,新增的行和列以0填充 使用先前同样的内核(乘以4)与放大后的图像卷积,获得近似值

23. 金字塔制作方法

  • 就是把图片放大缩小
import cv2


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


img = cv2.imread('AM.png')
cv_show('img', img)

up = cv2.pyrUp(img)
cv_show('up', up)
print(up.shape)

down = cv2.pyrDown(img)
cv_show('down', down)
print(down.shape)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lK9OkKZY-1667466692510)(image/拉普拉斯金字塔.png)]

24. 轮廓检测结果

import cv2


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


img = cv2.imread('car.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
res, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
cv_show('thresh', thresh)

binary, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
# contours 轮廓信息
# 传入绘制图像,轮廓,轮廓索引,颜色模式, 线条厚度
# 注意需要copy, 要不原图会变...
draw_img = img.copy()
res = cv2.drawContours(draw_img, contours, -1, (0, 0, 255), 2)  # -1是指全部的轮廓   2 线条的宽度
cv_show('res', res)

draw_img = img.copy()
res = cv2.drawContours(draw_img, contours, 0, (0, 0, 255), 2)  # 0 按顺序进行选择
cv_show('res', res)

25. 匹配效果展示

import numpy as np
import matplotlib.pyplot as plt
import cv2

img = cv2.imread('lena.jpg', 0)
template = cv2.imread('face.jpg', 0)
methods = ['cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCORR', 'cv2.TM_CCORR_NORMED', 'cv2.TM_SQDIFF',
           'cv2.TM_SQDIFF_NORMED']
w, h = template.shape[:2]
for meth in methods:
    img2 = img.copy()

    # 匹配方法的真值
    method = eval(meth)
    print(method)
    res = cv2.matchTemplate(img, template, method)
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)

    # 如果是平方差匹配TM_SQDIFF 或 归一化平方差匹配TM_SQDIFF_NORMED, 取最小值
    if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:
        top_left = min_loc
    else:
        top_left = max_loc
    bottom_right = (top_left[0] + w, top_left[1] + h)

    # 画矩形
    cv2.rectangle(img2, top_left, bottom_right, 255, 2)

    plt.subplot(121), plt.imshow(res, cmap='gray')
    plt.xticks([]), plt.yticks([])  # 隐藏坐标轴
    plt.subplot(122), plt.imshow(img2, cmap='gray')
    plt.xticks([]), plt.yticks([])
    plt.suptitle(meth)
    plt.show()

# 匹配多个对象
img_rgb = cv2.imread('mario.jpg')
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template = cv2.imread('mario_coin.jpg', 0)
h, w = template.shape[:2]

res = cv2.matchTemplate(img_gray, template, cv2.TM_CCOEFF_NORMED)
threshold = 0.8

# 取匹配程度大于80%的坐标
loc = np.where(res >= threshold)
for pt in zip(*loc[::-1]):
    bottom_right = (pt[0] + w, pt[1] + h)
    cv2.rectangle(img_rgb, pt, bottom_right, (0, 0, 255), 2)
cv2.imshow('img_rgb', img_rgb)
cv2.waitKey(0)

26. 轮廓特征与近似

import cv2


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


img = cv2.imread('car.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
res, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
cv_show('thresh', thresh)

binary, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

# 轮廓特征
cnt = contours[0]  # 拿第一轮廓
# 面积
cv2.contourArea(cnt)
# 周长 True表示闭合
cv2.arcLength(cnt, True)

# 轮廓近似
img = cv2.imread('contours2.png')

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
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)

epsilon = 0.1 * cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, epsilon, True)

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

# 边界矩形
cnt = contours[0]
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)

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)

你可能感兴趣的:(PyTorch,opencv,计算机视觉,pytorch)