Python第五周学习笔记 Opencv进阶

一、OpenCV基础——threshold函数的使用

图像的二值化就是将图像上的像素点的灰度值设置为0或255,这样将使整个图像呈现出明显的黑白效果。在数字图像处理中,二值图像占有非常重要的地位,图像的二值化使图像中数据量大为减少,从而能凸显出目标的轮廓。OpenCV中提供了函数cv::threshold();

threshold函数作用: 去掉噪,例如过滤很小或很大像素值的图像点。

threshold函数python版原型:

retval, dst = cv.threshold( src, thresh, maxval, type[, dst] ) 

参数说明:

  • src:原图像。
  • dst:结果图像。
  • thresh:当前阈值。
  • maxVal:最大阈值,一般为255.
  • thresholdType:阈值类型,主要有下面几种:
enum ThresholdTypes {
    
    
    THRESH_BINARY     = 0,
    THRESH_BINARY_INV = 1,
    THRESH_TRUNC      = 2,
    THRESH_TOZERO     = 3,
    THRESH_TOZERO_INV = 4,
    THRESH_MASK       = 7,
    THRESH_OTSU       = 8,
    THRESH_TRIANGLE   = 16
};

返回值:

  • retval: 与参数thresh一致
  • dst: 结果图像

1、阈值理解

PS解释:“阈值”命令将灰度或彩色图像转换为高对比度的黑白图像。您可以指定某个色阶作为阈值。所有比阈值亮的像素转换为白色;而所有比阈值暗的像素转换为黑色。“阈值”命令对确定图像的最亮和最暗区域很有用。
这里的解释,就是拿黑白2色去阐述你的图片,是可调节的。

二、cv.findContours()寻找轮廓

轮廓可以简单地解释为连接具有相同颜色或强度的所有连续点(沿边界)的曲线。轮廓是用于形状分析以及对象检测和识别的有用工具。

  • 为了获得更高的准确性,请使用二进制图像。因此,在找到轮廓之前,请应用阈值或canny边缘检测。
  • 从OpenCV 3.2开始,findContours()不再修改源图像。
  • 在OpenCV中,找到轮廓就像从黑色背景中找到白色物体。因此请记住,要找到的对象应该是白色,背景应该是黑色。

找到二进制图像的轮廓

# 找到二进制图像的轮廓
import numpy as np
import cv2 as cv

im = cv.imread('鸭子.jpg')
imgray = cv.cvtColor(im, cv.COLOR_BGR2GRAY)  # 得到灰度图
ret, thresh = cv.threshold(imgray, 127, 255, 0)  # 图像阈值/二值化
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
# 输出等高线和层次结构                    原图像     轮廓检索模式     轮廓逼近方法

findcontour()函数中有三个参数,第一个是源图像,第二个是轮廓检索模式,第三个是轮廓逼近方法输出等高线和层次结构轮廓是图像中所有轮廓的Python列表每个单独的轮廓一个(x,y)坐标的Numpy数组的边界点的对象

1、轮廓检索模式 cv.findContours()第二个参数

建立轮廓索引时,按照轮廓从小到大分配索引号。

RECT_EXTERNAL只检测最外层轮廓。
RECT_LIST检测所有轮廓。
这两种模式不建立轮廓等级关系,不管轮廓嵌套与否,均按照轮廓大小依次分配索引。

RECT_CCOMPRECT_TREE检测所有轮廓
RECT_CCOMP在有轮廓嵌套时,无论嵌套个数多少,只建立两级等级关系
RECT_TREE在有轮廓嵌套时,建立多级等级关系

2、轮廓近似方法 cv.findContours()第三个参数

这是cv.findContours函数中的第三个参数。

上面我们告诉我们轮廓是强度相同的形状的边界。它存储形状边界的(x,y)坐标。但是它存储所有坐标吗?这是通过这种轮廓近似方法指定的。

如果传递cv.CHAIN_APPROX_NONE,则将存储所有边界点。但是实际上我们需要所有这些要点吗?例如,您找到了一条直线的轮廓。您是否需要线上的所有点来代表该线?不,我们只需要该线的两个端点即可。这就是cv.CHAIN_APPROX_SIMPLE所做的。它删除所有冗余点并压缩轮廓,从而节省内存。
下面的矩形图像演示了此技术。只需在轮廓数组中的所有坐标上绘制一个圆(以蓝色绘制)。第一幅图像显示了用cv.CHAIN_APPROX_NONE获得的积分(734个点),第二幅图像显示了用cv.CHAIN_APPROX_SIMPLE获得的效果(只有4个点)。看,它可以节省多少内存!!!
在这里插入图片描述

三、cv.drawContours()绘制轮廓

要绘制轮廓,请使用cv.drawContours函数。只要有边界点,它也可以用来绘制任何形状。它的第一个参数是源图像,第二个参数是应该作为Python列表传递的轮廓,第三个参数是轮廓的索引(在绘制单个轮廓时有用。要绘制所有轮廓,请递-1),其余参数是颜色,厚度等等

  • 在图像中绘制所有轮廓:
cv.drawContours(im, contours, -1, (0, 255, 0), 3)
  • 绘制单个轮廓,如第四个轮廓:
cv.drawContours(im, contours, 3, (0, 255, 0), 3)
  • 但是在大多数情况下,以下方法会很有用:
cnt = contours[4]
cv.drawContours(im, [cnt], 0, (0, 255, 0), 3)

【代码】学习使用OpenCV中的findContours函数对物体轮廓进行检测

# 找到二进制图像的轮廓
# import numpy as np
import cv2 as cv

im = cv.imread('han3.png')
print(im.shape)
im_background1 = cv.imread('han3.png')
ret2, thresh2 = cv.threshold(im, 127, 255, 0)
im2 = cv.imread('bgr.png')
im3 = cv.imread('bgr.png')
imgray = cv.cvtColor(im, cv.COLOR_BGR2GRAY)  # 得到灰度图
#     ↓结果图像
ret, thresh = cv.threshold(imgray, 127, 255, 0)  # 图像阈值/二值化
# ↑与参数thresh一致
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
# 输出↑层次结构和↑等高线                    原图像     轮廓检索模式     轮廓逼近方法
# Python列表传递的轮廓:层次结构

cv.drawContours(im_background1, contours, -1, (0, 255, 0), 3)  # 在图像中绘制所有轮廓
cv.drawContours(im2, contours, -1, (0, 0, 0), 3)  # 在图像中绘制所有轮廓
cv.drawContours(im3, contours, 100, (0, 255, 0), 3)  # 绘制单个轮廓/第四个轮廓

# 大多数情况使用如下方法
# cnt = contours[4]
# cv.drawContours(im_background1, [cnt], 0, (0, 255, 0), 3)

cv.imshow('thresh2', thresh2)
cv.imshow('thresh', thresh)
cv.imshow('im_background1', im_background1)
cv.imshow('im2', im2)
cv.imshow('im3', im3)
cv.waitKey(0)
cv.destroyAllWindows()

四、【代码】contourArea()函数计算面积

轮廓区域由函数cv.contourArea()或从矩 M[‘m00’] 中给出。

area = cv.contourArea(cnt)

实现代码如下

import cv2

img = cv2.imread('han3.png')
background = cv2.imread('bgr.png')
background_one = cv2.imread('bgr.png')
imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
retval, threshold = cv2.threshold(imgray, 20, 255, 0)
contours, hierarchy = cv2.findContours(threshold, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

cv2.drawContours(background, contours, -1, (0, 0, 0), 1)

cnt = contours[100]
cv2.drawContours(background_one, [cnt], 0, (0, 255, 0), 3)

area = cv2.contourArea(cnt)  # 计算面积
print(area)

cv2.imshow('img', img)
cv2.imshow('threshold', threshold)
cv2.imshow('background', background)
cv2.imshow('background_one', background_one)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43232564/article/details/107932246