文章目录
- 前言
- 一、鼠标点击的角度测量
- 二、二维码条形码识别
前言
一、鼠标点击的角度测量
首先导入一个带有角度的照片
然后下面的代码注册了一个鼠标按下的回调函数,
还有一个点的数列,鼠标事件为按下的时候就记录点,并画出点,由于点是画在图像上面的,那么就要求了img是需要刷新的所以将他们放在while True里面
当有按键按下的的时候就把图片归为原来的以及清除列表的值。
按键的使用可以看这个文章
简述
cv2.waitKey(1)在有按键按下的时候返回按键的ASCII值,否则返回-1
& 0xFF的按位与操作只取cv2.waitKey(1)返回值最后八位,因为有些系统cv2.waitKey(1)的返回值不止八位
ord(‘q’)表示q的ASCII值
总体效果:按下q键后break
import cv2
import math
img = cv2.imread('jiaodu.png')
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])
print(pointslist)
while True:
cv2.imshow('image',img)
cv2.setMouseCallback('image',mousepoints)
keycc = cv2.waitKey(1) & 0xFF
if keycc == ord('q'):
pointslist = []
img = cv2.imread('jiaodu.png')
if keycc == ord('c'):
exit()
当在图像上点击的时候有红点,当按下q的时候清除,当按下c的时候退出
接着我们要做的就是每点击一下就会出现三角的边,我们用size来做判断,当取余后值为2的时候就说明要画一个直线,当按下第三个点的时候要是第二条直线,那么就elif size % 3 == 0 and size != 0:
就可以得到啦
还是用了tuple()
函数因为 cv2.line 需要点的坐标作为元组,所以我们使用 tuple 函数将列表转换为元组。
使用到了画线函数cv2.line
可以参考这篇文章
简述:
cv2.line(img, pt1, pt2, color[, thickness[, lineType[, shift]]]) → img
img,背景图
pt1,直线起点坐标
pt2,直线终点坐标
color,当前绘画的颜色。如在BGR模式下,传递(255,0,0)表示蓝色画笔。灰度图下,只需要传递亮度值即可。
thickness,画笔的粗细,线宽。若是-1表示画封闭图像,如填充的圆。默认值是1.
lineType,线条的类型,
如8-connected类型、anti-aliased线条(反锯齿),默认情况下是8-connected样式ide,cv2.LINE_AA表示反锯齿线条,在曲线的时候视觉效果更佳。
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])
size = len(pointslist)
if size % 3 == 2:
cv2.line(img, tuple(pointslist[-2]), tuple(pointslist[-1]), (255, 0, 0), 2)
# 当添加第三个点时,使用第一个点和第三个点绘制线
elif size % 3 == 0 and size != 0:
cv2.line(img, tuple(pointslist[-3]), tuple(pointslist[-1]), (255, 0, 0), 2)
print(pointslist)
现在我们还需要计算出,直接使用math中的函数,不过,我们需要由梯度来求,具体公式百度,最终的代码:
import cv2
import math
img = cv2.imread('jiaodu.png')
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])
size = len(pointslist)
if size % 3 == 2:
cv2.line(img, tuple(pointslist[-2]), tuple(pointslist[-1]), (255, 0, 0), 2)
# 当添加第三个点时,使用第一个点和第三个点绘制线
elif size % 3 == 0 and size != 0:
cv2.line(img, tuple(pointslist[-3]), tuple(pointslist[-1]), (255, 0, 0), 2)
print(pointslist)
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+(m1 * m2)))
angd = round(math.degrees(angr))
cv2.putText(img,str(angd),(pt1[0]-40,pt1[1]),cv2.FONT_HERSHEY_SIMPLEX,1,(255,0,0),1)
print(angd)
while True:
if len(pointslist) % 3 == 0 and len(pointslist) != 0:
getAngle(pointslist)
cv2.imshow('image',img)
cv2.setMouseCallback('image',mousepoints)
keycc = cv2.waitKey(1) & 0xFF
if keycc == ord('q') or keycc == ord('Q') :
pointslist = []
img = cv2.imread('jiaodu.png')
if keycc == ord('c') or keycc == ord('C') :
exit()
二、二维码条形码识别
需要安装库numpy
和pyzbar
numpy是anaconda自带的,我们在终端输入 pip install pyzbar
就可以进行下载了。
我们首先有一张有二维码的图片
import cv2
import numpy as np
from pyzbar.pyzbar import decode
img = cv2.imread('qr.png')
code = decode(img)
print(code)
我们可以读取到图片中二维码的信息
[Decoded(data=b’111111’, type=‘QRCODE’, rect=Rect(left=182, top=381,
width=163, height=164), polygon=[Point(x=182, y=381), Point(x=182, y=545), Point(x=345, y=545), Point(x=345, y=381)], quality=1, orie ntation=‘UP’)]
其中data就是我们要的数据,而polygon是边框点
我们只打印出二维码的数据信息
import cv2
import numpy as np
from pyzbar.pyzbar import decode
img = cv2.imread('qr.png')
for barcode in decode(img):
print(barcode.data)
其中的b是编码
import cv2
import numpy as np
from pyzbar.pyzbar import decode
img = cv2.imread('qr.png')
for barcode in decode(img):
mydata = barcode.data.decode('utf-8')
print(mydata)
这样就可以只得到数据信息。
现在我们调用摄像头cv2.VideoCapture(0)
还需要在二维码周围画框cv2.polylines
,在周围显示 cv2.putText
二维码的数据。
NumPy 和 OpenCV 的用法。
np.array():
NumPy 的 array 函数用于创建一个数组。在这里,barcode.polygon
被转换成一个 NumPy 数组。
[barcode.polygon]:
这个语法是创建一个包含barcode.polygon
的列表。这在创建二维或者更高维度的数组时是常见的做法。
np.int32:
这是一个参数,指定了新创建的数组的数据类型应该是 32 位整数。在图像处理中,像素的坐标通常是整数。
pts:
这是一个变量,用于保存新创建的数组。
所以,pts = np.array([barcode.polygon], np.int32)
这句话的作用是创建一个新的NumPy
数组,数组的元素来自barcode.polygon
,并且这个数组的数据类型是 32 位整数。这通常用于处理图像,比如 OpenCV 的多边形(如轮廓等)。
import cv2
import numpy as np
from pyzbar.pyzbar import decode
cap = cv2.VideoCapture(0)
while True:
success,img = cap.read()
# img = cv2.imread('qr.png')
for barcode in decode(img):
mydata = barcode.data.decode('utf-8')
print(mydata)
pts = np.array([barcode.polygon],np.int32)
pts = pts.reshape((-1,1,2))
cv2.polylines(img,[pts],True,(255,0,255),5)
pts2 = barcode.rect
cv2.putText(img,mydata,(pts2[0],pts2[1]),cv2.FONT_HERSHEY_SIMPLEX,0.9,(255,0,255),2)
cv2.imshow('result',img)
keycc = cv2.waitKey(1)
if keycc == ord('c') or keycc == ord('C') :
exit()