Chapter 2 处理文件、摄像头及图形用户界面--基本IO脚本

2.1 基本IO脚本

2.1.1 读/写图像文件

主要关注颜色空间变换


def convertColorSpace():

    """"

    图像颜色空间转换

   """

    # 创建3*3大小的黑色正方形图像

    img = np.zeros((3, 3), dtype=np.uint8)

    print('Black Image\n', img)

    # 将灰度图转化为BGR颜色空间的彩色图,输出为三通道

    img = cv.cvtColor(img, cv.COLOR_GRAY2BGR)

    print('BGR Image\n', img)

  1. 读写图片:OpenCV中的imread()函数和imwrite()函数(支持静态图像文件格式,不同系统支持的文件格式不一样,但都支持BMP格式,通常还支持PNG\JPEG和TIEF格式)
  2. 主要关注读取图片时,原图片和读取后数据的变化,及写入图片时位深和透明通道的处理
def readWriteImage():
    """ 读写图片
    imread()函数,默认情况下,即使图片为灰度图,依旧返回BGR格式的图片
    (除IMREAD_UNCHANGED,IMREAD_LOAD_GDAL情况下,会删除alpha通道信息)
    其可选参数flags:
    IMREAD_UNCHANGED = -1               用图片的原来格式打开,     位深不变,          通道数不变
    IMREAD_GRAYSCALE = 0                用灰度图像的方式打开图片, 位深8bit,          通道数1
    IMREAD_COLOR = 1                    用彩色图像打开图片,       位深8bit,          通道数3
    IMREAD_ANYDEPTH = 2                 用灰度图像的方式打开图片, 位深不变,          通道数1
    IMREAD_ANYCOLOR = 4                 用图片的原来格式打开,     位深8bit,          通道数不变但<=3
    IMREAD_LOAD_GDAL = 8                使用GDAL驱动读取文件,      位深不变,         通道数不变
    """
    # 图片原始位深位16位,4通道数
    imgPath = './images/img1.png'
    # 默认情况
    img = cv.imread(imgPath)
    print('默认情况:', '位深', img.dtype, ',通道数', img.shape)

    # IMREAD_UNCHANGED
    img = cv.imread(imgPath, cv.IMREAD_UNCHANGED)
    print('IMREAD_UNCHANGED:', '位深', img.dtype, ',通道数', img.shape)

    # IMREAD_GRAYSCALE
    img = cv.imread(imgPath, cv.IMREAD_GRAYSCALE)
    print('IMREAD_GRAYSCALE:', '位深', img.dtype, ',通道数', img.shape)

    # IMREAD_COLOR
    img = cv.imread(imgPath, cv.IMREAD_COLOR)
    print('IMREAD_COLOR:', '位深', img.dtype, ',通道数', img.shape)

    # IMREAD_ANYDEPTH
    img = cv.imread(imgPath, cv.IMREAD_ANYDEPTH)
    print('IMREAD_ANYDEPTH:', '位深', img.dtype, ',通道数', img.shape)

    # IMREAD_ANYCOLOR
    img = cv.imread(imgPath, cv.IMREAD_ANYCOLOR)
    print('IMREAD_ANYCOLOR:', '位深', img.dtype, ',通道数', img.shape)

    # IMREAD_LOAD_GDAL
    img = cv.imread(imgPath, cv.IMREAD_LOAD_GDAL)
    print('IMREAD_LOAD_GDAL:', '位深', img.dtype, ',通道数', img.shape)
    # print(img[:, : 3])

    # 写入16位深,通道数4的图像数据,返回bool值
    # JPG、BMP存储的视频是unit8位深 RGB编码的,写入时将RGB三通道都用depth填充
    # PNG允许每个通道8位位深或16位位深
    cv.imwrite('./images/MyErrorJPGImg1.jpg', img)
    cv.imwrite('./images/MySucceedPNGImg1.png', img)
    # 位深分离,16位->8位
    cv.imwrite('./images/MySucceedJPGImg1.jpg', img // 255)

2.1.2 图像与原始字节之间的转换

主要就是形状的变化,reshape

def rawBytesImage():
    # 返回随机字节
    randomByteArray = bytearray(os.urandom(120000))
    flatNumpyArray = np.array(randomByteArray)
    # 将字节数组转换为400*300的灰度图片
    grayImg = flatNumpyArray.reshape((300, 400))
    cv.imwrite('./images/RandomGray.png', grayImg)
    # 将字节数组转换为400*100*3的彩色图片
    colorImg = flatNumpyArray.reshape((100, 400, 3))
    cv.imwrite('./images/RandomColor.png', colorImg)

2.1.3 使用numpy.array访问图像数据

以前没注意item用法,但索引用法更方便和趁手,切片对区域的操作也更友好,时间无差

def acccessImageData():
    # 使用item的方式
    img = cv.imread('./images/img1.png')
    print(img.item(150, 120, 0))
    itemStart = time.time()
    img.itemset((150, 120, 0), 255)
    itemEnd = time.time()
    print(img.item(150, 120, 0), 'itme time is', itemEnd - itemStart)

    # 使用索引和切片的方式
    sliceStart = time.time()
    img[150,120, 0] = 254
    sliceEnd = time.time()
    print(img.item(150, 120, 0), 'itme time is', sliceEnd - sliceStart)

2.1.4 视频文件的读/写

OpenCV提供VideoCapture类和VideoWriter类支持各种格式的视频文件,
文件指针到达文件末尾前,VideroCapture的read()函数获取新帧
主要关注读写函数,视频帧率、尺寸的获取与设置,及视频编码操作

def videoReadWrite():
    """
    cv.VideoWriter_fourcc('I','4','2','0')           = 未压缩YUV颜色编码,4:2:0色度子采样
    cv.VideoWriter_fourcc('M','J','P','G')           = motion-jpeg 编码
    cv.VideoWriter_fourcc('P','I','M','1')           = MPEG-1 编码
    cv.VideoWriter_fourcc('M', 'P', '4', '2')        = MPEG-4.2 编码
    cv.VideoWriter_fourcc('D', 'I', 'V', '3')        = MPEG-4.3 编码
    cv.VideoWriter_fourcc('D', 'I', 'V', 'X')        = MPEG-4 编码
    cv.VideoWriter_fourcc('U', '2', '6', '3')        = H263 编码
    cv.VideoWriter_fourcc('I', '2', '6', '3')        = H263I 编码
    cv.VideoWriter_fourcc('F', 'L', 'V', '1')        = FLV1 编码
    """
    # 参数为0时,表示摄像头设备0
    videoFile = cv.VideoCapture('./videos/test.mp4')
    success, frame = videoFile.read()
    # 获取视频帧率
    fps = videoFile.get(cv.CAP_PROP_FPS)
    # 获取视频尺寸
    size = (int(videoFile.get(cv.CAP_PROP_FRAME_WIDTH)), int(videoFile.get(cv.CAP_PROP_FRAME_HEIGHT)))
    # 写入新视频文件中,cv.VideoWriter_fourcc('F', 'L', 'V', '1')指定视频编码
    videoWriter = cv.VideoWriter('./videos/ccNew.flv', cv.VideoWriter_fourcc('F', 'L', 'V', '1'), fps, size)

    while success:
        videoWriter.write(frame)

        success, frame = videoFile.read()

2.1.5 捕获摄像头的帧

def capFromCam():
    cap = cv.VideoCapture(0)
    # 假设帧率为30
    fps = 25
    # 获取视频尺寸
    size = (int(cap.get(cv.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv.CAP_PROP_FRAME_HEIGHT)))
    # 写入新视频文件中,cv.VideoWriter_fourcc('F', 'L', 'V', '1')指定视频编码
    videoWriter = cv.VideoWriter('./videos/capFromCam.flv', cv.VideoWriter_fourcc('F', 'L', 'V', '1'), fps, size)

    success, frame = cap.read()
    # 存储10秒的摄像头图像
    numFramRema = 10 * fps - 1
    while success and numFramRema > 0:
        videoWriter.write(frame)
        success, frame = cap.read()
        numFramRema -= 1
    cap.release()
# 两个摄像头
def multiCam():
    cap0 = cv.VideoCapture(0)
    cap1 = cv.VideoCapture(1)
    success0 = cap0.grab()
    success1 = cap1.grab()

    if success0 and success1:
        print("没有两个摄像头")
        frame0 = cap0.retrieve()
        frame1 = cap1.retrieve()

    if success0:
        print('捕捉到摄像头0')
        su, frame0 = cap0.retrieve()
        cap0.release()
        cv.imshow('cam1', np.asarray(frame0))
        cv.waitKey()
        # cv2.destroyAllWindows()

2.1.7 在窗口显示摄像头帧

def showCamFrame():
    clicked = False
    # 鼠标点击事件回调
    def onMouse(event, x, y, flags, param):
        global clicked
        if event == cv.EVENT_LBUTTONUP:
            clicked = True
            print(clicked)


    cap = cv.VideoCapture(0)
    cv.namedWindow('Myself')
    cv.setMouseCallback('Myself', onMouse)
    print('点击窗口或按任意键退出')

    sucess, frame = cap.read()
    while sucess and cv.waitKey(1) == -1 and not clicked:
        cv.imshow('Myself', frame)
        sucess, frame = cap.read()
    cv.destroyAllWindows()
    cap.release()

参考自《OpenCV3计算机视觉 Python语言实现》

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容