Skip to content

Commit c4d676a

Browse files
committed
087~090
1 parent 3710dcc commit c4d676a

File tree

14 files changed

+300
-0
lines changed

14 files changed

+300
-0
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,3 +125,7 @@ code_083 | [Corner Detection-Sub-Pixel ](python/code_083) | ✔️
125125
code_084 | [Video Analysis-KLT Optical Flow-1](python/code_084) | ✏️
126126
code_085 | [Video Analysis-KLT Optical Flow-2](python/code_085) | ✏️
127127
code_086 | [Video Analysis-Dense Optical Flow](python/code_086) | ✏️
128+
code_087 | [Video Analysis-Frame Difference Moving Object Analysis](python/code_087) | ✔️
129+
code_088 | [Video Analysis-Meanshift](python/code_088) | ✏️
130+
code_089 | [Video Analysis-CamShift](python/code_089) | ✏️
131+
code_090 | [Video Analysis-Object Movement Trajectory Drawing](python/code_090) | ✔️

README_CN.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,7 @@ code_083 | [角点检测-亚像素角点检测](python/code_083) | ✔️
124124
code_084 | [视频分析-KLT光流跟踪算法-1](python/code_084) | ✏️
125125
code_085 | [视频分析-KLT光流跟踪算法-2](python/code_085) | ✏️
126126
code_086 | [视频分析-稠密光流分析](python/code_086) | ✏️
127+
code_087 | [视频分析-帧差移动对象分析](python/code_087) | ✔️
128+
code_088 | [视频分析-均值迁移](python/code_088) | ✏️
129+
code_089 | [视频分析-连续自适应均值迁移](python/code_089) | ✏️
130+
code_090 | [视频分析-对象移动轨迹绘制](python/code_090) | ✔️

python/code_087/bike.avi

436 KB
Binary file not shown.

python/code_087/opencv_087.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import numpy as np
2+
import cv2 as cv
3+
4+
cap = cv.VideoCapture("bike.avi")
5+
ret, prevFrame = cap.read()
6+
prevGray = cv.cvtColor(prevFrame, cv.COLOR_BGR2GRAY)
7+
prevGray = cv.GaussianBlur(prevGray, (0, 0), 15)
8+
k = cv.getStructuringElement(cv.MORPH_RECT, (7, 7))
9+
while True:
10+
ret, frame = cap.read()
11+
if ret is False:
12+
break
13+
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
14+
gray = cv.GaussianBlur(gray, (0, 0), 15)
15+
# 两帧法
16+
diff = cv.subtract(gray, prevGray)
17+
t, binary = cv.threshold(diff, 0, 255, cv.THRESH_BINARY | cv.THRESH_OTSU)
18+
binary = cv.morphologyEx(binary, cv.MORPH_OPEN, k)
19+
cv.imshow('input', frame)
20+
cv.imshow('result', binary)
21+
cv.imwrite("result.png", binary)
22+
c = cv.waitKey(50)&0xff
23+
prevGray = np.copy(gray)
24+
if c == 27:
25+
break
26+
cap.release()
27+
cv.destroyAllWindows()

python/code_087/result.png

652 Bytes
Loading

python/code_088/README.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# 基于均值迁移的对象移动分析(Meanshift)
2+
✏️ ⛳️👍
3+
4+
## 概述
5+
6+
**本质:**
7+
8+
✔️ Mean Shift均值漂移算法是无参密度估计理论的一种,无参密度估计不需要事先知道对象的任何先验知识,完全依靠训练数据进行估计,并且可以用于任意形状的密度估计,在某一连续点处的密度函数值可由该点邻域中的若干样本点估计得出。
9+
10+
**直观的理解:**
11+
12+
✔️ 一堆点集,一个圆形的窗口在不断的移动,移动的方向是沿着点的密度最大的区域移动,图示如下:
13+
14+
<img src="https://i.loli.net/2019/07/01/5d19bd30b369945214.jpg" alt="meanshift.jpg" title="meanshift.jpg" width=400/>
15+
16+
17+
## 函数
18+
19+
- 在OpenCV里使用均值平移,首先需要设置目标,找到它的直方图,这样我们可以为了计算均值平移向后投影目标到每一帧上,同时也需要提供窗口的初始位置。
20+
21+
- 对于直方图,只考虑色调(H),要避免低光线带来的错误值,低光线的值使用 `cv2.inRange()` 函数来丢弃掉。
22+
23+
```
24+
ret, track_window = cv2.meanShift(probImage, window, criteria )
25+
```
26+
> 输入值
27+
- probImage --> 输入图像,是直方图反向投影的结果
28+
- window --> 搜索窗口,ROI对象区域
29+
- criteria --> 均值迁移停止条件
30+
31+
> 返回值
32+
- ret --> 返回迭代次数
33+
- track_window --> 返回迭代后的窗口
34+
35+
36+
<img src="https://i.loli.net/2019/06/28/5d15ef132bd0239773.gif" alt="ss.gif" title="ss.gif" width= 400/>

python/code_088/opencv_088.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import cv2 as cv
2+
cap = cv.VideoCapture('test.mp4')
3+
4+
# 读取第一帧
5+
ret,frame = cap.read()
6+
cv.namedWindow("CAS Demo", cv.WINDOW_AUTOSIZE)
7+
# 可以在图片上选择roi区域
8+
x, y, w, h = cv.selectROI("CAS Demo", frame, True, False)
9+
track_window = (x, y, w, h)
10+
11+
# 获取ROI直方图
12+
roi = frame[y:y+h, x:x+w]
13+
hsv_roi = cv.cvtColor(roi, cv.COLOR_BGR2HSV)
14+
mask = cv.inRange(hsv_roi, (26, 43, 46), (34, 255, 255))
15+
16+
# 计算直方图,参数为 图片(可多),通道数,蒙板区域,直方图长度,范围
17+
roi_hist = cv.calcHist([hsv_roi],[0],mask,[180],[0,180])
18+
cv.normalize(roi_hist,roi_hist,0,255,cv.NORM_MINMAX)
19+
20+
# 设置迭代的终止标准,最多十次迭代
21+
term_crit = ( cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 1 )
22+
while True:
23+
ret, frame = cap.read()
24+
if ret is False:
25+
break;
26+
hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)
27+
dst = cv.calcBackProject([hsv],[0],roi_hist,[0,180],1)
28+
29+
# 均值迁移,搜索更新roi区域
30+
ret, track_window = cv.meanShift(dst, track_window, term_crit)
31+
# 绘制窗口
32+
x,y,w,h = track_window
33+
cv.rectangle(frame, (x,y), (x+w,y+h), 255,2)
34+
cv.imshow('CAS Demo',frame)
35+
k = cv.waitKey(60) & 0xff
36+
if k == 27:
37+
break
38+
else:
39+
cv.imwrite(chr(k)+".jpg",frame)
40+
cv.destroyAllWindows()
41+
cap.release()
42+

python/code_088/result.gif

2.4 MB
Loading

python/code_089/README.md

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
# 基于连续自适应均值迁移的对象移动分析(Camshift)
2+
3+
## 概述
4+
5+
✔️ 由于mean-shift算法的窗口是固定大小的,而我们需要让窗口大小和目标的大小以及旋转相适应,因此提出了Camshift。
6+
7+
✔️ CAM是连续自适应的均值迁移跟踪算法,它跟均值迁移相比较有两个改进
8+
- 会根据跟踪对象大小变化自动调整搜索窗口大小
9+
- 返回位置信息更加完整,包含了位置与角度信息。
10+
11+
✔️ CAM先采用均值平移,当平移覆盖后,更新窗口大小,公式如下:
12+
```math
13+
s=2 x \sqrt{\frac{M 00}{256}}
14+
```
15+
>它也计算最适合的椭圆的方向,然后它在使用新的大小的窗口在之前的位置开始进行均值平移,过程不断继续直到到达指定的准确率。
16+
17+
## 函数
18+
19+
```
20+
ret, track_box = cv2.CamShift(
21+
InputArray probImage,
22+
Rect & window,
23+
TermCriteria criteria )
24+
```
25+
>输入
26+
- probImage --> 输入图像,是直方图反向投影的结果
27+
- window --> 搜索窗口,ROI对象区域
28+
- criteria --> 均值迁移停止条件
29+
30+
>输出
31+
- ret --> 返回可变角度的最优外接椭圆
32+
- track_box --> 返回新的窗口
33+
34+
35+
<img src="https://i.loli.net/2019/07/01/5d19c0b1265c267527.gif" alt="ss.gif" title="ss.gif" width=400/>

python/code_089/opencv_089.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import cv2 as cv
2+
import numpy as np
3+
4+
cap = cv.VideoCapture('test.mp4')
5+
6+
# 读取第一帧
7+
ret,frame = cap.read()
8+
cv.namedWindow("Demo", cv.WINDOW_AUTOSIZE)
9+
10+
# 选择ROI区域
11+
x, y, w, h = cv.selectROI("Demo", frame, True, False)
12+
track_window = (x, y, w, h)
13+
14+
# 获取ROI直方图
15+
roi = frame[y:y+h, x:x+w]
16+
hsv_roi = cv.cvtColor(roi, cv.COLOR_BGR2HSV)
17+
mask = cv.inRange(hsv_roi, (26, 43, 46), (34, 255, 255))
18+
roi_hist = cv.calcHist([hsv_roi],[0],mask,[180],[0,180])
19+
cv.normalize(roi_hist,roi_hist,0,255,cv.NORM_MINMAX)
20+
21+
# 设置迭代的终止标准,最多十次迭代
22+
term_crit = ( cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 1 )
23+
while True:
24+
ret, frame = cap.read()
25+
if ret is False:
26+
break;
27+
hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)
28+
dst = cv.calcBackProject([hsv],[0],roi_hist,[0,180],1)
29+
30+
# 搜索更新roi区域
31+
ret, track_box = cv.CamShift(dst, track_window, term_crit)
32+
33+
# 可变角度的矩形框
34+
pts = cv.boxPoints(ret)
35+
pts = np.int0(pts)
36+
cv.polylines(frame, [pts], True, (0, 255, 0), 2)
37+
38+
# 更新窗口
39+
track_window = track_box
40+
#print(track_box)
41+
# 绘制窗口CAM,目标椭圆图
42+
cv.ellipse(frame, ret, (0, 0, 255), 3, 8)
43+
cv.imshow('Demo',frame)
44+
k = cv.waitKey(50) & 0xff
45+
if k == 27:
46+
break
47+
else:
48+
cv.imwrite(chr(k)+".jpg",frame)
49+
50+
cv.destroyAllWindows()
51+
cap.release()

0 commit comments

Comments
 (0)