在一些图像处理的应用中,通常需要提取具有同一特征的某一块,例如在一张苏南地图中寻找面积最大的湖(图中蓝色部分)。
本文以识别最大的拳头为例,来说明几个opencv函数的用法,介绍一种跟踪手部运动的方法。
(0)准备工作,打开摄像头,设置参数。
(1)根据肤色提取手部。
(2)彩色变灰色,灰色变二值化。
(3)轮廓提取。
(4)对比每个轮廓大小。
(5)将小于最大轮廓的连通域填黑。
(6)显示最大连通域。
(7)求最大连通域的坐标。
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
This program is debugged by Harden Qiu
"""
import cv2
import numpy as np
#肤色识别
def skin(frame):
lower = np.array([0, 40, 80], dtype="uint8")
upper = np.array([20, 255, 255], dtype="uint8")
converted = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
skinMask = cv2.inRange(converted, lower, upper)
skinMask = cv2.GaussianBlur(skinMask, (5, 5), 0)
skin = cv2.bitwise_and(frame, frame, mask=skinMask)
return skin
#求最大连通域的中心点坐标
def centroid(max_contour):
moment = cv2.moments(max_contour)
if moment['m00'] != 0:
cx = int(moment['m10'] / moment['m00'])
cy = int(moment['m01'] / moment['m00'])
return cx, cy
else:
return None
#主函数
def main():
capture = cv2.VideoCapture(0)
while capture.isOpened():
pressed_key = cv2.waitKey(1)
_, frame = capture.read()
frame=cv2.flip(frame,1)
#显示摄像头
cv2.imshow('Original',frame)
#皮肤粒子识别
frame = skin(frame)
#灰度
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
#高斯滤波
frame = cv2.GaussianBlur(frame, (5, 5), 0)
#二值化
ret, frame = cv2.threshold(frame, 50, 255, cv2.THRESH_BINARY)
#轮廓
_,contours,hierarchy = cv2.findContours(frame,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
print("number of contours:%d" % len(contours))
cv2.drawContours(frame, contours, -1, (0, 255, 255), 2)
#找到最大区域并填充
area = []
for i in range(len(contours)):
area.append(cv2.contourArea(contours[i]))
max_idx = np.argmax(area)
for i in range(max_idx - 1):
cv2.fillConvexPoly(frame, contours[max_idx - 1], 0)
cv2.fillConvexPoly(frame, contours[max_idx], 255)
#求最大连通域的中心坐标
cnt_centroid = centroid(contours[max_idx])
cv2.circle(contours[max_idx],cnt_centroid,5,[255,0,255],-1)
print("Centroid : " + str(cnt_centroid))
#处理后显示
cv2.imshow("Live",frame)
if pressed_key == 27:
break
cv2.destroyAllWindows()
capture.release()
if __name__ == '__main__':
main()
当只有一只手时,得到下面图像,左为原始图像,右为处理后图像。
当右两只手时,得到如下图像,可以看出,只保留了最大的那只手,并对手部空洞进行了填充。
为更进一步说明cv2.fillConvexPoly()函数,将脸部特征展于此处。从图中看出,脸内部的眼睛、眉毛等非肤色区域均作了填充。
本程序主要用于标记具有某种特征的区域,并跟踪其位置。
本程序一并给出肤色识别和求中心点的子函数程序,也就是说采用不同的物体识别算法可以得到不同的物体检测与位置跟踪,读者可根据其他资料进行修改来适应不同的情况。
本文只做学习研究!
如有疑问,可留言反馈或通过邮件交流([email protected])。