opencv-python学习笔记(一)


笔记来源于官方文档

安装

. 在控制台运行pip install opencv-python,等待下载安装完成就可以直接引用了

图片的读取显示和保存

. 使用cv2.imread()来读取图片,cv2.imshow()来显示图片,cv2.imwrite()来保存图片,例如:

import cv2

img = cv2.imread('kkxj.jpg')
#cv2.namedWindow('first',cv2.WINDOW_NORMAL)
cv2.imshow('first',img)
key = cv2.waitKey(0)
if key == 27:		#ESC
    cv2.destroyAllWindows()
elif key == ord('s'):
    cv2.imwrite('new.jpg',img)
    cv2.destroyAllWindows()

. cv2.imread()有两个参数,第一个参数是文件名,第二个参数是读取标识默认位(cv2.IMREAD_COLOR),标识有三种值:
cv2.IMREAD_COLOR :加载彩色图像,会忽略掉透明度信息;.
cv2.IMREAD_GRAYSCALE :以灰度模式加载图像;
cv2.IMREAD_UNCHANGED : 加载图像,包含alpha通道(透明度信息)。
. 值得注意的是,如果文件不存在是不会在读取这一步抛出异常,img的值将会是none,也会在之后的显示这一步出错。
. 代码中cv2.namedWindow() 函数用在显示前,用来决定窗口的大小能否通过拖拉鼠标改变,其默认值是cv2.WINDOW_AUTOSIZE 也就是窗口大小和图片大小相同,且不能拖拉窗口边缘改变其大小,如果要实现这点,可以在显示前调用该函数,给第二个参数赋值cv2.WINDOW_NORMAL
. cv2.waitKey() 是键盘绑定函数,参数的单位是毫秒,表示在指定时间内等待键盘事件,如果参数位0表示无限期等待键盘事件,也可以用来检测某个按键是否按下,类似之后的判断是按下的是ESC还是‘s’,如果是按下的是ESC将会直接摧毁所有的窗口,如果按下的是‘s’将调用cv2.imwrite保存img为新文件。

视频的读取显示和保存

. opencv提供了简单的接口方便对视频进行抓取,首先需要创建一个VideoCapture 对象,传入的参数可以是设备索引(比如笔记本电脑的摄像头),也可以是某个视频文件的名字。创建玩对象后就能实现对视频进行逐帧抓取了:

#cap = cv2.VideoCapture('jackychen.m4s')
cap = cv2.VideoCapture(0)
while(True):
    ret,frame = cap.read()
	#将图片转化为灰度模式
    gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
    #cv2.resizeWindow('frame',640,360)
    cv2.imshow('frame',gray )
    #加上&0xff是因为是64位机,但加不加在测试环境没看出区别
    if cv2.waitKey(1) & 0xff == ord('q'):			#对视频文件来说1毫秒太快了,一般25毫秒比较合适
        break;

cap.release()						#用完切记要释放
cv2.destroyAllWindows()

. cap.read()的返回值是bool值,即如果正确读取了一帧将会返回True,所以上面应该是ret是返回的bool值,frame是抓取的那帧画面;
VideoCapture 对象有时不能知道是否初始化,可以调用isOpened() 函数检查,如果没有可以调用open() 来打开。
. 关于对视频文件的操作可以通过get(propId)set(propId, value) 函数来做到,propId 值是特殊定义的整型变量,对应值的意义如下:

参数值(对应从0开始)描述
CV_CAP_PROP_POS_MSEC视频文件的当前位置(以毫秒为单位)
CV_CAP_PROP_POS_FRAMES接下来要解码/捕获的帧的基于0的索引
CV_CAP_PROP_POS_AVI_RATIO视频文件的相对位置:0-电影开始,1-电影结束
CV_CAP_PROP_FRAME_WIDTH视频流中帧的宽度(这个和下面的高度好像只能用在摄像头抓取的画面上,要改视频文件的窗口还是用resize函数)
CV_CAP_PROP_FRAME_HEIGHT视频流中帧的高度
CV_CAP_PROP_FPS帧率
CV_CAP_PROP_FOURCC编解码器的4个字符的代码
CV_CAP_PROP_FRAME_COUNT视频文件中的帧数
CV_CAP_PROP_FORMAT由retrieve()返回的Mat对象的格式
CV_CAP_PROP_MODE特定于后端的值,指示当前的捕获模式
CV_CAP_PROP_BRIGHTNESS图像亮度(仅适用于相机)
CV_CAP_PROP_CONTRAST图像的对比度(仅适用于相机)
CV_CAP_PROP_SATURATION图像饱和度(仅适用于相机)
CV_CAP_PROP_HUE图像的色相(仅适用于相机)
CV_CAP_PROP_GAIN图像增益(仅适用于相机)
CV_CAP_PROP_EXPOSURE曝光(仅适用于相机)
CV_CAP_PROP_CONVERT_RGB布尔标志,指示是否应将图像转换为RGB
CV_CAP_PROP_WHITE_BALANCE_U白平衡(摄像机对白色物体的还原)设置的U值(注意:当前仅由DC1394 v 2.x后端支持)
CV_CAP_PROP_WHITE_BALANCE_V白平衡设置的V值(注意:当前仅由DC1394 v 2.x后端支持)
CV_CAP_PROP_RECTIFICATION立体摄像机的整流标志()(注意:当前仅受DC1394 v 2.x后端支持)
CV_CAP_PROP_ISO_SPEED摄像机的ISO速度(快门速度)(注意:当前仅受DC1394 v 2.x后端支持)
CV_CAP_PROP_BUFFERSIZE内部缓冲存储器中存储的帧数(注:当前仅由DC1394 v 2.x后端支持)

. 保存抓取的视频比起图片稍微复杂一点。首先需要创建一个VideoWriter 对象,然后需要传递给他四个参数,第一个是需要输出的文件名,第二个是FourCC代码,第三个是帧率,第四个是画面显示大小,最后一个是isColor标志,如果为True,则编码器需要彩色框,否则将与灰度框一起使用。
. 关于FourCC代码,它是是一个4字节代码,用于指定视频编解码器,种类非常多,试了几个都没出现问题,可以在这里查看

cap = cv2.VideoCapture(0)
fourcc = cv2.VideoWriter_fourcc(*'DIVX')
out = cv2.VideoWriter('output.avi',fourcc,20.0,(640,480))

while(True):
    ret,frame = cap.read()

    if ret == True:
        out.write(frame)
        cv2.imshow('frame',frame)
        if cv2.waitKey(1) == ord('q'):
            break
    else:
        break

cap.release()
out.release()
cv2.destroyAllWindows()

画些图形

画线

. 画线使用的函数是cv2.line(),需要传递原图像开始坐标结束坐标线的颜色粗细

import cv2
import numpy as np
# 创建一块黑色背景
img = np.zeros((512,512,3), np.uint8)

# 画对角线
img = cv2.line(img,(0,0),(511,511),(255,0,0),5)
cv2.imshow('test',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

. numpy是一个用来处理复杂矩阵的库,也包含了一些数学函数,zeros()函数相当于初始化一个数组,每个元素的类型由第二个参数指定,这里是一个三位数组,可以前第一个参数中的将两个值认为是图像的长宽,第三个值是每个像素点的RGB值。

画矩形

. 画矩形使用的函数是cv2.rectangle(),与画线的函数类似,只是坐标表示的是左上角坐标和右下角坐标了:

img = cv2.rectangle(img,(384,0),(510,128),(0,255,0),3)

画圆

. 画圆的函数是cv2.circle(),其中的坐标参数换成了圆心坐标和半径

#最后一个参数为-1表示内部填充(实心)
img = cv2.circle(img,(447,63), 63, (0,0,255), -1)

画椭圆

. 画椭圆的函数是cv2.ellipse(),函数的参数变得更多了,第二个参数也是圆心坐标,接下来是长轴和短轴的长度,然后是图形的旋转角度,然后是开始绘制的角度位置,然后是结束绘制的角度位置,最后也是绘制的线条粗细

img = cv2.ellipse(img,(256,256),(100,50),0,120,360,(0,255,0),-1)

画多边形

. 画多边形的函数是cv2.polylines(),其参数主要是传递的各个顶点的坐标:

#创建数组
pts = np.array([[10,5],[20,30],[70,20],[50,10]], np.int32)
img = cv2.polylines(img,[pts],True,(0,255,255),3)

. 如果第三个参数传递的是False,将不会成为一个封闭的图形。第二个参数可以看出是一个三位数组,也就是说如果直接给一个三维数组,应该可以画出多个图形来,比如:

pts = np.array([
    [[10,5],[20,30],[70,20],[50,10]],
    [[100,50],[200,300],[170,200],[250,210]] ], np.int32)
img = cv2.polylines(img,pts,True,(0,255,255),5)

画一些文字

. 在图像上写字可以使用函数cv2.putText(),需要的参数有:
1.原始图像;
2.文字内容;
3.开始坐标;
4.字体(文字样式);
5.文字大小;
6.字体颜色;
7.笔迹粗细;
8.线形(线的样式)。

font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img,'OpenCV',(10,500), font, 4,(255,255,255),3,cv2.LINE_AA)

鼠标作画

鼠标事件

. 关于鼠标事件类型的定义和描述

绑定回调函数

. 使用cv2.setMouseCallback() 来绑定鼠标事件发生时调用的函数,需要给调用的函数传入事件类型变量:

#实现鼠标双击后自动生成一个圆
def draw_circle(event,x,y,falg,param):
    if event == cv2.EVENT_LBUTTONDBLCLK:
        cv2.circle(img,(x,y),100,(255,0,0),-1)

#生成黑色背景图
img = np.zeros((512,512,3), np.uint8)
#窗口命名
cv2.namedWindow('image')
#绑定窗口和鼠标回调函数
cv2.setMouseCallback('image',draw_circle)
while(1):
    cv2.imshow('image',img)
    if cv2.waitKey(20) == 27:				#ESC
        break

cv2.destroyAllWindows()
	

. 下面是一个更复杂的例子,通过鼠标拖动来画矩形和圆:

import cv2
import numpy as np

#鼠标事件
drawing = False
eraer = True
mode = True
ix,iy = -1,-1
bx,by = -1,-1		#上一次的坐标

def draw(event,x,y,falgs,param):
    global ix,iy,drawing,mode,eraer,bx,by

    if event == cv2.EVENT_LBUTTONDOWN:
        drawing = True
        eraer = True
        ix,iy = x,y
        bx, by = x, y
    elif event == cv2.EVENT_MOUSEMOVE:
        if drawing == True:
            if mode == True:
                if eraer == True:
                    cv2.rectangle(img, (ix, iy), (bx,by), (0, 0, 0), -1)
                cv2.rectangle(img,(ix,iy),(x,y),(0,255,0),-1)
                bx,by = x,y

            else:
                cv2.circle(img,(x,y),5,(0,0,255),1)
    elif event == cv2.EVENT_LBUTTONUP:
        drawing = False
        eraer = False
        if mode == True:
            cv2.rectangle(img, (ix, iy), (x, y), (0, 255, 0), 1)
        else:
            cv2.circle(img, (x, y), 5, (0, 0, 255), 1)


img = np.zeros((512,512,3), np.uint8)
cv2.namedWindow('image')
cv2.setMouseCallback('image',draw)
while(1):
    cv2.imshow('image',img)
    if cv2.waitKey(1) == ord('m'):
        mode = not mode
    elif cv2.waitKey(1) == 27:
        break

cv2.destroyAllWindows()

. 鼠标左键按下的时候定义原点坐标,通过拖动来画出矩形,左键释放的时候确定最终图形,通过按键‘m’来改变画的图形

使用TrackBar

. TrackBar的想滚动套一样可以通过滑动来改变值,也可以设置滚动条的值来实现像按钮开关一样的功能。
. 主要使用的函数是cv2.getTrackbarPos(), cv2.createTrackbar(),前者是获取当前trackbar的值,后者是创建一个trackbar,cv2.createTrackbar()的第一个参数是控件(trackbar)的名字,第二个参数是窗口名,第三个是trackbar的默认值,第四个参数是trackbar的最大值,第五个参数是当trackbar的值发生改变时调用的回掉函数。

. 以下是一个控制三基色的值改变屏幕背景色的例子:

def nothing(x):
    pass

img = np.zeros((300,400,3),np.uint8)
cv2.namedWindow('image')

#创建trackbars
cv2.createTrackbar('R','image',0,255,nothing)
cv2.createTrackbar('G','image',0,255,nothing)
cv2.createTrackbar('B','image',0,255,nothing)

#使用trackbar充当按钮开关一样的功能
switch = '0: OFF \n 1: ON'
cv2.createTrackbar(switch,'image',0,1,nothing)

while(1):
    cv2.imshow('img',img)
    k = cv2.waitKey(1) & 0xFF
    if k == 27:
        break

    #获取各个trackbar当前的值
    r = cv2.getTrackbarPos('R','image')
    g = cv2.getTrackbarPos('G','image')
    b = cv2.getTrackbarPos('B','image')
    s = cv2.getTrackbarPos(switch,'image')

    if s == 0:
        img[:] = 0
    else:
        img[:] = [b,g,r]

cv2.destroyAllWindows()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值