opencv(七)

[复制链接]
查看99737 | 回复0 | 2024-1-10 10:42:14 | 显示全部楼层 |阅读模式
轮廓检测

案例一,只检测外轮廓

import cv2
import numpy as np

# 读取图像
image = cv2.imread('img.png')

# 将图像转换为灰度
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 通过阈值处理得到二值图像
_, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)

# 寻找轮廓
contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 在原图上绘制轮廓
cv2.drawContours(image, contours, -1, (0, 255, 0), 2)

# 显示结果
cv2.imshow('Original Image', image)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 效果如图


PNB8QA39L}9K9W2_A63_V~N.jpg

image.png案例二,检索所有的轮廓

import cv2

# 读取图像
image = cv2.imread('yuan.png')

# 将图像转换为灰度
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 通过阈值处理得到二值图像
_, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)

# 寻找轮廓(使用cv2.RETR_TREE模式)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# 在原图上绘制轮廓及其层次结构
cv2.drawContours(image, contours, -1, (0, 255, 0), 2)

# 显示结果
cv2.imshow('Contours with Hierarchy', image)
cv2.waitKey(0)
cv2.destroyAllWindows()


image.png

image.png案例三,根据轮廓条件来筛选

import cv2

img = cv2.imread('./yuan.png', 1)
orgImg = img.copy()  # 创建一个深copy对象

img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img = cv2.GaussianBlur(img, (3, 3), 0)
# show(img,'gauss')
_, img = cv2.threshold(img, 200, 255, cv2.THRESH_BINARY)
# show(img, 'thres')
canny = cv2.Canny(img, 50, 150)
# show(img, 'canny')
# cv2.RETR_EXTERNAL 只检测外轮廓
# cv2.RETR_LIST  没有层级关系的轮廓
# cv2.RETR_CCOMP 有层级关系的轮廓
# cv2.RETR_TREE  树结构的轮廓

# cv2.CHAIN_APPROX_NONE    存储所有边界点
# cv2.CHAIN_APPROX_SIMPLE  压缩垂直、水平、对角方向,只保留端点

# contours:轮廓点。列表格式,每一个元素为一个3维数组(其形状为(n,1,2),其中n表示轮廓点个数,2表示像素点坐标),表示一个轮廓
# hierarchy:轮廓间的层次关系,为三维数组,形状为(1,n,4),其中n表示轮廓总个数,4指的是用4个数表示各轮廓间的相互关系
# 第一个数表示同级轮廓的下一个轮廓编号,第二个数表示同级轮廓的上一个轮廓的编号,
# 第三个数表示该轮廓下一级轮廓的编号,第四个数表示该轮廓的上一级轮廓的编号。
contours, hierarchy = cv2.findContours(canny, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 遍历轮廓,还原到原图中,人眼识别在那里
for i in range(len(contours)):
    # 1.特征,计算轮廓的面积【*****】
    area = cv2.contourArea(contours)
    if area > 40000 and area < 49000:
        print(f"轮廓的面积{i}:", area)
        #                      rgb图,  所有轮廓, 第几个轮廓
        # 为了调试,过滤才使用
        perimeter = cv2.arcLength(contours, True)
        print(f'当前轮廓的周长:{perimeter}')
        if perimeter > 1000: continue
        orgImg = cv2.drawContours(orgImg, contours, i, (0, 0, 255), 3)

cv2.imshow("yuan", orgImg)
cv2.waitKey(0)


image.png轮廓近似检测

import cv2

# 轮廓检测
img = cv2.imread('./20230927111939.jpg', 1)
cv2.imshow("", img)
cv2.waitKey(0)

oldImg = img.copy()  # 创建1个新对象
# 转换为灰度图
imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 二值 化
ret, thresh = cv2.threshold(imgray, 127, 255, 0)
# c.show(thresh)
# 高斯滤波
gau_shi = cv2.GaussianBlur(thresh, [3, 3], 0)
canny = cv2.Canny(img, 50, 150)

contours, hierarchy = cv2.findContours(canny, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for i in range(len(contours)):
    img = cv2.drawContours(img.copy(), contours, i, (0, 0, 255), 3)

cv2.imshow('old-con', img)
cv2.waitKey(0)
cnt = contours[0]
epsilon = 0.1 * cv2.arcLength(cnt, True)
approx = cv2.approxPolyDP(cnt, epsilon, True)
img3 = cv2.drawContours(oldImg, [approx], -1, (0, 0, 255), 3)

cv2.imshow("", img3)
cv2.waitKey(0)
img4 = cv2.polylines(oldImg.copy(), [approx], True, (0, 255, 0), 5)

cv2.imshow("", img4)
cv2.waitKey(0)


image.png直接获取近似轮廓

# 轮廓检测
img = cv2.imread('./20230927111939.jpg', 1)   
oldImg = img.copy()  # 创建1个新对象
# 转换为灰度图
imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 二值 化
ret, thresh = cv2.threshold(imgray, 127, 255, 0)
# c.show(thresh)
# 高斯滤波
gau_shi = cv2.GaussianBlur(thresh, [3, 3], 0)
canny = cv2.Canny(img, 50, 150)

contours, hierarchy = cv2.findContours(canny, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
for i in range(len(contours)):
    img = cv2.drawContours(img.copy(), contours, i, (0, 0, 255), 3)

cv2.imshow('old-con', img)
cv2.waitKey(0)
cnt = contours[0]
# 得到轮廓的外接矩形
x, y, w, h = cv2.boundingRect(cnt)
img = cv2.rectangle(oldImg, (x, y), (x + w, y + h), (255, 0, 0), 2)

cv2.imshow("", img)
cv2.waitKey(0)


image.png获取旋转矩形

import cv2
import numpy as np

# 读取图像
image = cv2.imread('20230927143717.jpg')

# 将图像转换为灰度
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 进行边缘检测
edges = cv2.Canny(gray, 50, 150, apertureSize=3)

# 寻找轮廓
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 遍历每个轮廓
for contour in contours:
    # 拟合外接矩形
    rect = cv2.minAreaRect(contour)
    box = cv2.boxPoints(rect)
    box = np.intp(box)

    # 在原始图像上绘制矩形
    # cv2.drawContours(image, [box], 0, (0, 255, 0), 2)
    cv2.polylines(image, [box], isClosed=True, color=(0, 255, 0), thickness=2)

# 显示结果
cv2.imshow('Rotated Rectangle Detection', image)
cv2.waitKey(0)
cv2.destroyAllWindows()


image.pngcv2.polylines和cv2.drawContours的区别

cv2.polylines 和 cv2.drawContours 是 OpenCV 中用于绘制多边形或轮廓的两个不同的函数。

    cv2.polylines:
      cv2.polylines 用于绘制多条线段,即可以绘制多边形。语法:cv2.polylines(img, pts, isClosed, color[, thickness[, lineType[, shift]]])
      img:要绘制线段的图像。pts:包含多边形顶点坐标的数组。isClosed:指定是否封闭多边形。如果为 True,则多边形将首尾相连形成封闭图形;如果为 False,则多边形只是一组线段而不封闭。color:线段的颜色。thickness:线段的宽度。默认值为 1。lineType:线段的类型。默认值为 8-connected(8 连通)。更多选项可以参考 OpenCV 文档。shift:坐标中的小数位数。默认值为 0。

    cv2.drawContours:
      cv2.drawContours 用于绘制轮廓。语法:cv2.drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset]]]]])
      image:要绘制轮廓的图像。contours:包含轮廓的列表。contourIdx:要绘制的轮廓的索引。如果为负数,则绘制所有轮廓。color:轮廓的颜色。thickness:轮廓线的宽度。如果为负数或cv2.FILLED,则填充轮廓。lineType:轮廓线的类型。hierarchy:轮廓的层次结构信息。maxLevel:绘制轮廓的最大层次。offset:每个轮廓的可选偏移量。


总的来说,cv2.polylines 适用于绘制多条线段,而 cv2.drawContours 适用于绘制轮廓。cv2.drawContours 的灵活性更高,可以用于处理更复杂的轮廓结构。
矩形识别的其他代码-混乱仅参考

import cv2
import numpy as np


def show(img, title=''):
    cv2.imshow(title, img)
    cv2.waitKey(0)


# 边缘检测都是针对灰度图像
img = cv2.imread("20230927143717.jpg", 0)
oldImg = img.copy()  # 创建1个新对象
gau_shi = cv2.GaussianBlur(oldImg, [3, 3], 0)
canny = cv2.Canny(gau_shi, 50, 150)
show(canny, 'canny')
contours, hierarchy = cv2.findContours(canny, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
for i in range(len(contours)):    # oldImg.copy(),每次运行的时候,会新建一个地址空间。避免内容叠加
    # img = cv2.drawContours(oldImg.copy(), contours, i, (0,0,255), 3)
    # c.show(img,i)    # x, y, w, h = cv2.boundingRect(contours) # 得到矩型 ,不包含旋转矩型
    # img = cv2.rectangle(oldImg, (x, y), (x + w, y + h), (0, 0, 255), 10)
    # c.show(img)

    rect = cv2.minAreaRect(contours)  # 返回回点集cnt的最小外接矩形
    box = cv2.boxPoints(rect)  # 获取最小外接矩形的4个顶点坐标
    box = np.intp(box)
    img2 = cv2.polylines(oldImg.copy(), [box], True, (0, 255, 0), 5)
    show(img2, 'xuanzhuan')
    (x, y), radius = cv2.minEnclosingCircle(contours)  # 得到最小外接圆
    center = (int(x), int(y))

    radius = int(radius)
    img = cv2.circle(img, center, radius, (0, 0, 255), 2)
    show(img, 'yuan')
    """
    (x, y)代表椭圆中心点的位置
         
    (a, b)代表长短轴长度,应注意a、b为长短轴的直径,而非半径
     angle 代表了中心旋转的角度
    """    ellipse = cv2.fitEllipse(contours)  # 得到椭圆
    im = cv2.ellipse(oldImg.copy(), ellipse, (0, 255, 0), 2)
    show(im, 'tuoyuan')
    # 根据一组点拟合出一条直线
    rows, cols = img.shape[:2]
    [vx, vy, x, y] = cv2.fitLine(contours, cv2.DIST_L2, 0, 0.01, 0.01)
    lefty = int((-x * vy / vx) + y)
    righty = int(((cols - x) * vy / vx) + y)
    img = cv2.line(oldImg.copy(), (cols - 1, righty), (0, lefty), (0, 255, 0), 2)
    show(img, 'ff')
获取最小外接圆

import cv2
import numpy as np

# 读取图像
image = cv2.imread('20230927143717.jpg')

# 将图像转换为灰度
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 进行边缘检测
edges = cv2.Canny(gray, 50, 150, apertureSize=3)

# 寻找轮廓
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 遍历每个轮廓
for contour in contours:
    # 获取最小外接圆
    (x, y), radius = cv2.minEnclosingCircle(contour)
    center = (int(x), int(y))
    radius = int(radius)

    # 在原始图像上绘制最小外接圆
    cv2.circle(image, center, radius, (0, 255, 0), 2)

# 显示结果
cv2.imshow('Minimum Enclosing Circle Detection', image)
cv2.waitKey(0)
cv2.destroyAllWindows()


外接圆获取外接椭圆

import cv2

# 读取图像
image = cv2.imread('20230927143717.jpg')

# 将图像转换为灰度
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 进行边缘检测
edges = cv2.Canny(gray, 50, 150, apertureSize=3)

# 寻找轮廓
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 遍历每个轮廓
for contour in contours:
    # 拟合外接椭圆
    ellipse = cv2.fitEllipse(contour)

    # 在原始图像上绘制椭圆
    cv2.ellipse(image, ellipse, (0, 255, 0), 2)

# 显示结果
cv2.imshow('Fitted Ellipses', image)
cv2.waitKey(0)
cv2.destroyAllWindows()
获取最小外接椭圆

import cv2

# 读取图像
image = cv2.imread('20230927143717.jpg')

# 将图像转换为灰度
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 进行边缘检测
edges = cv2.Canny(gray, 50, 150, apertureSize=3)

# 寻找轮廓
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 遍历每个轮廓
for contour in contours:
    # 拟合外接椭圆
    ellipse = cv2.fitEllipse(contour)

    # 在原始图像上绘制椭圆
    cv2.ellipse(image, ellipse, (0, 255, 0), 2)

# 显示结果
cv2.imshow('Fitted Ellipses', image)
cv2.waitKey(0)
cv2.destroyAllWindows()


image.png求平均颜色或者灰度

import cv2

# 读取图像
image = cv2.imread('20230927143717.jpg')

# 将图像转换为灰度
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 计算灰度平均值
average_value = cv2.mean(gray)[0]

# 打印平均值
print(f"灰度平均值: {average_value}")
获取极点

leftmost = tuple(cnt[cnt[:,:,0].argmin()][0])
rightmost = tuple(cnt[cnt[:,:,0].argmax()][0])
topmost = tuple(cnt[cnt[:,:,1].argmin()][0])
bottommost = tuple(cnt[cnt[:,:,1].argmax()][0])

用于找到轮廓 (cnt) 的最左边点 (leftmost)、最右边点 (rightmost)、最上边点 (topmost) 和最下边点 (bottommost)。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册哦

x
您需要登录后才可以回帖 登录 | 注册哦

本版积分规则