基于OpenCV的图像识别与追踪
num = 1 #计数器num2 = 0num3 = 0num,num2,num3分别为视频中三个模型的计数器flag1-flag6为三个模型的互斥锁。
Task1
import cv2
import numpy as np
# 读取模板
template1 = cv2.imread("Task1-template/template1.jpg")
template2 = cv2.imread("Task1-template/template2.jpg")
template3 = cv2.imread("Task1-template/template3.jpg")
template4 = cv2.imread("Task1-template/template4.jpg")
template5 = cv2.imread("Task1-template/template5.jpg")
template6 = cv2.imread("Task1-template/template6.jpg")
template7 = cv2.imread("Task1-template/template7.jpg")
template8 = cv2.imread("Task1-template/template8.jpg")
template9 = cv2.imread("Task1-template/template9.jpg")
template10 = cv2.imread("Task1-template/template10.jpg")
# 建立一个列表保存模板(后面会调用)
template = [template1, template2, template3, template4, template5, template6,
template7,template8,template9,template10]
# 打开视频文件
cap = cv2.VideoCapture("Task1-Tracking.mp4")
while True:
# 读取视频帧
ret, frame = cap.read()
if not ret: #如果没有获取去到帧就结束while
break # 视频结束
# resize每一帧(调整每一帧的格式大小)
(h, w) = frame.shape[:2]
width = 300
r = width / float(w)
dim = (width, int(h * r))
dim2 = (50, int((h * r)/10))
frame = cv2.resize(frame, dim, interpolation=cv2.INTER_AREA)
# 使用模板匹配
for i in template: #从template列表中循环调用模板(把每个模板从template列表取出,后面进行匹配)
# resize模板(调整每一个模板的格式大小,调整格式大小是为了能够有更高的匹配度)
i = cv2.resize(i, dim2, interpolation=cv2.INTER_AREA)
result = cv2.matchTemplate(frame, i, cv2.TM_CCOEFF_NORMED)
# 获取匹配结果的最小值、最大值,以及它们的位置
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
# 判断是否匹配成功
threshold=0.58 #匹配度
if max_val >= threshold:
# 在原始图像上标记匹配区域
h, w = i.shape[:2]
top_left = max_loc
bottom_right = (top_left[0] + w, top_left[1] + h)
cv2.rectangle(frame, top_left, bottom_right, (0, 255, 0), 2)
# 显示结果
cv2.imshow('Matching Result', frame)
cv2.waitKey(1)
# 按 'q' 键退出循环
# if cv2.waitKey(30) & 0xFF == ord('q'):
# break
# 释放视频流和关闭窗口
cap.release()
cv2.destroyAllWindows()
代码详解
1.读取模板模块:
# 读取模板
template1 = cv2.imread("Task1-template/template1.jpg")
template2 = cv2.imread("Task1-template/template2.jpg")
template3 = cv2.imread("Task1-template/template3.jpg")
template4 = cv2.imread("Task1-template/template4.jpg")
template5 = cv2.imread("Task1-template/template5.jpg")
template6 = cv2.imread("Task1-template/template6.jpg")
template7 = cv2.imread("Task1-template/template7.jpg")
template8 = cv2.imread("Task1-template/template8.jpg")
template9 = cv2.imread("Task1-template/template9.jpg")
template10 = cv2.imread("Task1-template/template10.jpg")
通过cv2.imread()直接读入每个模板
2.模板列表:
# 建立一个列表保存模板(后面会调用)
template = [template1, template2, template3, template4, template5, template6,template7,template8,template9,template10]
建立一个列表来保存模板,后面可以通过for语句来调用列表里面的每一个模板
i in template: #从template列表中循环调用模板(把每个模板从template列表取出,后面进行匹配)
3.视频文件读取模块:
# 打开视频文件
cap = cv2.VideoCapture("Task1-Tracking.mp4")
while True:
# 读取视频帧
ret, frame = cap.read()
if not ret: #如果没有获取到帧就结束while
break # 视频结束
cv2.VideoCapature()来打开视频文件
ret,frame = cap.read() 来读取视频帧
read()有两个参数:
1.ret:一个布尔值,表示是否成功读取了帧。如果成功读取,则为 True;否则为 False
2.frame: 一个表示当前视频帧的图像矩阵(NumPy数组)
4.调整每一帧:
# resize每一帧(调整每一帧的格式大小)
(h, w) = frame.shape[:2]
width = 300
r = width / float(w)
dim = (width, int(h * r))
dim2 = (50, int((h * r)/10))
frame = cv2.resize(frame, dim, interpolation=cv2.INTER_AREA)
调整每一帧的格式大小主要调节dim中的参数
# resize模板(调整每一个模板的格式大小,调整格式大小是为了能够有更高的匹配度)
i = cv2.resize(i, dim2, interpolation=cv2.INTER_AREA)
调整每一个模板的格式大小,调整格式大小是为了能够有更高的匹配度(threshold),dim2在上面就已经给出了,写在此处也行。
5.模板匹配模块:
result = cv2.matchTemplate(frame, i, cv2.TM_CCOEFF_NORMED)
# 获取匹配结果的最小值、最大值,以及它们的位置
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
cv2.matchTemplate()函数是用来匹配模板的函数
frame是帧,模板要在上面进行匹配
i是从template列表中取出的一个模板,用于模板匹配
cv2.TM_CCOEFF_NORMED是一种模板匹配的算法
cv2.minMaxLoc() 是 OpenCV 中用于在图像中找到最小值、最大值及其对应位置的函数
min_val, max_val, min_loc, max_loc:
- minVal: 输入图像中的最小值。
- maxVal: 输入图像中的最大值。
- minLoc: 最小值的坐标位置,以 (x, y) 的形式表示。
- maxLoc: 最大值的坐标位置,以 (x, y) 的形式表示。
6.标记追踪框:
# 判断是否匹配成功
threshold=0.58 #匹配度
if max_val >= threshold:
# 在原始图像上标记匹配区域
h, w = i.shape[:2]
top_left = max_loc
bottom_right = (top_left[0] + w, top_left[1] + h)
cv2.rectangle(frame, top_left, bottom_right, (0, 255, 0), 2)
大于threshold(匹配度)就代表匹配成功
h, w = i.shape[:2]
top_left = max_loc
bottom_right = (top_left[0] + w, top_left[1] + h)
cv2.rectangle(frame, top_left, bottom_right, (0, 255, 0), 2)
此代码块负责在原图上标记出匹配的区域
7.显示结果:
# 显示结果
cv2.imshow('Matching Result', frame)
cv2.waitKey(1)
cv2.imshow(winname, mat)是OpenCV 中用于显示图像的函数
winname: 窗口的名称
mat: 要显示的图像矩阵(NumPy 数组)
cv2.waitKey(delay)是 OpenCV 中用于在图像窗口上等待用户按键的函数
delay: 等待时间(以毫秒为单位)
8.释放视频流和窗口:
# 释放视频流和关闭窗口
cap.release()
cv2.destroyAllWindows()
效果展示


Task2
主要功能:
实现对零件的目标追踪,并在零件周围产生追踪框,对零件的来回移动次数进行统计
设计难点:
通过对两端的零件模板匹配来确定是否到达两端,如果两端都到达记为一次。计数功能需要互斥算法来实现并且模板需要调整相应规格才能更好的进行模板匹配。为了能够更好的调整模板的规格特别编写了一个Python文件"test.py"。
模板展示:
1.追踪模板:



2.统计模板:





完整代码
import cv2
import numpy as np
# 读取计数模板
template1 = cv2.imread('Task2-template/template1.jpg')
template2 = cv2.imread('Task2-template/template2.jpg')
template3 = cv2.imread('Task2-template/template3.jpg')
template4 = cv2.imread('Task2-template/template4.jpg')
template5 = cv2.imread('Task2-template/template5.jpg')
# 读取追踪模板
template6 = cv2.imread("Task2-template/template6.jpg")
template7 = cv2.imread("Task2-template/template7.jpg")
template8 = cv2.imread("Task2-template/template8.jpg")
template = [template6, template7, template8]
# 打开视频文件
cap = cv2.VideoCapture("Task2-Count.mp4")
num = 1 #计数器
num2 = 0
num3 = 0
flag1 = False
flag2 = False
flag3 = False
flag4 = False
flag5 = False
flag6 = False
while True:
# 取当前帧
ret, frame = cap.read()
if not ret:
break # 视频结束
# cv2.imshow("template",template6) # 查看模板
# resize每一帧
(h, w) = frame.shape[:2]
width = 600
r = width / float(w)
dim = (width, int(h * r))
dim2 = (100, int(h*r))
dim3 = (140, int(h*r))
dim4 = (76, int((h * r) / 1.6))
dim5 = (110, int((h * r) / 2))
dim6 = (115, int((h * r) / 1.1))
Dim=[dim4, dim5, dim6]
frame = cv2.resize(frame, dim, interpolation=cv2.INTER_AREA)
# resize模板
template1 = cv2.resize(template1, dim2, interpolation=cv2.INTER_AREA)
template2 = cv2.resize(template2, dim2, interpolation=cv2.INTER_AREA)
template3 = cv2.resize(template3, dim2, interpolation=cv2.INTER_AREA)
template4 = cv2.resize(template4, dim2, interpolation=cv2.INTER_AREA)
template5 = cv2.resize(template5, dim3, interpolation=cv2.INTER_AREA)
# 判断匹配第一张模板是否匹配成功
result = cv2.matchTemplate(frame, template1, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
threshold = 0.95
if max_val >= threshold :
flag1 = True
# 判断匹配第二张模板是否匹配成功
result = cv2.matchTemplate(frame, template2, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
threshold = 0.92
if max_val >= threshold :
flag2 = True
# 判断匹配第三张模板是否匹配成功
result = cv2.matchTemplate(frame, template3, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
threshold = 0.95
if max_val >= threshold:
flag3 = True
# 判断匹配第四张模板是否匹配成功
result = cv2.matchTemplate(frame, template4, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
threshold = 0.91
if max_val >= threshold:
flag4 = True
# 判断匹配第五张模板是否匹配成功
result = cv2.matchTemplate(frame, template5, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
threshold = 0.92
if max_val >= threshold:
flag5 = True
elif max_val < threshold:
flag6 = True
# 统计次数
# 统计模型1的次数
if(flag1==True and flag2==True):
num = num+1
flag1 = False
flag2 = False
# 统计模型2的次数
if (flag3 == True and flag4 == True):
num2 = num2 + 1
flag3 = False
flag4 = False
# 统计模型3的次数
if (flag5 == True and flag6 == True):
num3 = num3 + 1
flag5 = False
flag6 = False
# # 按下n键可以查看当前次数
# key = cv2.waitKey(1)
# if key == ord("n"):
if num3 > 1:
print(((num)//2)+(num2//2)+(num3//4))
elif num2 > 1:
print(((num)//2)+(num2//2))
else:
print(num//2)
# 添加统计数字
image = np.zeros((500, 500, 3), dtype=np.uint8) # Black background
if num3 > 1:
text = f"Count num={((num//2)+(num2//2)+(num3//4))}"
elif num2 > 1:
text = f"Count num={((num//2)+(num2//2))}"
else:
text = f"Count num={(num//2)}"
font = cv2.FONT_HERSHEY_SIMPLEX
font_scale = 0.7
font_thickness = 2
font_color = (255, 0, 0)
text_size = cv2.getTextSize(text, font, font_scale, font_thickness)[0]
text_position = ((image.shape[1] - text_size[0] + 50) // 2,
(image.shape[0] + text_size[1] + 100) // 2)
cv2.putText(frame, text, text_position, font, font_scale, font_color, font_thickness)
# cv2.imshow('frame',frame) # 展示每一帧
# cv2.waitKey(0)
for i in range(3):
# resize模板
Template = cv2.resize(template[i], Dim[i], interpolation=cv2.INTER_AREA)
result = cv2.matchTemplate(frame, Template, cv2.TM_CCOEFF_NORMED)
# 获取匹配结果的最小值、最大值,以及它们的位置
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
# 判断是否匹配成功
if(i==2):
threshold =0.7
else:
threshold = 0.85
if max_val >= threshold:
# 在原始图像上标记匹配区域
h, w = Template.shape[:2]
top_left = max_loc
bottom_right = (top_left[0] + w, top_left[1] + h)
cv2.rectangle(frame, top_left, bottom_right, (0, 255, 0), 2)
# cv2.imshow("1",Template) # 查看模板
# 显示结果
cv2.imshow('Matching Result', frame)
cv2.waitKey(1)
print(((num//2)+(num2//2)+(num3//4)))
cap.release()
cv2.destroyAllWindows()
代码详解
1.读取模板:
# 读取计数模板
template1 = cv2.imread('Task2-template/template1.jpg')
template2 = cv2.imread('Task2-template/template2.jpg')
template3 = cv2.imread('Task2-template/template3.jpg')
template4 = cv2.imread('Task2-template/template4.jpg')
template5 = cv2.imread('Task2-template/template5.jpg')
# 读取追踪模板
template6 = cv2.imread("Task2-template/template6.jpg")
template7 = cv2.imread("Task2-template/template7.jpg")
template8 = cv2.imread("Task2-template/template8.jpg")
template = [template6, template7, template8]
使用cv2.imread()读入计数模板和追踪模板,将追踪模板存入列表(template)后面通过for语言来调用列表里面的模板
2.打开视频文件:
# 打开视频文件
cap = cv2.VideoCapture("Task2-Count.mp4")
3.初始定义:
num = 1 #计数器
num2 = 0
num3 = 0
flag1 = False
flag2 = False
flag3 = False
flag4 = False
flag5 = False
flag6 = False
num,num2,num3分别为视频中三个模型的计数器
flag1-flag6为三个模型的互斥锁
4.读入每一帧:
while True:
# 取当前帧
ret, frame = cap.read()
if not ret:
break # 视频结束
通过while循环和read()函数来读入每一帧
5.调整规格:
# resize每一帧
(h, w) = frame.shape[:2]
width = 600
r = width / float(w)
dim = (width, int(h * r))
dim2 = (100, int(h*r))
dim3 = (140, int(h*r))
dim4 = (76, int((h * r) / 1.6))
dim5 = (110, int((h * r) / 2))
dim6 = (115, int((h * r) / 1.1))
Dim=[dim4, dim5, dim6]
frame = cv2.resize(frame, dim, interpolation=cv2.INTER_AREA)
# resize模板
template1 = cv2.resize(template1, dim2, interpolation=cv2.INTER_AREA)
template2 = cv2.resize(template2, dim2, interpolation=cv2.INTER_AREA)
template3 = cv2.resize(template3, dim2, interpolation=cv2.INTER_AREA)
template4 = cv2.resize(template4, dim2, interpolation=cv2.INTER_AREA)
template5 = cv2.resize(template5, dim3, interpolation=cv2.INTER_AREA)
dim-dim6是六个不同的规格,用于调整模板和帧以达到更高的匹配度
6.判断计数模板是否匹配成功:
# 判断匹配第一张模板是否匹配成功
result = cv2.matchTemplate(frame, template1, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
threshold = 0.95
if max_val >= threshold :
flag1 = True
# 判断匹配第二张模板是否匹配成功
result = cv2.matchTemplate(frame, template2, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
threshold = 0.92
if max_val >= threshold :
flag2 = True
# 判断匹配第三张模板是否匹配成功
result = cv2.matchTemplate(frame, template3, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
threshold = 0.95
if max_val >= threshold:
flag3 = True
# 判断匹配第四张模板是否匹配成功
result = cv2.matchTemplate(frame, template4, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
threshold = 0.91
if max_val >= threshold:
flag4 = True
# 判断匹配第五张模板是否匹配成功
result = cv2.matchTemplate(frame, template5, cv2.TM_CCOEFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
threshold = 0.92
if max_val >= threshold:
flag5 = True
elif max_val < threshold:
flag6 = True
通过cv2.matchTemplate()来匹配模板
cv2.TM_CCOEFF_NORMED是一种模板匹配的算法
下面是六种模板匹配算法:


cv2.minMaxLoc() 是 OpenCV 中用于在图像中找到最小值、最大值及其对应位置的函数
min_val, max_val, min_loc, max_loc:
- minVal: 输入图像中的最小值。
- maxVal: 输入图像中的最大值。
- minLoc: 最小值的坐标位置,以 (x, y) 的形式表示。
- maxLoc: 最大值的坐标位置,以 (x, y) 的形式表示。
7.统计次数
# 统计次数
# 统计模型1的次数
if(flag1==True and flag2==True):
num = num+1
flag1 = False
flag2 = False
# 统计模型2的次数
if (flag3 == True and flag4 == True):
num2 = num2 + 1
flag3 = False
flag4 = False
# 统计模型3的次数
if (flag5 == True and flag6 == True):
num3 = num3 + 1
flag5 = False
flag6 = False
# # 按下n键可以查看当前次数
# key = cv2.waitKey(1)
# if key == ord("n"):
if num3 > 1:
print(((num)//2)+(num2//2)+(num3//4))
elif num2 > 1:
print(((num)//2)+(num2//2))
else:
print(num//2)
通过互斥算法来统计各个模型下零件的往返次数
8.显示次数:
# 添加统计数字
image = np.zeros((500, 500, 3), dtype=np.uint8) # Black background
if num3 > 1:
text = f"Count num={((num//2)+(num2//2)+(num3//4))}"
elif num2 > 1:
text = f"Count num={((num//2)+(num2//2))}"
else:
text = f"Count num={(num//2)}"
font = cv2.FONT_HERSHEY_SIMPLEX
font_scale = 0.7
font_thickness = 2
font_color = (255, 0, 0)
text_size = cv2.getTextSize(text, font, font_scale, font_thickness)[0]
text_position = ((image.shape[1] - text_size[0] + 50) // 2, (image.shape[0] + text_size[1] + 100) // 2)
cv2.putText(frame, text, text_position, font, font_scale, font_color, font_thickness)
通过cv2.getTextSize()和cv2.putText()实现显示次数
font_scale 调整字体大小
font_thickness 调整字体粗细
font_color 调整字体颜色
text_size 调整字体尺寸
text_position 调整字体位置
9.判断追踪模板是否匹配成功:
for i in range(3):
# resize模板
Template = cv2.resize(template[i], Dim[i], interpolation=cv2.INTER_AREA)
result = cv2.matchTemplate(frame, Template, cv2.TM_CCOEFF_NORMED)
# 获取匹配结果的最小值、最大值,以及它们的位置
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
# 判断是否匹配成功
if(i==2):
threshold =0.7
else:
threshold = 0.85
if max_val >= threshold:
# 在原始图像上标记匹配区域
h, w = Template.shape[:2]
top_left = max_loc
bottom_right = (top_left[0] + w, top_left[1] + h)
cv2.rectangle(frame, top_left, bottom_right, (0, 255, 0), 2)
判断追踪模板是否匹配成功,如果匹配成功则画出追踪框
8.释放视频流和窗口:
# 释放视频流和关闭窗口
cap.release()
cv2.destroyAllWindows()
效果展示



火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)