简单学习了OpenCV,使用OpenCV框架对视频中的色块进行跟踪以及绘制轨迹
原视频
Source
图片
首先,我们使用下面的代码将Source.mp4中的一帧截取下来
import cv2
import numpy as np
cap = cv2.VideoCapture('Source.mp4')
#cap = cv2.VideoCapture('C:/Users/Test.mp4')
#创建属性为WINDOW_NORMAL,名字为'Video'的窗口
cv2.namedWindow('Video', cv2.WINDOW_NORMAL)
#设置窗口尺寸为640*480
cv2.resizeWindow('Video', 640, 480)
while True:
#每次从cap中读取一帧图像
ret, frame = cap.read()
#如果读取视频失败则退出循环
if not ret:
break
#正常读取显示图像帧
cv2.imshow('Video', frame)
#按下s保存图片(picture.jpg)并退出
if cv2.waitKey(1) == ord('s'):
cv2.imwrite('picture.jpg',frame)
break
cap.release()
cv2.destroyAllWindows()
HSV图片
使用以下代码将截取的图片调黑白图片,图片中只有一个白色矩形色块,将其保存并输出HSV值
# -*- coding:utf-8 -*-
import cv2
import numpy as np
"""
function:读取一张图片,显示出来,转化为HSV色彩空间,并通过滑块调节HSV阈值,实时显示
"""
cv2.namedWindow('BGR', cv2.WINDOW_NORMAL)
cv2.resizeWindow('BGR', 640, 480)
cv2.namedWindow('dst', cv2.WINDOW_NORMAL)
cv2.resizeWindow('dst', 640, 480)
image = cv2.imread('picture.jpg') # 根据路径读取一张图片,opencv读出来的是BGR模式
cv2.imshow("BGR", image) # 显示图片
hsv_low = np.array([0, 0, 0])
hsv_high = np.array([179, 255, 255])
# 下面几个函数,写得有点冗余
def h_low(value):
hsv_low[0] = value
def h_high(value):
hsv_high[0] = value
def s_low(value):
hsv_low[1] = value
def s_high(value):
hsv_high[1] = value
def v_low(value):
hsv_low[2] = value
def v_high(value):
hsv_high[2] = value
cv2.namedWindow('image',cv2.WINDOW_AUTOSIZE)
#H low:
# 0:指向整数变量的可选指针,该变量的值反映滑块的初始位置。
# 179:表示滑块可以达到的最大位置的值为179,最小位置始终为0。
#h_low:指向每次滑块更改位置时要调用的函数的指针,指针指向h_low元组,有默认值0。
cv2.createTrackbar('H low', 'image', 0, 179, h_low)
cv2.createTrackbar('H high', 'image', 0, 179, h_high)
cv2.createTrackbar('S low', 'image', 0, 255, s_low)
cv2.createTrackbar('S high', 'image', 0, 255, s_high)
cv2.createTrackbar('V low', 'image', 0, 255, v_low)
cv2.createTrackbar('V high', 'image', 0, 255, v_high)
while True:
dst = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) # BGR转HSV
dst = cv2.inRange(dst, hsv_low, hsv_high) # 通过HSV的高低阈值,提取图像部分区域
cv2.imshow('dst', dst)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
if cv2.waitKey(1) == ord('s'):
print(hsv_low,hsv_high)
cv2.imwrite('HSV_pic.jpg',dst)
cv2.destroyAllWindows()
视频
利用OpenCV将实时读取视频流,将每一帧的图像转换为hsv类型,标记HSV值为设置的值,使用findContours()函数找出轮廓,通过contourArea()函数,经过判断找出最大面积的那个轮廓,最后使用drawContours()函数画出轮廓。
import cv2
import numpy as np
cap = cv2.VideoCapture('Source.mp4')#入口
cv2.namedWindow('Video', cv2.WINDOW_NORMAL)
cv2.resizeWindow('Video', 640, 480)#窗口大小
lower_green = np.array([30,205,200]) #hsv值 # lower_green = np.array([30, 220,188])
upper_green = np.array([40,255,255]) # upper_green = np.array([34, 254,215])
while True:
ret, frame = cap.read() #每次从cap中读取一帧图像
if not ret: #如果读取视频失败则退出循环
break
hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
cv2.imshow('Video', frame) #正常读取显示图像帧
mask = cv2.inRange(hsv, lower_green, upper_green)
contours, hierarchy = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
#找最大面积的那个
max = 0.0
max_num = 0
if len(contours) > 1: # 找到面积最大的轮廓
for i in range(len(contours)):
c = cv2.contourArea(contours[i])
if c > max:
max = c
max_num = i
M = cv2.moments(contours[max_num])#中点
cx = int(M['m10']/M['m00'])#这两行是计算中心点坐标
cy = int(M['m01']/M['m00'])
print((cx, cy))
frame = cv2.circle(frame, (cx, cy), 3, (0, 0, 255), -1)
result=cv2.drawContours(frame, contours[max_num], -1, (0,0,255), 3)#最终图像
cv2.imshow('result',result)
if cv2.waitKey(1) == ord('q'):
cv2.imwrite('picture.jpg',frame)
break
#释放
cap.release()
cv2.destroyAllWindows()
mid_demo
绘制轨迹
首先获取视频的第一帧,找出轮廓的中点并保存在pot列表中,然后读取视频,依次计算并保存,使用line()函数在视频上层画线,最后使用add()函数将画的轨迹展示在原视频上。
import cv2
import numpy as np
cap = cv2.VideoCapture('hwk.mp4')
cv2.namedWindow('Video', cv2.WINDOW_NORMAL)
cv2.resizeWindow('Video', 640, 480)
#hsv值
lower_green = np.array([32,205,199]) # lower_green = np.array([30, 220,188])
upper_green = np.array([39,255,255]) # upper_green = np.array([34, 254,215])
#这里可以使用moments函数计算中点并保存
pot = [(121,123)]#保留点的位置
ret_old, frame_old = cap.read() #每次从cap中读取第一帧图像
hsv_old = cv2.cvtColor(frame_old, cv2.COLOR_BGR2HSV)
mask_L = np.zeros_like(frame_old)
while True:
ret_new, frame_new = cap.read() #每次从cap中读取一帧图像
if not ret_old: #如果读取视频失败则退出循环
break
hsv_new = cv2.cvtColor(frame_new, cv2.COLOR_BGR2HSV)
cv2.imshow('Video', frame_new) #正常读取显示图像帧
mask = cv2.inRange(hsv_new, lower_green, upper_green)
contours, hierarchy = cv2.findContours(mask.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
#找最大面积的那个
max = 0.0
max_num = 0
if len(contours) > 1: # 找到面积最大的轮廓
for i in range(len(contours)):
c = cv2.contourArea(contours[i])
if c > max:
max = c
max_num = i
#c = max(contours, key=cv2.contourArea)
M = cv2.moments(contours[max_num])#中点
cx = int(M['m10']/M['m00'])#这两行是计算中心点坐标
cy = int(M['m01']/M['m00'])
pot.append((cx,cy))
print((cx, cy))
a = 121
b = 123
for x, y in (pot):
mask_L = cv2.line(mask_L, (a,b),(x,y), (0, 0, 255), 2)#画直线
pot_old = cv2.circle(frame_old,(a,b),3,(0, 0, 255), -1)#画点
a = x
b = y
#pot_old = cv2.circle(frame_old, (cx, cy), 3, (0, 0, 255), -1)
result_old = cv2.drawContours(frame_new, contours[max_num], -1, (0,0,255), 3)
#print(contours[max_num])
# 更新上一帧的图像和追踪点
hsv_old = hsv_new.copy()
#frame_old = frame_new.copy()
img = cv2.add(mask_L, frame_new)
cv2.imshow('frame',img)
if cv2.waitKey(1) == ord('q'):
cv2.imwrite('picture.jpg',frame_old)
break
#释放
cap.release()
cv2.destroyAllWindows()
final_demo