提示:本项目是由微信公众号:小白学视觉,中Opencv视觉实战项目里为源文,等下也会分享链接。有兴趣的小伙伴们可以关注哦,里面还有很多的基础视觉项目,我个人觉得还是很有意思的。
例如:非常感谢微信公众号:小白学视觉,提供的开源的openCV视觉项目。链接:小白学视觉 有兴趣的小伙伴赶紧去关注吧。
没有添加库的记得到控制台添加这两个库哦,安装非常简单,下面也给出了下载方式,不然会面临报错的风险。
通过pip下载方式:
• pip install opencv
• pip install numpy
import cv2 as cv
import numpy as np
开源中的图像图片:
导入图像
img_path = "图片地址"
# 读取图片
img = cv.imread(img_path)
# 显示图片
cv.imshow('palm image',img)
cv.waitKey(0)
# 将BGR(蓝色,绿色,红色)图像更改为HSV(色相,饱和度,值)
hsvim = cv.cvtColor(img, cv.COLOR_BGR2HSV)
# 设置HSV中的肤色范围下限
lower = np.array([0, 48, 80], dtype="uint8")
# 设置HSV中的肤色范围上限
upper = np.array([20, 255, 255], dtype="uint8")
# 在HSV色彩空间的上下像素值范围内检测皮肤
skinRegionHSV = cv.inRange(hsvim, lower, upper)
# 进行均值滤波
blurred = cv.blur(skinRegionHSV, (2, 2))
# 去噪
ret, thresh = cv.threshold(blurred, 0, 255, cv.THRESH_BINARY)
# 寻找轮廓
contours, hierarchy = cv.findContours(mask_img, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
# 寻找最大轮廓 cv.contourArea()计算轮廓面积
contours = max(contours, key=lambda x: cv.contourArea(x))
# 寻找凸包返回点并绘制凸包的轮廓
hull = cv.convexHull(contours)
# 寻找凸包点地址的索引并绘制凸包的轮廓
hull = cv.convexHull(contours, returnPoints=False)
# 计算轮廓凸缺陷
defects = cv.convexityDefects(contours, hull)
原理啥的大家自行到原文中去看吧,再来一次链接:小白学视觉
# 手指标志数
cnt = 0
# 获取缺陷行数
for i in range(defects.shape[0]):
# 获取该行所有列的值(起点、终点、最远点、到最远点的大概距离)
s, e, f, d = defects[i][0]
# 获取起点坐标
start = tuple(contours[s][0])
# 获取终点坐标
end = tuple(contours[e][0])
# 获取最远点坐标
far = tuple(contours[f][0])
# 计算a的边长
a = np.sqrt((end[0] - start[0]) ** 2 + (end[1] - start[1]) ** 2)
# 计算b的边长
b = np.sqrt((far[0] - start[0]) ** 2 + (far[1] - start[1]) ** 2)
# 计算c的边长
c = np.sqrt((end[0] - far[0]) ** 2 + (end[1] - far[1]) ** 2)
# 计算两根手指的夹角
angle = np.arccos((b ** 2 + c ** 2 - a ** 2) / (2 * b * c))
# 如果夹角小于90度,我们会将其视为手指
if angle <= np.pi / 2:
# 手指数加1
cnt += 1
# 在原图上绘制圆 颜色:蓝色
cv.circle(img, far, 4, [0, 0, 255], -1)
# 检测到手指
if cnt > 0:
# 自加
cnt = cnt + 1
在这里其实对环境的要求是比较高的,而且再检测时,对一只手指头检测也并不是特别的灵敏,这还需要更为细致的调整。
import cv2 as cv
import numpy as np
# 检测皮肤肤色Mask
def skinmask(img):
# 将BGR(蓝色,绿色,红色)图像更改为HSV(色相,饱和度,值)
hsvim = cv.cvtColor(img, cv.COLOR_BGR2HSV)
# 设置HSV中的肤色范围下限
lower = np.array([0, 48, 80], dtype="uint8")
# 设置HSV中的肤色范围上限
upper = np.array([20, 255, 255], dtype="uint8")
# 在HSV色彩空间的上下像素值范围内检测皮肤
skinRegionHSV = cv.inRange(hsvim, lower, upper)
# 进行均值滤波
blurred = cv.blur(skinRegionHSV, (2, 2))
# 去噪
ret, thresh = cv.threshold(blurred, 0, 255, cv.THRESH_BINARY)
return thresh
# 轮廓线绘制
def getcnthull(mask_img):
# 寻找轮廓
contours, hierarchy = cv.findContours(mask_img, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)
# 寻找最大轮廓 cv.contourArea()计算轮廓面积
contours = max(contours, key=lambda x: cv.contourArea(x))
# 寻找凸包返回点并绘制凸包的轮廓
hull = cv.convexHull(contours)
return contours, hull
# 凸包缺陷检测 手掌与凸包检测轮廓线的任何偏离的地方都可以视为凸度缺陷
def getdefects(contours):
# 寻找凸包点地址的索引并绘制凸包的轮廓
hull = cv.convexHull(contours, returnPoints=False)
# 计算轮廓凸缺陷
defects = cv.convexityDefects(contours, hull)
return defects
if __name__ == '__main__':
xuan = input("本案例可以实现图像和实时视频的手指检测:\n"
"1.输入0进行视频检测:\n"
"2,输入绝对地址的图片,进行图片检测:")
if xuan == "0":
# vc = cv2.VideoCapture(0) 参数是0,表示打开笔记本的内置摄像头,
# 参数是filename(视频文件路径)则打开视频
cap = cv.VideoCapture(0)
else:
cap = cv.VideoCapture(xuan)
while cap.isOpened():
# 读取视频数据
_, img = cap.read()
try:
# 调用肤色检测函数
mask_img = skinmask(img)
# 调用肤色绘制
contours, hull = getcnthull(mask_img)
# 轮廓绘制 颜色:红色 宽度:2
cv.drawContours(img, [contours], -1, (255, 0, 0), 2)
# 包点轮廓绘制 颜色:绿色 宽度:2
cv.drawContours(img, [hull], -1, (0, 255, 0), 2)
# 调用凸包缺陷函数
defects = getdefects(contours)
# 如果缺陷不为空
if defects is not None:
# 手指标志数
cnt = 0
# 获取缺陷行数
for i in range(defects.shape[0]):
# 获取该行所有列的值(起点、终点、最远点、到最远点的大概距离)
s, e, f, d = defects[i][0]
# 获取起点坐标
start = tuple(contours[s][0])
# 获取终点坐标
end = tuple(contours[e][0])
# 获取最远点坐标
far = tuple(contours[f][0])
# 计算a的边长
a = np.sqrt((end[0] - start[0]) ** 2 + (end[1] - start[1]) ** 2)
# 计算b的边长
b = np.sqrt((far[0] - start[0]) ** 2 + (far[1] - start[1]) ** 2)
# 计算c的边长
c = np.sqrt((end[0] - far[0]) ** 2 + (end[1] - far[1]) ** 2)
# 计算两根手指的夹角
angle = np.arccos((b ** 2 + c ** 2 - a ** 2) / (2 * b * c))
# 如果夹角小于90度,我们会将其视为手指
if angle <= np.pi / 2:
# 手指数加1
cnt += 1
# 在原图上绘制圆 颜色:蓝色
cv.circle(img, far, 4, [0, 0, 255], -1)
# 检测到手指
if cnt > 0:
# 自加
cnt = cnt + 1
# 在图像上显示检测到的手指个数
cv.putText(img, str(cnt), (0, 50), cv.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2, cv.LINE_AA)
# 显示图像
cv.imshow("img", img)
except:
pass
# 按ESC键退出
if cv.waitKey(1) == 27:
break
# 释放内存
cap.release()
cv.destroyAllWindows()
这是一个非常有意思的OpenCV视觉项目,哪怕是一个想我这样的视觉小白也能看得懂。不过视觉是个很深的学问,如果大家对这个有兴趣,坚持下去肯定很有意思。我是一个喜欢发现各种开源项目的路人刘。