上一篇博文实现了图片上目标的定位,并给出了较为详细的代码解释。这一篇在此基础上实现视频的图像处理,依旧是目标定位。
原理是选择合适的 HSV 阈值,选取特定颜色。当找到目标时,框选最大目标,并打印其中心位置。
代码如下:
#!/usr/bin/env python3
# -*- coding:utf-8 -*-
import cv2
import numpy as np
cap = cv2.VideoCapture(0) # 设置为视频捕获
cap.set(3, 640) # 设置图像宽度 640px
cap.set(4, 480) # 设置图像高度 480px
ret, frame = cap.read() # ret=True 读取成功,frame为读取的图像
rows, cols, channels = frame.shape # 获取行、列与通道数
print("video size: (%d x %d x %d) " % (rows, cols, channels))
thresh1 = np.array([0, 180, 180]) # 目标 HSV 低阈值
thresh2 = np.array([10, 255, 255]) # 目标 HSV 高阈值
def img_p(img_bgr):
img_hsv = cv2.cvtColor(img_bgr, cv2.COLOR_BGR2HSV) # 转换为 HSV
img_inthresh = cv2.inRange(img_hsv, thresh1, thresh2) # 找到满足阈值的目标
img_morph = img_inthresh.copy() # 复制图像
cv2.erode(img_morph, (3, 3), img_morph, iterations = 3) # 形态学腐蚀
cv2.dilate(img_morph, (3, 3), img_morph, iterations = 3) # 形态学膨胀
_, cnts, _ = cv2.findContours(img_morph, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # cnts = 目标的轮廓点数,多个目标则返回列表
if (len(cnts) != 0): # 只有一个目标
cnts_sort = sorted(cnts, key= cv2.contourArea, reverse= True) # 找到包含最大面积的轮廓
box = cv2.minAreaRect(cnts_sort[0]) # 绘制最小外接矩形
points = np.int0(cv2.boxPoints(box)) # 矩形的四个顶点坐标
cen_v = (points[0,0] + points[2,0]) / 2 # 最小外接矩形中心横坐标
cen_h = (points[0,1] + points[2,1]) / 2 # 最小外接矩形中心纵坐标
print("mid (" + str(cen_h) + " , " + str(cen_v) + ")")
dst = cv2.drawContours(img_bgr, [points], -1, (0, 255, 0), 2) # 在原图上添加最小外接矩形
else: # 没有目标直接返回原图像
dst = img_bgr
return dst
while(1):
ret, frame = cap.read() # 一直读取图像
dst = img_p(frame) # 图像处理
cv2.imshow('usb camera', dst) # 显示图像
k = cv2.waitKey(50)
if (k == ord('q')): # 按下 q 退出
break
cap.release()
cv2.destroyAllWindows()
运行效果: