OpenCV 基本操作

OpenCV 基本操作

0 图像读取、展示

读取显示图片

1
2
3
4
5
img_apple = cv2.imread("apple.jpg")
img_apple = cv2.resize(img_apple, (int(1706/5), int(1280/5)))
roi = img_apple[0:100, 0:100, 0]
cv2.imshow("res", roi)
cv2.waitKey(0)

读取显示视频

1
2
3
4
5
6
7
8
9
10
11
12
13
cap = cv2.VideoCapture('school.mp4')
while cap.isOpened():
ret, frame = cap.read()
# if frame is read correctly ret is True
if not ret:
print("Can't receive frame (stream end?). Exiting ...")
break
#gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.imshow('frame', frame)
if cv2.waitKey(1) == ord('q'):
break
cap.release()
cv2.destroyAllWindows()

1 形态学操作

1.1 膨胀、腐蚀

  1. 先设定一个结构元,相当一个卷积核(可以是不同形状的),核元素为 0 或 1 。
  2. 核内为 1 的位置的膨胀取最大值,腐蚀取最小值。
  3. 效果分别为增大亮的面积和缩小亮的面积。
1
2
3
4
5
element0 = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
img_character_erode = cv2.erode(img_character, element0)

element1 = cv2.getStructuringElement(cv2.MORPH_CROSS, (3,3))
img_character_dialect1 = cv2.dilate(img_character, element1, iterations=1)

1.2 开闭、梯度、礼帽黑帽运算

  1. 开:先腐蚀后膨胀,保持大小基本不变,但是去掉亮的小点,小桥。
  2. 闭:先膨胀后腐蚀,保持大小基本不变,但连接亮处断线。
  3. 梯度:膨胀 - 腐蚀,得出暗边界。
  4. 礼帽:原始图像 - 开运算,得到亮点噪声。
  5. 黑帽:闭运算 - 原始图像,得到暗点噪声。
1
2
3
img_open = cv2.morphologyEx(img_character, cv2.MORPH_OPEN, element0)

img_gradient = cv2.morphologyEx(img_character, cv2.MORPH_GRADIENT, element0)

2 边缘检测

2.1 Sobel 算子

Sobel算子
Sobel算子相当于卷积核,有两种(横向和纵向),当相应位置得相乘然后相加。得出大小,如果大说明颜色梯度很大,就是边缘。当出现负数时应取绝对值。

1
2
3
4
img_hourse_sobelx = cv2.Sobel(img_hourse, cv2.CV_64F, 1, 0, ksize=3)
img_hourse_sobely = cv2.Sobel(img_hourse, cv2.CV_64F, 0, 1, ksize=3)
img_hourse_sobel2 = cv2.convertScaleAbs(img_hourse_sobel1)
img_hourse_sobel = cv2.addWeighted(img_hourse_sobelx, 0.5, img_hourse_sobely, 0.5, 0)

2.2 Scharr 算子

Scharr 算子
Scharr 算子原理和 Sobel 算子类似,数值更大对边缘更敏感。

1
img_hourse_scharr = cv2.Scharr(img_hourse, -1, 1, 0)

2.3 Laplacian 算子

Laplacian 算子
Laplacian 算子同时对 x,y 两个方向检测。

1
img_hourse_laplacian = cv2.Laplacian(img_hourse, -1)

2.4 Canny 边缘检测

Canny 边缘检测包括

  1. 高斯滤波
  2. 用 Sobel 算子计算各点梯度值
  3. 进行非极大值抑制,只有该点梯度值比该点梯度方向上相邻两点梯度值大,才能算成边缘。
  4. 双阈值过滤,只有该点超过大阈值才算边缘。同时在双阈值之间的点相邻的点已经是边缘也可以作为边缘。
1
res1 = cv2.Canny(img_hourse, 50, 100, 2)

3 滤波

效果是去掉噪声

  1. 均值滤波:用全为 1 得卷积核,各位相加然后平均。
  2. 高斯滤波:核内各点有相应权重,然后相加。信息保留更全
  3. 中止滤波:故名思意。
1
2
img_character_blur = cv2.blur(img_character, (5,5))
img_character_gaussian = cv2.GaussianBlur(img_character, (5,5), 0)

4 阈值处理

一般在灰度图或HSV图像中进行

1
2
3
img_character_grey = cv2.cvtColor(img_character, cv2.COLOR_BGR2GRAY)

thres, img_character_thres = cv2.threshold(img_character_grey, 50, 255, cv2.THRESH_BINARY)

5 轮廓检测

找出二值图边界处

1
2
contours, hierarchy = cv2.findContours(img_hourse_canny, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
cv2.drawContours(res, approx, -1, (0,0,255), 2)

轮廓拟合,找外接矩形,外接圆

1
2
3
4
5
6
approx = cv2.approxPolyDP(max_area_contour, expilon, True)
x,y,w,h = cv2.boundingRect(max_length_contour)
cv2.rectangle(res, (x,y), (x+w,y+h), (0,0,255), 2)
(x,y), r = cv2.minEnclosingCircle(max_length_contour)
center = (int(x), int(y))
cv2.circle(res, center, int(r), (255,0,0), 2)

6 模板匹配

将模板与目标图片依次比对,计算出各点差异,最后找到差异最小得点。

1
2
3
4
5
6
7
8
res = cv2.matchTemplate(img_apple, template_apple, cv2.TM_SQDIFF_NORMED)

min_value, max_value, min_locate, max_locate = cv2.minMaxLoc(res)
w = template_apple.shape[0]
h = template_apple.shape[1]
bottomright = (min_locate[0]+w, min_locate[1]+h)

cv2.rectangle(img_apple, min_locate, bottomright, (255,0,0), 3)

7 图像金字塔

  1. 向上采样(图像变大):加入为 0 得行列
  2. 向下采样(图像变小):用高斯滤波去噪,然后去掉偶数得行和列。
1
2
img_hourse_down = cv2.pyrDown(img_hourse)
img_hourse_up = cv2.pyrUp(img_hourse)