OpenCV与AI深度学习 | 实战 | 使用OpenCV确定对象的方向(附源码)

本文来源公众号“OpenCV与AI深度学习”,仅用于学术分享,侵权删,干货满满。

原文链接:实战 | 使用OpenCV确定对象的方向(附源码)

导读

本文将介绍如何使用OpenCV确定对象的方向(即旋转角度,以度为单位)。 

1 先决条件

    安装Python3.7或者更高版本。可以参考下文链接:

    https://automaticaddison.com/how-to-set-up-anaconda-for-windows-10/

    或者自行下载安装:https://www.python.org/getit/

2 相关包安装与设置

    在我们开始之前,让我们确保我们已经安装了所有的软件包。检查您的机器上是否安装了OpenCV 。如果你使用 Anaconda,你可以输入:

conda install -c conda-forge opencv

或者使用pip安装,指令:

pip install opencv-python

安装科学计算库 Numpy:

pip install numpy

3 准备测试图像

    找一张图片。我的输入图像宽度为 1200 像素,高度为 900 像素。我的输入图像的文件名是input_img.jpg。

4 编写代码

    这是代码。它接受一个名为input_img.jpg的图像并输出一个名为output_img.jpg的带注释的图像。部分代码来自官方 OpenCV 实现:

https://docs.opencv.org/4.x/d1/dee/tutorial_introduction_to_pca.html

代码示例:


import cv2 as cv
from math import atan2, cos, sin, sqrt, pi
import numpy as npdef drawAxis(img, p_, q_, color, scale):p = list(p_)q = list(q_)## [visualization1]angle = atan2(p[1] - q[1], p[0] - q[0]) # angle in radianshypotenuse = sqrt((p[1] - q[1]) * (p[1] - q[1]) + (p[0] - q[0]) * (p[0] - q[0]))# Here we lengthen the arrow by a factor of scaleq[0] = p[0] - scale * hypotenuse * cos(angle)q[1] = p[1] - scale * hypotenuse * sin(angle)cv.line(img, (int(p[0]), int(p[1])), (int(q[0]), int(q[1])), color, 3, cv.LINE_AA)# create the arrow hooksp[0] = q[0] + 9 * cos(angle + pi / 4)p[1] = q[1] + 9 * sin(angle + pi / 4)cv.line(img, (int(p[0]), int(p[1])), (int(q[0]), int(q[1])), color, 3, cv.LINE_AA)p[0] = q[0] + 9 * cos(angle - pi / 4)p[1] = q[1] + 9 * sin(angle - pi / 4)cv.line(img, (int(p[0]), int(p[1])), (int(q[0]), int(q[1])), color, 3, cv.LINE_AA)## [visualization1]def getOrientation(pts, img):## [pca]# Construct a buffer used by the pca analysissz = len(pts)data_pts = np.empty((sz, 2), dtype=np.float64)for i in range(data_pts.shape[0]):data_pts[i,0] = pts[i,0,0]data_pts[i,1] = pts[i,0,1]# Perform PCA analysismean = np.empty((0))mean, eigenvectors, eigenvalues = cv.PCACompute2(data_pts, mean)# Store the center of the objectcntr = (int(mean[0,0]), int(mean[0,1]))## [pca]## [visualization]# Draw the principal componentscv.circle(img, cntr, 3, (255, 0, 255), 2)p1 = (cntr[0] + 0.02 * eigenvectors[0,0] * eigenvalues[0,0], cntr[1] + 0.02 * eigenvectors[0,1] * eigenvalues[0,0])p2 = (cntr[0] - 0.02 * eigenvectors[1,0] * eigenvalues[1,0], cntr[1] - 0.02 * eigenvectors[1,1] * eigenvalues[1,0])drawAxis(img, cntr, p1, (255, 255, 0), 1)drawAxis(img, cntr, p2, (0, 0, 255), 5)angle = atan2(eigenvectors[0,1], eigenvectors[0,0]) # orientation in radians## [visualization]# Label with the rotation anglelabel = "  Rotation Angle: " + str(-int(np.rad2deg(angle)) - 90) + " degrees"textbox = cv.rectangle(img, (cntr[0], cntr[1]-25), (cntr[0] + 250, cntr[1] + 10), (255,255,255), -1)cv.putText(img, label, (cntr[0], cntr[1]), cv.FONT_HERSHEY_SIMPLEX, 0.5, (0,0,0), 1, cv.LINE_AA)return angle# Load the image
img = cv.imread("input_img.jpg")# Was the image there?
if img is None:print("Error: File not found")exit(0)cv.imshow('Input Image', img)# Convert image to grayscale
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)# Convert image to binary
_, bw = cv.threshold(gray, 50, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)# Find all the contours in the thresholded image
contours, _ = cv.findContours(bw, cv.RETR_LIST, cv.CHAIN_APPROX_NONE)for i, c in enumerate(contours):# Calculate the area of each contourarea = cv.contourArea(c)# Ignore contours that are too small or too largeif area < 3700 or 100000 < area:continue# Draw each contour only for visualisation purposescv.drawContours(img, contours, i, (0, 0, 255), 2)# Find the orientation of each shapegetOrientation(c, img)cv.imshow('Output Image', img)
cv.waitKey(0)
cv.destroyAllWindows()# Save the output image to the current directory
cv.imwrite("output_img.jpg", img)

5 运行结果

    使用PCA(主成分分析)方法获取物体的主方向,效果如下:

了解旋转轴

    每个对象的正 x 轴是红线。每个对象的正 y 轴是蓝线。 

    全局正x 轴从左到右水平穿过图像。全局正z 轴指向此页外。全局正y 轴从图像底部垂直指向图像顶部。

    使用右手定则测量旋转,将四根手指伸直(食指到小指)沿全局正 x 轴方向伸出。

    然后将四根手指逆时针旋转 90 度。您的指尖指向正 y 轴,而您的拇指指向页面外指向正 z 轴。

计算0~180°之间的方向

    如果我们要计算对象的方向并确保结果始终在 0 到 180 度之间,我们可以使用以下代码:


# This programs calculates the orientation of an object.
# The input is an image, and the output is an annotated image
# with the angle of otientation for each object (0 to 180 degrees)import cv2 as cv
from math import atan2, cos, sin, sqrt, pi
import numpy as np# Load the image
img = cv.imread("input_img.jpg")# Was the image there?
if img is None:print("Error: File not found")exit(0)cv.imshow('Input Image', img)# Convert image to grayscale
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)# Convert image to binary
_, bw = cv.threshold(gray, 50, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)# Find all the contours in the thresholded image
contours, _ = cv.findContours(bw, cv.RETR_LIST, cv.CHAIN_APPROX_NONE)for i, c in enumerate(contours):# Calculate the area of each contourarea = cv.contourArea(c)# Ignore contours that are too small or too largeif area < 3700 or 100000 < area:continue# cv.minAreaRect returns:# (center(x, y), (width, height), angle of rotation) = cv2.minAreaRect(c)rect = cv.minAreaRect(c)box = cv.boxPoints(rect)box = np.int0(box)# Retrieve the key parameters of the rotated bounding boxcenter = (int(rect[0][0]),int(rect[0][1])) width = int(rect[1][0])height = int(rect[1][1])angle = int(rect[2])if width < height:angle = 90 - angleelse:angle = -anglelabel = "  Rotation Angle: " + str(angle) + " degrees"textbox = cv.rectangle(img, (center[0]-35, center[1]-25), (center[0] + 295, center[1] + 10), (255,255,255), -1)cv.putText(img, label, (center[0]-50, center[1]), cv.FONT_HERSHEY_SIMPLEX, 0.7, (0,0,0), 1, cv.LINE_AA)cv.drawContours(img,[box],0,(0,0,255),2)cv.imshow('Output Image', img)
cv.waitKey(0)
cv.destroyAllWindows()# Save the output image to the current directory
cv.imwrite("min_area_rec_output.jpg", img)

最终输出结果:

参考链接:https://automaticaddison.com/how-to-determine-the-orientation-of-an-object-using-opencv/

THE END!

文章结束,感谢阅读。您的点赞,收藏,评论是我继续更新的动力。大家有推荐的公众号可以评论区留言,共同学习,一起进步。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据库入门-----SQL基础知识

目录 &#x1f4d6;前言&#xff1a; &#x1f4d1;SQL概述&&通用语法&#xff1a; &#x1f433;DDL&#xff1a; &#x1f43b;操作数据库&#xff1a; &#x1f41e;数据类型&#xff1a; &#x1f989;操作表&#xff1a; &#x1f9a6;DML: 语法规则&#x…

xgo: golang基于-toolexec实现猴子补丁

注&#xff1a; 转载请注明出处&#xff0c; 原文链接。 概述 在这篇博客中&#xff0c;我将详细介绍 xgo 的实现细节。 如果你不知道&#xff0c;xgo 项目位于 https://github.com/xhd2015/xgo。 它的作用很简单&#xff0c;就是在每个 Go 函数的开头添加拦截器&#xff0…

吴恩达深度学习 (week1,2)

文章目录 1、神经网络监督学习2、深度学习兴起原因3、深度学习二元分类4、深度学习Logistic 回归5、Logistic 回归损失函数6、深度学习梯度下降法7、深度学习向量法8、Python 中的广播9、上述学习总结10、大作业实现:rocket::rocket:&#xff08;1&#xff09;训练初始数据&…

Android 关于apk反编译d2j-dex2jar classes.dex失败的几种方法

目录 确认路径正确直接定位到指定目录确定目录正确&#xff0c;按如下路径修改下面是未找到相关文件正确操作 确认路径正确 &#xff0c;即d2j-dex2jar和classes.dex是否都在一个文件夹里&#xff08;大部分的情况都是路径不正确&#xff09; 直接定位到指定目录 路径正确的…

2024年32款数据分析工具分五大类总览

数据分析工具在现代商业和科学中扮演着不可或缺的角色&#xff0c;为组织和个人提供了深入洞察和明智决策的能力。这些工具不仅能够处理大规模的数据集&#xff0c;还能通过强大的分析和可视化功能揭示隐藏在数据背后的模式和趋势。数据分析工具软件主要可以划分为以下五个类别…

2024年抖音小店还有机会吗?多年小店商家,带来最新判断!

大家好&#xff0c;我是电商糖果 糖果做电商有7年时间了&#xff0c;从2020年开始做抖音小店&#xff0c;现在已经经营了多家小店。 关于抖音小店的热度这几年一直居高不下&#xff0c;说实话几乎每天都有不少朋友找糖果咨询&#xff0c;2024年抖音小店还有机会吗&#xff1f…

JS 表单验证

点击注册的时候&#xff0c;渲染出来&#xff0c;验证码是自动获取出来的 html&#xff1a; <div class"div1">用户名<input type"text" id"yhm"><span id"span1"></span><br>密码<input type"…

一起学习python——基础篇(10)

前言&#xff0c;Python 是一种面向对象的编程语言。以前大学读书的时候经常开玩笑说的一句话“如果没有对象&#xff0c;就new一个”。起因就是编程老师上课时经常说一句“首先&#xff0c;我们new一个对象”。 今天讲一下python的类和对象。 类是什么&#xff1f;它是一种用…

外包干了25天,技术退步明显.......

先说一下自己的情况&#xff0c;大专生&#xff0c;18年通过校招进入杭州某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落! 而我已经在一个企业干了四年的功能测…

【运输层】TCP 的可靠传输是如何实现的?

目录 1、发送和接收窗口&#xff08;滑动窗口&#xff09; &#xff08;1&#xff09;滑动窗口的工作流程 &#xff08;2&#xff09;滑动窗口和缓存的关系 &#xff08;3&#xff09;滑动窗口的注意事项 2、如何选择超时重传时间 &#xff08;1&#xff09;加权平均往返…

爬虫 BeautifulSoup模块

爬虫 BeautifulSoup模块 【一】介绍 【1】说明 BeautifulSoup库是python的一个第三方库&#xff0c;主要用于处理HTML和XML文档他提供了一些简单的、python式的函数来解析、导航、搜索以及修改分析树&#xff0c;使得从网页抓取的数据变得简单高效BeautifulSoup自动将输入文…

ctfshow web入门 命令执行 web53--web77

web53 日常查看文件 怎么回事不让我看十八 弄了半天发现并不是很对劲&#xff0c;原来我发现他会先回显我输入的命令再进行命令的回显 ?cnl${IFS}flag.php||web54 绕过了很多东西 基本上没有什么命令可以用了但是 grep和?通配符还可以用 ?cgrep${IFS}ctfshow${IFS}???…

BFS宽度优先搜索例题(蓝桥杯)——逃跑的牛

问题描述&#xff1a; 农夫John的一头牛逃跑了&#xff0c;他想要将逃跑的牛找回来。现假设农夫John和牛的位置都在一条直线上&#xff0c;农夫John的初始位置为N&#xff08;0≤N≤100,000&#xff09;&#xff0c;牛的初始位置为K&#xff08;0≤K≤100,000&#xff09;。农夫…

R语言数据操纵:常用函数

目录 处理循环的函数 lapply函数 apply函数 mapply函数 tapply函数 split函数 排序的函数 sort函数与order函数 总结数据信息的函数 head函数与tail函数 summary函数 str函数 table函数 any函数 all函数 xtab函数 object.size函数 这篇文章主要介绍R语言中处理…

APP测试面试题详解

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号【互联网杂货铺】&#xff0c;回复 1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、基础篇 1、请介绍一下&#xff0c;APP测试流程&#xff1f…

【算法统治世界】动态规划 个人笔记总结

&#x1f389;&#x1f389;欢迎光临&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;特别推荐给大家我的最新专栏《数据结构与算法&#xff1a;初学者入门指南》&#x1f4d8;&am…

分布式主键ID生成策略

业务系统对分布式ID的要求 唯一性&#xff1a;在分布式系统中&#xff0c;每个节点都需要生成唯一的标识符来确保数据的唯一性。传统的单点生成ID方式无法满足分布式环境下的需求&#xff0c;而分布式ID能够在整个系统中保证每个节点生成的ID都是唯一的。 顺序性&#xff1a;某…

CSS设置网页颜色

目录 前言&#xff1a; 1.颜色名字&#xff1a; 2.十六进制码&#xff1a; 3.RGB&#xff1a; 4.RGBA&#xff1a; 5.HSL&#xff1a; 1.hue&#xff1a; 2.saturation&#xff1a; 3.lightness&#xff1a; 6.HSLA&#xff1a; 前言&#xff1a; 我们在电脑显示器&…

Linux 多线程

目录 初识线程 线程的概念 Linux下的线程 线程优缺点 线程控制 线程创建 线程终止 线程等待 线程分离 线程取消 其它 线程互斥 互斥的概念 互斥锁的使用 锁的本质 线程同步 线程同步的概念 条件变量的概念 条件变量的使用 信号量 信号量的概念 信号量接口…

007 CSS的继承和层叠 元素特性

文章目录 CSS属性的继承CSS属性的层叠选择器的权重 HTML元素的类型编写HTML注意事项元素隐藏方法CSS属性-overflowCSS样式不生效可能原因 CSS属性的继承 如果一个属性具备继承性&#xff0c;那么在该元素上设置后&#xff0c;它的后代元素都可以继承这个属性 如果后代元素自己…