基于OpenCV测量角的度数

你好啊

 

今天我来分享一个测量角度的小程序

首先你需要准备一个学习角度的练习题,应该是小学的那种课后习题作为图片即可。

这是我找的图片

基于OpenCV测量角的度数_第1张图片

第一步很简单,就是读出图片:

import cv2
import  math

path  = 'text.jpg'
img = cv2.imread(path)
cv2.imshow('Image',img),
cv2.waitKey(0)

我们要利用鼠标来定点,定三个点,这样就可以求角的大小了。那么我们利用函数setMouseCallback():


 void setMousecallback(const string& winname, MouseCallback onMouse, void* userdata=0)
    winname:窗口的名字
    onMouse:鼠标响应函数,回调函数。指定窗口里每次鼠标时间发生的时候,被调用的函数指针。 这个函 
            数的原型应该为void mousePoints(int event, int x, int y, int flags, void* param);
    userdate:传给回调函数的参数

再来介绍MouseCallback mousePoints的函数原型:

void mousePoints(int event, int x, int y, int flags, void* param);
event是 CV_EVENT_*变量之一
x和y是鼠标指针在图像坐标系的坐标(不是窗口坐标系) 
flags是CV_EVENT_FLAG的组合, param是用户定义的传递到setMouseCallback函数调用的参数。

利用该函数我们可以得到的鼠标点击左键时候的坐标,常用的event自己用到可以去百度:

import cv2
import  math

path  = 'text.jpg'
img = cv2.imread(path)

def mousePoints(event,x,y,flags,params):
    if event == cv2.EVENT_LBUTTONDOWN:
        print(x,y)


cv2.imshow('Image',img)
cv2.setMouseCallback('Image',mousePoints)
cv2.waitKey(0)

基于OpenCV测量角的度数_第2张图片

 坐标就可打印出来了。那么接下来我们开始存储三个点的坐标即可:

import cv2
import  math

path  = 'text.jpg'
img = cv2.imread(path)
pointsList = []

def mousePoints(event,x,y,flags,params):
    if event == cv2.EVENT_LBUTTONDOWN:
        cv2.circle(img,(x,y),5,(0,255,125),cv2.FILLED)#对选择的点的位置进行标记
        pointsList.append([x,y])#添加坐标
        print(pointsList)
        print(x,y)

while True:
    cv2.imshow('Image',img)
    cv2.setMouseCallback('Image',mousePoints)
    if cv2.waitKey(1) & 0xFF == ord('q'):#当输入Q的时候,可以清除存储的坐标
        pointsList = []
        img = cv2.imread(path)

基于OpenCV测量角的度数_第3张图片接下来完备求解角度的算法,首先是计算角度的公式

 其中A,B为直线斜率,所以还要求两条直线的斜率:

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)
    angR = math.atan((m2-m1)/(1+(m2*m1)))
    angD = round(math.degrees(angR))#将弧度转化成角度,并且以整数输出
    print(angD)

基于OpenCV测量角的度数_第4张图片

 可能有点误差,因为直线的粗细,点的位置等等都有影响。

最后在完善一下程序,首先添加一个画线的动作,在加上度数的显示:

import cv2
import  math

path  = 'text.jpg'
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,225),2)
        #画点
        cv2.circle(img,(x,y),5,(0,255,125),cv2.FILLED)
        pointsList.append([x,y])
        #print(pointsList)
        #print(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)
    angR = math.atan((m2-m1)/(1+(m2*m1)))
    angD = round(math.degrees(angR))#将弧度转化成角度,并且以整数输出
    cv2.putText(img,str(angD),(pt1[0]-40,pt1[1]-20),cv2.FONT_HERSHEY_DUPLEX,2,(255,0,0),2)


while True:

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


    cv2.imshow('Image',img)
    cv2.setMouseCallback('Image',mousePoints)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        pointsList = []
        img = cv2.imread(path)

基于OpenCV测量角的度数_第5张图片

 ok,下一个小项目再见吧。

你可能感兴趣的:(opencv实战小项目,opencv,计算机视觉,python)