Skip to content

Commit 29ec6fc

Browse files
committed
update ch21
1 parent 051f311 commit 29ec6fc

15 files changed

+385
-3
lines changed

ch18-图像梯度/box.png

-255 Bytes
Binary file not shown.

ch18-图像梯度/一个重要的事.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
import numpy as np
2323
from matplotlib import pyplot as plt
2424

25-
img = cv2.imread('box.png', 0)
25+
img = cv2.imread('../data/box.png', 0)
2626

2727
# Output dtype = cv2.CV_8U
2828
sobelx8u = cv2.Sobel(img, cv2.CV_8U, 1, 0, ksize=5)

ch21-OpenCV中的轮廓Contours/21-findContour.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
ret, thresh = cv2.threshold(src=imgray, thresh=127, maxval=255, type=cv2.THRESH_BINARY)#src, thresh, maxval, type
1919

2020
cv2.imshow("thresh", thresh)
21-
21+
#轮廓提取模式 Contour_Retrieval_Mode
2222
image, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
2323
print("contours size: ", len(contours))
2424

ch21-OpenCV中的轮廓Contours/21-moments.py

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
__author__ = 'play4fun'
33
"""
44
create time:15-10-23 下午12:56
5+
图像的矩可以帮助我们计算图像的质心, 面积等。
56
"""
67

78
import cv2
@@ -10,15 +11,50 @@
1011
from pprint import pprint
1112

1213
img = cv2.imread('../data/star.png', 0)
14+
# img = cv2.imread('../data/box.png', 0)
15+
1316
ret, thresh = cv2.threshold(img, 127, 255, 0)
1417
# ret, binary = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)
1518
# contours,hierarchy = cv2.findContours(thresh, 1, 2)
1619
image, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
1720
# contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
1821

22+
print('contours len:', len(contours))
1923

20-
cnt = contours[0]
24+
cnt = contours[0] # 第一个
2125
M = cv2.moments(cnt)
2226

2327
# print(M)
2428
pprint(M) # 好看一点
29+
30+
# 根据 这些矩的值 我们可以 计算出对象的重心
31+
cx = int(M['m10'] / M['m00'])
32+
cy = int(M['m01'] / M['m00'])
33+
print('重心:', cx, cy)
34+
35+
#
36+
area = cv2.contourArea(cnt)
37+
print('面积:', area)
38+
39+
# 第二参数可以用来指定对象的形状是闭合的 True 是打开的FALSE 一条曲线 。
40+
perimeter = cv2.arcLength(cnt, True)
41+
print('周长:', perimeter)
42+
43+
'''
44+
将轮廓形状近似到另外一种由更少点组成的 廓形状 新 廓的点的数目 由我们 定的准确度来决定。
45+
使用的Douglas-Peucker算法
46+
为了帮助理解,假设我们 在一幅图像中查找一个矩形
47+
但是由于图像的 种种原因,我们不能得到一个完美的矩形 而是一个 坏形状 如下图所示 。
48+
49+
现在你就可以使用这个函数来近似 个形状 了。
50+
这个函数的第二个参数叫 epsilon 它是从原始 廓到近似轮廓的最大距离。它是一个准确度参数。
51+
选择一个好的 epsilon 对于得到满意结果非常重要
52+
'''
53+
epsilon = 0.1*cv2.arcLength(cnt,True)
54+
print('epsilon:',epsilon)
55+
approx = cv2.approxPolyDP(cnt,epsilon,True)
56+
cv2.drawContours(image,[approx],0,(255,0,0),3)
57+
cv2.imshow('approxPolyDP',image)
58+
59+
cv2.waitKey(0)
60+
cv2.destroyAllWindows()
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# -*- coding: utf-8 -*-
2+
# @Time : 2017/7/12 下午7:49
3+
# @Author : play4fun
4+
# @File : 21.1.2 怎样绘制轮轮廓.py
5+
# @Software: PyCharm
6+
7+
"""
8+
21.1.2 怎样绘制轮轮廓.py:
9+
函数 cv2.drawContours() 可以 用来绘制 轮廓。它可以根据你提供 的 界点绘制任何形状。
10+
第一个参数是原始图像
11+
第二个参数是 轮廓 一 个 Python 列表。
12+
第三个参数是 轮廓的索引
13+
在绘制独立 轮廓是很有用 当 设置为 -1 时绘制所有轮廓 。
14+
接下来的参数是 轮廓的颜色和厚度等。
15+
"""
16+
17+
import numpy as np
18+
import cv2
19+
20+
im = cv2.imread('test.jpg')
21+
imgray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
22+
23+
ret, thresh = cv2.threshold(imgray, 127, 255, 0)
24+
25+
img, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
26+
27+
# 绘制独立 轮廓 如第四个 轮廓
28+
cv2.drawContours(img, contours, -1, (0, 255, 0), 3)
29+
# To gdraw an individual contour, say 4th contour:
30+
31+
cv2.drawContours(image=img, contours=contours, contourIdx=3, color=(0, 255, 0), thickness=3)
32+
# drawContours(image, contours, contourIdx, color, thickness=None, lineType=None, hierarchy=None, maxLevel=None, offset=None)
33+
34+
# But most of the time, below method will be useful:
35+
# 但是大多数时候 下 的方法更有用
36+
cnt = contours[4]
37+
cv2.drawContours(img, [cnt], 0, (0, 255, 0), 3)
38+
39+
'''
40+
这个参数如果 设置为 cv2.CHAIN_APPROX_NONE
41+
所有的边界点 都 会被存储。但是我们真的需要那么多点吗 ?
42+
例如 当我们找的边界是一条直线时。你需要直线上所有的点来表示直线吗 ?
43+
不是的 我们只需要1 条直线 的两个端点而已。
44+
就是 cv2.CHAIN_APPROX_SIMPLE 做的。它会
45+
将 轮廓上的冗余点 去掉, 压缩 轮廓 ,从而节省内存开支。
46+
'''
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# -*- coding: utf-8 -*-
2+
# @Time : 2017/7/12 下午8:47
3+
# @Author : play4fun
4+
# @File : 21.4 轮廓-更多函数.py
5+
# @Software: PyCharm
6+
7+
"""
8+
21.4 轮廓-更多函数.py:
9+
"""
10+
11+
import cv2
12+
import numpy as np
13+
14+
'''
15+
Point Polygon Test
16+
求 图像中的一个点到一个对 廓的最短 离。如果点在 廓的外 回值为 。如果在 廓上 回值为 0。如果在 廓内 回值为正。
17+
下 我们以点 50 50 为例
18+
19+
dist = cv2.pointPolygonTest(cnt,(50,50),True)
20+
21+
此函数的第三个参数是 measureDist。如果 置为 True 就会 算最 短 离。如果是 False 只会判断 个点与 廓之 的位置关系 回值为 +1 -1 0
22+
23+
注意 如果你不 知 具体 离 建 你将第三个参数 为 False 这样速度会提 2 到 3 倍。
24+
'''
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# -*- coding: utf-8 -*-
2+
# @Time : 2017/7/12 下午9:30
3+
# @Author : play4fun
4+
# @File : 21.4.3-形状匹配.py
5+
# @Software: PyCharm
6+
7+
"""
8+
21.4.3-形状匹配.py:
9+
函数 cv2.matchShape() 可以帮我们比 两个形状或 廓的相似度。
10+
如果返回值越小, 匹配越好。它是根据 Hu 矩来计算的。文档中对不同的方法有解释。
11+
12+
"""
13+
14+
import cv2
15+
import numpy as np
16+
17+
img1 = cv2.imread('star.jpg', 0)
18+
img2 = cv2.imread('star2.jpg', 0)
19+
20+
ret, thresh = cv2.threshold(img1, 127, 255, 0)
21+
ret, thresh2 = cv2.threshold(img2, 127, 255, 0)
22+
23+
contours, hierarchy = cv2.findContours(thresh, 2, 1)
24+
cnt1 = contours[0]
25+
contours, hierarchy = cv2.findContours(thresh2, 2, 1)
26+
cnt2 = contours[0]
27+
28+
ret = cv2.matchShapes(cnt1, cnt2, 1, 0.0)
29+
print(ret)
30+
31+
#Hu 矩是归一化中心矩的线性组合
32+
# 之所以 样做是为了能够获取 代表图像的某个特征的矩函数
33+
# 这些矩函数对某些变化如缩放 旋转, 镜像映射 ( 除了 h1) 具有不变形。
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
什么是轮廓
2+
3+
轮廓可以简单 为成将连续的点 着 界 在一 的曲线 具有相同
4+
的 色或者灰度。 轮廓在形状分析和物体的检测和 别中很有用。
5+
• 为了更加准确 使用二值化图像。在寻找 轮廓之前 ,要进行阈值化处理
6+
或者 Canny 边界检测。
7+
• 查找 轮廓的函数会修改原始图像。如果你在找到 轮廓之后 想使用原始图
8+
像的 你应 将原始图像存储到其他变 中。
9+
• 在 OpenCV 中 查找 轮廓就像在黑色背景中超白色物体。你应该记住 找的物体应 是白色而背景应该是黑色。
10+
11+
我们看看如何在一个二值图像中查找 轮廓
12+
函数 cv2.findContours() 有三个参数
13+
第一个是 入图像
14+
第二个是轮廓检索模式
15+
第三个是 轮廓近似方法。
16+
17+
返回值有三个
18+
第一个是图像
19+
第二个 是 轮廓
20+
第三个是 轮廓的 层析结构。
21+
22+
轮廓 第二个 回值 是一个 Python 列表
23+
其中存储 图像中的所有 轮廓。
24+
每一个 轮廓 是一个 Numpy 数组 包含对 边界点 x y 的坐标。
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# -*- coding: utf-8 -*-
2+
# @Time : 2017/7/12 下午8:28
3+
# @Author : play4fun
4+
# @File : 凸包-凸性检测-边界矩形-最小外接圆-拟合.py
5+
# @Software: PyCharm
6+
7+
"""
8+
凸包-凸性检测-边界矩形-最小外接圆-拟合.py:
9+
"""
10+
import cv2
11+
12+
'''
13+
函数 cv2.convexHull() 可以用来检测一个曲线是否具有凸性缺 并能纠 正缺 。一般来 凸性曲线总是凸出来的 至少是平的。如果有地方凹 去 了就 叫做凸性缺
14+
例如下图中的手。红色曲线显示了手的凸包 凸性缺 双箭头标出来了。
15+
'''
16+
# convexHull(points, hull=None, clockwise=None, returnPoints=None)
17+
hull = cv2.convexHull(points, hull, clockwise, returnPoints)
18+
19+
'''
20+
points 我们 传入的 廓
21+
• hull 输出 通常不需要
22+
• clockwise 方向标志。如果 置为 True 出的凸包是顺时针 方向的。 否则为逆时针 方向。
23+
• returnPoints 值为 True。它会 回凸包上点的坐标。如果 置 为 False 就会 回与凸包点对应的 廓上的点。
24+
'''
25+
hull = cv2.convexHull(cnt)
26+
27+
# 凸性检测
28+
# 函数 cv2.isContourConvex() 可以可以用来检测一个曲线是不是凸的。它只能 回 True 或 False。没什么大不了的。
29+
k = cv2.isContourConvex(cnt)
30+
31+
# 边界矩形
32+
'''
33+
直边界矩形 一个直矩形 就是没有旋 的矩形 。它不会考虑对象是否旋转。 所以边界矩形的 积不是最小的。可以使用函数 cv2.boundingRect() 查 找得到。
34+
x y 为矩形左上角的坐标 w h 是矩形的宽和 。
35+
'''
36+
x, y, w, h = cv2.boundingRect(cnt)
37+
img = cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
38+
39+
'''
40+
旋 的 界矩形 个 界矩形是 积最小的 因为它考 了对 的旋 。用 到的函数为 cv2.minAreaRect()。 回的是一个 Box2D 结构 其中包含 矩形左上 点的坐标 x y 矩形的宽和 w h 以及旋 度。但是 绘制 个矩形 矩形的 4 个 点 可以 函数 cv2.boxPoints() 获 得。
41+
'''
42+
x, y, w, h = cv2.boundingRect(cnt)
43+
img = cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
44+
45+
# 最小外接圆
46+
# 函数 cv2.minEnclosingCircle() 可以帮我们找到一个对 的外切圆。它是所有能够包括对 的圆中 积最小的一个。
47+
(x, y), radius = cv2.minEnclosingCircle(cnt)
48+
center = (int(x), int(y))
49+
radius = int(radius)
50+
img = cv2.circle(img, center, radius, (0, 255, 0), 2)
51+
52+
# 椭圆拟合
53+
# 使用的函数为 cv2.ellipse() 回值其实就是旋 界矩形的内切圆
54+
ellipse = cv2.fitEllipse(cnt)
55+
im = cv2.ellipse(im, ellipse, (0, 255, 0), 2)
56+
57+
# 直线拟合
58+
# 我们可以根据一组点拟合出一条直线 同样我们也可以为图像中的白色点 拟合出一条直线。
59+
rows, cols = img.shape[:2]
60+
[vx, vy, x, y] = cv2.fitLine(cnt, cv2.DIST_L2, 0, 0.01, 0.01)
61+
lefty = int((-x * vy / vx) + y)
62+
righty = int(((cols - x) * vy / vx) + y)
63+
cv2.line(img, (cols - 1, righty), (0, lefty), (0, 255, 0), 2)
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# -*- coding: utf-8 -*-
2+
# @Time : 2017/7/12 下午9:25
3+
# @Author : play4fun
4+
# @File : 凸缺陷.py
5+
# @Software: PyCharm
6+
7+
"""
8+
凸缺陷.py:
9+
"""
10+
11+
# 凸缺陷
12+
# 前 我们已经学习了 廓的凸包 对 上的任何凹 成为凸缺 。
13+
# OpenCV 中有一个函数 cv.convexityDefect() 可以帮助我们找到凸缺
14+
15+
16+
# hull = cv2.convexHull(cnt, returnPoints=False)
17+
# defects = cv2.convexityDefects(cnt, hull)
18+
19+
20+
# 注意 如果 查找凸缺 在使用函数 cv2.convexHull 找凸包时 参数 returnPoints 一定 是 False
21+
'''
22+
它会 回一个数组 其中每一 包含的值是 [ 点 终点 最 的点 到最 点的 似 离]。我们可以在一张图上显示它。我们将 点和终点用一条绿线 接 在最 点画一个圆圈 住的是 回结果的前三个值是 廓点的索引。 所以我们 到 廓点中去找它们。
23+
'''
24+
import cv2
25+
import numpy as np
26+
27+
img = cv2.imread('star.jpg')
28+
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
29+
30+
ret, thresh = cv2.threshold(img_gray, 127, 255, 0)
31+
contours, hierarchy = cv2.findContours(thresh, 2, 1)
32+
33+
cnt = contours[0]
34+
hull = cv2.convexHull(cnt, returnPoints=False)
35+
defects = cv2.convexityDefects(cnt, hull)
36+
37+
for i in range(defects.shape[0]):
38+
s, e, f, d = defects[i, 0]
39+
start = tuple(cnt[s][0])
40+
end = tuple(cnt[e][0])
41+
far = tuple(cnt[f][0])
42+
cv2.line(img, start, end, [0, 255, 0], 2)
43+
cv2.circle(img, far, 5, [0, 0, 255], -1)
44+
cv2.imshow('img', img)
45+
cv2.waitKey(0)
46+
cv2.destroyAllWindows()

0 commit comments

Comments
 (0)