这里有一个想法。你知道如何使用opencv循环遍历视频的帧,对吧?那么,在while
循环的每个帧中,将接下来的一帧存储在变量中,并比较当前帧和未来帧之间的差异。
通过两个帧之间的差异,您可以检测移动的轮廓。假设我们用绿色在图像上绘制轮廓。
在while
循环之前定义一个空白数组作为热力图; 每次循环迭代,向热力图的每个坐标添加一定数量,其中该坐标在帧上是绿色的,并从热力图中去除某些数量,其中该坐标在图像上不是绿色的。
- 导入必要的模块:
import cv2
import numpy as np
- 定义一个函数来处理两帧之间的差异,使其更容易检测轮廓。这些值可以根据您的需求进行调整:
def process(img):
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_blur = cv2.GaussianBlur(img_gray, (5, 5), 25)
img_canny = cv2.Canny(img_blur, 5, 50)
kernel = np.ones((3, 3))
img_dilate = cv2.dilate(img_canny, kernel, iterations=4)
img_erode = cv2.erode(img_dilate, kernel, iterations=1)
return img_erode
定义一个函数,该函数将接收两个帧之间差异的处理图像和您想要在其上绘制轮廓的图像。它将返回在图像上绘制轮廓(绿色)后的图像:
def get_contours(img, img_original):
img_contours = img_original.copy()
contours, hierarchies = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
cv2.drawContours(img_contours, contours, -1, (0, 255, 0), -1)
return img_contours
- 定义捕获设备并在
while
循环之前读取两个帧,第一个帧是每次迭代while
循环的当前帧,第二个帧是每次迭代while
循环的未来帧。同时,为热图定义空白图像heat_map
:
cap = cv2.VideoCapture("Bar fight security cam.mp4")
success, img1 = cap.read()
success, img2 = cap.read()
heat_map = np.zeros(img1.shape[:-1])
在while
循环中,找到两帧之间的差异,并使用绘制在其上的差异轮廓获取每个循环的当前帧:
while success:
diff = cv2.absdiff(img1, img2)
img_contours = get_contours(process(diff), img1)
- 在先前定义的
get_contours
函数返回的图像上,对于每个绿色区域,将其所在的heat_map
坐标全部加上数字3
,对于非绿色区域则减去3
。为确保不会出现小于0
或大于255
的值,请将边界应用于热度图:
heat_map[np.all(img_contours == [0, 255, 0], 2)] += 3
heat_map[np.any(img_contours != [0, 255, 0], 2)] -= 3
heat_map[heat_map < 0] = 0
heat_map[heat_map > 255] = 255
将
heat_map
数组转换为灰度图像,然后再转换为热度图像:
img_mapped = cv2.applyColorMap(heat_map.astype('uint8'), cv2.COLORMAP_JET)
最后,显示帧并检索下一次迭代的帧:
cv2.imshow("Original", img1)
cv2.imshow("Heat Map", img_mapped)
img1 = img2
success, img2 = cap.read()
if cv2.waitKey(1) == ord('q'):
break
总之:
import cv2
import numpy as np
def process(img):
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_blur = cv2.GaussianBlur(img_gray, (5, 5), 25)
img_canny = cv2.Canny(img_blur, 5, 50)
kernel = np.ones((3, 3))
img_dilate = cv2.dilate(img_canny, kernel, iterations=4)
img_erode = cv2.erode(img_dilate, kernel, iterations=1)
return img_erode
def get_contours(img, img_original):
img_contours = img_original.copy()
contours, hierarchies = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
cv2.drawContours(img_contours, contours, -1, (0, 255, 0), -1)
return img_contours
cap = cv2.VideoCapture("Bar fight security cam.mp4")
success, img1 = cap.read()
success, img2 = cap.read()
heat_map = np.zeros(img1.shape[:-1])
while success:
diff = cv2.absdiff(img1, img2)
img_contours = get_contours(process(diff), img1)
heat_map[np.all(img_contours == [0, 255, 0], 2)] += 3
heat_map[np.any(img_contours != [0, 255, 0], 2)] -= 3
heat_map[heat_map < 0] = 0
heat_map[heat_map > 255] = 255
img_mapped = cv2.applyColorMap(heat_map.astype('uint8'), cv2.COLORMAP_JET)
cv2.imshow("Original", img1)
cv2.imshow("Heat Map", img_mapped)
img1 = img2
success, img2 = cap.read()
if cv2.waitKey(1) == ord('q'):
break