2

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

在此处输入图像描述

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

我怎样才能做到最好?首先,我需要设法找到奇怪的闭合轮廓,然后从那里开始?

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

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", "TrackBars", 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, value_BSize,
                                   cVal)
    imgDial = cv2.dilate(gaussC, kernel, iterations=3)
    imgErode = cv2.erode(imgDial, kernel, 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, 255, 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, value_BSize, cVal)
        getContours(imPrePro)
        cv2.imshow("Preprocessed", imPrePro)
        cv2.imshow("Original", imgCon)

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

4

3 回答 3

2

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

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

阈值手

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

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

于 2021-02-08T22:00:22.123 回答
0

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

在此处输入图像描述

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, contours, -1, (0, 255, 0), 3);

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

# save
cv2.imwrite("marked_hand.png", marked);
于 2021-02-01T22:35:09.873 回答
0

你有没有研究过谷歌的媒体管道,作为 opencv 的替代品?

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

于 2021-02-11T23:04:54.773 回答