用python学OpenCV3计算机视觉: 02 文件操作

Computer Vision前一篇文章我们搭建好了OpenCV的Python开发环境,接下来接着讨论如何处理各种文件。文件是机器视觉的材料,本节内容将会为后续的项目打下基础。

处理文件

# -*- coding: utf-8 -*-
import numpy as np 
import cv2 #[注0]

# 创建一张黑色的正方形图像
img = np.zeros((3,3), dtype = np.uint8)
print (img,img.dtype)

# 将灰度图(grayscale)转化成BGR(Blue-Green-Red)格式图片
img = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)
print (img,img.dtype) #[注1]

转化图片格式


# -*- coding: utf-8 -*- import cv2 image = cv2.imread('LFS.png') cv2.imwrite('LFS.jpg',image)

稍作修改,我们可以将上述程序变成一个实用的图片格式转换工具

#!/usr/bin/env python
# -*- coding: utf-8 -*-
import cv2 , sys
image = cv2.imread(sys.argv[1])
cv2.imwrite(sys.argv[2],image)

如下演示了如何在Linux下将Python脚本变成可执行文件,如何利用命令行参数将上述程序变成图片转化工具。
如何变为可执行文件

彩色图像变灰度图

# -*- coding: utf-8 -*-
import cv2 
grayImage = cv2.imread('LFS.png',cv2.IMREAD_GRAYSCALE)
cv2.imwrite('LFS_gray.jpg',grayImage)

上述程序要求LFS.png要和该程序文件在同一个目录下。

注0:
cv2不代表OpenCV的版本为2,而是说相比以前的cv模块更高级了。

注1:
使用python3运行该程序可能会出现如下警告

Failed to load OpenCL runtime

解决办法是通过下述命令安装缺少的文件

sudo apt-get install ocl-icd-opencl-dev

一维数据转灰度/彩色图片

# -*- coding: utf-8 -*-
import cv2
import numpy
import os

# 生成一个120000随机一维数组
randomByteArray = bytearray(os.urandom(120000))
flatNumpyArray = numpy.array(randomByteArray)

# 将随机数组转换为一张400x300的灰度图片
grayImage = flatNumpyArray.reshape(300,400)
cv2.imwrite('RandomGray.png',grayImage)

# 将随机数组转换为一张400x100的彩色图片
bgrImage = flatNumpyArray.reshape(100,400,3)
cv2.imwrite('RandomColor.png',bgrImage)

使用numpy.array访问数据图像

# -*- coding: utf-8 -*-
import cv2
import numpy as np

# 读取并显示图片
img = cv2.imread('colorful.png')
cv2.imshow("原始图片",img)
cv2.waitKey(0)

# 修改图片左上角的像素点为白色
img[0,0] = [255,255,255]
cv2.imshow("变左上角像素变为白色",img)
cv2.waitKey(0)

# 输出位置(50,20)处像素蓝色(B)通道的值
# 通道索引值0对应蓝色(B)通道,1对应绿色(G)通道, 2对应红色(R)通道
print img.item( 50,20,0 )
img.itemset((50,20,0), 255)
print img.item( 50,20,0 )


# Region Of Interest, ROI 的操作--一个区域复制到图像的另外一个区域
my_roi = img[100:200, 100:200]
img[200:300,200:300] = my_roi
cv2.imshow("感兴趣区域的复制",img)
cv2.waitKey(0)

# 使用索引的方式改变图片所有像素G通道的值为0
# 比起循环操作速度快
img[:,:,1] = 0
cv2.imshow("使用索引改变G通道的值为0",img)
cv2.waitKey(0)

# 获取图片的属性
# 高度,宽度,通道数
print img.shape
print img.size
print img.dtype

视频文件的读和写

# -*- coding: utf-8 -*-
import cv2
# 一个获取视频相关的类
videoCapture = cv2.VideoCapture('MyInputVid.avi')
# 每秒的帧数
fps = videoCapture.get(cv2.CAP_PROP_FPS)
# 视频的宽度,高度
size = (int(videoCapture.get(cv2.CAP_PROP_FRAME_WIDTH)),
        int(videoCapture.get(cv2.CAP_PROP_FRAME_HEIGHT)))
# 输出视频的每秒的帧数, 视频的宽高
print (fps,size)

# 一个写入视频的类,
videoWriter = cv2.VideoWriter('MyOutputVid.avi',cv2.VideoWriter_fourcc('X','V','I','D'),fps,size)

# 将输入文件的每一帧经过编解码器输出到输入文件
success, frame = videoCapture.read()
while success: # 不断循环直到最后一帧
    videoWriter.write(frame)
    success, frame = videoCapture.read()

获取摄像头数据保存为视频文件

# -*- coding: utf-8 -*-
import cv2

cameraCapture = cv2.VideoCapture(0) # 0是摄像头的索引,表示第0个摄像头
fps = 30 # 给定一个假设的帧速值
size = (int(cameraCapture.get(cv2.CAP_PROP_FRAME_WIDTH)),
        int(cameraCapture.get(cv2.CAP_PROP_FRAME_HEIGHT))) # 视频宽,高
print(fps, size)

# 创建一个写视频类
videoWriter = cv2.VideoWriter(
'MyOutputVid.avi', cv2.VideoWriter_fourcc('X','V','I','D'),
fps, size)

# 读摄像头,输出视频文件
success, frame = cameraCapture.read()
numFramesRemaining = 5 * fps - 1
while success and numFramesRemaining > 0:
    videoWriter.write(frame)
    success, frame = cameraCapture.read()
    numFramesRemaining -= 1

# 释放摄像头
cameraCapture.release()

实时显示摄像头拍摄画面

# -*- coding: utf-8 -*-
import cv2
# 一个标记值
clicked = False

# 一个函数获取鼠标的输入
def onMouse(event, x, y, flags, param):
    global clicked
    if event == cv2.EVENT_LBUTTONUP:
        clicked = True
# 摄像头索引根据实际情况调整
cameraCapture = cv2.VideoCapture(3)
cv2.namedWindow('MyWindow')

# 有鼠标事件就调用onMouse
cv2.setMouseCallback('MyWindow', onMouse)
print ('Showing camera feed. Click window or press any key tostop.')

success, frame = cameraCapture.read()
while success and cv2.waitKey(1) == -1 and not clicked:
    cv2.imshow('MyWindow', frame)
    success, frame = cameraCapture.read()

cv2.destroyWindow('MyWindow')
cameraCapture.release()

总结:
这一小结,我们熟悉了Numpy的使用,图片,视频文件的输入输出。

发表评论

电子邮件地址不会被公开。