东莞网站制作搭建,网站怎么php做微信登录,微信推广图片,抖音制作图片的软件文章目录 1、功能描述2、代码实现3、效果展示4、完整代码5、涉及到的库函数cv2.inRange 6、参考 1、功能描述
给出一张仅含有手指的图片#xff0c;判断图片中有多少根手指
2、代码实现
导入库函数#xff0c;图像预处理
import numpy as np
import cv2 as cv
img cv.im… 文章目录 1、功能描述2、代码实现3、效果展示4、完整代码5、涉及到的库函数cv2.inRange 6、参考 1、功能描述
给出一张仅含有手指的图片判断图片中有多少根手指
2、代码实现
导入库函数图像预处理
import numpy as np
import cv2 as cv
img cv.imread(./5.png)
mask_img skinmask(img)
cv.imwrite(mask_img.jpg, mask_img)其中 def skinmask 实现如下
def skinmask(img):hsvim cv.cvtColor(img, cv.COLOR_BGR2HSV)lower np.array([0, 48, 80], dtype uint8)upper np.array([20, 255, 255], dtype uint8)skinRegionHSV cv.inRange(hsvim, lower, upper)cv.imwrite(skinRegionHSV.jpg, skinRegionHSV)blurred cv.blur(skinRegionHSV, (2,2))ret, thresh cv.threshold(blurred,0,255,cv.THRESH_BINARY)return thresh先转化为 HSV 彩色模式然后 cv2.inRange 二值化处理接着模糊二值化
skinRegionHSV.jpg mask_img.jpg
接下里计算轮廓和凸包
contours, hull getcnthull(mask_img)cv.drawContours(img, [contours], -1, (255,255,0), 2)
cv.imwrite(contours.jpg, img)cv.drawContours(img, [hull], -1, (0, 255, 255), 2)
cv.imwrite(hull.jpg, img)其中 def getcnthull 实现如下
def getcnthull(mask_img):contours, hierarchy cv.findContours(mask_img, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)contours max(contours, keylambda x: cv.contourArea(x))hull cv.convexHull(contours)return contours, hull可以看到凸包是通过计算最大面积的轮廓计算得到的
轮廓 contours.jpg 凸包 hull.jpg 接着计算凸缺陷也即介于凸包和轮廓间的区域
defects getdefects(contours)其中 def getdefects 的实现如下
def getdefects(contours):hull cv.convexHull(contours, returnPointsFalse)defects cv.convexityDefects(contours, hull)return defects遍历凸缺陷计算角度判断是否为手指夹缝输出手指个数
if defects is not None:cnt 0for i in range(defects.shape[0]): # calculate the angles, e, f, d defects[i][0]start tuple(contours[s][0])end tuple(contours[e][0])far tuple(contours[f][0])a np.sqrt((end[0] - start[0]) ** 2 (end[1] - start[1]) ** 2)b np.sqrt((far[0] - start[0]) ** 2 (far[1] - start[1]) ** 2)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)) # cosine theoremif angle np.pi / 2: # angle less than 90 degree, treat as fingerscnt 1cv.circle(img, far, 4, [0, 0, 255], -1)if cnt 0:cnt cnt1cv.putText(img, str(cnt), (0, 50), cv.FONT_HERSHEY_SIMPLEX,1, (255, 0, 0) , 2, cv.LINE_AA)
cv.imshow(img, img)
cv.imwrite(fresult_{str(cnt)}.jpg, img)
cv.waitKey()
cv.destroyAllWindows()其中 angle 的计算原理如下 当然仔细看代码这图和代码中对应的字母有差异代码中 start 到 end 是 a 对应上图的 c代码中 start 到 far 和 end 到 far 为 b 和 c 对应上图的 a 和 b 小于 90 度我们才认为是手指
3、效果展示
5 根手指
输入
输出 4 根手指 3 根手指 2 根手指 1 根手指 翻车 可以看到几个缺点
十分依赖前处理前处理不行轮廓不对后续结果判断则会相应的出现问题
只有一个手指的时候或者握拳的时候这套流程应该是判断不出来有几根手指的
4、完整代码
import cv2
import numpy as np
import cv2 as cvdef skinmask(img):hsvim cv.cvtColor(img, cv.COLOR_BGR2HSV)lower np.array([0, 48, 80], dtype uint8)upper np.array([20, 255, 255], dtype uint8)skinRegionHSV cv.inRange(hsvim, lower, upper)cv.imwrite(skinRegionHSV.jpg, skinRegionHSV)blurred cv.blur(skinRegionHSV, (2,2))ret, thresh cv.threshold(blurred,0,255,cv.THRESH_BINARY)return threshdef getcnthull(mask_img):contours, hierarchy cv.findContours(mask_img, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)contours max(contours, keylambda x: cv.contourArea(x))hull cv.convexHull(contours)return contours, hulldef getdefects(contours):hull cv.convexHull(contours, returnPointsFalse)defects cv.convexityDefects(contours, hull)return defectsimg cv.imread(./5.png)
mask_img skinmask(img)
cv.imwrite(mask_img.jpg, mask_img)contours, hull getcnthull(mask_img)cv.drawContours(img, [contours], -1, (255,255,0), 2)
cv.imwrite(contours.jpg, img)cv.drawContours(img, [hull], -1, (0, 255, 255), 2)
cv.imwrite(hull.jpg, img)defects getdefects(contours)if defects is not None:cnt 0for i in range(defects.shape[0]): # calculate the angles, e, f, d defects[i][0]start tuple(contours[s][0])end tuple(contours[e][0])far tuple(contours[f][0])a np.sqrt((end[0] - start[0]) ** 2 (end[1] - start[1]) ** 2)b np.sqrt((far[0] - start[0]) ** 2 (far[1] - start[1]) ** 2)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)) # cosine theoremif angle np.pi / 2: # angle less than 90 degree, treat as fingerscnt 1cv.circle(img, far, 4, [0, 0, 255], -1)if cnt 0:cnt cnt1cv.putText(img, str(cnt), (0, 50), cv.FONT_HERSHEY_SIMPLEX,1, (255, 0, 0) , 2, cv.LINE_AA)
cv.imshow(img, img)
cv.imwrite(fresult_{str(cnt)}.jpg, img)
cv.waitKey()
cv.destroyAllWindows()5、涉及到的库函数
关于 cv2.convexHull 和 cv2.convexityDefects 的使用说明可以参考 【python】OpenCV—findContours4.2
cv2.inRange
cv2.inRange 是 OpenCV 库中的一个函数用于检查数组元素是否位于两个指定的范围之间。这个函数通常用于图像处理和计算机视觉任务中特别是在进行图像阈值处理、颜色空间转换后的颜色过滤等场景。
cv2.inRange(src, lowerb, upperb, dstNone)src: 输入数组通常是图像它应该是一个单通道或多通道的数组。lowerb: 范围的下限包含与 src 同类型、同大小的数组或者是一个标量值。upperb: 范围的上限不包含与 src 同类型、同大小的数组或者是一个标量值。dst: 输出数组与 src 同大小、同类型。函数将结果存储在这里。如果为 None则会自动创建一个与 src 同大小、同类型的数组。
工作原理
对于 src 中的每个元素cv2.inRange 会检查它是否位于 [lowerb, upperb) 范围内注意上限是开区间即不包括上限值。如果元素值在这个范围内则对应的 dst 中的元素被设置为 255对于 8 位图像否则被设置为 0。这样dst 数组最终会是一个二值图像只有 0 和 255 的值其中白色255表示满足条件的像素黑色0表示不满足条件的像素。
应用场景
颜色过滤在 HSV 颜色空间中可以通过 cv2.inRange 来提取特定颜色的物体。例如提取图像中的红色部分。阈值处理在灰度图像中可以用来提取特定亮度范围内的像素。背景分割如果背景的颜色或亮度与前景有明显的区别可以用这个函数来分离背景和前景。
示例代码
以下是一个简单的示例展示如何使用 cv2.inRange 来提取图像中的红色部分
import cv2
import numpy as np# 读取图像
image cv2.imread(example.jpg)# 转换到 HSV 颜色空间
hsv cv2.cvtColor(image, cv2.COLOR_BGR2HSV)# 定义红色的 HSV 范围
lower_red np.array([0, 120, 70])
upper_red np.array([10, 255, 255])
mask1 cv2.inRange(hsv, lower_red, upper_red)lower_red np.array([170, 120, 70])
upper_red np.array([180, 255, 255])
mask2 cv2.inRange(hsv, lower_red, upper_red)# 合并两个掩码
mask mask1 | mask2# 使用掩码提取红色部分
result cv2.bitwise_and(image, image, maskmask)# 显示结果
cv2.imshow(Original Image, image)
cv2.imshow(Red Extracted, result)
cv2.waitKey(0)
cv2.destroyAllWindows()这个示例首先读取一张图像然后将其转换到 HSV 颜色空间。接着定义了两个红色的 HSV 范围因为红色在 HSV 空间中跨越了两个范围并使用 cv2.inRange 生成两个掩码。之后合并这两个掩码并使用掩码提取图像中的红色部分。最后显示原始图像和提取的红色部分。
6、参考
凸缺陷 convexityDefects基于OpenCV的手掌检测和手指计数https://github.com/madhav240/hand-detection-and-finger-counting/blob/master/finger_counting_video.py