采用Python OpenCV检测图形

需求

        根据图片中图形的形状,得出对应的用户群体,比如长方形对应严肃的年长人群,圆形对应活泼的少女人群。

步骤

  1. 获取图片的灰度,使用高斯模糊Canny算子检测对图片进行滤波
  2. 获取图形的轮廓顶点
  3. 根据图形的顶点数目周长面积比,进行分类
  4. 基于第3点,返回对应的人群数组

代码

# -*- coding: utf-8 -*-

import cv2
import numpy as np
# import sys


# 定义形状检测函数
def ShapeDetection(img, imgContour):
    # 寻找轮廓点
    # cv2.RETR_EXTERNAL只检测最外围轮廓
    contours, hierarchy = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    # 总面积
    all_area = 0
    return_value_list = []
    for obj in contours:
        # 计算轮廓内区域的面积
        contour_area = cv2.contourArea(obj)
        all_area += contour_area
    for obj in contours:
        # 绘制轮廓线
        cv2.drawContours(imgContour, obj, -1, (255, 0, 0), 4)
        # 计算轮廓周长
        perimeter = cv2.arcLength(obj, True)
        # print(perimeter)
        # 计算轮廓内区域的面积
        contour_area = cv2.contourArea(obj)
        # 面积占比
        area_proportion = contour_area / all_area
        area_proportion = round(area_proportion, 2)
        # print(contour_area)
        # 计算周长面积比
        if contour_area != 0:
            perimeter_area = perimeter / contour_area
            # print(perimeter_area)
        # 获取轮廓角点坐标
        approx = cv2.approxPolyDP(obj, 0.02*perimeter, True)
        # 轮廓角点的数量
        CornerNum = len(approx)
        # 获取坐标值和宽度、高度
        x, y, w, h = cv2.boundingRect(approx)

        # 三角形
        objType = "None"
        return_value = 0
        if CornerNum == 3:
            objType = "triangle" + str(CornerNum)
            return_value = 1
        # 矩形
        elif CornerNum == 4:
            # 正方形
            if w == h:
                objType = "Square" + str(CornerNum)
                return_value = 2
            # 非正方形的矩形
            else:
                objType = "Rectangle" + str(CornerNum)
                return_value = 3
        elif CornerNum == 5:
            # 五边形
            objType = "5" + str(CornerNum)
            return_value = 4
        elif CornerNum == 6:
            # 六边形
            objType = "6" + str(CornerNum)
            return_value = 5
        elif CornerNum == 7:
            # 七边形
            objType = "7" + str(CornerNum)
            return_value = 6
        # 8个顶点的情况:圆角三角形
        elif CornerNum == 8:
            # 椭圆形
            if 0.015 < perimeter_area < 0.019:
                objType = "Ellipse long" + str(CornerNum)
                return_value = 7
            # 圆角三角形
            if 0.049 < perimeter_area < 0.050:
                objType = "triangle" + str(CornerNum)
                return_value = 1
        elif CornerNum > 8:
            # 圆
            if w == h:
                objType = "Circle" + str(CornerNum)
                return_value = 8
            else:
                objType = "Curved edge graphics" + str(CornerNum)
                return_value = 0
        else:
            objType = "Curved edge graphics" + str(CornerNum)
            return_value = 0
        return_value_list.append([return_value, area_proportion])

    return_people = [30, 31, 32, 33, 34]
    if len(contours) > 1:
        # 遍历图形分类和面积
        # 各种面积
        # 0 曲面图形
        curved_edge_area_sum = 0
        # 1 三角图形
        triangle_area_sum = 0
        # 2 正方形
        square_area_sum = 0
        # 3 长方形
        rectangle_area_sum = 0
        pentagon_area_sum = 0
        hexagon_area_sum = 0
        heptagon_area_sum = 0
        ellipse_area_sum = 0
        circle_area_sum = 0

        for index in return_value_list:
            if index[0] == 0:
                curved_edge_area_sum += index[1]
            elif index[0] == 1:
                triangle_area_sum += index[1]
            elif index[0] == 2:
                square_area_sum += index[1]
            elif index[0] == 3:
                rectangle_area_sum += index[1]
            elif index[0] == 4:
                pentagon_area_sum += index[1]
            elif index[0] == 5:
                hexagon_area_sum += index[1]
            elif index[0] == 6:
                heptagon_area_sum += index[1]
            elif index[0] == 7:
                ellipse_area_sum += index[1]
            elif index[0] == 8:
                circle_area_sum += index[1]
            else:
                pass
        sum456 = pentagon_area_sum + hexagon_area_sum + heptagon_area_sum
        # if rectangle_area_sum > 0 and square_area_sum >= triangle_area_sum >= rectangle_area_sum:
        if square_area_sum >= triangle_area_sum >= rectangle_area_sum:
            return_people = [0]
        # if rectangle_area_sum == 0 and triangle_area_sum > 0 and square_area_sum >= triangle_area_sum:
        if rectangle_area_sum == 0 and square_area_sum >= triangle_area_sum:
            return_people = [1, 4]
        # if circle_area_sum == 0 and sum456 > 0 and rectangle_area_sum >= sum456:
        if circle_area_sum == 0 and rectangle_area_sum >= sum456:
            return_people = [10, 11, 14]
        # if circle_area_sum > 0 and rectangle_area_sum >= sum456 >= circle_area_sum:
        if rectangle_area_sum >= sum456 >= circle_area_sum:
            return_people = [12, 13]
        # if ellipse_area_sum == 0 and triangle_area_sum > 0 and sum456 > circle_area_sum > triangle_area_sum:
        if ellipse_area_sum == 0 and sum456 > circle_area_sum > triangle_area_sum:
            return_people = [20]
        # if ellipse_area_sum > 0 and sum456 > circle_area_sum > ellipse_area_sum:
        if sum456 > circle_area_sum > ellipse_area_sum:
            return_people = [21, 22, 23]
        # if ellipse_area_sum > 0 and sum456 > curved_edge_area_sum > ellipse_area_sum:
        if sum456 > curved_edge_area_sum > ellipse_area_sum:
            return_people = [24]
        # if ellipse_area_sum > 0 and sum456 == 0 and circle_area_sum >= ellipse_area_sum:
        if sum456 == 0 and circle_area_sum >= ellipse_area_sum:
            return_people = [30, 31, 32, 33, 34]
        if sum456 == 0 and curved_edge_area_sum >= ellipse_area_sum:
            return_people = [40, 41, 42, 43, 44]
    else:
        if return_value_list[0][0] == 1 or return_value_list[0][0] == 2:
            return_people = [10, 11, 12, 13, 14]
        elif return_value_list[0][0] == 3:
            return_people = [20, 21, 22, 23, 24]
        elif return_value_list[0][0] == 4 or return_value_list[0][0] == 5 or return_value_list[0][0] == 6:
            return_people = [30, 31, 32, 33, 34]
        elif return_value_list[0][0] == 8:
            return_people = [30, 31, 32, 33, 34]
        elif return_value_list[0][0] == 0:
            return_people = [40, 41, 42, 43, 44]
        elif return_value_list[0][0] == 7:
            return_people = [30, 31, 32, 33, 34, 40, 41, 42, 43, 44]
        else:
            return_people = [30, 31, 32, 33, 34]
    return return_people

    # return return_value_list
        # 显示
        # print(CornerNum)
        # objType += str(perimeter) + " " + str(contour_area) # + "  " + str(perimeter_area)
        # 绘制边界框
        # cv2.rectangle(imgContour, (x, y), (x+w, y+h), (0, 0, 255), 2)
        # 绘制文字
        # cv2.putText(imgContour, objType, (x+(w//2), y + (h//2)), cv2.FONT_HERSHEY_COMPLEX, 0.6, (0, 0, 0), 1)


# 主函数
def contour_calculator_main(filepath):
    # 读取图片
    img = cv2.imread(filepath)
    imgContour = img.copy()
    # 转灰度图
    imgGray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
    # 高斯模糊
    imgBlur = cv2.GaussianBlur(imgGray, (5, 5), 1)
    # Canny算子边缘检测
    imgCanny = cv2.Canny(imgBlur, 60, 60)
    # 形状检测
    print(ShapeDetection(imgCanny, imgContour))

    # cv2.imshow("Original img", img)
    # cv2.imshow("imgGray", imgGray)
    # cv2.imshow("imgBlur", imgBlur)
    # cv2.imshow("imgCanny", imgCanny)
    # cv2.imshow("shape Detection", imgContour)
    # cv2.waitKey(0)


# 测试代码
# 测试中文路径:不可行
# any_filepath = 'D:/pic/shop.png'
# 圆角长方体
# any_filepath = 'D:/MyProject/OpenCV2/photo/targetRectangle.jpg'
# any_filepath = 'D:/MyProject/OpenCV2/photo/targetOval.jpg'
# any_filepath = 'D:/MyProject/OpenCV2/photo/targetIncludeWord.jpg'
# any_filepath = 'D:/MyProject/OpenCV2/photo/targetInregular.png'
# any_filepath = 'D:/MyProject/OpenCV2/photo/target01.png'
any_filepath = 'D:/Projects/PersonalProjects/ShapeDetection/photo/target02.jpg'
contour_calculator_main(any_filepath)


# 主函数
# if __name__ == '__main__':
#     any_filepath = sys.argv[1]
#     contour_calculator_main(any_filepath)


# 自动识别几何轮廓,把圆识别
# 圆角的长方形
# 拟合曲线,滤波
# 识别图形的关节角度
# 找图形之间的阈值


# 2022年9月27日
# 可以识别png
# 轮廓太浅,边界颜色太浅无法识别

# 1.识别圆角
# 2.查找比例
# 圆角三角形,8个顶点,周长面积比0.0493567,可以定为0.049-0.050之间
# 长椭圆:6或者8个顶点,周长面积比0.015-0.022


# 分类逻辑:
# 1.单个图形,利用顶点和长宽比进行区分
# 三个顶点:三角形
# 四个顶点:
#     长宽相等:正方形
#     长宽不等: 长方形
# 五个顶点:五边形
# 六个顶点:六边形
# 七个顶点:七边形
# 八个顶点:
#     0.015 < perimeter_area < 0.019:椭圆形
#     0.049 < perimeter_area < 0.050:圆角三角形
# 八个以上顶点:
#     长宽相等:圆形
# 长宽不等:其他图形
# 其余情况:其他图形
#
# 2.多个图形,在1的基础按照面积占比分类。占比顺序与表一致。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
OpenCV-Python实战系列提供了丰富的教程和示例,涵盖了图像处理、图像识别、深度学习等多个方面。其OpenCV-Python实战(10)详细介绍了OpenCV的轮廓检测。\[2\]轮廓检测是一种用于检测图像物体边界的技术。在OpenCV,可以使用cv2.findContours()函数来进行轮廓检测。该函数会返回一个包含所有轮廓的列表。在进行轮廓检测之前,需要先将图像转换为灰度图像,并通过cv2.threshold()函数获取二值图像。\[3\] 在OpenCV,可以通过绘制预定义的形状来进行轮廓检测。例如,可以使用cv2.rectangle()函数绘制矩形,使用cv2.circle()函数绘制圆形。然后,将绘制的形状转换为灰度图像,并应用cv2.threshold()函数获取二值图像。最后,使用cv2.findContours()函数进行轮廓检测。\[3\] 需要注意的是,轮廓检测是一项复杂的任务,需要根据具体的应用场景和需求进行参数调整和算法选择。在实际应用,还可以结合其他图像处理技术和机器学习算法来进一步优化和改进轮廓检测的结果。 #### 引用[.reference_title] - *1* *2* *3* [OpenCV-Python实战(10)——详解 OpenCV 轮廓检测](https://blog.csdn.net/LOVEmy134611/article/details/120865039)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值