文章目录
一、读入图像
使用函数cv2.imread(filepath,flags)读入一副图片
filepath:要读入图片的完整路径
flags:读入图片的标志,取值->1,0,-1
cv2.IMREAD_COLOR:1->默认参数,读入一副彩色图片,忽略alpha通道
cv2.IMREAD_GRAYSCALE:0->读入灰度图片
cv2.IMREAD_UNCHANGED:-1->读入完整图片,包括alpha通道
注意:
- 通道一般为rgb存储,但是opencv中是以bgr存储的
- 路径名不能含有中文,否则不能读出图片数据
\# img = cv2.imread('1.jpg',cv2.IMREAD_GRAYSCALE)
\# 也可以写成下面这种形式
img =cv2.imread('1.jpg',0)
二、 显示图像
使用函数cv2.imshow(wname,img)显示图像,第一个参数是显示图像的窗口的名字,第二个参数是要显示的图像(imread读入的图像),窗口大小自动调整为图片大小
cv2.waitKey(0)
cv2.destroyAllWindows()
\# cv2.destroyWindow(wname)
- cv2.waitKey()等待键盘输入,单位为毫秒,即等待指定的毫秒数看是否有键盘输入,若在等待时间内按下任意键则返回按键的ASCII码,程序继续运行。若没有按下任何键,超时后返回-1。参数为0表示无限等待。不调用waitKey的话,窗口会一闪而逝,看不到显示的图片。
- cv2.destroyAllWindows()销毁所有窗口
- cv2.destroyWindow(wname)销毁指定窗口
三 、保存图像
使用函数cv2.imwrite(file,img,num)保存一个图像。第一个参数是要保存的文件名,第二个参数是要保存的图像。可选的第三个参数,它针对特定的格式:对于JPEG,其表示的是图像的质量,用0 - 100的整数表示,默认95;对于png ,第三个参数表示的是压缩级别。默认为3.
cv2.imwrite('1.png',img, [int(cv2.IMWRITE_PNG_COMPRESSION), 9])
注意:
- cv2.IMWRITE_JPEG_QUALITY类型为 long ,必须转换成 int
- cv2.IMWRITE_PNG_COMPRESSION, 从0到9 压缩级别越高图像越小。
四 、图片操作
4.1 图像翻转
使用函数cv2.flip(img,flipcode)翻转图像,flipcode控制翻转效果。
flipcode = 0:沿x轴翻转
flipcode > 0:沿y轴翻转
flipcode < 0:x,y轴同时翻转
imgflip = cv2.flip(img,1)
4.2 图像复制
imgcopy=img.copy()
4.3 颜色空间转换
# 彩色图像转为灰度图像
img2 = cv2.cvtColor(img,cv2.COLOR_RGB2GRAY)
# 灰度图像转为彩色图像
img3 = cv2.cvtColor(img,cv2.COLOR_GRAY2RGB)
# cv2.COLOR_X2Y,其中X,Y = RGB, BGR, GRAY, HSV, YCrCb, XYZ, Lab, Luv, HLS
4.4 实例
4.4.1 读入一副图像,按’s’键保存后退出,按’q’键则退出
img = cv2.imread('1.jpg',cv2.IMREAD_UNCHANGED)
cv2.imshow('image',img)
k = cv2.waitKey(0)
if k == ord('s'): # wait for 's' key to save and exit
cv2.imwrite('1.png',img)
cv2.destroyAllWindows()
if k == ord('q'):
cv2.destroyAllWindows()
4.4.2 读入一副图像,给图片加文本
> import cv2
# img=cv2.imread('1.jpg',cv2.IMREAD_COLOR)
img=cv2.imread('1.png',cv2.IMREAD_COLOR) # 打开文件
font = cv2.FONT_HERSHEY_DUPLEX # 设置字体
\# 图片对象、文本、像素位置、字体、字体大小、颜色、字体粗细
imgzi = cv2.putText(img, "0000", (200, 100), font, 5.5, (0, 0, 0), 2,)
cv2.imshow('1',img)
cv2.imwrite('2.png',img) # 写磁盘
cv2.destroyAllWindows() # 毁掉所有窗口
cv2.destroyWindow(wname) # 销毁指定窗口
### 4.4.3 画图
```import numpy as np
import cv2
\# 创建一个宽512高512的黑色画布,RGB(0,0,0)即黑色
img=np.zeros((512,512,3),np.uint8)
\# 画直线,图片对象,起始坐标(x轴,y轴),结束坐标,颜色,宽度
cv2.line(img,(0,0),(311,511),(255,0,0),10)
\# 画矩形,图片对象,左上角坐标,右下角坐标,颜色,宽度
cv2.rectangle(img,(30,166),(130,266),(0,255,0),3)
\# 画圆形,图片对象,中心点坐标,半径大小,颜色,宽度
cv2.circle(img,(222,222),50,(255.111,111),-1)
\# 画椭圆形,图片对象,中心点坐标,长短轴,顺时针旋转度数,开始角度(右长轴表0度,上短轴表270度),颜色,宽度
cv2.ellipse(img,(333,333),(50,20),0,0,150,(255,222,222),-1)
\# 写字,字体选择
font=cv2.FONT_HERSHEY_SCRIPT_COMPLEX
\# 图片对象,要写的内容,左边距,字的底部到画布上端的距离,字体,大小,颜色,粗细
cv2.putText(img,"OpenCV",(10,400),font,3.5,(255,255,255),2)
a=cv2.imwrite("picture.jpg",img)
cv2.imshow("picture",img)
cv2.waitKey(0)
cv2.destroyAllWindows()
五 、基本图像处理
5.1存取图片
读图像用cv2.imread(),可以按照不同模式读取,一般最常用到的是读取单通道灰度图,或者直接默认读取多通道。存图像用cv2.imwrite(),注意存的时候是没有单通道这一说的,根据保存文件名的后缀和当前的array维度,OpenCV自动判断存的通道,另外压缩格式还可以指定存储质量,来看代码例子:
import cv2
# 读取一张400x600分辨率的图像
color_img = cv2.imread(‘test_400x600.jpg’)
print(color_img.shape)
# 直接读取单通道
gray_img = cv2.imread(‘test_400x600.jpg’, cv2.IMREAD_GRAYSCALE)
print(gray_img.shape)
# 把单通道图片保存后,再读取,仍然是3通道,相当于把单通道值复制到3个通道保存
cv2.imwrite(‘test_grayscale.jpg’, gray_img)
reload_grayscale = cv2.imread(‘test_grayscale.jpg’)
print(reload_grayscale.shape)
# cv2.IMWRITE_JPEG_QUALITY指定jpg质量,范围0到100,默认95,越高画质越好,文件越大
cv2.imwrite(‘test_imwrite.jpg’, color_img, (cv2.IMWRITE_JPEG_QUALITY, 80))
# cv2.IMWRITE_PNG_COMPRESSION:指定png质量,范围0到9,默认3,越高文件越小,画质越差
cv2.imwrite(‘test_imwrite.png’, color_img, (cv2.IMWRITE_PNG_COMPRESSION, 5))
5.2 缩放、裁剪、补边
缩放通过cv2.resize()实现,裁剪则是利用array自身的下标截取实现,此外OpenCV还可以给图像补边,这样能对一幅图像的形状和感兴趣区域实现各种操作。下面的例子中读取一幅400×600分辨率的图片,并执行一些基础的操作:
import cv2
# 读取图片
img = cv2.imread(‘tiger_tibet_village.jpg’)
# 缩放成200x200的方形图像
img_200x200 = cv2.resize(img, (200, 200))
# 不直接指定缩放后大小,通过fx和fy指定缩放比例,0.5则长宽都为原来一半
# 等效于img_200x300 = cv2.resize(img, (300, 200)),注意指定大小的格式是(宽度,高度)
# 插值方法默认是cv2.INTER_LINEAR,这里指定为最近邻插值
img_200x300 = cv2.resize(img, (0, 0), fx=0.5, fy=0.5,
interpolation=cv2.INTER_NEAREST)
# 在上张图片的基础上,上下各贴50像素的黑边,生成300x300的图像
img_300x300 = cv2.copyMakeBorder(img, 50, 50, 0, 0,
cv2.BORDER_CONSTANT,
value=(0, 0, 0))
# 对图片进行剪裁
crop = img[20:150, -180:-50]
cv2.imwrite(‘crop.jpg’, crop)
cv2.imwrite(‘resized_200x200.jpg’, img_200x200)
cv2.imwrite(‘resized_200x300.jpg’, img_200x300)
cv2.imwrite(‘bordered_300x300.jpg’, img_300x300)
5.3 色调、明暗
除了区域,图像本身的属性操作也非常多,比如可以通过HSV空间对色调和明暗进行调节。HSV空间是由美国的图形学专家A. R. Smith提出的一种颜色空间,HSV分别是色调(Hue),饱和度(Saturation)和明度(Value)。在HSV空间中进行调节就避免了直接在RGB空间中调节是还需要考虑三个通道的相关性。OpenCV中H的取值是[0, 180),其他两个通道的取值都是[0, 256),下面例子接着上面例子代码,通过HSV空间对图像进行调整:
\ # 通过cv2.cvtColor把图像从BGR转换到HSV
img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# H空间中,绿色比黄色的值高一点,所以给每个像素+15,黄色的树叶就会变绿
turn_green_hsv = img_hsv.copy()
turn_green_hsv[:, :, 0] = (turn_green_hsv[:, :, 0]+15) % 180
turn_green_img = cv2.cvtColor(turn_green_hsv, cv2.COLOR_HSV2BGR)
cv2.imwrite(‘turn_green.jpg’, turn_green_img)
# 减小饱和度会让图像损失鲜艳,变得更灰
colorless_hsv = img_hsv.copy()
colorless_hsv[:, :, 1] = 0.5 * colorless_hsv[:, :, 1]
colorless_img = cv2.cvtColor(colorless_hsv, cv2.COLOR_HSV2BGR)
cv2.imwrite(‘colorless.jpg’, colorless_img)
# 减小明度为原来一半
darker_hsv = img_hsv.copy()
darker_hsv[:, :, 2] = 0.5 * darker_hsv[:, :, 2]
darker_img = cv2.cvtColor(darker_hsv, cv2.COLOR_HSV2BGR)
cv2.imwrite(‘darker.jpg’, darker_img)
5.4 图像的仿射变换
图像的仿射变换涉及到图像的形状位置角度的变化,是深度学习预处理中常到的功能,在此简单回顾一下。仿射变换具体到图像中的应用,主要是对图像的缩放,旋转,剪切,翻转和平移的组合。在OpenCV中,仿射变换的矩阵是一个2×3的矩阵,其中左边的2×2子矩阵是线性变换矩阵,右边的2×1的两项是平移项:
M
=
[
A
B
]
=
[
a
11
a
12
b
1
a
21
a
22
b
2
]
M=[AB]=\begin{bmatrix} a_{11} & a_{12} & b_{1} \\ a_{21} & a_{22} & b_{2} \end{bmatrix}
M=[AB]=[a11a21a12a22b1b2]
对于图像上的任一位置(x,y),仿射变换执行的是如下的操作:
X Y n e w = A [ x y ] + B = M [ x y 1 ] XY_{new}= A\begin{bmatrix} x \\ y \end{bmatrix}+B=M\begin{bmatrix} x \\ y \\1 \end{bmatrix} XYnew=A[xy]+B=M⎣⎡xy1⎦⎤
import numpy as np
import cv2
# 定义一个3维数组,相当于是画布,大小H*W,,初始化白色
canvas=np.zeros((400,600,3),dtype=np.uint8)+255
# 画一条纵向的正中央的黑色分界线
cv2.line(canvas, pt1=(300, 0), pt2=(300, 399), color=(0, 0, 0), thickness=1)
# 画一条右半部份画面以150为界的横向分界线
cv2.line(canvas, pt1=(300, 149), pt2=(599, 149), color=(0, 0, 0), thickness=2)
# 左半部分的右下角画个红色的圆
cv2.circle(canvas, center=(200, 300), radius=75, color=(0, 0, 255), thickness=5)
# 定义两个三角形,并执行内部填充
triangles = np.array([[(200, 240), (145, 333), (255, 333)],[(60, 180), (20, 237), (100, 237)]])
cv2.fillPoly(canvas, triangles, (255, 0,255))
cv2.polylines(canvas, triangles, isClosed=True, color=(255, 0,0),thickness=2)
# 画一个黄色五角星
# 第一步通过旋转角度的办法求出五个顶点
phi = 4 * np.pi / 5
rotations = [[[np.cos(i * phi), -np.sin(i * phi)], [i * np.sin(phi), np.cos(i * phi)]] for i in range(1, 5)]
pentagram = np.array([[[[0, -1]] + [np.dot(m, (0, -1)) for m in rotations]]], dtype=np.float)
# 定义缩放倍数和平移向量把五角星画在左半部分画面的上方
pentagram = np.round(pentagram * 80 + np.array([160, 120])).astype(np.int)
# 将5个顶点作为多边形顶点连线,得到五角星
cv2.polylines(canvas, pentagram, True, (0, 255, 255),thickness=3)
for x in range(302, 600):
color_pixel = np.array([[[round(180*float(x-302)/298), 255, 255]]], dtype=np.uint8)
line_color = [int(c) for c in cv2.cvtColor(color_pixel, cv2.COLOR_HSV2BGR)[0][0]]
cv2.line(canvas, (x, 0), (x, 147), line_color)
# 如果定义圆的线宽大于半径,则等效于画圆点,随机在画面右下角的框内生成坐标
np.random.seed(42)
n_pts = 30
pts_x = np.random.randint(310, 590, n_pts)
pts_y = np.random.randint(160, 390, n_pts)
pts = zip(pts_x, pts_y)
# 画出每个点,颜色随机
for pt in pts:
pt_color = [int(c) for c in np.random.randint(0, 255, 3)]
cv2.circle(canvas, pt, radius=1, color=pt_color, thickness=2)
# 在左半部分最上方打印文字
text="Python-OpenCV Drawing Example"
font=cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(canvas,text,(5, 15),font,0.5,(0, 0, 0),1)
# 调整窗口
cv2.namedWindow('EXAMPLE',cv2.WINDOW_NORMAL)
cv2.imshow('EXAMPLE', canvas)
cv2.waitKey()
六、 视频功能
视频中最常用的就是从视频设备采集图片或者视频,或者读取视频文件并从中采样。所以比较重要的也是两个模块,一个是VideoCapture,用于获取相机设备并捕获图像和视频,或是从文件中捕获。还有一个VideoWriter,用于生成视频。还是来看例子理解这两个功能的用法。
6.1 摄像头录制视频
import cv2
import time
# 用摄像头录取视频
class CapVideo(object):
def __init__(self, out_fps=24, size=(640, 480)):
self.fps = out_fps
self.size = size
def cap_video(self, filename):
# 输出文件的帧率
out_fps = self.fps
# 表示打开默认的相机
cap = cv2.VideoCapture(0)
# 获取捕获图像的分辨率
size = self.size
# 编码格式
fourcc = cv2.VideoWriter_fourcc('M', 'P', '4', '2')
# 设置视频的编码,分辨率和帧率
video = cv2.VideoWriter(filename, fourcc, out_fps, size)
while cap.isOpened():
ret, frame = cap.read()
if ret:
cv2.imshow('frame', frame)
video.write(frame)
# 这个函数接收一个整型值,如果这个值是零,那么函数不会有返回值,
# 如果delay大于0,那么超过delayms后,如果没有按键,那么会返回 - 1,如果按键那么会返回键盘值
if cv2.waitKey(1) & 0xFF == 27:
break
else:
break
video.release()
cap.release()
cv2.destroyAllWindows()
6.2从视频中截取图片
# 从视频文件中获取图片
class CapFrame(object):
def __init__(self, filename, fps=24):
self.filename = filename
self.fps = fps
def cap_frame(self):
import os
# 要提取视频
filename = self.filename
timestamp = 0
# 提取视频的频率,
fps = self.fps
# 输出图片到当前目录images文件夹下
out_put_dir = 'images/'
if not os.path.exists(out_put_dir):
# 如果文件目录不存在则创建目录
os.makedirs(out_put_dir)
cap = cv2.VideoCapture(filename)
while True:
timestamp += 1
res, image = cap.read()
if not res:
print('not res , not image')
break
# 每24帧提取一张
if timestamp % fps == 0:
cv2.imwrite(out_put_dir + str(timestamp) + '.jpg', image)
print(out_put_dir + str(timestamp) + '.jpg')
print('图片提取结束')
cap.release()
if __name__=="__main__":
video=CapVideo()
video.cap_video('test_video.avi')
frame=CapFrame('test_video.avi')
frame.cap_frame()