I 走进 OpenCV 10
1 关于 OpenCV-Python 教程 10
2 在 Windows 上安装 OpenCV-Python 11
3 在 Fedora 上安装 OpenCV-Python
以上内容略
4.1 读入图像 cv2.imread()
4.2 显示图像 cv2.imshow()
cv2.waitKey() 是一个键盘绑定函数。需要指出的是它的时间尺度是毫秒级。函数等待特定的几毫秒,看是否有键盘输入。特定的几毫秒之内,如果按下任意键,这个函数会返回按键的 ASCII 码值,程序将会继续运行。如果没有键盘输入,返回值为 -1,如果我们设置这个函数的参数为 0,那它将会无限期的等待键盘输入。它也可以被用来检测特定键是否被按下,例如按键 a 是否被按下,这个后面我们会接着讨论。 P.20
cv2.destroyAllWindows() 可以轻易删除任何我们建立的窗口。如果你想删除特定的窗口可以使用 cv2.destroyWindow(),在括号内输入你想删除的窗口名。
建 议: 一种特殊的情况是,你也可以先创建一个窗口, 之后再加载图像。 这种情况下, 你可以决定窗口是否可以调整大小。
使用到的函数是 cv2.namedWindow()。 初始设定函数标签是cv2.WINDOW _AUTOSIZE。 但是如果你把标签改成cv2.WINDOW_NORMAL,你就可以调整窗口大小了。当图像维度太大,或者要添加轨迹条时,调整窗口大小将会很有用
4.3 保存图像 cv2.imwrite()
警告: 如果你用的是 64 位系统,你需要将k=cv2.waitKey(0) 这行改成k=cv2.waitKey(0)&0xFF。
注意: 彩色图像使用 OpenCV 加载时是 BGR 模式。但是 Matplotib 是 RGB模式。所以彩色图像如果已经被 OpenCV 读取,那它将不会被 Matplotib 正确显示。
5.1 用摄像头捕获视频 cv2.VideoCapture()
cap.read() 返回一个布尔值(True/False)。如果帧读取的是正确的,就是 True。所以最后可以通过检查他的返回值来查看视频文件是否已经到了结尾。
使用 cap.isOpened(),来检查摄像头设备是否成功初始化了。如果返回值是True,那就没有问题。否则就要使用函数 cap.open()
可以使用 cap.get(3) 和 cap.get(4) 来查看每一帧的宽和高。默认情况下得到的值是 640X480。但是我可以使用 ret=cap.set(3,320)和 ret=cap.set(4,240) 来把宽和高改成 320X240。
5.3 保存视频 cv2.imwrite()
应确定一个输出文件的名字。接下来指定 FourCC 编码(下面会介绍)。播放频率和帧的大小也都需要确定。最后一个是 isColor 标签。如果是 True,每一帧就是彩色图,否则就是灰度图。
FourCC 就是一个 4 字节码,用来确定视频的编码格式。可用的编码列表可以从fourcc.org查到。
eg. fourcc = cv2.cv.FOURCC(*‘XVID’)
out = cv2.VideoWriter(‘output.avi’,fourcc, 20.0, (640,480))
6.1 画线
cv2.line(img,(0,0),(511,511),(255,0,0),5) # 从左上方到右下角的蓝色线段, 5代表笔画粗细
6.2 画矩形
cv2.rectangle(img,(384,0),(510,128),(0,255,0),3) # 告诉函数的左上角顶点和右下角顶点的坐标,绿色的矩形
6.3 画圆 cv2.circle(img,(447,63), 63, (0,0,255), -1) # 指定圆形的中心点坐标和半径大小
6.4 画椭圆 cv2.ellipse(img,(256,256),(100,50),0,0,180,255,-1)
#一个参数是中心点的位置坐标。下一个参数是长轴和短轴的长度。椭圆沿逆时针方向旋转的角度。椭圆弧沿顺时针方向起始的角度和结束角度,如果是 0 - 360,就是整个椭圆。
cv2.ellipse() 可以得到更多信息。
6.5 画多边形 cv2.polylines() # 可以被用来画很多条线
6.6 在图片上添加文字
font=cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img,‘OpenCV’,(10,500), font, 4,(255,255,255),2)
参数:要绘制的文字,要绘制的位置,字体类型(通过查看 cv2.putText() 的文档找到支持的字体),字体大小
文字的一般属性如颜色,粗细,线条的类型等。为了更好看一点推荐使用 linetype=cv2.LINE_AA
!!警 告: 所有的绘图函数的返回值都是None, 所以不能使用 img =cv2.line(img,(0,0),(511,511),(255,0,0),5)
7 把鼠标当画笔
1.创建一个鼠标事件回调函数 cv2.setMouseCallback()
创建一个鼠标事件回调函数,当鼠标事件发生时就会被执行。鼠标事件可以是鼠标上的任何动作,比如左键按下,左键松开,左键双击等。可以通过鼠标事件获得与鼠标对应的图片上的坐标。
event=cv2.EVENT_LBUTTONDBLCLK 双击鼠标?
event=cv2.EVENT_LBUTTONUP # 鼠标松开
event=cv2.EVENT_LBUTTONDOWN # 按下左键
event=cv2.EVENT_MOUSEMOVE # 查看移动
flags=cv2.EVENT_FLAG_LBUTTON # 查看是否按下
8 用滑动条做调色板
cv2.getTrackbarPos()
函数的一个参数是滑动条的名字,第二个参数是滑动条被放置窗口的名字,第三个参数是滑动条的默认位置。第四个参数是滑动条的最大值,第五个函数是回调函数,每次滑动条的滑动都会调用回调函数。回调函数通常都会含有一个默认参数,就是滑动条的位置。
滑动条的另外一个重要应用就是用作转换按钮。默认情况下 OpenCV 本身不带有按钮函数。所以我们使用滑动条来代替。
cv2.createTrackbar(switch,‘image’,0,1,nothing)
9.1 获取并修改像素值
上面提到的方法被用来选取矩阵的一个区域,比如说前5行的后3列。对于获取每一个像素值,也许使用 Numpy 的 array.item() 和 array.itemset() 会更好。但是返回值是标量。如果你想获得所有 B, G, R 的值,你需要使用 array.item() 分割他们。 P. 44
获取像素值及修改的更好方法:
img.itemset((10,10,2),100)
9.2 获取图像属性
图像的属性包括:行,列,通道,图像数据类型,像素数目等
img.shape 可以获取图像的形状。他的返回值是一个包含行数,列数,通道数的元组
img.size 可以返回图像的像素数目
img.dtype 在除虫(debug)时 img.dtype 非常重要。因为在 OpenCVPython 代码中经常出现数据类型的不一致
9.3 图像 ROI
ROI 也是使用 Numpy 索引来获得的。 P. 47
9.4 拆分及合并图像通道
把 BGR 拆分成单个通道,或者把独立通道的图片合并成一个 BGR 图像
b,g,r=cv2.split(img)
img=cv2.merge(b,g,r)
或者:
b=img[:,:,0]
img[:,:,2]=0 # 使所有像素的红色通道值都为0的快速方法
!!警告:cv2.split() 是一个比较耗时的操作。只有真正需要时才用,能用Numpy 索引就尽量用。
9.5 为图像扩边(填充)
cv2.copyMakeBorder() # 经常在卷积运算或 0 填充时被用到
参数如下:
• src 输入图像
• top, bottom, left, right 对应边界的像素数目。
• borderType 要添加那种类型的边界,类型如下 P. 48
• value 边界颜色,如果边界的类型是 cv2.BORDER_CONSTANT
10 图像上的算术运算
10.1 图像加法
cv2.add() 将两幅图像进行加法运算
也可以直接使用 numpy:res=img1+img。
两幅图像的大小,类型必须一致,或者第二个图像是一个简单的标量值
不同:OpenCV 的加法是一种饱和操作,而 Numpy 的加法是一种模操作
如:print(cv2.add(x,y)) # 250+10 = 260 => 255 print(x+y) # 250+10 = 260 % 256 = 4
这种差别在对两幅图像进行加法时会更加明显。 OpenCV 的结果会更好一点。所以我们尽量使用 OpenCV 中的函数。
10.2 图像混合
cv2.addWeighted()
dst=cv2.addWeighted(img1,0.7,img2,0.3,0) # 第一幅图权重是 0.7,第二幅图权重是 0.3
计算公式: g (x) = (1 − α) f0 (x) + α f1 (x)
dst = α · img1 + β · img2 + γ
10.3 按位运算
包括的按位操作有: AND, OR, NOT, XOR 等
11 程序性能检测及优化
11.1 使用 OpenCV 检测程序效率
cv2.getTickCount 返回从参考点到这个函数被执行的时钟数
cv2.getTickFrequency 返回时钟频率,或者说每秒钟的时钟数
#按照下面的方式可以得到一个函数运行了多少秒
e1 = cv2.getTickCount()
#your code execution 即在 e1 e2 中间加上需要计算时间的函数
e2 = cv2.getTickCount()
time = (e2 - e1)/ cv2.getTickFrequency()
也可以用time 模块实现上面的功能。 要用的函数是 time.time() 而不是cv2.getTickCount。
11.2 OpenCV 中的默认优化
cv2.useOptimized() 查看优化是否被开启
cv2.setUseOptimized() 开启优化 P. 57
11.3 在 IPython 中检测程序效率
有时需要比较两个相似操作的效率,可以使用 IPython 中的魔法命令%time
一般情况下 OpenCV 的函数要比 Numpy 函数快。所以对于相同的操作最好使用 OpenCV 的函数。当然也有例外,尤其是当使用 Numpy 对视图(而非复制)进行操作时。
11.4 更多 IPython 的魔法命令
11.5 效率优化技术
13.1 转换颜色空间
经常用到的也就两种: BGR G r a y 和 B G R Gray 和 BGR Gray和BGRHSV
cv2.cvtColor(input_image, flag),其中 flag就是转换类型,主要的两种如下:
cv2.COLOR_BGR2GRAY
v2.COLOR_BGR2HSV
OpenCV 的 HSV 格式中, H(色彩/色度)的取值范围是 [0, 179],S(饱和度)的取值范围 [0, 255], V(亮度)的取值范围 [0, 255]。但是不同的软件使用的值可能不同。所以当你需要拿 OpenCV 的 HSV 值与其他软件的 HSV 值进行对比时,一定要记得归一化。
13.2 物体跟踪
提取带有某个特定颜色的物体的步骤:
• 从视频中获取每一帧图像
• 将图像转换到 HSV 空间
• 设置 HSV 阈值到蓝色范围。
• 获取蓝色物体,当然我们还可以做其他任何我们想做的事,比如:在蓝色物体周围画一个
code in P. 64 !!!重要重要重要!!!
13.3 怎样找到要跟踪对象的 HSV 值
code in P. 65
green=np.uint8([[[0,255,0]]])
hsv_green=cv2.cvtColor(green,cv2.COLOR_BGR2HSV)
#不能用 [0,255,0],而要用 [[[0,255,0]]]
有疑问的地方:
frame = cv2.flip(frame,0) ?什么功能
cv2.circle(img,(447,63), 63, (0,0,255), -1) 最后的-1是什么含义
event==cv2.EVENT_LBUTTONDBLCLK 双击鼠标?
cv2.createTrackbar(switch,‘image’,0,1,nothing) P. 40
ROI 的作用?
P.57 - P.59的代码