python cv2 绘制不规则形状的最小外接矩形、最大内接矩形、最大内接圆、最小外接圆、拟合椭圆_python最小外接矩形-程序员宅基地

技术标签: python  canvas  cv  计算机视觉  最小内接矩阵  opencv  

目录

一、最小外接矩形

二、最大内接矩形

三、最大内接圆

四、最小外接圆

五、拟合椭圆


一、最小外接矩形

这里的图片是mask,类似于这样的:

绘制如上图片的最小外接矩阵:

def draw_min_rect_rectangle(mask_path):
    image = cv2.imread(mask_path)

    thresh = cv2.Canny(image, 128, 256)

    contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    img = np.copy(image)

    for cnt in contours:
        x, y, w, h = cv2.boundingRect(cnt)
        # 绘制矩形
        cv2.rectangle(img,  (x, y+h), (x+w, y), (0, 255, 255))

绘制结果:

也可以将矩形区域作成新的mask:

    # 将最小内接矩形填充为白色
    white = [255, 255, 255]
    for col in range(x, x+w):
        for row in range(y, y+h):
            image[row, col] = white

那么我们的最小内接矩阵mask就绘制好了:

也可以通过x,y,w,h对图片进行切割:

    pic = cv2.imread(original_img_path) # 读取mask对应的图片
    cut = pic[y:y+h, x:x+w]   # 根据内接矩形的顶点切割图片
    cv2.imwrite(save_path, cut) # 保存切割好的图片

也可以通过最小内接矩形mask来进行切割:

    rectangle_mask_gray = cv2.cvtColor(rectangle_mask, cv2.COLOR_RGB2GRAY) # 此处的image是我们之前获取的最小内接矩形的mask
    pic = cv2.imread(original_img_path)  # 读取mask对应的图像
    out = cv2.bitwise_and(pic, pic, mask=rectangle_mask) # 根据mask切割
    cv2.imshow("min rect rectangle mask cut img", out)

效果如下:

二、最大内接矩形

def maximum_internal_rectangle(mask_path):
    img = cv2.imread(mask_path)
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    ret, img_bin = cv2.threshold(img_gray, 0, 255, cv2.THRESH_BINARY)

    contours, _ = cv2.findContours(img_bin, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)

    contour = contours[0].reshape(len(contours[0]), 2)

    rect = []

    for i in range(len(contour)):
        x1, y1 = contour[i]
        for j in range(len(contour)):
            x2, y2 = contour[j]
            area = abs(y2 - y1) * abs(x2 - x1)
            rect.append(((x1, y1), (x2, y2), area))

    all_rect = sorted(rect, key=lambda x: x[2], reverse=True)

    if all_rect:
        best_rect_found = False
        index_rect = 0
        nb_rect = len(all_rect)

        while not best_rect_found and index_rect < nb_rect:

            rect = all_rect[index_rect]
            (x1, y1) = rect[0]
            (x2, y2) = rect[1]

            valid_rect = True

            x = min(x1, x2)
            while x < max(x1, x2) + 1 and valid_rect:
                if any(img[y1, x]) == 0 or any(img[y2, x]) == 0:
                    valid_rect = False
                x += 1

            y = min(y1, y2)
            while y < max(y1, y2) + 1 and valid_rect:
                if any(img[y, x1]) == 0 or any(img[y, x2]) == 0:
                    valid_rect = False
                y += 1

            if valid_rect:
                best_rect_found = True

            index_rect += 1

        if best_rect_found:
            # 如果要在灰度图img_gray上画矩形,请用黑色画(0,0,0)
            cv2.rectangle(img, (x1, y1), (x2, y2), (255, 0, 0), 1)
            cv2.imshow("rec", img)
            cv2.waitKey(0)

        else:
            print("No rectangle fitting into the area")

    else:
        print("No rectangle found")

三、最大内接圆

先看效果:

再放代码:

# 读取图片,转灰度
mask = cv2.imread(mask_path)
mask_gray = cv2.cvtColor(mask, cv2.COLOR_BGR2GRAY)

# 识别轮廓
contours, _ = cv2.findContours(mask_gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# 计算到轮廓的距离
raw_dist = np.empty(mask_gray.shape, dtype=np.float32)
for i in range(mask_gray.shape[0]):
    for j in range(mask_gray.shape[1]):
        raw_dist[i, j] = cv2.pointPolygonTest(contours[0], (j, i), True)

# 获取最大值即内接圆半径,中心点坐标
minVal, maxVal, _, maxDistPt = cv2.minMaxLoc(raw_dist)
minVal = abs(minVal)
maxVal = abs(maxVal)

# 画出最大内接圆
result = cv2.cvtColor(mask_gray, cv2.COLOR_GRAY2BGR)
radius = np.int(maxVal)
center_of_circle = maxDistPt
cv2.circle(result, maxDistPt, radius, (0, 255, 0), 2, 1, 0)
cv2.imshow('Maximum inscribed circle', result)
cv2.waitKey(0)

四、最小外接圆

效果:

 代码:

def minimum_external_circle(mask_path):

    img = cv2.imread(mask_path)
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    contours, _ = cv2.findContours(img_gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

    cnt = contours[0]

    (x, y), radius = cv2.minEnclosingCircle(cnt)
    center = (int(x), int(y))  # 最小内接圆圆心
    radius = int(radius)
    cv2.circle(img, center, radius, (0, 255, 0), 2)
    cv2.circle(img, center, 1, (0, 255, 0), 2)
    cv2.imshow('ret', img)

    cv2.waitKey(0)

五、拟合椭圆

效果:

 代码:

def fit_ellipse(mask_path):
    img = cv2.imread(mask_path)
    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    contours, _ = cv2.findContours(img_gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    # 拟合椭圆
    ellipse = cv2.fitEllipse(contours[0])

    cv2.ellipse(img, ellipse, (255, 0, 255), 2)
    ellipse_center = (int(ellipse[0][0]), int(ellipse[0][1]))  # 椭圆圆心坐标
    cv2.circle(img, ellipse_center, 1, (255, 0, 255), 2)
    cv2.imshow('ellipse', img)
    cv2.waitKey(0)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_21420941/article/details/109249528

智能推荐

docker删除重装,以及极其重要的/etc/docker/key.json文件-程序员宅基地

文章浏览阅读8.9k次,点赞2次,收藏2次。先说以下我为何要删除docker的原因吧:因为我感觉Docker Hub有点慢,就配置了阿里云的镜像加速器,可是按阿里云的官方配置完后我怎么感觉它更慢了,对比昨天配置阿里的maven镜像仓库后快到起飞的速度,我认为是此次配置没有生效。多次确认新加入的/etc/docker/demon.json文件无误后又多次systemctl了未果,随即我怀疑阿里给出的以下方案中的“修改”的/etc/dock...

空间物理——概述_空间物理概论-程序员宅基地

文章浏览阅读1.9k次,点赞3次,收藏4次。文章目录空间物理的研究对象太阳风能量向地球传输的三种方式和所需要的时间太阳内部结构、太阳活动太阳内部结构太阳活动太阳风速度从太阳表面到地球轨道附近变化参考空间物理的研究对象大气层:10KM以上,分成平流层、中层、低热层、热层、逃逸层电离层:60-90KM以上,一直到1000KM左右,部分电离气体,中性成风碰撞的影响不可忽略地球磁层:完全电离的气体,1000KM以上,可忽略碰撞,有太阳风和..._空间物理概论

BQ4050学习笔记(二)-程序员宅基地

文章浏览阅读2.9k次,点赞5次,收藏25次。BQ4050学习笔记(二)永久失效:如果发⽣严重故障,该设备可以永久禁⽤电池组。永久故障检查(IFC 和 DFW 除外)可以通过设置Settings:Enabled PFA、 Settings:Enabled PF B、 Settings:Enabled PF C 和Settings:Enabled PF D 中的相应位单独启⽤或禁⽤。所有永久在设置ManufacturingStatus()[PF]之前,故障检查(IFC 和 DFW 除外)被禁⽤。当任何PFStatus()位置位时,器件进⼊ PER_bq4050

SpringCloudAlibaba-Nacos注册中心的使用_spring-cloud-alibaba 使用nacos 2.1版本-程序员宅基地

文章浏览阅读152次。第二步:填写配置文件参数,这里定义了一个名字为application-user-dev.yaml的配置,使用的是YAML格式。DataID : 非常重要,可以看做是配置的文件的名字,在程序中拉取配置文件的时候需要指定Data ID。如果不使用默认的public命名空间,那么需要指定namespace配置为要使用的命名空间的Id值。第一步:打开Nacos监控面板,进入配置列表,新增一个user服务的配置文件。进入配置列表 ,切换到新建立的命名空间,创建配置文件。修改Nacos,添加命名空间。_spring-cloud-alibaba 使用nacos 2.1版本

CVE-2023-21716 Microsoft Word远程代码执行漏洞Poc_cve-2023-21716复现-程序员宅基地

文章浏览阅读293次。受害者打开python代码生成的RTF文件,RTF解析器解析恶意代码,触发堆溢出,Microsoft Word会闪退,用户其它Word中未保存的内容会丢失。_cve-2023-21716复现

c语言程序设计让a变成A,c语言程序设计a期末模拟试题.docx-程序员宅基地

文章浏览阅读451次。文件排版存档编号:[UYTR-OUPT28-KBNTL98-UYNN208]文件排版存档编号:[UYTR-OUPT28-KBNTL98-UYNN208]C语言程序设计A期末模拟试题C语言程序设计A期末模拟试题一一、单项选择题(每小题2分,共20分)由C++目标文件连接而成的可执行文件的缺省扩展名为( )。A. cpp B. exe C. obj D. li..._c语言如何将a转换成a

随便推点

利用beef和msf实现session远程命令_msf如何切换一个session-程序员宅基地

文章浏览阅读534次。笔记beef启动 beef 的方法msfbeef工具目录 /usr/share/beef-xss配置文件 config.yaml启动 beef 的方法1.beef-xss2./usr/share/beef-xss/beef(使用前需要修改默认的用户名称和密码)Web 管理界面 http://127.0.0.1:3000/ui/panelShellcode http://127.0.0.1:3000/hook.js测试页面 http://127.0.0.1:3000/demos/butch_msf如何切换一个session

python判断丑数_丑数问题及变种小结-程序员宅基地

文章浏览阅读503次。丑数问题及变种小结声明1 判断丑数因子只包含2,3,5的数称为丑数(Ugly Number),习惯上把1当作第一个丑数面试lintcode 517 ugly numbersegmentfault剑指offer 面试题34 丑数数组解法:参考剑指offer,将待判断目标依次连续整除2,3,5,若是最后获得1,证实该数为丑数;优化/*** 依次整除2,3,5判断(2,3,5顺序判断时间最优)* htt..._编写python来证明一个数是丑数

python自动化测试实战 —— WebDriver API的使用_python webdriver api-程序员宅基地

文章浏览阅读1.9k次,点赞30次,收藏11次。Selenium 简介: WebDriver是Selenium Tool套件中最重要的组件。Selenium 2.0之后已经将Selenium和WebDriver进行合并,作为一个更简单、简洁、有利于维护的API提供给测试人员使用。 它提供了一套标准的接口,可以用多种编程语言调用,并且和浏览器进行交互。 WebDriver可以对浏览器进行控制,包括输入URL,点击按钮,填写表单,滚动页面,甚至是执行JavaScript代码。同时,它也能够获取网页中的信息,如文本,标签,属_python webdriver api

Nodejs crypto模块公钥加密私钥解密探索_crypto.publicencrypt-程序员宅基地

文章浏览阅读1w次。1.什么是公钥加密私钥解密 简单一点来说一般加密解密都用的是同一个秘钥或者根本不用,而这里采用的是加密用一个秘钥,解密用另一个秘钥且能解密成功.这就属于不对称加密解密算法的一种了.2.公钥秘钥的生成 由于这种加密方案,公钥秘钥是成对的,所以需要一些工具生成 利用 openssl 生成公钥私钥 生成公钥: openssl genrsa -out rsa_private_key...._crypto.publicencrypt

Maven简明教程(5)---依赖关系(实例篇)_依赖关系怎么写-程序员宅基地

文章浏览阅读1.7k次。[工欲善其事,必先利其器]上文中,我们简单介绍了依赖关系的基本理论与配置方式。但是由于这个知识点在我们日后的开发过程中会经常使用到,因此,我们在本篇中通过演示实例来说明依赖关系,请各位看官一定跟着步骤,亲自尝试一番。仔细观察通过这种方式对我们程序架构造成的影响。特别的,这里以一份已经调试完成的工程为例,因此,与前文说的工程命名不一致,敬请谅解。准备工作:a.操作系统:win7 x6_依赖关系怎么写

2017多校联合第五场1006/hdu6090Rikka with Graph(思维公式)-程序员宅基地

文章浏览阅读343次。Rikka with GraphTime Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 592 Accepted Submission(s): 353Problem DescriptionAs we know,