先放结论:

  • 可以学到角度测量的公式。
  • 可以学到如果按下鼠标时,就获取坐标点。

目录

相关库:

导入图片:

定义鼠标事件回调函数:

计算角度:

结果分析,发现原因:

完整代码:


接下来,就愉快地开始讲解这个项目的代码。

相关库:

opencv库需要下载安装,math不用下载安装。

import cv2
import math

导入图片:

非常入门的导入图片。

path = 'test.png'
img = cv2.imread(path)
cv2.imshow('img', img)
cv2.waitKey(0)

定义鼠标事件回调函数:

event == cv2.EVENT_LBUTTONDOWN是用来判断鼠标是否按下:如果按下了,那么就在那个点画一个半径为5的、轮廓颜色为红色、填充了的圆形。

将鼠标按下的位置(x,y)存入pointsList数组里。

由于角度测量,需要确定三个点。因此使用一个循环不停的回调来获取鼠标点击的位置坐标。

pointsList = []# 定义鼠标事件的回调函数
def mousePoints(event,x,y,flags,params):if event == cv2.EVENT_LBUTTONDOWN:cv2.circle(img,(x,y),5,(0,0,255),cv2.FILLED)pointsList.append([x,y])while True:cv2.imshow('img', img)# 调用回调函数:cv2.setMouseCallback('img', mousePoints)# 如果按下键盘上的q键,就会清空img窗口上的涂鸦,同时清空pointsList数组if cv2.waitKey(1) & 0xFF == ord('q'):pointsList = []img = cv2.imread(path)# 如果按下键盘上的esc键,那就关闭退出循环,关闭窗口if cv2.waitKey(1) & 0xFF == 27:break

结果:

但是咱们需要三个点,而且将这三个点画成两条线的样子组成一个角;

或者再画出三个点,这三个点连成新的两条线组成新角。以此类推。

这将如何操作?

咱们在鼠标回调函数里面加入一些东西,改成了以下的形式:

def mousePoints(event,x,y,flags,params):if event == cv2.EVENT_LBUTTONDOWN:size = len(pointsList)if size != 0 and size % 3 != 0:cv2.line(img, tuple(pointsList[round((size-1)/3)*3]), (x, y), (0, 0, 255), 2)cv2.circle(img,(x,y),5,(0,0,255),cv2.FILLED)pointsList.append([x,y])

size存放了数组的长度。

使用cv2.line函数进行画线的操作是需要确定起点和终点的位置坐标。数学上,角是由两条射线组成;在咱这里,简单的认为是由一个顶点往外延申出了两条线段。鼠标点击的第一个就是顶点,和点击的第二点构成第一条线,和点击的第三点构成第二条线。

不是3的倍数进入判断条件,比如1、2、4、5、7、8......

当点击次数为1、2时,round((size-1)/3)*3,得到的是0;pointsList[0]是第一个角的顶点位置。

当点击次数为4、5时,round((size-1)/3)*3,得到的是3;pointsList[0]是第二个角的顶点位置。

(python里面的索引都是从0开始往后数的)

以此类推,得到起点和终点,然后连成线。

round函数,也不是咱们数学上的四舍五入方法。比如round(0.50)输出是0,round(0.51)输出是1。

应该是大于整数的一半时,结果为那个整数;如果小于或者等于整数的一半时,结果为整数减一。

计算角度:

求两条直线之间的角度,需要使用斜率的方式。在编程里,斜率就是指梯度。但这个公式求出来的夹角是弧度,最后需要用math.degrees()函数转换成以度为单位的。

于是定义一个求梯度的函数:

def gradient(pt1,pt2):return (pt2[1]-pt1[1])/(pt2[0]-pt1[0])

就相当于第一个点的坐标为(x1,y1),第二个点的坐标为(x2,y2),斜率就是(y2-y1)/(x2-x1)。

定义一个求角度的函数:

def getAngle(pointsList):# 将pointsList里面的数组,从右边开始往前三个进行切片# 将pointsList最后的三个坐标给pt1,pt2,pt3pt1, pt2, pt3 = pointsList[-3:]# 计算第一条线段的斜率m1 = gradient(pt1, pt2)# 计算第二条线段的斜率m2 = gradient(pt1, pt3)num = (m2-m1)/(1+(m2*m1))if num>0:num = numelse:num = -numangR = math.atan(num)# math.degrees函数:用于将弧度值转换为对应的角度angD = round(math.degrees(angR))# 将角度值放在顶点旁边的位置cv2.putText(img, str(angD), ((pt1[0]-10),(pt1[1])), cv2.FONT_HERSHEY_SIMPLEX,1.5, (0, 0, 255), 2)print(angD)

最后需要在鼠标每点击三次后就调用计算角度的函数:

if len(pointsList) % 3 == 0 and len(pointsList) !=0:getAngle(pointsList)

结果:

结果分析,发现原因:

钝角的度数不准确。直角也不知道是不是画的原因,导致没有90度。

回归公式,会发现,反三角函数的极限是-90和90,咱用反三角函数进行反解,当然就得不到大于或者等于90度的角了,也就得不到钝角和直角。

完整代码:

import cv2
import mathpath = 'test.png'
img = cv2.imread(path)
pointsList = []# 定义一个函数获取鼠标点,每当按下鼠标时调用此函数
def mousePoints(event,x,y,flags,params):if event == cv2.EVENT_LBUTTONDOWN:size = len(pointsList)if size != 0 and size % 3 != 0:cv2.line(img, tuple(pointsList[round((size-1)/3)*3]), (x, y), (0, 0, 255), 2)cv2.circle(img,(x,y),5,(0,0,255),cv2.FILLED)pointsList.append([x,y])def gradient(pt1,pt2):return (pt2[1]-pt1[1])/(pt2[0]-pt1[0])def getAngle(pointsList):pt1, pt2, pt3 = pointsList[-3:]m1 = gradient(pt1, pt2)m2 = gradient(pt1, pt3)num = (m2-m1)/(1+(m2*m1))if num>0:num = numelse:num = -numangR = math.atan(num)angD = round(math.degrees(angR))cv2.putText(img, str(angD), ((pt1[0]-10),(pt1[1])), cv2.FONT_HERSHEY_SIMPLEX,1.5, (0, 0, 255), 2)print(angD)while True:if len(pointsList) % 3 == 0 and len(pointsList) !=0:getAngle(pointsList)cv2.imshow('img', img)cv2.setMouseCallback('img',mousePoints)if cv2.waitKey(1) & 0xFF == ord('q'):pointsList = []img = cv2.imread(path)if cv2.waitKey(1) & 0xFF == 27:break

opencv实战---角度测量相关推荐

  1. OpenCV实战——角度测量

    角度测量 1. OpenCV鼠标操作基本知识 链接:鼠标操作 对于这个项目而言,知道这么多已经够用了. 2. 获取鼠标点击得到的点坐标 import cv2 import math# 读入带有角度的图 ...

  2. 使用opencv进行角度测量

    这个项目很简单,要做的就是,在两条线之间形成一个角度,因此我们将使用以下方式定义这些线,我们将定义三个不同的点,这三个点将创建两条不同的线,我们测量出这两线之间的角度,第一个点为角度顶点,第二点和第三 ...

  3. OpenCV C++案例实战二十七《角度测量》

    OpenCV C++案例实战二十七<角度测量> 前言 一.鼠标响应事件 1.1功能源码 1.2功能效果 二.计算直线角度 2.1 计算直线斜率 2.2计算直线角度 2.3功能源码 三.绘制 ...

  4. OpenCV学习笔记(六)之轮廓提取与角度测量

      查找图像的轮廓在图像处理及应用中扮演着重要的角色.openCV 中的轮廓指的是由一系列点组成的点的集合,不同的轮廓可以有不同的点集.openCV中,轮廓是由STL风格的vector<> ...

  5. unity 知道2点计算线段选择角度_影像测量仪实战技巧之角度测量

    如何提高角度测量精度,一直以来是二维测量仪器难以攻克的难关.现在市场上流行的二维测量仪器关于角度测量的方法基本有两种,一种是切线法,一种是采点计算法. 切线法是指人工旋转屏幕上或者镜头内刻线,分别对准 ...

  6. OpenCV实战(7)——OpenCV色彩空间转换

    OpenCV实战(7)--OpenCV色彩空间转换 0. 前言 1. RGB 色彩空间 2. 色彩空间转换 2.1 CIE L*a*b* 色彩空间 2.2 其它色彩空间 3. 用色调.饱和度和亮度表示 ...

  7. OpenCV实战系列:高通滤波器及其应用

    OpenCV实战系列:高通滤波器及其应用 0. 前言 1. 检测图像边缘 1.2 Sobel 滤波器 1.2 梯度算子 1.3 高斯导数 2. 图像拉普拉斯算子 2.1 拉普拉斯算子 2.2 使用拉普 ...

  8. Opencv实战 | 用摄像头自动化跟踪特定颜色物体

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自:新机器视觉 1. 导语 在之前的某个教程里,我们探讨了如 ...

  9. Angle Finder(角度测量)

    目录 一 前言 二 实现步骤 1 需要的第三方库 2 读取图像 3 获取鼠标点 (1)打印鼠标点击的位置(演示,不一定要实现) (2)创建列表存储坐标并将点击生成的点绘制出来 4 计算三个点组成的角的 ...

最新文章

  1. WITH AS【原创】
  2. JS中绑定事件顺序(事件冒泡与事件捕获区别)
  3. php代码实现对word文件的查找与替换,ThinkPHP5使用phpword实现文件模板字符替换
  4. 动态规划之最长公共子串
  5. mysql备份和还原
  6. java什么是隐式说明,java中 显式和隐式是怎么回事
  7. 《深入浅出统计学》笔记二--第二章:集中趋势的量度,第三章:分散性与变异性的量度
  8. Canal部署linux mysql同步数据
  9. android 连接魅族手机,关于魅族手机adb连接不上的问题
  10. 学了这么久的高并发编程,连Java中的并发原子类都不知道?这也太Low了吧
  11. 用H5STEAM实现大华摄像头的WEB开发
  12. android psensor测试,MTK camera驱动结构
  13. 【Python计算机视觉】图像到图像的映射(单应性变换、图像扭曲)
  14. openfoam学习心得——openfoam编程进阶
  15. 分析全基因组上的蛋白信息
  16. 【JSTL】JSP 标准标签库JSTL学习
  17. 入门C语言模板,C语言入门经典-C语言编程
  18. 最新苹果开发者账号注册申请流程最强详解!
  19. 围绕边框宽度的html,设置围绕表格的边框宽度的HTML代码是?
  20. HEXO启动,初始化,本地页面成功启动,(Win 7 64 bit)可以在浏览器打开http://localhost:4000

热门文章

  1. 构建之法——团队第一次作业
  2. 第 2 章 马尔可夫决策过程
  3. 达人评测 i9 13900H 和i7 12700h差多少 酷睿i913900H 和i712700h对比
  4. Springboot整合Mybatis generator
  5. 「艾尔斯马克绘」数绘的线稿,用马克笔如何上色呢?
  6. 代码随想录之路经总和
  7. 纪宁罗峰鸿蒙秦羽,你们说楚阳霍雨浩唐三萧炎林动姬动纪宁罗峰秦羽龙皓晨打起来谁赢...
  8. IT行业 经验···
  9. Echarts 报错 Uncaught Error: Invalid geoJson format coordinate.charCodeAt is not a function
  10. [转载]Android相关开发网站