opencv-python(十)

发布于:2024-06-17 ⋅ 阅读:(18) ⋅ 点赞:(0)

绘制直线

cv2.line(img, pt1, pt2, color, thickness=1, lineType=LINE_8)

上述代码可以从pt1点绘一条线到pt2点。

 img:绘图对象

pt1:线段的起点,画布的左上角坐标是(0, 0)

pt2:线段的终端

color:(B,G,R),所以(255,0,0)是蓝色

thickness:线条宽度,默认是1

lineType:可选参数,指线条样式,有LINE_4、LINE_8和LINE_AA可选,默认是LINE_8

import cv2
import numpy as np

img = np.ones((350,500,3),np.uint8)*255  # 建立白色底的画布
cv2.line(img,(1,1),(300,1),(255,0,0))  # 上方水平直线
cv2.line(img,(300,1),(300,300),(255,0,0))  # 右边垂直直线
cv2.line(img,(300,300),(1,300),(255,0,0))  # 下边水平直线
cv2.line(img,(1,300),(1,1),(255,0,0))  # 左边垂直直线
cv2.imshow("My Draw",img)

cv2.waitKey(0)
cv2.destroyAllWindows()

import cv2
import numpy as np

img = np.ones((350,500,3),np.uint8)*255
img[1:300,1:300] = (0,255,255)  # 设定黄色底

cv2.line(img, (1,1), (300,1),(255,0,0))
cv2.line(img,(300,1),(300,300),(255,0,0))
cv2.line(img,(300,300),(1,300),(255,0,0))
cv2.line(img,(1,300),(1,1),(255,0,0))
for x in range(150,300,10):
    cv2.line(img,(x,1),(300,x-150),(255,0,0))
for y in range(150,300,10):
    cv2.line(img,(1,y),(y-150,300),(255,0,0))

cv2.imshow('My Draw', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

绘制矩形

import cv2
import numpy as np

img = np.ones((350,500,3),np.uint8)*255
cv2.rectangle(img,(1,1),(300,300),(255,0,0)) # 绘制矩形
for x in range(150,300,10):
    cv2.line(img,(x,1),(300,x-150),(255,0,0))
for y in range(150,300,10):
    cv2.line(img,(1,y),(y-150,300),(255,0,0))
cv2.imshow("My Draw",img)
cv2.waitKey(0)
cv2.destroyAllWindows()

cv2.rectangle(img, pt1, pt2, color, thickness=1, lineType=LINE_8)

img:绘图对象

pt1:矩形的左上角坐标,数据格式是元组(x,y)

pt2:矩形的右下角坐标,数据格式是元组(x,y)

color:(B,G,R)方式处理色彩

thickness:线条宽度,默认是1.如果宽度设为-1,则建立实心矩形

lineType:可选参数,指线条样式,有LINE_4、LINE_8和LINE_AA可选,默认是LINE_8

import cv2
import numpy as np

img = np.ones((350,500,3),np.uint8)*255
cv2.rectangle(img,(1,1),(300,300),(0,255,255),-1) # 设定黄色底
cv2.rectangle(img,(1,1),(300,300),(255,0,0))  # 绘制矩形
for x in range(150,300,10):
    cv2.line(img,(x,1),(300,x-150),(255,0,0))
for y in range(150,300,10):
    cv2.line(img,(1,y),(y-150,300),(255,0,0))
cv2.imshow("My Draw",img)
cv2.waitKey(0)
cv2.destroyAllWindows()

绘制圆形

import cv2
import  numpy as np

height = 400
width = 600
img = np.zeros((height,width,3),np.uint8)
for i in range(0,50):
    cx = np.random.randint(0,width)
    cy = np.random.randint(0,height)
    color = np.random.randint(0,256,size=3).tolist()  # tolist()函数可以将数组改为列表
    r = np.random.randint(5, 100)
    cv2.circle(img,(cx,cy),r,color,-1)
cv2.imshow("Random Circle",img)
cv2.waitKey(0)
cv2.destroyAllWindows()

cv2.circle(img, center, radius, color, thickness=1, lineType=LINE_ 8 )

center:设定圆中心坐标,数据格式是元组(x,y)

radius:设定半径

color:(B,G,R)

thickness:线条宽度,默认是1,如果宽度设为-1,则建立实心圆形

lineType:可选参数,指线条样式,有LINE_4、LINE_8和LINE_AA可选,默认是LINE_8

绘制椭圆或椭圆弧

cv2.ellipse(img, center, axes, angle, startAngle, endAngle, color, thickness=1, lineType=LINE_ 8 )

axes:轴的长度

angle:椭圆偏移的角度

startAngle:圆弧起点的角度

endAngle:圆弧终点的角度

import cv2
import numpy as np

img = cv2.imread('antarctic.jpg')
cy = img.shape[0] // 2  # 中心点y的坐标
cx = img.shape[1] // 2  # 中心点x的坐标
size = (200,120)
for i in range(0,15):
    angle = np.random.randint(0,361)
    color = np.random.randint(0,256,size=3).tolist()
    cv2.ellipse(img,(cx,cy),size,angle,0,360,color,1)

cv2.imshow('My Draw',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

绘制多边形

cv2.polylines(img,pts,isClosed,color,thickness=1,lineType=LINE_8)

pts:Numpy数组,内含多边形顶点的坐标

isClosed:如果是True则建立封闭式多边形,也就是第一个点和最后一个点会连接。如果是False则建立开放式多边形,也就是第一个点和最后一个点不会连接。

import cv2
import numpy as np

img1 = np.ones((200,300,3),np.uint8)*255
pts = np.array([[50,50],[250,50],[200,150],[100,150]])
cv2.polylines(img1,[pts],True,(255,0,0),5)

img2 = np.ones((200,300,3),np.uint8)*255
cv2.polylines(img2,[pts],False,(0,0,255),3)

cv2.imshow('isClosed_Ture',img1)
cv2.imshow('isClosed_False',img2)
cv2.waitKey(0)
cv2.destroyAllWindows()

输出文字

 cv2.putText(img, text,org, fontFace,fontScale,color,thickness=1,lineType=LINE_8,bottomLeftOrigin=False)

text:要输出的文字

org:文字位置,是指第一个文字左下方的坐标(x,y)

fontFace:文字的字体样式,常见字体样式如下

FONT_HERSHEY_SIMPLEX:sans-serif字型,正常大小

FONT_HERSHEY_PLAIN:sans-serif字型,较小字型

FONT_HERSHEY_COMPLEX:sans字型,正常字型

FONT_HERSHEY_TRIPLEX:sans字型,较小字型

FONT_HERSHEY_SCRIPT_SIMPLEX:手写风格的字型

FONT_ITALIC:italic字型(斜体字)

frontScale:文字的字体大小

bottomLeftOrigin:默认是False,当设为True时,可以有垂直倒影的效果。

import cv2
import numpy as np

img = np.ones((300,600,3),np.uint8)*255
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img,'Python',(150,180),font,3,(255,0,0),12)
cv2.putText(img,"Python",(150,180),font,3,(0,255,255),5)

cv2.imshow("Python",img)
cv2.waitKey(0)
cv2.destroyAllWindows()

中文输出

opencv默认只支持英文,不过可以使用PIL模块,设置成可以输出中文,

1.将opencv的图像格式转换成PIL图像格式

2.使用PIL格式输出中文

3.将PIL的图像格式转换成Opencv图像格式

import cv2
import numpy as np
from PIL import Image,ImageDraw,ImageFont

def cv2_Chinese_Text(img,text,left,top,textColor,fontSize):
    if(isinstance(img,np.ndarray)):
        img = Image.fromarray(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
    draw = ImageDraw.Draw(img)
    fontText = ImageFont.truetype(
        r"C:\Users\System-Pc\Desktop\simsun.ttc",
        fontSize,
        encoding="utf-8"
    )
    draw.text((left,top),text,textColor,font=fontText)
    return cv2.cvtColor(np.asarray(img),cv2.COLOR_RGB2BGR)

img = cv2.imread("antarctic.jpg")
img = cv2_Chinese_Text(img, "我在南极",220,100,(0,0,255),50)
cv2.imshow("Antarctic",img)
cv2.waitKey(0)
cv2.destroyAllWindows()

反弹球的设计

(1)选定位置显示反弹球

(2)让反弹球显示一段时间

(3)在新位置显示反弹球

(4)回到步骤(2)

import time

time.sleep(speed)   # 单位是秒

import cv2
import numpy as np
import time
from random import *

width = 640
height = 480
r = 15
speed = 0.01
x = int(width/2)-r
y = 50
y_step = 5
while cv2.waitKey(1) == -1:
    if y > height - r or y<r:  # 反弹球超出画布下边界或者上边界
        y_step = -y_step
    y += y_step
    img = np.zeros((height,width,3),np.uint8)*255
    cv2.circle(img,(x,y),r,(255,0,0),-1)
    cv2.imshow("Bouncing Ball",img)
    time.sleep(speed)

cv2.destroyAllWindows()

上述反弹球是垂直移动,可以使用y_step设定移动步伐,如果y_step是正值则球往下方移动,如果y_step是负值则球往上移动。

import  cv2
import numpy as np
import time
from random import *

width = 640
height = 480
r = 15
speed = 0.01
x = 50
y = 50
random_step = [3,4,5,6,7]
shuffle(random_step)
x_step = random_step[0]  # 随机产生x步伐
y_step = 5
while cv2.waitKey(1) == -1:
    if x >width -r or x<r:
        x_step = -x_step
    if y>height-r or y<r:
        y_step = -y_step
    x+=x_step
    y+=y_step
    img = np.ones((height,width,3),np.uint8)*255
    cv2.circle(img,(x,y),r,(255,0,0),-1)
    cv2.imshow("Bouncing Ball",img)
    time.sleep(speed)

cv2.destroyAllWindows()

 鼠标事件

OnMouseAction(event, x, y, flags, param)

event:鼠标事件名称

EVENT_MOUSEMOVE:0,移动鼠标

EVENT_LBUTTONDOWN:1,单击

EVENT_RBUTTONDOWN:2,右击

EVENT_MBUTTONDOWN:3,单击鼠标中间键

EVENT_LBUTTONUP:4,放开鼠标左键

EVENT_RBUTTONUP:5,放开鼠标右键

EVENT_MBUTTONUP:6,放开鼠标中键

EVENT_LBUTTONBCLK:7,双击

EVENT_RBUTTONBCLK:8,双击鼠标右键

EVENT_MBUTTONBCLK:9,双击鼠标中间键

x,y:鼠标事件发生时,鼠标所在x轴,y轴坐标

flag:代表鼠标拖曳事件,或是键盘与鼠标综合事件

EVENT_FLAG_LBUTTON:1,按住左键拖曳

EVENT_FLAG_RBUTTON:2,按住右键拖曳

EVENT_FLAG_MBUTTON:4,按住中间键拖曳

EVENT_FLAG_CTRLKEY:8~15,按住ctrl键不放

EVENT_FLAG_SHIFTKEY:16~31,按住Shift键不放

EVENT_FLAG_ALTKEY:32~39,按住Alt键不放

param:标记函数ID

import cv2
import numpy as np
def OnMouseAction(event,x,y,flags,param):
    if event == cv2.EVENT_LBUTTONDOWN:
        print(f"在x={x},y={y},单击")
    elif event == cv2.EVENT_RBUTTONDOWN:
        print(f"在x={x},y={y},右击")
    elif event == cv2.EVENT_MBUTTONDOWN:
        print(f"在x={x},y={y},单击鼠标中间键")
    elif flags == cv2.EVENT_FLAG_LBUTTON:
        print(f"在x={x},y={y},按住鼠标左键拖曳")
    elif flags == cv2.EVENT_FLAG_RBUTTON:
        print(f"在x={x},y={y},按住鼠标右键拖曳")

image = np.ones((200,300,3),np.uint8)*255
cv2.namedWindow('Opencv Mouse Event')
cv2.setMouseCallback("Opencv Mouse Event",OnMouseAction)
cv2.imshow('Opencv Mouse Event',image)

cv2.waitKey(0)
cv2.destroyAllWindows()

cv2.setMouseAction('image', OnMouseAction)

image:窗口名称

OnMouseAction:

单击可以在鼠标光标位置建立实心圆,圆半径10~50随机产生,色彩也随即生成。右击可以建立线条宽度为3的随机空心圆,英文模式下,按下Q键可以结束程序。

import cv2
import numpy as np

def OnMouseAction(event, x, y, flag, param):
    color = np.random.randint(0,high=256,size=3).tolist()
    r = np.random.randint(10,50)
    if event == cv2.EVENT_LBUTTONDOWN:
        cv2.circle(image, (x,y), r, color,-1)
    elif event == cv2.EVENT_RBUTTONDOWN:
        cv2.circle(image, (x,y),r,color,3)

height = 400
width = 600
image = np.ones((height,width,3),np.uint8)*255
cv2.namedWindow('Draw Circle')
cv2.setMouseCallback('Draw Circle', OnMouseAction)
while 1:
    cv2.imshow('Draw Circle', image)
    key = cv2.waitKey(100)  # 0.1秒检查一次
    if key == ord('Q') or key == ord('q'):
        break

cv2.destroyAllWindows()

如果按住键盘S键,再单击可以建立实心圆;如果没有按键盘S键,可以产生空心圆。

如果按住键盘S键,再右击可以建立实心矩形;如果没有按键盘S键,可以产生空心矩形。

在英文输入模式下,按下Q键可以结束程序。

import cv2
import numpy  as np

def OnMouseAction(event, x,y,flags,param):
    color = np.random.randint(0,high=256,size=3).tolist()
    if event == cv2.EVENT_LBUTTONDOWN:
        r = np.random.randint(10,50)
        if key == ord('s'):
            cv2.circle(image, (x,y),r,color,-1)
        else:
            cv2.circle(image,(x,y),r,color,3)
    elif event == cv2.EVENT_RBUTTONDOWN:
        px = np.random.randint(10,100)
        py = np.random.randint(10,100)
        if key == ord('s'):
            cv2.rectangle(image,(x,y),(px,py),color,-1)
        else:
            cv2.rectangle(image,(x,y),(px,py),color,3)

height = 400
width = 600
image = np.ones((height,width,3),np.uint8)*255
cv2.namedWindow("MyDraw")
cv2.setMouseCallback("MyDraw",OnMouseAction)
while 1:
    cv2.imshow("MyDraw",image)
    key = cv2.waitKey(100)
    if key == ord('Q') or key == ord('q'):
        break
cv2.destroyAllWindows()

滚动条

cv2.createTrackbar(trackbarname, winname, value, count, onChange)

trackbarname:滚动条的名称

winname:窗口名称

value:滚动条的初值

count:滚动条的最大值

onChange:回调函数,将滚动条所要执行的操作写在此处

程序执行过程中用户可以操作滚动条,OpenCv提供了getTrackbarPos()函数,可以使用它获得滚动条的目前值

code = getTrackbarPos(trackername, winname)

trackername:滚动条名称

winname:窗口名称

import cv2
import numpy as np
def onChange(x):
    b = cv2.getTrackbarPos("B",'canvas')
    g = cv2.getTrackbarPos("G",'canvas')
    r = cv2.getTrackbarPos("R",'canvas')
    canvas[:]=[b,g,r]

canvas = np.ones((200,640,3),np.uint8)*255
cv2.namedWindow("canvas")
cv2.createTrackbar("B",'canvas',0,255,onChange)
cv2.createTrackbar("G",'canvas',0,255,onChange)
cv2.createTrackbar("R",'canvas',0,255,onChange)
while 1:
    cv2.imshow('canvas',canvas)
    key = cv2.waitKey(100)
    if key ==27:   # 按Esc键结束
        break
cv2.destroyAllWindows()

滚动条当作开关

将滚动条当作开关的应用,默认开关是0,这时单击可以绘制空心圆。

单击滚动条轨迹可以将开关设为1,这时单击可以绘制实心圆。按Q键则程序结束。

import cv2
import numpy as np

def onChange(x):
    pass

def OnMouseAction(event,x,y,flags,param):
    color = np.random.randint(0,high=256,size=3).tolist()
    r = np.random.randint(10,50)
    if event == cv2.EVENT_LBUTTONDOWN:
        cv2.circle(image,(x,y),r,color,thickness)

thickness = -1
height =400
width = 600
image = np.ones((height,width,3),np.uint8)*255
cv2.namedWindow("Draw Circle")
cv2.setMouseCallback("Draw Circle",OnMouseAction)
cv2.createTrackbar('Thickness','Draw Circle',0,1,onChange)
while 1:
    cv2.imshow('Draw Circle',image)
    key = cv2.waitKey(100)
    num = cv2.getTrackbarPos('Thickness','Draw Circle')
    if num == 0:
        thickness = -1
    else:
        thickness = 3
    if key == ord('Q') or key == ord('q'):
        break
cv2.destroyAllWindows()