OpenCV(Python)根底—9小时入门版

# =============================================
# Author : Mikigo
# Time   : 2021/12/1
# =============================================

一、一句话简介

OpenCV (Open Source Computer Vision Library) 是用 C++ 语言编写,供给 PythonJava 等语言 API的一个开源计算机视觉库。

二、装置

1、Debian 系运用 apt 装置 OpencCV

sudo apt install python-opencv

UOS 体系上,也能够运用:

sudo apt install python3-opencv

支撑 AMDARMMIPS 架构装置。

2、装置 NumPy

NumPy 是 Python中的一个运算速度十分快的数学库,数组玩到起飞,假如你玩数据科学、机器学习,这是必学库。一切 OpenCV 数组结构都转化为 NumPy 数组,要想 OpenCV 学得好,必须了解它,学习 OpenCV 根底多少需求了解一点。

sudo apt -y install python3-numpy

好多同学装置 Python 库都习惯运用 pip 装置,实际上 OpenCV 也能够,可是现在只支撑在 AMD,所以考虑到兼容性还是建议运用 apt 进行装置,而且官方文档也是建议运用 apt 装置。

三、入门根底

一切 OpenCV 类和函数都放在 cv 称号空间中,在 py 文件中导入:

import cv2 as cv

后续内容默许都运用了导入。

1、图画

1.1、读图画

img = cv.imread()
  • 参数1:文件途径。(str)
  • 参数2:读取图画的办法。
    • cv.IMREAD_COLOR 加载一个彩色图画,疏忽 alpha 通道。(默许值)
    • cv.IMREAD_GRAYSCALE 加载图画为灰度模式。
    • cv.IMREAD_UNCHANGED 加载图画,包含 alpha 通道。
    • 还能够简单地分别传递整数1、0或 -1。

1.2、显现图画

cv.show()
  • 参数1:窗口称号。(str)
  • 参数2:图画。(obj)

在窗口中显现图画,窗口主动适合图画大小。

毁掉窗口

cv.destroyAllWindows() # 毁掉一切窗口
cv.destroyWindow("window_name") # 毁掉某个窗口,参数传入窗口称号

1.3、写图画

cv.imwrite()
  • 参数1:文件名。
  • 参数2:图画。(obj)

2、视频

2.1、从摄像头捕获视频

cap = cv.VideoCapture(0)

它的参数能够是设备索引或视频文件的称号。设备索引便是指定哪个摄像头的数字。一般咱们连接一个摄像头,所以传0(或-1)。当然能够经过传递1来挑选第二个相机,以此类推。

import cv2 as cv
cap = cv.VideoCapture(0)
 # 判别是否翻开
if not cap.isOpened(): 
    exit()
while True:  
    # 逐帧捕获
    ret, frame = cap.read()  
    # 判别是否读取到
    if not ret:  
        break
    # 转灰度
    gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
    # 显现图画
    cv.imshow('frame', gray)
    # 监控键盘信号
    if cv.waitKey(1) == ord('q'):
        break
# 开释
cap.release()
cv.destroyAllWindows()

一切都看起来很调和哈。

需求留意其他的两个判别:

  • 有时候摄像头或许没有初始化成功,所以用cap.isOpened() 来判别,并退出。
  • 或许没有接收到帧,停止循环。

获取视频的一些特点:

cap.get(id)

id 是一个从0到18的数字,每个数字表明视频的一个特点。每个特点代表什么→(docs.opencv.org/4.1.2/d4/d1…

cap.set() 属于进阶用法,这儿按下不表。

2.2、从文件中播映视频

原理和从摄像头中捕获是一样的,区别在于:

cap = cv.VideoCapture('vtest.avi')

参数是文件称号。

2.3、保存视频

out = VideoWriter()
  • 参数1:文件名
  • 参数2:fourcc = cv.VideoWriter_fourcc(*’XVID’)
    • FourCC 是一个4字节的代码,用于指定视频编解码器。
    • DIVX, XVID, MJPG, X264, WMV1, WMV2
    • 不同的操作体系有差异 www.fourcc.org/codecs.php
  • 参数3:帧率
  • 参数3:分辨率
import cv2 as cv
cap = cv.VideoCapture(0)
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:
        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()

结合前面摄像头捕获视频的代码,看起来很简单~

3、绘图

3.1、画线

cv.line()

举例:创立一个黑色图画,并从左上角到右下角在上面画一条蓝线

import numpy as np
import cv2 as cv
# 写一个黑色的图画
img = np.zeros((512,512,3), np.uint8)
# 画一根5像素款的蓝线
cv.line(img,(0,0),(511,511),(255,0,0),5)

(255,0,0) 代表蓝色,最终一个参数是线的宽度。

3.2、画圆

cv.circle(img,(447,63), 63, (0,0,255), -1)

参数:中心坐标和半径

3.3、画矩形

cv.rectangle(img,(384,0),(510,128),(0,255,0),3)

参数:矩形的左上角和右下角

支撑其他图形。。。

四、核心功用

1、图画的基本操作

1.1、拜访和修正像素值

import numpy as np  # 官方建议固定写法
import cv2 as cv
img = cv.imread('messi5.jpg')
px = img[100,100]  
# (100, 100)的像素值[157 166 200](B、G和R值)
blue = img[100,100,0] 

修正

img[100,100] = [255,255,255]

直接赋值即可修正,可是直接拜访十分缓慢,更好的像素拜访和编辑办法:

img.item(10,10,2)  # 拜访R值
img.itemset((10,10,2),100)  # 修正R值

1.2、拜访图画特点

图画特点包含行数、列数和通道数、图画数据类型、像素数等。

img.shape
# (342,548,3)

回来一个行、列和通道数的元组。

img.size  # 拜访像素总数

1.3、特定区域

机器学习中经常需求抠图,比方人脸辨认时,一般会先挑选人脸区域,查找其间的眼睛,而不是查找整个图画,以供给精确度。

ball = img[280:340, 330:390] # 抠一个区域
img[273:333, 100:160] = ball # 复制到另一个区域

1.4、图画信道的分裂与兼并

b,g,r = cv.split(img)  # 分裂
img = cv.merge((b,g,r))  # 兼并

或者

b = img[:,:,0]

比方将一切红色像素设置为零

img[:,:,2] = 0

2、图画的算术运算

2.1、图片增加

cv.add()

能够增加两个图画

x = np.uint8([250])
y = np.uint8([10])
cv.add(x + y)  # 250+10 = 260 => 255

OpenCV 的加法和 Numpy 的加法是有区别的。OpenCV 加法是一个饱满操作,而 Numpy 加法是一个除余操作。

x + y  # 250+10 = 260 % 256 = 4

2.2、图画混合

cv.addWeighted()

也是图画增加,但不同的权重给予图画,使它给人一种混合或透明的感觉。

  • 参数1、2:图画1及其权重。
  • 参数3、4:图画2及其权重。
  • 参数5:图画混合的 值,经过改动 从0→1,你能够在一张图片到另一张图片之间进行一个很魔幻的转化。
img1 = cv.imread('ml.png')
img2 = cv.imread('opencv-logo.png')
# 榜首幅图画的权重为0.7,第二幅图画的权重为0.3
dst = cv.addWeighted(img1,0.7,img2,0.3,0)
cv.imshow('dst',dst)
cv.waitKey(0)
cv.destroyAllWindows()

2.3、按位操作

按位 AND、 OR、 NOT 和 XOR 操作。

能够理解为图画的逻辑运算:

img1 = cv.imread('messi5.jpg')
img2 = cv.imread('opencv-logo-white.png')
# 把标志放在左上角,所以创立了一个roi
rows,cols,channels = img2.shape
roi = img1[0:rows, 0:cols ]
# 创立一个标志图案,以及它的反面
img2gray = cv.cvtColor(img2,cv.COLOR_BGR2GRAY) # 灰度处理
ret, mask = cv.threshold(img2gray, 10, 255, cv.THRESH_BINARY)
mask_inv = cv.bitwise_not(mask)
# 黑掉 ROI 中的 logo 区域
img1_bg = cv.bitwise_and(roi,roi,mask = mask_inv)
# 只取标志图画中的标志区域
img2_fg = cv.bitwise_and(img2,img2,mask = mask)
# 将 logo 放入 ROI 中,并修正主图画
dst = cv.add(img1_bg,img2_fg)
img1[0:rows, 0:cols ] = dst
cv.imshow('res',img1)
cv.waitKey(0)
cv.destroyAllWindows()

五、图画处理

1、改动色彩空间

OpenCV 现在有150多种色彩空间转化办法。但其间两个最广泛运用的:

1.1、Gray

cv.COLOR_BGR2GRAY

望文生义:BGR → Gray

这个图画辨认中经常运用,能够供给辨认速度和准确度。

1.2、HSV

cv.COLOR_BGR2HSV

望文生义:BGR → HSV

HSV 图画能够用它来提取有色物体在 HSV 中,比在 BGR 色彩空间中更容易表明色彩。

import cv2 as cv
import numpy as np
cap = cv.VideoCapture(0)
while True:
    # 取出视频的每一帧
    _, frame = cap.read()
    # 从 BGR 到 HSV 色彩空间的转化
    hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)
    # 界说 HSV 中蓝色的范围
    lower_blue = np.array([110,50,50])
    upper_blue = np.array([130,255,255])
    # 得到蓝色
    mask = cv.inRange(hsv, lower_blue, upper_blue)
    # 按位-and 蒙版和原始图画
    res = cv.bitwise_and(frame,frame, mask= mask)
    cv.imshow('frame',frame)
    cv.imshow('mask',mask)
    cv.imshow('res',res)
    k = cv.waitKey(5) & 0xFF
    if k == 27:
        break
cv.destroyAllWindows()

2、几许变换

2.1、缩放

res = cv.resize(InputArray, OutputArray, Size, fx, fy, interpolation)
参数 解释
nputArray src 输入图片
OutputArray dst 输出图片
Size 输出图片尺寸
fx, fy 沿x轴,y轴的缩放系数
interpolation 刺进办法

interpolation 默许情况下,运用的插值办法是 cv.INTER_LINEAR,用于一切调整大小。

举例:

import numpy as np
import cv2 as cv
img = cv.imread('messi5.jpg')
res = cv.resize(img,None,fx=2, fy=2, interpolation = cv.INTER_CUBIC)

2.2、旋转

cv.getRotationMatrix2D()

旋转90度:

img = cv.imread('messi5.jpg',0)
rows,cols = img.shape
# cols-1 and rows-1 are the coordinate limits.
M = cv.getRotationMatrix2D(((cols-1)/2.0,(rows-1)/2.0),90,1)
dst = cv.warpAffine(img,M,(cols,rows))

3、图画阈值化

3.1、自适应阈值分割

假如像素值小于阈值,则将其设置为0,不然将其设置为最大值。

ret,thresh1 = cv.threshold(img,127,255,cv.THRESH_BINARY)
  • cv.THRESH_BINARY
  • cv.THRESH_BINARY_INV
  • cv.THRESH_TRUNC
  • cv.THRESH_TOZERO
  • cv.THRESH_TOZERO_INV

假如一个图画在不同的区域有不同的照明条件,全局运用一个阈值一般是不可用的,对同一幅图画的不同区域选用不同的阈值,对不同光照条件下的图画取得了较好的效果。

  • cv.ADAPTIVE_THRESH_MEAN_C 阈值是附近区域的平均值减去常数 c
  • cv.ADAPTIVE_THRESH_GAUSSIAN_C 阈值是邻域值减去常数 c 的高斯加权和
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
img = cv.imread('sudoku.png',0)
img = cv.medianBlur(img,5)
ret,th1 = cv.threshold(img,127,255,cv.THRESH_BINARY)
th2 = cv.adaptiveThreshold(img,255,cv.ADAPTIVE_THRESH_MEAN_C,cv.THRESH_BINARY,11,2)
th3 = cv.adaptiveThreshold(img,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,cv.THRESH_BINARY,11,2)
titles = ['Original Image', 'Global Thresholding (v = 127)',
            'Adaptive Mean Thresholding', 'Adaptive Gaussian Thresholding']
images = [img, th1, th2, th3]
for i in xrange(4):
    plt.subplot(2,2,i+1),plt.imshow(images[i],'gray')
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])
plt.show()

4、模板匹配

4.1、单方针匹配

模板匹配是一种在较大图画中查找和查找模板图画方位的办法。

cv.matchTemplate()
  • 参数1:大图
  • 参数2:小图
  • 参数3:匹配办法
    • cv.TM_CCOEFF
    • cv.TM_CCOEFF_NORMED
    • cv.TM_CCORR
    • cv.TM_CCORR_NORMED
    • cv.TM_SQDIFF
    • cv.TM_SQDIFF_NORMED

查找最大/最小值

 cv.minMaxLoc()
res = cv.matchTemplate(source, template, cv.TM_CCOEFF_NORMED)
cv.minMaxLoc(res)

4.2、多方针匹配

cv.minMaxLoc()不会给出一切方位。

经过阈值处理多个模板匹配。

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
img_rgb = cv.imread('mario.png')
img_gray = cv.cvtColor(img_rgb, cv.COLOR_BGR2GRAY)
template = cv.imread('mario_coin.png',0)
w, h = template.shape[::-1]
res = cv.matchTemplate(img_gray,template,cv.TM_CCOEFF_NORMED)
loc = np.where( res >= 0.8)
for pt in zip(*loc[::-1]):
    cv.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2)
cv.imwrite('res.png',img_rgb)