使用opencv截取旋转框目标

news2024/11/18 5:36:57

使用opencv截取旋转框目标

  • 1、第一种方法
  • 2、第二种方法
  • 3、两种方法的简单对比
  • 4、opencv 最小面积矩形返回角度的理解
    • 4.1、version4.2之前
    • 4.1、version4.2之后

本文列举了两种方法,使用的数据如图,用的是改版rolabelimg标注的

在这里插入图片描述
标注文件有四个点的坐标:
在这里插入图片描述

1、第一种方法

总体思路是,找最小面积矩形,接着旋转,最后crop

import cv2
import numpy as np
import matplotlib.pyplot as plt


def crop_rect(img, rect):
    # get the parameter of the small rectangle
    center, size, angle = rect[0], rect[1], rect[2]
    center, size = tuple(map(int, center)), tuple(map(int, size))

    # get row and col num in img
    height, width = img.shape[0], img.shape[1]

    # calculate the rotation matrix
    M = cv2.getRotationMatrix2D(center, angle, 1)
    # rotate the original image
    img_rot = cv2.warpAffine(img, M, (width, height))

    # now rotated rectangle becomes vertical, and we crop it
    img_crop = cv2.getRectSubPix(img_rot, size, center)

    return img_crop, img_rot

cnts = []
labels=[]
with open('rodog.txt') as f:
    lines = f.read().strip().splitlines()
for line in lines:
    data = line.split()
    cnt=list(map(int,data[:8]))
    label=data[8]
    cnts.append(cnt)
    labels.append(label)

num=len(cnts)
plt.figure(figsize=(15,num*5))
for i,cnt in enumerate(cnts):
    img = cv2.imread("rodog.jpeg")
    cnt = np.reshape(cnt,[4,2])
    # print("cnt:",cnt)
    # find the exact rectangle enclosing the text area
    # rect is a tuple consisting of 3 elements: the first element is the center
    # of the rectangle, the second element is the width, height, and the
    # third element is the detected rotation angle.
    # Example output: ((227.5, 187.50003051757812),
    # (94.57575225830078, 417.98736572265625), -36.982906341552734)
    rect = cv2.minAreaRect(cnt)
    print("rect: {}".format(rect))
    
    # the order of the box points: bottom left, top left, top right,
    box = cv2.boxPoints(rect)
    box = np.int0(box)
    print("box:",box)
    
    # print("bounding box: {}".format(box))
    cv2.drawContours(img, [box], 0, (255, 0, 0), 2)
    # img_crop will the cropped rectangle, img_rot is the rotated image
    img_crop, img_rot = crop_rect(img, rect)
    plt.subplot(num,3,1+i*3)
    plt.imshow(img)
    plt.title('orig')
    plt.subplot(num,3,2+i*3)
    plt.imshow(img_rot)
    plt.title('rotate')
    plt.subplot(num,3,3+i*3)
    plt.imshow(img_crop)
    plt.title('crop')
    # cv2.imwrite(f"orig_img_{i}.jpg", img)
    # cv2.imwrite(f"rotate_img_{i}.jpg", img_rot)
    # cv2.imwrite(f"cropped_img_{i}.jpg", img_crop)

    # cv2.waitKey(0)
rect: ((370.5, 164.50001525878906), (140.75865173339844, 306.3152160644531), 43.54475784301758)
box: [[213 227]
 [425   5]
 [527 101]
 [316 324]]
rect: ((266.9999694824219, 53.499996185302734), (38.984642028808594, 44.95772933959961), 24.22774314880371)
box: [[239  65]
 [258  25]
 [293  41]
 [275  81]]
rect: ((277.5, 132.0), (533.65625, 161.2079315185547), 11.457330703735352)
box: [[  0 157]
 [ 32   0]
 [555 106]
 [523 264]]

显示是用的bgr图,没转rgb

在这里插入图片描述
这种方法目前还没有遇到问题,如果遇到问题,可能需要在原图上做pad,相应的标签文件也做好修改再进行处理

2、第二种方法

思路是先找最小矩形,接着透视变换得到目标图。

import cv2
import numpy as np
import matplotlib.pyplot as plt


cnts = []
labels=[]
with open('rodog.txt') as f:
    lines = f.read().strip().splitlines()
for line in lines:
    data = line.split()
    cnt=list(map(int,data[:8]))
    label=data[8]
    cnts.append(cnt)
    labels.append(label)


num=len(cnts)
plt.figure(figsize=(10,num*5))
for i,cnt in enumerate(cnts):
    img = cv2.imread("rodog.jpeg")
    cnt = np.reshape(cnt,[4,2])
    # print("cnt:",cnt)
    # find the exact rectangle enclosing the text area
    # rect is a tuple consisting of 3 elements: the first element is the center
    # of the rectangle, the second element is the width, height, and the
    # third element is the detected rotation angle.
    # Example output: ((227.5, 187.50003051757812),
    # (94.57575225830078, 417.98736572265625), -36.982906341552734)
    rect = cv2.minAreaRect(cnt)
    # print("rect: {}".format(rect))


    # the order of the box points: bottom left, top left, top right,
    # bottom right
    box = cv2.boxPoints(rect)
    box = np.int0(box)
    # print('box:',box)

    # print("bounding box: {}".format(box))
    cv2.drawContours(img, [box], 0, (0, 255, 0), 2)

    # get width and height of the detected rectangle
    width = int(rect[1][0])
    height = int(rect[1][1])
    # print("width,height:",width,height)
    src_pts = box.astype("float32")
    # coordinate of the points in box points after the rectangle has been
    # straightened
    dst_pts = np.array([[0, height-1],
                        [0, 0],
                        [width-1, 0],
                        [width-1, height-1]
                        ], dtype="float32")

    # the perspective transformation matrix
    M = cv2.getPerspectiveTransform(src_pts, dst_pts)

    # directly warp the rotated rectangle to get the straightened rectangle
    warped = cv2.warpPerspective(img, M, (width, height))

    # cv2.imwrite("crop_img.jpg", warped)
    # cv2.waitKey(0)
    plt.subplot(num,2,1+i*2)
    plt.imshow(img)
    plt.title('orig')
    plt.subplot(num,2,2+i*2)
    plt.imshow(warped)
    plt.title('crop')

在这里插入图片描述

3、两种方法的简单对比

img_crop.shape
(161, 533, 3)
warped.shape
(161, 533, 3)

两种方式看效果是一样的,图像尺寸也一样,但要对比像素值,还是不一样,如下代码,绝对误差大于20有4.56%

try:
    np.testing.assert_allclose(img_crop,warped,atol=20)
except Exception as e:
    print(e)
Not equal to tolerance rtol=1e-07, atol=20

Mismatched elements: 11739 / 257439 (4.56%)
Max absolute difference: 255
Max relative difference: 255.
 x: array([[[255,   0,   0],
        [255,   0,   0],
        [237,  15,  18],...
 y: array([[[  0, 255,   0],
        [  0, 255,   0],
        [  0, 255,   0],...

4、opencv 最小面积矩形返回角度的理解

center, size, angle=cv2.minAreaRect(points)

points就是一系的(x,y)的点,center,size,angle分别是最小矩形的中心点,宽高,及angle。对于opencv的这个角度的理解,这里简单写一些,实际是与opencv版本有关,以opencv4.2为分界

4.1、version4.2之前

https://blog.csdn.net/weixin_43229348/article/details/125986969 (https://theailearner.com/tag/cv2-minarearect/) 参考这个博客就好,一句话说,就是x轴逆时针转,接触到的第一条边就是宽边w(不在意长短),转的过程就是角度从0到-90 ,不包括0。
那么最小面积矩形的四个点及顺序是啥,用以下代码获取:

rect = CV2.minAreaRect(cnt)
box = cv2.boxPoints(rect)

box就是四个点的坐标,我们会用这四个点做旋转或透视变换都是需要的。那么顺序是什么呢?
在这里插入图片描述
可以理解为x轴与w边相交,箭头反方向的点为起点,接着顺时针。

4.1、version4.2之后

x轴顺时针转,接触到的第一条边就是宽边w(不在意长短),转的过程就是角度从0到90 ,不包括0。x轴也与4.2之前的相反。
点顺序如下:
在这里插入图片描述
可以理解为x轴与w边相交,箭头同方向的点为起点,接着顺时针。

本文另一篇参考文章:https://jdhao.github.io/2019/02/23/crop_rotated_rectangle_opencv/#fn:2

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/70315.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

mybatis详述

文章目录一、引言1.1 什么是框架?1.2 什么是ORM框架?1.3使用JDBC完成ORM操作的缺点?二、MyBatis框架2.1概念2.2 MyBatis开发步骤2.3 如何编写mybatis映射文件(规范)三、mybatis-config.xml 配置补充四、mybatis接口与映射文件指令间 传递参数4.1 传递…

安卓APP源码和设计报告——北京旅游系统

目 录 一、概述11 1.1 课题描述11 1.2 需求分析22 1.3 开发环境33 二、系统分析与概要设计55 2.1 系统功能分析55 2.2 系统模块结构图66 2.3 数据库表的设计66 三、北京旅游系统的登录功能模块的详细设计88 3.1 登录模块的功能描述88 3.2 登录模块的界面布局的设计9…

185: vue+openlayers 引用hover插件,展示各种鼠标cursor样式

第185个 点击查看专栏目录 本示例的目的是介绍演示如何在vue+openlayers中使用hover效果,这里是引用了一个hover插件。鼠标对应到相应的feature中时候,获取其类型,并且设定不同的鼠标样式。 直接复制下面的 vue+openlayers源代码,操作2分钟即可运行实现效果; 注意如果Ope…

一篇知晓-内存竟被”无意“破坏,真相究竟如何?

内存是C/C程序员的好帮手,我们通常说C/C程序性能更高其原因之一就在于可以自己来管理内存,然而计算机科学中没有任何一项技术可以包治百病,内存问题也给C/C程序员带来无尽的烦恼。 野指针、数组越界、错误的内存分配或者释放、多线程读写导致…

kotlin之hello world

如果你想一个人写全栈的话,Kotlin Multiplatform (以下简称MPP)是目前这个星球上最好的选择,没有之一。 Kotlin 是一种在 Java 虚拟机上运行的静态类型编程语言,被称之为 Android 世界的Swift,由 JetBrain…

CTFSHOW web入门 java反序列化篇(更新中)

在做这部分题前,推荐大家先去学习下java反序列化,尤其是CC链 可以看下两个系列视频,收获颇多 https://space.bilibili.com/2142877265/channel/collectiondetail?sid29805&ctype0 https://www.bilibili.com/video/BV16h411z7o9/?spm_i…

手写Spring2(实现 Bean 的定义、注册、获取)

文章目录前言本章目标一、实现1、项目结构2、BeanFactory-bean工厂3、BeanDefinition -bean定义4、单例注册接口定义和实现-SingletonBeanRegistry 、DefaultSingletonBeanRegistry5、AbstractBeanFactory-抽象bean工厂类(定义模板方法)6、AbstractAutowireCapableBeanFactory-…

python配置环境问题记录------2022/12/07

python配置问题记录1、版本匹配的问题2、指令安装相关依赖包3、pycharm指定解释器4、运行网络模块5、总结1、版本匹配的问题 到官网下载合适的版本(注意位数,我这里选的是64位),pycharm选的是21年版本的,太新的话会有…

【C++】异常exception

目录 一.C语言错误处理方式 1.assert(断言) 2.返回/设置错误码 二.C异常的概念与使用 1.异常的概念 2.异常的使用 三.自定义异常体系MyException 四.异常的重新抛出 五.异常安全问题 六.异常规范 七.异常的优缺点对比 一.C语言错误处理方式 一个C语言程序, 在运行期…

回归分析与相关分析的区别和联系

在本节中,我们将首先讨论相关性分析,它用于量化两个连续变量之间的关联(例如,独立变量与因变量之间或两个独立变量之间)。 最近我们被客户要求撰写关于回归分析与相关分析的研究报告,包括一些图形和统计输…

软件测试经验与教训

下面精选出10条,和大家分享。 01 测试人员是项目的前灯 一个项目就像是一次陆上旅行。有些项目很简单、很平常,就像是大白天开车去商店买东西。但是大多数值得开发的项目更像是夜间在山里开越野卡车,这些项目需要前灯,而测试员要照…

直播带货行业如何入局?先了解一下直播商城源码吧

直播行业的爆火已经持续了多个年头,直到今天,在人们的生活中依然有着举足轻重的地位,它通过多元化的方案为许多行业带来了新的思路,特别是与传统商业所结合的“直播电商”、“直播商城”的卖货新形式,让多方因此而受益…

数理化解题研究杂志社数理化解题研究编辑部2022年第30期目录

教学改革探索 信息技术下中职数学“翻转课堂”教学创新策略研究 李宇仙; 2-4《数理化解题研究》投稿:cn7kantougao163.com 基于高中数学核心素养的错题讲评课之探索与实践 施浩妹; 17-20 高中数学“问题导学”模式的实践研究 吴金桥; 21-23 立于神而…

【测试沉思录】21. 如何用 JMeter 编写性能测试脚本?

作者:宋赟 编辑:毕小烦 Apache JMeter 应该是应用最广泛的性能测试工具。怎么用 JMeter 编写性能测试脚本? 1. 编写 HTTP 性能测试脚本 STEP 1. 添加 HTTP 请求 STEP 2. 了解配置信息 HTTP 请求各项信息说明(以 JMeter 5.1 为例…

【强化学习论文合集】十.2018智能体和多智能体系统国际联合会议论文(AAMAS2018)

强化学习(Reinforcement Learning, RL),又称再励学习、评价学习或增强学习,是机器学习的范式和方法论之一,用于描述和解决智能体(agent)在与环境的交互过程中通过学习策略以达成回报最大化或实现特定目标的问题。 本专栏整理了近几年国际顶级会议中,涉及强化学习(Rein…

十四、SpringBoot-自动装配原理

十四、SpringBoot-自动装配原理 SpringBoot与Spring比较起来,优化的点主要有: 自动配置:是一个运行时(应用程序启动时)的过程,考虑了众多因素,才决定Spring配置应该用哪个,不该用哪…

软件测试基础丨测试工程师之间要善于发现闪光点——测试理念篇

测试理念有多种,有一些理念,深藏于我的心中, 而这些理念,您或许偶尔想到,却没有说出,或许您感受到了,却因为工作生活的忙碌,没有将其背后的含义想具体, 在此我非常愿意和…

零基础小白hadoop分布式集群环境搭建(超详细)

搭建集群所需要安装包 虚拟机、ubuntu镜像文件、jdk安装包、hadoop安装包 百度云盘地址: 链接:https://pan.baidu.com/s/1ejVamlrlyoWtJRo1QQqlsA提取码:fcqm 本文的环境是两台windows笔记本,在每台笔记本上安装一个虚拟机&…

超详细的水果FL Studio21最新版更新全功能详细介绍!80项更新与改进!

万众期待的 FL Studio 21 版本将于正式发布上线,目前在紧锣密鼓的安排上线中,届时所有购买正版 FL Studio 的用户,都可以免费升级到21版!按照惯例,本次新版也会增加全新插件,来帮助大家更好地创作。今天先给…

SMART原则介绍

一、SMART原则简介 什么是SMART原则? SMART原则(S=Specific、M=Measurable、A=Attainable、R=Relevant、T=Time-bound)是为了利于员工更加明确高效地工作,更是为了管理者将来对员工实施绩效考核提供了考核目标和考核标准,使考核更加科学化、规范化,更能保证考核的公正、…