当前位置:   article > 正文

2024年C C++最新OpenCV 图像处理四(轮廓查找、画线、矩特征、轮廓),2024年最新讲的太清楚了_设图4-1的绘制函数为drawrect(),图4-2的绘制函数为drawtriangle(),

设图4-1的绘制函数为drawrect(),图4-2的绘制函数为drawtriangle(),

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

* 将原始图像转换为灰度图。
* 对灰度图进行二值化处理。
  • 1
  • 2
  1. 查找轮廓:
image, contours, hierarchy = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

  • 1
  • 2
* 使用 `cv2.findContours()` 函数查找二值图像中的轮廓。
* `cv2.RETR_EXTERNAL` 参数表示只检测外部轮廓。
* `cv2.CHAIN_APPROX_SIMPLE` 参数表示使用简化的轮廓表示。
  • 1
  • 2
  • 3
  1. 绘制并显示每个轮廓:
n = len(contours)
contoursImg = []

for i in range(n):
    temp = np.zeros(o.shape, np.uint8)
    contoursImg.append(temp)
    contoursImg[i] = cv2.drawContours(contoursImg[i], contours, i, (255, 255, 255), 5)

    # Display each contour using plt
    plt.imshow(cv2.cvtColor(contoursImg[i], cv2.COLOR_BGR2RGB))
    plt.title(f'Contour {i + 1}')
    plt.show()

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
* 遍历所有检测到的轮廓,每个轮廓都被绘制在 `contoursImg` 的相应元素中。
* 使用 Matplotlib 显示每个绘制了轮廓的图像,标题显示轮廓的序号。
  • 1
  • 2

总体而言,这段代码的目的是在原始图像中找到轮廓,然后将每个轮廓在图像上绘制出来并使用 Matplotlib 逐个显示,以便用户更好地理解轮廓检测的结果。

三、矩特征:用于描述图像的形状、轮廓和其他特征的数学描述符

矩可以得到图像的形状和结构信息,可以用来识别图像中的对象、测量物体的大小和姿态等。

矩的能力包括对图像的特征提取、形状匹配、边缘检测等,可以帮助计算机视觉系统理解和处理图像信息。

3.1 cv2.moments():该函数计算图像的矩

函数原型为:

cv2.moments(array[, binaryImage])

  • 1
  • 2
请注意,要正确使用`cv2.moments()`函数,
需要先加载图像并将其转换为灰度图像

  • 1
  • 2
  • 3

参数

  • array:这个参数可以是一个点集(contour),也可以是灰度图像或二值图像。当array是一个点集时,函数会将这些点看作轮廓的顶点,将整个点集作为一个轮廓,而不是将它们视为独立点
  • binaryImage:可选参数,默认为False。如果设置为Truearray内的所有非零值都会被处理为1,这样函数会将其视为二值图像进行处理。

返回值
字典对象,包含了图像的矩特征。

(1)空间矩
零阶矩:m00
一阶矩:m10, m01
二阶矩:m20, m11, m02
三阶矩:m30, m21, m12, m03
(2)中心矩
二阶中心矩:mu20, mu11, mu02
三阶中心矩:mu30, mu21, mu12,mu03
(3)归一化中心矩
二阶 Hu 矩:nu20, nu11, nu02
三阶 Hu 矩:nu30, nu21, nu12, nu03

GPT
在这里插入图片描述

Demo
import cv2
import numpy as np

# 读取图片
image = cv2.imread("img/img.png")
cv2.imshow("Original Image", image)

# 形态学处理
kernel = np.ones((14, 14), np.uint8)
morphology_result = cv2.morphologyEx(image, cv2.MORPH_OPEN, kernel)
cv2.imshow("Morphology Result", morphology_result)

# 灰度转换
gray_image = cv2.cvtColor(morphology_result, cv2.COLOR_BGR2GRAY)

# 二值化
_, binary_image = cv2.threshold(gray_image, 100, 255, cv2.THRESH_OTSU)
cv2.imshow("Binary Image", binary_image)

# 寻找轮廓
contours, _ = cv2.findContours(binary_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

n = len(contours)
contoursImg = []
for i in range(n):
    temp = np.zeros(image.shape, np.uint8)
    contoursImg.append(temp)
    contoursImg[i] = cv2.drawContours(contoursImg[i], contours, i, 255, 3)
    cv2.imshow("contours[" + str(i) + "]", contoursImg[i])
print("观察各个轮廓的矩(moments):")
for i in range(n):
    print("轮廓" + str(i) + "的矩:\n", cv2.moments(contours[i]))
print("观察各个轮廓的面积:")
for i in range(n):
    print("轮廓" + str(i) + "的面积:%d" % cv2.moments(contours[i])['m00'])
cv2.waitKey(0)
cv2.destroyAllWindows()


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

在这里插入图片描述

在这里插入图片描述

3.2 cv2.contourArea()计算图像中对象的大小

函数原型为:

cv2.contourArea(contour [, oriented] ))

  • 1
  • 2

参数:

  • contour: 轮廓对象,是一个包含轮廓点坐标的数组。
  • oriented (可选): 一个布尔值,指定是否计算有方向的面积。默认为 False,表示计算无方向的面积。如果设置为 True,则计算有方向的面积。

返回值:

该函数返回轮廓的面积,单位为像素。如果计算有方向的面积,返回的值可能为负数。

示例:
import cv2
import numpy as np

# 创建一张图像并找到轮廓
image = np.zeros((100, 100), dtype=np.uint8)
cv2.rectangle(image, (20, 20), (80, 80), 255, -1)
contours, _ = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 计算轮廓的面积
area = cv2.contourArea(contours[0])

print("Contour Area:", area)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

在这个例子中,我们创建了一张100x100的黑色图像,在其中绘制了一个白色矩形。然后使用cv2.findContours找到轮廓,最后使用cv2.contourArea计算轮廓的面积。

Demo
import cv2

# 读取图像并灰度化
import matplotlib.pyplot as plt

image = cv2.imread('img/S1.jpg')
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 轮廓提取
contours, hierarchy = cv2.findContours(gray_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 检查是否找到轮廓
if len(contours) > 0:
    # 计算m00
    m00 = cv2.moments(contours[0])['m00']
    print("m00: ", m00)

    # 计算contourArea
    area = cv2.contourArea(contours[0])
    print("contourArea: ", area)
else:
    print("No contours found.")
plt.imshow(gray_image, cmap='gray')

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

在这里插入图片描述

3.3 cv2.arcLength():这个函数计算给定轮廓的弧长。弧长用于度量轮廓的周长或曲线的长度。

cv2.arcLength(contour, closed)

  • 1
  • 2

这个函数是OpenCV库中的一个函数,用于计算给定轮廓的弧长。弧长是指曲线的长度,可以用于测量轮廓的周长或曲线的总长度。

参数

  • contour: 这是输入的轮廓参数,通常是一个由点组成的列表或数组,表示图像中的对象的边界。
  • closed: 一个布尔值,指定轮廓是否是封闭的。如果为True,函数会假设轮廓是封闭的,计算封闭曲线的周长;如果为False,函数将计算非封闭曲线的长度。

返回值

  • retval: 弧长或曲线的长度。
示例
import cv2
import numpy as np

# 创建一个简单的闭合轮廓
contour = np.array([[0, 0], [0, 1], [1, 1], [1, 0]], dtype=np.float32)
closed = True

# 计算轮廓的弧长
arc_length = cv2.arcLength(contour, closed)

print("Arc Length:", arc_length)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
Demo
import numpy as np
import cv2
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection

# 创建图像并在中心设置一个3x3的方块
image = np.zeros((5,5), dtype=np.uint8)
image[2:5, 2:5] = 1

# 找到轮廓
contours, _ = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

# 假设只有一个轮廓
contour = contours[0]

# 轮廓点的数量
num_points = contour.shape[0]

# 创建一个线段集合,用于绘制不同颜色的边
lines = []
colors = ['r', 'g', 'b', 'c']  # 红、绿、蓝、青(这里只用于示例,实际情况下可能需要更多颜色或循环使用)

# 遍历轮廓的边
for i in range(num_points):
    # 获取当前点和下一个点(或第一个点,如果我们在最后一个点上)
    point1 = tuple(contour[i][0])
    point2 = tuple(contour[(i + 1) % num_points][0])

    # 添加线段到集合中
    lines.append([point1, point2])

# 创建线段集合
lc = LineCollection(lines, colors=colors, linewidths=2)

# 使用matplotlib显示图像
fig, ax = plt.subplots()

# 添加线段集合到图像上
ax.add_collection(lc)

# 设置坐标轴限制
ax.set_xlim(0, 9)
ax.set_ylim(0, 9)

# 关闭坐标轴
ax.axis('off')

# 显示图像
plt.show()

# 注意:这里我们假设了颜色和线段数量的匹配,
# 在实际应用中,您可能需要处理颜色和线段数量的对应关系。

# 遍历每个轮廓
for contour in contours:
    # 轮廓是一个点的数组,我们需要遍历这些点来计算相邻点之间的距离
    # 注意:轮廓是闭合的,所以最后一个点和第一个点是相连的
    num_points = contour.shape[0]
    for i in range(num_points):
        # 获取当前点和下一个点(或第一个点,如果我们在最后一个点上)
        point1 = contour[i]
        point2 = contour[(i + 1) % num_points]

        # 计算两点之间的距离(使用欧几里得距离)
        edge_length = np.linalg.norm(point1 - point2)

        # 输出边的长度
        print(f"Edge length {i + 1}: {edge\_length}")

# 计算所有轮廓的总弧长
total_arc_length = 0
for contour in contours:
    arc_length = cv2.arcLength(contour, True)
    total_arc_length += arc_length

print("Total Arc Length:", total_arc_length)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77

在这里插入图片描述
在这里插入图片描述

import cv2
import numpy as np

o = cv2.imread('img/S1.jpg')
if o is None:
    print("Error loading image!")
    exit()

cv2.imshow("original", o)

# 轮廓
gray = cv2.cvtColor(o, cv2.COLOR_BGR2GRAY)
ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)

# 注意:根据OpenCV版本,findContours的返回值可能会有所不同
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

# --------------计算各轮廓的长度之和、平均长度--------------------
n = len(contours)  # 获取轮廓的个数
cntLen = [cv2.arcLength(contours[i], True) for i in range(n)]
cntLenSum = np.sum(cntLen)  # 各轮廓的长度之和
cntLenAvr = cntLenSum / n  # 轮廓长度的平均值

print("轮廓的总长度为:%f" % cntLenSum)
print("轮廓的平均长度为:%f" % cntLenAvr)

# --------------显示长度超过平均值的轮廓--------------------
result = np.zeros_like(o)
for i in range(n):
    if cv2.arcLength(contours[i], True) > cntLenAvr:
        cv2.drawContours(result, contours, i, (255, 255, 255), 3)

cv2.imshow("Contours above average", result)
cv2.waitKey()
cv2.destroyAllWindows()

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

在这里插入图片描述
在这里插入图片描述

四、Hu矩

Hu矩是通过对图像的几何矩进行归一化和线性组合得到的,主要用于图像的旋转、缩放和平移不变性的描述

  • 1
  • 2

4.1 Hu矩函数 cv2.HuMoments()

该函数使用 cv2.moments()函数的返回值作为参数,返回 7 个 Hu 矩值。

二阶 Hu 矩:eta20, eta11, eta02
 三阶 Hu 矩:eta30, eta21, eta12, eta03
在这里插入图片描述

4.1.1 验证hu1 = eta20 + eta02
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

img = cv.imread('img/S1.jpg')
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
HuM=cv.HuMoments(cv.moments(gray))
print("cv.monents:\n",cv.moments(gray))

print("\nHuMoments:\n",HuM)
print("HuM1[0]=",HuM[0])
x=cv.moments(gray)['nu20']+cv.moments(gray)['nu02']
print(x)
print(x-HuM[0])

plt.imshow()

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

在这里插入图片描述

4.2 比较Hu矩差异:形状匹配

cv2.matchShapes()是OpenCV中的一个函数,用于计算两个形状之间的相似性或匹配度。它通过计算形状的Hu矩来比较两个形状的差异程度。

retval = cv2.matchShapes(contour1, contour2, method, parameter)

  • 1
  • 2

其中:

  • contour1contour2分别是两个轮廓(即形状)或者灰度图像。
  • method指定了计算相似性的方法,可以是以下值之一:
    • cv2.CONTOURS_MATCH_I1:使用I1方法进行匹配。
    • cv2.CONTOURS_MATCH_I2:使用I2方法进行匹配。
    • cv2.CONTOURS_MATCH_I3:使用I3方法进行匹配。
  • parameter是可选参数,用于控制匹配精度。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/919994
推荐阅读
相关标签