欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

[opencv自学笔记]读写图像、视频和几何图形的绘制

程序员文章站 2022-06-04 23:36:55
...

1、基本操作,图像、视频操作以及鼠标事件进行人机交互

import cv2
import numpy as np


def imageTest():
    '''
        测试opencv对二维图像的读取,复制和展示
    :return:
    '''
    path = "e:/images/1.JPEG"
    # cv2.read(path,flag)
    # 读取图像,第一个参数是文件路径,第二个参数是打开文件的方式
    # cv2.IMREAD_GRAYSCALE 以灰度图像打开
    # cv2.IMREAD_COLOR 以彩色图像打开,也就是RGB三通道,但是在opencv库是按照BRG的顺序!!
    # 返回值是一个列表,如果是灰度图像打开的话,返回的是每一行的灰度值列表,
    # 如果是以彩色图像打开的,返回的是每个像素点的三个通道的值,一行一行排列的
    # 如果路径错误,返回None
    img = cv2.imread(path,cv2.IMREAD_COLOR)
    # cv2.imshow(winname,mat)
    # 用于在GUI显示图像,第一个参数是窗口名称,第二个参数是图像
    # 但是这个程序执行完之后就结束了,会一闪而过
    cv2.imshow("Image",img)
    # cv2.waitKey(delay)
    # 等待键盘事件,在delay毫秒内有没有键盘键入,如果有返回ASCII码,超过delay就退出了,返回0
    # 如果参数为0,则表示一直等待键盘事件,如果有键盘事件,则退出
    cv2.waitKey(0)
    # 可以关闭打开的窗口,不过cv2.waitKey(delay)已经退出了,不知道为什么还要加这句话
    cv2.destroyAllWindows()
    # cv2.imwrite(filename, img, params=None)
    # 用于图片复制,第一个参数为复制到哪
    # 第二个参数是要复制的图像,第三个参数是压缩级别,现在可以不用考虑,使用缺省参数就行
    cv2.imwrite("d:/windows/output.jpeg",img)

def videoTest():
    '''
        测试opencv读取视频,显示视频,保存视频和打开摄像头操作
    :return:
    '''

    # cv2.VideoCaputure(param) 里面的参数是摄像头编号,
    # 0代表本机摄像头,如果有好几个,可以设置成1或者其他的
    cap = cv2.VideoCapture(0)

    # fourcc是一种视频编码格式,如果需要对摄像头的进行视频复制会使用到
    # cv2.VideoWriter(filename, fourcc, fps, frameSize[, isColor])
    # 第三个参数是frame per second 每秒多少帧
    # 最后一个参数是可选的,如果是True则是彩色图,False是灰度图
    fourcc = cv2.VideoWriter_fourcc('M','J','P','G')
    out = cv2.VideoWriter("D:/output.avi",fourcc,20.0,(640,480))

    # cap.read() 返回的是一个包含三个元素的元组,第一个元素是摄像头打开状态true或者false,
    # 第二个元素是当前一帧的数据(顺序是BRG),后面还有类型dtype,比如uint8编码,这个整体是第二个元素
    # 比如cap.read()的返回值是(Ture,array([[[174, 164, 155],
    #    [184, 174, 165],
    #    [176, 182, 176],.....,dtype=uint8))

    # cap.isOpened()方法是检测摄像头是否已经初始化了,换句话说,如果没有初始化,则需要初始化
    while(cap.isOpened()):
        ret,frame = cap.read()
        # 显示当前帧的图片
        cv2.imshow("camera",frame)
        # 等待用户键入,如果键入的不是q,则进行下一帧,如果是q退出
        # 当然你必须得键入,不键入的话肯定会一直等待的
        out.write(frame)
        key = cv2.waitKey(100)
        if(key == ord('q')):
            break

    # 释放资源
    cap.release()
    cv2.destroyAllWindows()

def drawImageTest():
    '''
        测试用opencv画几何图形,比如人脸识别测试中,要在检测的人脸画个方框
    :return:
    '''
    # zeros(shape, dtype=None, order='C')
    # 先建立一个空的图片,并显示出来,
    # (512,512,3)前两个分别是长和宽,第三个参数代表图像的通道数,只能是1,3,4
    # 当然shape可以只写长和宽,那么就是单通道,也就是灰度图像
    img = np.zeros((512,512,3),np.uint8)
    # 画直线函数line(img, pt1, pt2, color, thickness=None, lineType=None, shift=None)
    # 参数分别是原图像,一个点,另外一个点,画笔颜色(也是BRG的顺序),线的类型
    cv2.line(img, (0, 0), (511, 511), (255, 0, 0), 5)
    # 画矩形函数rectangle(img, pt1, pt2, color, thickness=None, lineType=None, shift=None)
    cv2.rectangle(img, (384, 0), (510, 128), (0, 255, 0), 3)
    # 画圆形函数circle(img, center, radius, color, thickness=None, lineType=None, shift=None)
    cv2.circle(img, (447, 63), 63, (0, 0, 255), -1)
    # 指定字体,写字函数,不支持中文
    font = cv2.FONT_HERSHEY_SIMPLEX
    cv2.putText(img, 'OpenCV', (10, 500), font, 2, (255, 255, 255), 2)
    cv2.imshow("image",img)
    cv2.waitKey(0)

def mouseEventTest():
    '''
        处理鼠标事件,进行人机交互,在grabcut用到了
    :return:
    '''

    # 查看cv2里面有多少个事件 有18种事件,其中跟鼠标事件相关的有,
    # 'EVENT_LBUTTONDBLCLK', 'EVENT_LBUTTONDOWN', 'EVENT_LBUTTONUP',
    # 'EVENT_MBUTTONDBLCLK', 'EVENT_MBUTTONDOWN', 'EVENT_MBUTTONUP',
    # 'EVENT_MOUSEHWHEEL', 'EVENT_MOUSEMOVE', 'EVENT_MOUSEWHEEL',
    # 'EVENT_RBUTTONDBLCLK', 'EVENT_RBUTTONDOWN', 'EVENT_RBUTTONUP']
    # 其中L代表左键,R代表右键,M代表中间滚轮
    # CLK表示点击,DBLCLK代表双击
    # DOWN代表按下,UP代表释放
    # MOVE代表移动

    events = [i for i in dir(cv2) if 'EVENT' in i]
    num = len(events)

    # 建立一个名字为image的窗口并添加鼠标回调事件函数
    # 可以记录鼠标的轨迹
    cv2.namedWindow('image')
    cv2.setMouseCallback('image', drawByMouseEvent)
    while (1):
        cv2.imshow('image', img)
        k = cv2.waitKey(100) & 0xFF
        if k == ord('q'):
            break;

img = np.zeros((512,512,3),np.uint8)
# 当鼠标按下时变为True
drawing=False
ix,iy=-1,-1
# 定义一个回调函数,相当于java里面的监听器,只要有对应的事件触发,就会执行
def drawByMouseEvent(event,x,y,flags,param):
    global ix,iy,mode,drawing
    # 左键按下
    if event == cv2.EVENT_LBUTTONDOWN:
        drawing = True
    # 鼠标移动并且左键按下
    elif event==cv2.EVENT_MOUSEMOVE and flags==cv2.EVENT_FLAG_LBUTTON:
        ix = x
        iy = y
        if drawing==True:
            cv2.line(img, (ix, iy), (x, y), (255, 0, 0), 5)
    # 鼠标左键释放
    elif event == cv2.EVENT_LBUTTONUP:
        drawing == False

def main():
    drawImageTest()

if __name__ == '__main__':
    main()

摄像头那个函数就不贴执行结果了。。。。其它函数执行结果如下
imageTest函数执行结果如下(图片以我女神赵丽颖为例,贼漂亮):
[opencv自学笔记]读写图像、视频和几何图形的绘制
drawImageTest函数执行结果如下:
[opencv自学笔记]读写图像、视频和几何图形的绘制
mouseEventTest函数执行结果如下:
[opencv自学笔记]读写图像、视频和几何图形的绘制

2、图像的一些属性和RBG通道分解与合并

import cv2
import numpy as np

def getImageInfo():
    path = "e:/images/1.JPEG"
    img = cv2.imread(path)
    # 获取横坐标和纵坐标为100的像素值,因为是彩色格式读取的,所以是BGR三个参数
    print(img[100, 100])
    # 获取横坐标和纵坐标为100的像素值的0通道,也就是B通道的值
    print(img[100, 100, 0])
    # shape属性是一个元组(width,height,channels)
    print(img.shape)
    # size属性返回像素个数,不仅仅是width*height,还要乘channels
    print(img.size)
    # dtype属性返回编码类型 如uint8
    print(img.dtype)
    # ROI,就是我们想处理的区域都叫ROI,其实就是像素点的集合,举例
    # 横坐标从280-340,纵坐标330-390的这段区域,类似于裁剪一样
    t = img[280:340,330:390]
    cv2.imshow("image",t)
    cv2.waitKey(0)

def devideImageTest():
    '''
        一个彩色图像,假设是RGB三通道的,分解成三个单通道的
    :return:
    '''
    path = "e:/images/1.JPEG"
    img = cv2.imread(path)
    # img是三通道的,也就是说img本身是一个list,这个list是把像素点一行一行存放的,每一行也是一个list
    # 每一行的list里面存放各个位置的像素点,每个像素点都是按照[b,g,r]构成的list,
    # 因此img图像是一个三层中括号的list,也就是一个三位数组,第三维就是通道数,012对应bgr
    # 先看一下每个通道单独展示是什么结果
    cv2.imshow("origin", img)
    cv2.imshow("b", img[:, :, 0])
    cv2.imshow("g", img[:, :, 1])
    cv2.imshow("r", img[:, :, 2])
    # 假设把g通道全部变成零,原图像会怎么样?
    img[:,:,1] = 0
    cv2.imshow("image",img)
    cv2.waitKey(0)
    # 再把b通道全部变成零,原图像会怎么样?
    img[:, :, 0] = 0
    cv2.imshow("image", img)
    cv2.waitKey(0)
    # 再把r通道全部变成零,原图像会怎么样?
    img[:, :,2] = 0
    cv2.imshow("image", img)
    cv2.waitKey(0)

def combineImageTest():
    '''
        一个彩色图像,成三个单通道的合成一个图像
    :return:
    '''
    path = "e:/images/1.JPEG"
    img = cv2.imread(path)
    g = img[:, :, 1]
    b = img[:, :, 0]
    r = img[:, :, 2]
    # 单通道图像
    cv2.imshow("b", b)
    cv2.imshow("g", g)
    cv2.imshow("r", r)
    # 合成merge(mv, dst=None)
    image = cv2.merge((b,g,r))
    cv2.imshow("merge",image)
    cv2.waitKey(0)



def main():
    combineImageTest()

if __name__ == '__main__':
    main()

devideImageTest函数执行结果如下:
这是去掉b通道之后的:
[opencv自学笔记]读写图像、视频和几何图形的绘制
这是去掉b通道和g通道之后的:
[opencv自学笔记]读写图像、视频和几何图形的绘制
去掉三个通道的(就是纯黑):
[opencv自学笔记]读写图像、视频和几何图形的绘制

combineImageTest函数执行结果如下:
单独B通道的图:
[opencv自学笔记]读写图像、视频和几何图形的绘制
单独G通道的图(好像G通道比B通道皮肤细致一些):
[opencv自学笔记]读写图像、视频和几何图形的绘制
单独R通道的图(亮度大一些):
[opencv自学笔记]读写图像、视频和几何图形的绘制
他们三个图都是单通道的图,单通道都是灰度图,并不是想象的红色,绿色,蓝色,那红绿蓝是啥,比如红吧,红是把R通道和B=0,G=0合成得到的,绿和蓝也是一样的,在这里不做演示。
最后,三个单通道合成的图(也就是原图):
[opencv自学笔记]读写图像、视频和几何图形的绘制