opencv 提供了方便的绘图功能,可以方便的绘制直线,矩形,圆,椭圆等几何图形,还可以在指定位置添加文字说明
处理图像时,可能需要与当前正在处理的图像进行交互,提供了鼠标事件,使用户可以通过鼠标与图像交互,鼠标事件可以识别常用的鼠标操作,比如滑动,点击等
还有滚动条提供交互功能,用户可以拖动滚动条在某一个范围内设置特定的值,并将该值用于后续的图像处理中,而且如果设置为二值形式,滚动条还可以作为开关选择器。
我们见过了了绘制直线的函数 cv2.line()、绘制矩形的函数 cv2.rectangle()、绘制圆的函数 cv2.circle()、绘制椭圆的函数 cv2.ellipse()、绘制多边形的函数 cv2.polylines()、在图像内添加文字的函数 cv2.putText()等多种绘图函数。
这些绘图函数有一些共有参数,主要用于设置原图像,颜色,线条属性等。
img = cv2.line( img, pt1, pt2, color[, thickness[, lineType ]])
pt1 pt2 对应线段的起点,终点
img = cv2.rectangle( img, pt1, pt2, color[, thickness[, lineType]] )
pt1, pt2 对应矩阵的顶点,和对角的顶点
img = cv2.circle( img, center, radius, color[, thickness[, lineType]] )
img=cv2.ellipse(img, center, axes, angle, startAngle, endAngle, color[, thickness[, lineType]])
img = cv2.polylines( img, pts, isClosed, color[, thickness[, lineType[, shift]]])
d = 400
img = np.ones((d,d,3),dtype="uint8")*255
pts=np.array([[200,50],[300,200],[200,350],[100,200]], np.int32)
pts=pts.reshape((-1,1,2))
print(pts) # [[[200,50],[300,200],[200,350],[100,200]]] 就变成这样的。直接构造这样的也行就不用再reshape。
# 第 1 个参数为-1, 表明它未设置具体值,它所表示的维度值是通过其他参数值计算得到的
cv2.polylines(img,[pts],False,(0,255,0),8)
cv2.imshow("demo19.6",img)
cv2.waitKey(0)
cv2.destroyAllWindows()
img=cv2.putText(img, text, org, fontFace, fontScale, color[, thickness[, lineType[, bottomLeftOrigin]]])
对触发的鼠标事件做出相应,我们通过创建相应函数 OnMouseAction(event , x, y ,flags, param)
cv2.setMouseCallback(winname,onMouse)
这个函数将函数和窗口绑定。def Demo(event,x,y,flags,param): # 触发对应事件就发送对应标识
if event == cv2.EVENT_LBUTTONDOWN:
print("单击了鼠标左键")
elif event==cv2.EVENT_RBUTTONDOWN :
print("单击了鼠标右键")
elif flags==cv2.EVENT_FLAG_LBUTTON:
print("按住左键拖动了鼠标")
elif event==cv2.EVENT_MBUTTONDOWN :
print("单击了中间键")
img = np.ones((300,300,3),np.uint8)*255
cv2.namedWindow('Demo19.9')
cv2.setMouseCallback('Demo19.9',Demo) # 实现绑定
cv2.imshow('Demo19.9',img)
cv2.waitKey()
cv2.destroyAllWindows() # 在出现的窗口中操作
单击了鼠标左键
按住左键拖动了鼠标
单击了鼠标右键
单击了鼠标左键
按住左键拖动了鼠标
按住左键拖动了鼠标
d = 400
def draw(event,x,y,flags,param):
if event==cv2.EVENT_LBUTTONDBLCLK: # 双击左键绘制一个随机矩形
p1x=x
p1y=y
p2x=np.random.randint(1,d-50) # 随机对角点
p2y=np.random.randint(1,d-50)
color = np.random.randint(0,high = 256,size = (3,)).tolist()
cv2.rectangle(img,(p1x,p1y),(p2x,p2y),color,2) # 坐标是 (y,x)or(x,y)无所谓了
img = np.ones((d,d,3),dtype="uint8")*255
cv2.namedWindow('Demo19.10')
cv2.setMouseCallback('Demo19.10',draw)
while(1):
cv2.imshow('Demo19.10',img)
if cv2.waitKey(20)==27: # ESC键
break
cv2.destroyAllWindows()
thickness=-1
mode=1
d=400
def draw_circle(event,x,y,flags,param):
if event==cv2.EVENT_LBUTTONDOWN: # 按下左键
a=np.random.randint(1,d-50)
r=np.random.randint(1,d/5)
angle = np.random.randint(0,361)
color = np.random.randint(0,high = 256,size = (3,)).tolist()
if mode==1:
cv2.rectangle(img,(x,y),(a,a),color,thickness) # 矩形
elif mode==2:
cv2.circle(img,(x,y),r,color,thickness) # 圆
elif mode==3:
cv2.line(img,(a,a),(x,y),color,3) # 线
elif mode==4: # 椭圆
cv2.ellipse(img, (x,y), (100,150), angle, 0, 360,color,thickness)
elif mode==5: # 文字
cv2.putText(img,'OpenCV',(0,round(d/2)), cv2.FONT_HERSHEY_SIMPLEX, 2,color,5)
img=np.ones((d,d,3),np.uint8)*255
cv2.namedWindow('image')
cv2.setMouseCallback('image',draw_circle)
while(1):
cv2.imshow('image',img)
k=cv2.waitKey(1)
if k==ord('r'): # 按键检测
mode=1
elif k==ord('c'):
mode=2
elif k==ord('l'):
mode=3
elif k==ord('e'):
mode=4
elif k==ord('t'):
mode=5
elif k==ord('f'): # 挺好玩的,,,
thickness=-1
elif k==ord('u'):
thickness=3
elif k==27:
break
cv2.destroyAllWindows()
依附于特定的窗口而存在,通过调节滚到条可以设置,获取指定范围内的特定值
cv2.createTrackbar(trackbarname, winname, value, count, onChange)
retval=getTrackbarPos( trackbarname,winname )
获取滚动条返回的值,参数是滚动条名和依附窗口名
通过RGB 各通道的值混合设计一个调色板,三个滚动条分别设置 RGB 的值。
def changeColor(x):
r=cv2.getTrackbarPos('R','image')
g=cv2.getTrackbarPos('G','image')
b=cv2.getTrackbarPos('B','image') # 读取滚动条的值,修改img
img[:]=[b,g,r]
img=np.zeros((100,700,3),np.uint8)
cv2.namedWindow('image')
cv2.createTrackbar('R','image',0,255,changeColor)
cv2.createTrackbar('G','image',0,255,changeColor)
cv2.createTrackbar('B','image',0,255,changeColor)
while(1):
cv2.imshow('image',img)
k=cv2.waitKey(1)
if k==27:
break
cv2.destroyAllWindows()
Type=0 # 阈值处理方式
Value=0 # 使用的阈值
# retval, dst=cv2.threshold(src, thresh, maxval, type)
def onType(a):
Type= cv2.getTrackbarPos(tType, windowName)
Value= cv2.getTrackbarPos(tValue, windowName)
ret, dst = cv2.threshold(o, Value,255, Type)
cv2.imshow(windowName,dst)
def onValue(a):
Type= cv2.getTrackbarPos(tType, windowName)
Value= cv2.getTrackbarPos(tValue, windowName)
ret, dst = cv2.threshold(o, Value, 255, Type)
cv2.imshow(windowName,dst)
o = cv2.imread("5.jpg",0)
windowName = "Demo19.13" #窗体名
cv2.namedWindow(windowName)
cv2.imshow(windowName,o)
tType = "Type" # 用来选取阈值处理方式的滚动条
tValue = "Value" # 用来选取阈值的滚动条
cv2.createTrackbar(tType, windowName, 0, 4, onType)
cv2.createTrackbar(tValue, windowName,0, 255, onValue)
print(1)
if cv2.waitKey(0) == 27: # 这里应该是等待按键所以停在了 waitKey() 这。。
cv2.destroyAllWindows()
这是滚动条只有两种值,0和1,出来逻辑关系,0,1也可以标识任意两种不同的状态
d=400
global thickness # 好久没见过全局变量了。。。
thickness=-1
def fill(x):
pass
def draw(event,x,y,flags,param):
if event==cv2.EVENT_LBUTTONDBLCLK: # 还是那个绘制矩形的
p1x=x
p1y=y
p2x=np.random.randint(1,d-50)
p2y=np.random.randint(1,d-50)
color = np.random.randint(0,high = 256,size = (3,)).tolist()
cv2.rectangle(img,(p1x,p1y),(p2x,p2y),color,thickness)
img=np.ones((d,d,3),np.uint8)*255
cv2.namedWindow('image')
cv2.setMouseCallback('image',draw)
cv2.createTrackbar('R','image',0,1,fill)
while(1):
cv2.imshow('image',img)
k=cv2.waitKey(1)
g=cv2.getTrackbarPos('R','image') # 用滚动条决定绘制实心还是虚心的
if g==0:
thickness=-1
else:
thickness=2
if k==27:
break
cv2.destroyAllWindows()