opencv轮廓处理功能

人工智能 2025-04-17 10:07:38
import cv2 as cv
import numpy as np


class ContourProcessing:
    def __init__(self, image_path):
        self.image_path = image_path
        self.img = cv.imread(self.image_path)
        if self.img is None:
            raise FileNotFoundError(f"无法读取图像文件: {self.image_path}")
        self.imgray = cv.cvtColor(self.img, cv.COLOR_BGR2GRAY)

    def draw_contours(self):
        """
        绘制图像的轮廓
        """
        ret, thresh = cv.threshold(self.imgray, 127, 255, 0)
        contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)

        # 绘制所有轮廓
        cv.drawContours(self.img, contours, -1, (0, 255, 0), 3)
        # 绘制索引为3的轮廓
        cv.drawContours(self.img, contours, 3, (0, 255, 0), 3)
        # 绘制索引为4的轮廓
        cnt = contours[4]
        cv.drawContours(self.img, [cnt], 0, (0, 255, 0), 3)

        cv.imshow('Contours', self.img)
        cv.waitKey(0)
        cv.destroyAllWindows()

    def contour_features(self):
        """
        计算并显示轮廓的特征
        """
        img_gray = cv.imread(self.image_path, 0)
        ret, thresh = cv.threshold(img_gray, 127, 255, 0)
        contours, hierarchy = cv.findContours(thresh, 1, 2)
        cnt = contours[0]

        # 特征矩
        M = cv.moments(cnt)
        if M['m00'] != 0:
            cx = int(M['m10'] / M['m00'])
            cy = int(M['m01'] / M['m00'])
        else:
            cx, cy = 0, 0

        # 轮廓面积
        area = cv.contourArea(cnt)
        # 轮廓周长
        perimeter = cv.arcLength(cnt, True)
        # 轮廓近似
        epsilon = 0.1 * cv.arcLength(cnt, True)
        approx = cv.approxPolyDP(cnt, epsilon, True)
        # 轮廓凸包
        hull = cv.convexHull(cnt)
        # 检查凸度
        k = cv.isContourConvex(cnt)

        # 边界矩形(直角矩形)
        x, y, w, h = cv.boundingRect(cnt)
        cv.rectangle(img_gray, (x, y), (x + w, y + h), (0, 255, 0), 2)

        # 最小闭合圈
        (x, y), radius = cv.minEnclosingCircle(cnt)
        center = (int(x), int(y))
        radius = int(radius)
        cv.circle(img_gray, center, radius, (0, 255, 0), 2)

        # 拟合一个椭圆
        ellipse = cv.fitEllipse(cnt)
        cv.ellipse(img_gray, ellipse, (0, 255, 0), 2)

        print(f"质心: ({cx}, {cy})")
        print(f"轮廓面积: {area}")
        print(f"轮廓周长: {perimeter}")
        print(f"轮廓近似: {approx}")
        print(f"轮廓凸包: {hull}")
        print(f"凸度: {k}")

        cv.imshow('Contour Features', img_gray)
        cv.waitKey(0)
        cv.destroyAllWindows()

    def contour_properties(self):
        """
        计算并显示轮廓的属性
        """
        img_gray = cv.imread(self.image_path, 0)
        ret, thresh = cv.threshold(img_gray, 127, 255, 0)
        contours, hierarchy = cv.findContours(thresh, 1, 2)
        cnt = contours[0]

        # 长宽比
        x, y, w, h = cv.boundingRect(cnt)
        if h != 0:
            aspect_ratio = float(w) / h
        else:
            aspect_ratio = 0

        # 范围
        area = cv.contourArea(cnt)
        rect_area = w * h
        if rect_area != 0:
            extent = float(area) / rect_area
        else:
            extent = 0

        # 坚实度
        hull = cv.convexHull(cnt)
        hull_area = cv.contourArea(hull)
        if hull_area != 0:
            solidity = float(area) / hull_area
        else:
            solidity = 0

        # 等效直径
        if area != 0:
            equi_diameter = np.sqrt(4 * area / np.pi)
        else:
            equi_diameter = 0

        # 取向
        (x, y), (MA, ma), angle = cv.fitEllipse(cnt)

        # 极端点
        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])

        print(f"长宽比: {aspect_ratio}")
        print(f"范围: {extent}")
        print(f"坚实度: {solidity}")
        print(f"等效直径: {equi_diameter}")
        print(f"取向: 中心({x}, {y}), 长轴 {MA}, 短轴 {ma}, 角度 {angle}")
        print(f"极端点: 最左 {leftmost}, 最右 {rightmost}, 最上 {topmost}, 最下 {bottommost}")

    def convexity_defects(self):
        """
        检测并显示轮廓的凸性缺陷
        """
        img = cv.imread(self.image_path)
        img_gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
        ret, thresh = cv.threshold(img_gray, 127, 255, 0)
        contours, hierarchy = cv.findContours(thresh, 2, 1)
        cnt = contours[0]
        hull = cv.convexHull(cnt, returnPoints=False)
        defects = cv.convexityDefects(cnt, hull)

        if defects is not None:
            for i in range(defects.shape[0]):
                s, e, f, d = defects[i, 0]
                start = tuple(cnt[s][0])
                end = tuple(cnt[e][0])
                far = tuple(cnt[f][0])
                cv.line(img, start, end, [0, 255, 0], 2)
                cv.circle(img, far, 5, [0, 0, 255], -1)

        cv.imshow('Convexity Defects', img)
        cv.waitKey(0)
        cv.destroyAllWindows()

    def point_polygon_test(self, point=(50, 50)):
        """
        进行点多边形测试
        """
        img_gray = cv.imread(self.image_path, 0)
        ret, thresh = cv.threshold(img_gray, 127, 255, 0)
        contours, hierarchy = cv.findContours(thresh, 1, 2)
        cnt = contours[0]
        dist = cv.pointPolygonTest(cnt, point, True)
        print(f"点 {point} 到多边形的距离: {dist}")

    def shape_matching(self, other_image_path):
        """
        进行形状匹配
        """
        img1 = cv.imread(self.image_path, 0)
        img2 = cv.imread(other_image_path, 0)

        if img1 is None or img2 is None:
            raise FileNotFoundError("无法读取图像文件")

        ret, thresh = cv.threshold(img1, 127, 255, 0)
        ret, thresh2 = cv.threshold(img2, 127, 255, 0)

        contours, hierarchy = cv.findContours(thresh, 2, 1)
        cnt1 = contours[0]
        contours, hierarchy = cv.findContours(thresh2, 2, 1)
        cnt2 = contours[0]

        ret = cv.matchShapes(cnt1, cnt2, 1, 0.0)
        print(f"形状匹配结果: {ret}")
...全文
99 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

4

社区成员

发帖
与我相关
我的任务
社区描述
学习交流人工智能相关算法及技术栈
opencv计算机视觉人工智能 技术论坛(原bbs) 广东省·深圳市
社区管理员
  • 亿只小灿灿
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧