opencv - 1 - 初入门径
配置环境
1、 下载python
2、 下载pycharm
3、 利用pip安装以下库
pip install numpy
pip install matplotlib
pipinstall opencv-python-i https://pypi.tuna.tsinghua.edu.cn/simple
4、 测试环境
import cv2 as cv
print(cv.__version__)
读取/写入图像
1、只读取
import numpy as np
import cv2 as cv
#加载彩色灰度图像
img = cv.imread('img/1.png',0)
cv.imshow('First img',img)
cv.waitKey(0)
cv.destroyAllWindows()
- waitKey()会检测按下了什么按键,如果一直不按就会一直等待直到按下再继续下面的程序,另外还可以返回按下按键的值,如esc代表27,也可以用ord('s')直接指代s按键。
- cv.destroyAllWindows()只会破坏我们创建的所有窗口。如果要销毁任何特定的窗口,请使用函数 cv.destroyWindow()在其中传递确切的窗口名称作为参数。
2、用matplotlib读取opencv得到的img对象
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('img/1.png',0)
plt.imshow(img, cmap = 'gray', interpolation = 'bicubic')
plt.xticks([]), plt.yticks([]) # 隐藏 x 轴和 y 轴上的刻度值
plt.show()
2、读取加写入
import numpy as np
import cv2 as cv
img = cv.imread('img/1.png',0)
cv.imshow('image',img)
k = cv.waitKey(0)
if k == 27: # 等待ESC退出
cv.destroyAllWindows()
elif k == ord('s'): # 等待关键字,保存和退出
cv.imwrite('img/1.png',img)
cv.destroyAllWindows()
- cv.imwrite('img/1.png',img)中路径和原来一致就是覆盖,若不是就是创建一个新的图片,如cv.imwrite('img/4.png',img)
读取/写入视频
1、读取摄像头
import numpy as np
import cv2 as cv
cap = cv.VideoCapture(0) #传入数字时表示哪个摄像头,传入视频路径就是读取视频
if not cap.isOpened():
print("Cannot open camera")
cap.release()
exit()
while True:
# 逐帧捕获,ret表示是否读取到这一帧,frame表示这一帧的图像
ret, frame = cap.read()
# 如果正确读取帧,ret为True
if not ret:
print("Can't receive frame (stream end?). Exiting ...")
break
# 上一步已经得到了帧的img,在下一步读取之前,该位置可以对图像做一定处理,如翻转,改颜色等等,此处尝试翻转
cv.imshow('frame', gray)
if cv.waitKey(1) == ord('q') or cv.waitKey(1) == 27:
break
# 完成所有操作后,释放捕获器
cap.release()
cv.destroyAllWindows()
2、读取视频
cap = cv.VideoCapture(0) 中
cv.VideoCapture()传入数字时表示哪个摄像头,传入视频路径就是读取视频
所以只需要改成
cap = cv.VideoCapture("img/vtest.avi")
即可读取视频
3、保存视频
主要是根据需要创建特定的写入器,然后在读取到帧和显示帧之间做一个帧处理然后保存该帧图像
import numpy as np
import cv2 as cv
cap = cv.VideoCapture(0)
# 定义编解码器并创建VideoWriter对象
fourcc = cv.VideoWriter_fourcc(*'XVID')
out = cv.VideoWriter('output.avi', fourcc, 20.0, (640, 480))
while cap.isOpened():
ret, frame = cap.read()
if not ret:
print("Can't receive frame (stream end?). Exiting ...")
break
frame = cv.flip(frame, 0)
# 写翻转的框架
out.write(frame)
cv.imshow('frame', frame)
if cv.waitKey(1) == ord('q'):
break
# 完成工作后释放所有内容
cap.release()
out.release()
cv.destroyAllWindows()
所以我们捕捉一个视频,一帧一帧地处理,我们想要保存这个视频。对于图像,它非常简单,只需使用 cv.imwrite()。这里还需要做一些工作。
创建一个 VideoWriter 对象。我们应该指定输出文件名(例如: output.avi)。然后我们应该指定 FourCC 代码(详见下一段)。然后传递帧率的数量和帧大小。最后一个是颜色标志。如果为 True,编码器期望颜色帧,否则它与灰度帧一起工作。
FourCC:http://en.wikipedia.org/wiki/FourCC 是用于指定视频编解码器的4字节代码。可用代码列表可在fourcc.org中:http://www.fourcc.org/codecs.php 找到。它取决于平台。遵循编解码器对我来说效果很好。
在Fedora中:DIVX,XVID,MJPG,X264,WMV1,WMV2。(最好使用XVID。MJPG会生成大尺寸的视频。X264会生成非常小的尺寸的视频)
在Windows中:DIVX(尚待测试和添加)
在OSX中:MJPG(.mp4),DIVX(.avi),X264(.mkv)。
绘制图像
主要需要学习函数有:
- cv.line()
- cv.circle()
- cv.rectangle()
- cv.ellipse()
- cv.putText()
常见参数有:
- img:您要绘制形状的图像
- color:形状的颜色。对于BGR,将其作为元组传递,例如:(255,0,0)对于蓝色。对于灰度,只需传递标量值即可(标量即就一个参数数字)。
- 厚度:线或圆等的粗细。如果对闭合图形(如圆)传递-1 ,它将填充形状。默认厚度= 1
- lineType:线的类型,是否为8连接线,抗锯齿线等。默认情况下,为8连接线。cv.LINE_AA给出了抗锯齿的线条,看起来非常适合曲线。
1、创建直线
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
# 创建黑色的图像
img = np.zeros((512,512,3), np.uint8)
# 绘制一条厚度为5的蓝色对角线
cv.line(img,(0,0),(511,250),(255,0,0),5)
cv.imwrite("img/4.png",img)
cv.imshow("img",img)
cv.waitKey(0)
cv.destroyAllWindows()
- np.zeros()可知img对象的本质就是numpy的数组对象,现在是创建了一个512*512大小的图像,np.uint8指里面每个元素的符号类型,是一种无符号整型。
- cv.line()参数有:被绘制图像对象、起点、终点、颜色、厚度
2、绘制圆
cv.circle(img,(447,63), 63, (0,0,255), -1)
3、画椭圆
要绘制椭圆,我们需要传递几个参数。一个参数是中心位置(x,y)。下一个参数是轴长度(长轴长度,短轴长度)。angle是椭圆沿逆时针方向旋转的角度。startAngle和endAngle表示从主轴沿顺时针方向测量的椭圆弧的开始和结束。即给出0和360给出完整的椭圆。有关更多详细信息,请参阅cv.ellipse的文档。下面的示例在图像的中心绘制一个椭圆形。
cv.ellipse(img,(256,256),(100,50),0,0,180,255,-1)
4、画多边形
要绘制多边形,首先需要顶点的坐标。将这些点组成形状为ROWSx1x2的数组,其中ROWS是顶点数,并且其类型应为int32。在这里,我们绘制了一个带有四个顶点的黄色小多边形。
pts = np.array([[10,5],[20,30],[70,20],[50,10]], np.int32)
pts = pts.reshape((-1,1,2))
cv.polylines(img,[pts],True,(0,255,255))
5、向图像添加文本
要将文本放入图像中,需要指定以下内容。 - 您要写入的文字数据 - 您要放置它的位置坐标(即数据开始的左下角)。 - 字体类型(检查cv.putText文档以获取受支持的字体) - 字体比例(指定字体大小) - 常规的内容,例如颜色,厚度,线条类型等。为了获得更好的外观,建议使用lineType = cv.LINE_AA。
我们将在白色图像上写入OpenCV。
font = cv.FONT_HERSHEY_SIMPLEX
cv.putText(img,'OpenCV',(10,500), font, 4,(255,255,255),2,cv.LINE_AA)
画笔绘制
本质上就是给特定窗口绑定事件返回函数,然后对事件返回函数进行特定的改造
import numpy as np
import cv2 as cv
def draw_circle(event,x,y,flags,param):
if event == cv.EVENT_LBUTTONDOWN:
cv.circle(img,(x,y),10,(255,0,0),-1)
img = np.zeros((512, 512, 3), np.uint8)
cv.namedWindow("image")
cv.setMouseCallback("image",draw_circle)
# 该函数给某个窗口设定特定函数,这就说明我们必需按照他的要求写事件函数
while True:
cv.imshow("image",img)
if cv.waitKey(20) & 0xFF == 27:
break
cv.destroyAllWindows()
更好的利用返回函数
drawing = False # 如果按下鼠标,则为真
mode = True # 如果为真,绘制矩形。按 m 键可以切换到曲线
ix,iy = -1,-1
# 鼠标回调函数
def draw_circle(event,x,y,flags,param):
global ix,iy,drawing,mode
if event == cv.EVENT_LBUTTONDOWN:
drawing = True
ix,iy = x,y
elif event == cv.EVENT_MOUSEMOVE:
if drawing == True:
if mode == True:
cv.rectangle(img,(ix,iy),(x,y),(0,255,0),-1)
else:
cv.circle(img,(x,y),5,(0,0,255),-1)
elif event == cv.EVENT_LBUTTONUP:
drawing = False
if mode == True:
cv.rectangle(img,(ix,iy),(x,y),(0,255,0),-1)
else:
cv.circle(img,(x,y),5,(0,0,255),-1)