微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

OpenCV - 使用凸包和自适应阈值在手指上绘制轮廓

如何解决OpenCV - 使用凸包和自适应阈值在手指上绘制轮廓

我对 OpenCV 还很陌生,正在尝试使用网络摄像头沿着手部轮廓绘制简单的轮廓。我决定使用 cv2.adaptiveThreshold() 来处理相机适应手部移动时不同的光线强度。一切似乎都很好,只是它在寻找手指然后绘制闭合轮廓时遇到了困难。 看这里:

enter image description here

我想尝试检测一个凸包,并以某种方式检测任何偏离它的东西。

我该如何做到最好?首先,我需要设法找到奇怪的封闭轮廓,然后从那里开始?

这是代码,我为您修复了轨迹栏值:)

import cv2
import numpy as np

#####################################
winWidth = 640
winHeight = 840
brightness = 100

cap = cv2.VideoCapture(0)
cap.set(3,winWidth)
cap.set(4,winHeight)
cap.set(10,brightness)

kernel = (7,7)


#######################################################################
def empty(a):
    pass


cv2.namedWindow("TrackBars")
cv2.resizeWindow("TrackBars",640,240)
cv2.createTrackbar("cVal","TrackBars",10,40,empty)
cv2.createTrackbar("bSize",77,154,empty)


def preprocessing(frame,value_BSize,cVal):
    imgGray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
    # mask = cv2.inRange(imgHsv,lower,upper)
    imgBlurred = cv2.GaussianBlur(imgGray,kernel,4)
    gaussC = cv2.adaptiveThreshold(imgBlurred,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY_INV,cVal)
    imgDial = cv2.dilate(gaussC,iterations=3)
    imgErode = cv2.erode(imgDial,iterations=1)

    return imgDial


def getContours(imPrePro):
    contours,hierarchy = cv2.findContours(imPrePro,cv2.RETR_TREE,cv2.CHAIN_APPROX_NONE)
    for cnt in contours:
        area = cv2.contourArea(cnt)
        if area > 60:
            cv2.drawContours(imgCon,cnt,-1,(0,0),2,cv2.FONT_HERShey_SIMPLEX)
            peri = cv2.arcLength(cnt,True)
            approx = cv2.approxpolyDP(cnt,0.02 * peri,True)


#######################################################################################################

while cap.isOpened():
    success,frame = cap.read()
    cVal = cv2.getTrackbarPos("cVal","TrackBars")
    bVal = cv2.getTrackbarPos("bVal","TrackBars")
    value_BSize = cv2.getTrackbarPos("bSize","TrackBars")
    value_BSize = max(3,value_BSize)
    if (value_BSize % 2 == 0):
        value_BSize += 1

    if success == True:
        frame = cv2.flip(frame,1)
        imgCon = frame.copy()
        imPrePro = preprocessing(frame,cVal)
        getContours(imPrePro)
        cv2.imshow("Preprocessed",imPrePro)
        cv2.imshow("Original",imgCon)

        if cv2.waitKey(1) & 0xFF == ord("q"):
            cv2.destroyAllWindows()
            break

解决方法

L*a*b color space 可以帮助找到比背景更亮的物体。一个优点是色彩空间与硬件无关,因此它应该从任何相机产生相对相似的结果。使用 OTSU 选项对图像设置阈值可以帮助它在不同的闪电条件下工作,因为它会计算最佳阈值强度以分离图像中的亮区和暗区。显然它不是灵丹妙药,也不会在所有情况下都完美地工作,尤其是在极端情况下,但只要您手部的亮度与背景相对不同,它应该可以工作。

lab = cv2.cvtColor(frame,cv2.COLOR_BGR2LAB)
tv,thresh = cv2.threshold(lab[:,:,0],255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
plt.imshow(thresh)

Thresholded hand

一旦手被正确设置阈值,您就可以继续查找轮廓并根据需要进行分析。

注意:阈值图像中的伪影是由于从原始发布图像中去除绿色轮廓线造成的。

,

我使用的是光阈值,因此根据图像的不同,这可能会有所不同,但这是适用于该阈值的方法。

enter image description here

import cv2
import numpy as np

# load image
img = cv2.imread("hand.jpg");

# lab
lab = cv2.cvtColor(img,cv2.COLOR_BGR2LAB);
l,a,b = cv2.split(lab);

# threshold
thresh = cv2.inRange(l,90,255);

# contour
_,contours,_ = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE);

# filter contours by size
marked = img.copy();
cv2.drawContours(marked,-1,(0,0),3);

# show
cv2.imshow("marked",marked);
cv2.imshow("Thresh",thresh);
cv2.waitKey(0);

# save
cv2.imwrite("marked_hand.png",marked);
,

你有没有研究过谷歌的 mediapipe,作为 opencv 的替代品?

另外,我想知道在框架上添加一个细的底部黑色边框是否有助于知道轮廓环绕手腕。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。