OpenCV图像处理综合案例

图像校正实现案例

利用Opencv实现图片校正:

纸张原图 ===> 校正后图片
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
"""
通过观察分析图片,制定校正流程:
1. 需要查找轮廓
2. 找到四个顶点坐标
3. 根据四个顶点坐标计算高度、宽度,进行透视变换
"""
# 图像校正示例
import cv2
import numpy as np
import math
from pylab import *

# 读取原图
im = cv2.imread("../data/paper.jpg")
# 灰度化处理
gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
# 高斯模糊
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
# 膨胀(可填补分割后的空白)
dilate = cv2.dilate(blurred, (3, 3))
# 检测边沿(实验发现Canny效果较好)
edged = cv2.Canny(dilate,
30, # 滞后阈值
120) # 模糊度
# 轮廓检测
cnts, hie = cv2.findContours(edged.copy(),
cv2.RETR_EXTERNAL, # 只检测外轮廓
cv2.CHAIN_APPROX_SIMPLE) # 只保留该方向的终点坐标
docCnt = None
# 绘制轮廓
im_cnt = cv2.drawContours(im, # 绘制图像
cnts, # 轮廓点列表
-1, # 绘制全部轮廓
(0, 0, 255), # 轮廓颜色:红色
2) # 轮廓粗细
# cv2.imshow("im_cnt", im_cnt)

# 计算轮廓面积,并排序
if len(cnts) > 0:
cnts = sorted(cnts, # 数据
key=cv2.contourArea, # 排序依据,根据contourArea函数结果排序
reverse=True)
for c in cnts:
peri = cv2.arcLength(c, True) # 计算轮廓周长
approx = cv2.approxPolyDP(c, 0.02 * peri, True) # 轮廓多边形拟合
# 轮廓为4个点表示找到纸张
if len(approx) == 4:
docCnt = approx
break

# print(docCnt)

# 用圆圈标记处角点
points = []
for peak in docCnt:
peak = peak[0]
# 绘制圆
cv2.circle(im, # 绘制图像
tuple(peak), # 圆心
10, # 半径
(0, 0, 255), # 颜色
2) # 粗细
points.append(peak) # 添加到列表

# print(points)
# cv2.imshow("im_point", im)

# 根据勾股定理计算宽度、高度,再做透视变换
h = int(math.sqrt((points[0][0] - points[1][0]) ** 2 + (points[0][1] - points[1][1]) ** 2))
w = int(math.sqrt((points[0][0] - points[3][0]) ** 2 + (points[0][1] - points[3][1]) ** 2))
# print('h:{},w:{}'.format(h,w))

src = np.array(points, np.float32)
dst = np.array([[0, 0],
[0, h],
[w, h],
[w, 0]], np.float32)

M = cv2.getPerspectiveTransform(src, dst)
im_rect = cv2.warpPerspective(gray,
M,
(w, h))
cv2.imshow("im_rect", im_rect)

while True:
key = cv2.waitKey()
if key == 27:
cv2.destroyAllWindows()
break

查找到轮廓 ==> 查找到坐标点 ==> 透视变换

图像瑕疵检测案例

利用OpenCV实现芯片区域瑕疵检测:

芯片原图 ===> 检测后图片
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
"""
1.读取图像
2.灰度化
3.二值化,查找到合适阈值
4.在二值化上查找轮廓(只检测外层轮廓)
5.构建和二值化shape一样的纯黑色图像(值为0)
6.将度盘区域轮廓,使用实心化填充,画在mask上,白色
7.二值化图像,与实心化填充的结果 做减法,找到瑕疵区域
8.对瑕疵区域做闭运算(先膨胀,后腐蚀)
9.找到瑕疵区域的轮廓
10.计算瑕疵区域的面积,判断是否属于瑕疵(大于10为瑕疵)
11.如果为瑕疵,拟合瑕疵区域的最小外接圆
12.将最小外接圆画在原始图像上
"""
import cv2
import numpy as np
import math

# 1. 读取图像
im_cpu = cv2.imread("../data/cv_cpu.png")
# 2. 灰度化
im_gray = cv2.cvtColor(im_cpu, cv2.COLOR_BGR2GRAY)
# 3. 二值化
ret, im_bin = cv2.threshold(im_gray, 162, 255, cv2.THRESH_BINARY)
#cv2.imshow("im_cpu", im_cpu)
#cv2.imshow("im_gray", im_gray)
#cv2.imshow("im_bin", im_bin)
# 4. 提取轮廓、绘制边沿
contours, hierarchy = cv2.findContours(im_bin, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
# 5. 构建和二值化shape一样的纯黑色图像(值为0)
mask = np.zeros(im_bin.shape, np.uint8)
# 6. 将度盘区域轮廓,使用实心化填充,画在mask上,白色
mask = cv2.drawContours(mask, contours, -1, (255, 0, 0), -1) # 绘制实心轮廓
#cv2.imshow("mask", mask)
# 7. 二值化图像,与实心化填充的结果 做减法,找到瑕疵区域
im_sub = cv2.subtract(mask, im_bin)
#cv2.imshow("im_sub", im_sub)
# 8.对瑕疵区域做闭运算(先膨胀,后腐蚀)
k = np.ones((10, 10), np.uint8)
im_close = cv2.morphologyEx(im_sub, cv2.MORPH_CLOSE, k, iterations=3)
#cv2.imshow("im_close", im_close)
# 9.找到瑕疵区域的轮廓
contours, hierarchy = cv2.findContours(im_close, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

# 10.计算瑕疵区域的面积,判断是否属于瑕疵(大于12为瑕疵)
(x, y), radius = cv2.minEnclosingCircle(contours[1])
center = (int(x), int(y))
radius = int(radius)
area = math.pi * radius * radius
print("area:", area)
if area > 12:
print("度盘表面有缺陷")
# 11.如果为瑕疵,拟合瑕疵区域的最小外接圆
print("center:", center, " radius:", radius)
cv2.circle(im_close, center, radius, (255, 0, 0), 2) # 绘制圆
cv2.imshow("im_gaussian_blur2", im_close)
# 12.将最小外接圆画在原始图像上
cv2.circle(im_cpu, center, radius, (0, 0, 255), 2) # 绘制圆
cv2.imshow("im_cpu2", im_cpu)
else:
print("无瑕疵")

while True:
key = cv2.waitKey()
if key == 27:
cv2.destroyAllWindows()
break
原图 灰度化 二值化 查找轮廓
运算找到瑕疵 闭运算 最小外接圆 原图绘制

胶囊图像分类案例