Skip to content

Commit 96aedbd

Browse files
committed
076-080
1 parent 4730a9c commit 96aedbd

16 files changed

+314
-2
lines changed

README.md

+6-1
Original file line numberDiff line numberDiff line change
@@ -113,4 +113,9 @@ code_071 | [Hit and Miss](python/code_071/opencv_071.py) | ✔️
113113
code_072 | [Defect Detecting-1](python/code_072) | ✔️
114114
code_073 | [Defect Detecting-2](python/code_073/opencv_073.py) | ✔️
115115
code_074 | [Extract the Maximum Contour and Coding Key Points](python/code_074) | ✔️
116-
code_075 | [Image Inpainting](python/code_075/opencv_075.py) | ✔️
116+
code_075 | [Image Inpainting](python/code_075/opencv_075.py) | ✔️
117+
code_076 | [Perspective Transformation](python/code_076/opencv_076.py) | ✏️
118+
code_077 | [Video Read, Write and Process](python/code_077/opencv_077.py) | ✏️
119+
code_078 | [Identify and Track Specific Color Objects in Video](python/code_078) | ✔️
120+
code_079 | [Video Analysis-Background/Foreground Extraction](python/code_079/opencv_079.py) | ✔️
121+
code_080 | [Video Analysis–Background Subtraction and ROI Extraction of the Foreground](python/code_080) | ✔️

README_CN.md

+6-1
Original file line numberDiff line numberDiff line change
@@ -112,4 +112,9 @@ code_071 | [击中击不中](python/code_071/opencv_071.py) | ✔️
112112
code_072 | [缺陷检测1](python/code_072) | ✔️
113113
code_073 | [缺陷检测2](python/code_073/opencv_073.py) | ✔️
114114
code_074 | [提取最大轮廓和编码关键点](python/code_074) | ✔️
115-
code_075 | [图像修复](python/code_075/opencv_075.py) | ✔️
115+
code_075 | [图像修复](python/code_075/opencv_075.py) | ✔️
116+
code_076 | [图像透视变换应用](python/code_076/opencv_076.py) | ✏️
117+
code_077 | [视频读写和处理](python/code_077/opencv_077.py) | ✏️
118+
code_078 | [识别与跟踪视频中的特定颜色对象](python/code_078) | ✔️
119+
code_079 | [视频分析-背景/前景 提取](python/code_079/opencv_079.py) | ✔️
120+
code_080 | [视频分析–背景消除与前景ROI提取](python/code_080) | ✔️

python/code_076/binary.png

5.28 KB
Loading

python/code_076/opencv_076.py

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import cv2 as cv
2+
import numpy as np
3+
4+
src = cv.imread("st_02.png")
5+
cv.namedWindow("input", cv.WINDOW_AUTOSIZE)
6+
cv.imshow("input", src)
7+
8+
# 图像二值化
9+
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
10+
ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU)
11+
12+
se = cv.getStructuringElement(cv.MORPH_RECT, (3, 3), (-1, -1))
13+
binary = cv.morphologyEx(binary, cv.MORPH_OPEN, se)
14+
cv.imshow("binary", binary)
15+
cv.imwrite("binary.png", binary)
16+
17+
# 轮廓提取, 发现最大轮廓
18+
out, contours, hierarchy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
19+
20+
# 寻找最大面积轮廓
21+
cnt_maxArea = sorted(contours, key=cv.contourArea)[0]
22+
23+
# 寻找最小外接矩形,返回最小外接矩形的(中心(x,y), (宽,高), 旋转角度)
24+
rect = cv.minAreaRect(cnt_maxArea)
25+
print(rect[2])
26+
print(rect[0])
27+
# trick
28+
height, width = rect[1]
29+
print(rect[1])
30+
box = cv.boxPoints(rect)
31+
src_pts = np.int0(box)
32+
print(src_pts)
33+
34+
dst_pts = []
35+
dst_pts.append([width,height])
36+
dst_pts.append([0, height])
37+
dst_pts.append([0, 0])
38+
dst_pts.append([width, 0])
39+
40+
# 透视变换
41+
M, status = cv.findHomography(src_pts, np.array(dst_pts)) #原图到透视后的图的四个点的转换矩阵
42+
result = cv.warpPerspective(src, M, (np.int32(width), np.int32(height)))
43+
44+
if height < width:
45+
result = cv.rotate(result, cv.ROTATE_90_CLOCKWISE)
46+
47+
cv.imshow("result", result)
48+
cv.imwrite("result.png", result)
49+
50+
cv.waitKey(0)
51+
cv.destroyAllWindows()

python/code_076/result.png

395 KB
Loading

python/code_076/st_02.png

458 KB
Loading

python/code_077/opencv_077.py

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import cv2 as cv
2+
3+
capture = cv.VideoCapture(1)
4+
height = capture.get(cv.CAP_PROP_FRAME_HEIGHT)
5+
width = capture.get(cv.CAP_PROP_FRAME_WIDTH)
6+
count = capture.get(cv.CAP_PROP_FRAME_COUNT)
7+
fps = capture.get(cv.CAP_PROP_FPS)
8+
print(height, width, count, fps)
9+
10+
11+
def process(image, opt=1):
12+
dst = None
13+
if opt == 0:
14+
dst = cv.bitwise_not(image)
15+
if opt == 1:
16+
dst = cv.GaussianBlur(image, (0, 0), 15)
17+
if opt == 2:
18+
dst = cv.Canny(image, 100, 200)
19+
return dst
20+
21+
22+
index = 0
23+
while(True):
24+
ret, frame = capture.read()
25+
if ret is True:
26+
cv.imshow("video-input", frame)
27+
c = cv.waitKey(50)
28+
if c >= 49:
29+
index = c -49
30+
result = process(frame, index)
31+
cv.imshow("result", result)
32+
#print(c)
33+
if c == 27: #ESC
34+
break
35+
else:
36+
break
37+
cv.waitKey(0)
38+
cv.destroyAllWindows()
39+

python/code_078/README.md

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#### 识别与跟踪视频中的特定颜色对象
2+
3+
这个是其实图像处理与二值分析的视频版本,通过读取视频每一帧的图像,然后对图像二值分析,得到指定的色块区域,主要步骤如下:
4+
1. 色彩转换BGR2HSV
5+
2. inRange提取颜色区域mask
6+
3. 对mask区域进行二值分析得到位置与轮廓信息
7+
4. 绘制外接椭圆与中心位置
8+
5. 显示结果
9+
10+
其中涉及到的知识点主要包括图像处理、色彩空间转换、形态学、轮廓分析等。
11+
12+
函数:
13+
```python
14+
def process(image, opt=1):
15+
16+
# BGR转换为HSV
17+
hsv = cv.cvtColor(image, cv.COLOR_BGR2HSV)
18+
19+
line = cv.getStructuringElement(cv.MORPH_RECT, (15, 15), (-1, -1))
20+
21+
# Inrange
22+
mask = cv.inRange(hsv, (0, 43, 46), (10, 255, 255))
23+
24+
# 开操作,去除吊小的噪点
25+
mask = cv.morphologyEx(mask, cv.MORPH_OPEN, line)
26+
27+
# 轮廓提取, 发现最大轮廓
28+
out, contours, hierarchy = cv.findContours(mask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
29+
index = -1
30+
max = 0
31+
for c in range(len(contours)):
32+
area = cv.contourArea(contours[c])
33+
if area > max:
34+
max = area
35+
index = c
36+
# 绘制
37+
if index >= 0:
38+
rect = cv.minAreaRect(contours[index])
39+
cv.ellipse(image, rect, (0, 255, 0), 2, 8)
40+
cv.circle(image, (np.int32(rect[0][0]), np.int32(rect[0][1])), 2, (255, 0, 0), 2, 8, 0)
41+
return image
42+
43+
```
44+
45+
<img src=../code_078/result.jpg width=300>

python/code_078/opencv_078.py

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import cv2 as cv
2+
import numpy as np
3+
4+
capture = cv.VideoCapture("test.mp4")
5+
height = capture.get(cv.CAP_PROP_FRAME_HEIGHT)
6+
width = capture.get(cv.CAP_PROP_FRAME_WIDTH)
7+
count = capture.get(cv.CAP_PROP_FRAME_COUNT)
8+
fps = capture.get(cv.CAP_PROP_FPS)
9+
print(height, width, count, fps)
10+
11+
12+
def process(image, opt=1):
13+
hsv = cv.cvtColor(image, cv.COLOR_BGR2HSV)
14+
line = cv.getStructuringElement(cv.MORPH_RECT, (15, 15), (-1, -1))
15+
#mask = cv.inRange(hsv, (0, 43, 46), (10, 255, 255))
16+
cv.imshow("mask", mask)
17+
mask = cv.morphologyEx(mask, cv.MORPH_OPEN, line)
18+
#cv.imshow("masks", mask)
19+
20+
# 轮廓提取, 发现最大轮廓
21+
out, contours, hierarchy = cv.findContours(mask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
22+
index = -1
23+
max = 0
24+
for c in range(len(contours)):
25+
area = cv.contourArea(contours[c])
26+
if area > max:
27+
max = area
28+
index = c
29+
# 绘制
30+
if index >= 0:
31+
rect = cv.minAreaRect(contours[index])
32+
cv.ellipse(image, rect, (0, 255, 0), 2, 8)
33+
cv.circle(image, (np.int32(rect[0][0]), np.int32(rect[0][1])), 2, (255, 0, 0), 2, 8, 0)
34+
return image
35+
36+
37+
while(True):
38+
ret, frame = capture.read()
39+
if ret is True:
40+
cv.imshow("video-input", frame)
41+
result = process(frame)
42+
cv.imshow("result", result)
43+
c = cv.waitKey(50)
44+
#print(c)
45+
if c == 27: #ESC
46+
cv.imwrite("result.jpg", result)
47+
break
48+
else:
49+
break
50+
cv.waitKey(0)
51+
cv.destroyAllWindows()
52+

python/code_078/result.jpg

42.4 KB
Loading

python/code_079/opencv_079.py

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import numpy as np
2+
import cv2 as cv
3+
4+
cap = cv.VideoCapture('color_object.mp4')
5+
fgbg = cv.createBackgroundSubtractorMOG2(history=500, varThreshold=1000, detectShadows=False)
6+
while True:
7+
ret, frame = cap.read()
8+
fgmask = fgbg.apply(frame)
9+
background = fgbg.getBackgroundImage()
10+
cv.imshow('input', frame)
11+
cv.imshow('mask',fgmask)
12+
cv.imshow('background', background)
13+
k = cv.waitKey(10)&0xff
14+
if k == 27:
15+
break
16+
cap.release()
17+
cv.destroyAllWindows()

python/code_080/README.md

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
#### 视频分析 – 背景消除与前景ROI提取
2+
3+
通过视频中的背景进行建模,实现背景消除,生成mask图像,通过对mask二值图像分析实现对前景活动对象ROI区域的提取,是很多视频监控分析软件常用的手段之一,该方法很实时!整个步骤如下:
4+
1. 初始化背景建模对象GMM
5+
2. 读取视频一帧
6+
3. 使用背景建模消除生成mask
7+
4. 对mask进行轮廓分析提取ROI
8+
5. 绘制ROI对象
9+
10+
函数:
11+
12+
OpenCV中实现的背景模型提取算法有两种,一种是基于高斯混合模型GMM实现的背景提取,另外一种是基于最近邻KNN实现的。都有相关的API可以供开发者使用。
13+
**相关API:**
14+
```
15+
Ptr<BackgroundSubtractorMOG2> cv::createBackgroundSubtractorMOG2(
16+
int history = 500,
17+
double varThreshold = 16,
18+
bool detectShadows = true
19+
)
20+
```
21+
>参数解释如下:
22+
history表示过往帧数,500帧,选择history = 1就变成两帧差
23+
varThreshold表示像素与模型之间的马氏距离,值越大,只有那些最新的像素会被归到前景,值越小前景对光照越敏感。
24+
detectShadows 是否保留阴影检测,请选择False这样速度快点。
25+
26+
创建
27+
Ptr<BackgroundSubtractor> pBackSub = createBackgroundSubtractorMOG2();
28+
Ptr<BackgroundSubtractor> pBackSub = createBackgroundSubtractorKNN();
29+
30+
```python
31+
32+
# 创建背景提取器
33+
fgbg = cv.createBackgroundSubtractorMOG2(
34+
history=500, varThreshold=100, detectShadows=False)
35+
36+
37+
def process(image, opt=1):
38+
39+
# 提取前景mask
40+
mask = fgbg.apply(frame)
41+
line = cv.getStructuringElement(cv.MORPH_RECT, (1, 5), (-1, -1))
42+
mask = cv.morphologyEx(mask, cv.MORPH_OPEN, line)
43+
cv.imshow("mask", mask)
44+
# 轮廓提取, 发现最大轮廓
45+
out, contours, hierarchy = cv.findContours(mask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
46+
for c in range(len(contours)):
47+
area = cv.contourArea(contours[c])
48+
if area < 150:
49+
continue
50+
rect = cv.minAreaRect(contours[c])
51+
cv.ellipse(image, rect, (0, 255, 0), 2, 8)
52+
cv.circle(image, (np.int32(rect[0][0]), np.int32(rect[0][1])), 2, (255, 0, 0), 2, 8, 0)
53+
return image, mask
54+
55+
56+
```
57+
<img src=../code_080/input.png width=300>
58+
<img src=../code_080/mask.png width=300>
59+
<img src=../code_080/result.png width=300>

python/code_080/input.png

670 KB
Loading

python/code_080/mask.png

3.87 KB
Loading

python/code_080/opencv_080.py

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import numpy as np
2+
import cv2 as cv
3+
4+
cap = cv.VideoCapture('vtest.avi')
5+
fgbg = cv.createBackgroundSubtractorMOG2(
6+
history=500, varThreshold=100, detectShadows=False)
7+
8+
9+
def process(image, opt=1):
10+
mask = fgbg.apply(frame)
11+
line = cv.getStructuringElement(cv.MORPH_RECT, (1, 5), (-1, -1))
12+
mask = cv.morphologyEx(mask, cv.MORPH_OPEN, line)
13+
cv.imshow("mask", mask)
14+
# 轮廓提取, 发现最大轮廓
15+
out, contours, hierarchy = cv.findContours(mask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE)
16+
for c in range(len(contours)):
17+
area = cv.contourArea(contours[c])
18+
if area < 150:
19+
continue
20+
rect = cv.minAreaRect(contours[c])
21+
cv.ellipse(image, rect, (0, 255, 0), 2, 8)
22+
cv.circle(image, (np.int32(rect[0][0]), np.int32(rect[0][1])), 2, (255, 0, 0), 2, 8, 0)
23+
return image, mask
24+
25+
26+
while True:
27+
ret, frame = cap.read()
28+
cv.imwrite("input.png", frame)
29+
cv.imshow('input', frame)
30+
result, m_ = process(frame)
31+
cv.imshow('result', result)
32+
k = cv.waitKey(50)&0xff
33+
if k == 27:
34+
cv.imwrite("result.png", result)
35+
cv.imwrite("mask.png", m_)
36+
37+
break
38+
cap.release()
39+
cv.destroyAllWindows()

python/code_080/result.png

670 KB
Loading

0 commit comments

Comments
 (0)